1 // Copyright (c) 2014-2020 Daniel Kraft
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5 #include <script/names.h>
6
7 #include <hash.h>
8 #include <uint256.h>
9
CNameScript(const CScript & script)10 CNameScript::CNameScript (const CScript& script)
11 : op(OP_NOP), address(script)
12 {
13 opcodetype nameOp;
14 CScript::const_iterator pc = script.begin ();
15 if (!script.GetOp (pc, nameOp))
16 return;
17
18 opcodetype opcode;
19 while (true)
20 {
21 valtype vch;
22
23 if (!script.GetOp (pc, opcode, vch))
24 return;
25 if (opcode == OP_DROP || opcode == OP_2DROP || opcode == OP_NOP)
26 break;
27 if (!(opcode >= 0 && opcode <= OP_PUSHDATA4))
28 return;
29
30 args.push_back (vch);
31 }
32
33 // Move the pc to after any DROP or NOP.
34 while (opcode == OP_DROP || opcode == OP_2DROP || opcode == OP_NOP)
35 if (!script.GetOp (pc, opcode))
36 break;
37 pc--;
38
39 /* Now, we have the args and the operation. Check if we have indeed
40 a valid name operation and valid argument counts. Only now set the
41 op and address members, if everything is valid. */
42 switch (nameOp)
43 {
44 case OP_NAME_NEW:
45 if (args.size () != 1)
46 return;
47 break;
48
49 case OP_NAME_FIRSTUPDATE:
50 if (args.size () != 3)
51 return;
52 break;
53
54 case OP_NAME_UPDATE:
55 if (args.size () != 2)
56 return;
57 break;
58
59 default:
60 return;
61 }
62
63 op = nameOp;
64 address = CScript (pc, script.end ());
65 }
66
67 namespace
68 {
69
70 /**
71 * Concats together a base address and name prefix script.
72 */
73 CScript
AddNamePrefix(const CScript & addr,const CScript & prefix)74 AddNamePrefix (const CScript& addr, const CScript& prefix)
75 {
76 CScript res = prefix;
77 res.insert (res.end (), addr.begin (), addr.end ());
78 return res;
79 }
80
81 } // anonymous namespace
82
83 CScript
buildNameNew(const CScript & addr,const valtype & name,const valtype & rand)84 CNameScript::buildNameNew (const CScript& addr, const valtype& name,
85 const valtype& rand)
86 {
87 valtype toHash(rand);
88 toHash.insert (toHash.end (), name.begin (), name.end ());
89 const uint160 hash = Hash160 (toHash);
90
91 CScript prefix;
92 prefix << OP_NAME_NEW << ToByteVector (hash) << OP_2DROP;
93
94 return AddNamePrefix (addr, prefix);
95 }
96
97 CScript
buildNameFirstupdate(const CScript & addr,const valtype & name,const valtype & value,const valtype & rand)98 CNameScript::buildNameFirstupdate (const CScript& addr, const valtype& name,
99 const valtype& value, const valtype& rand)
100 {
101 CScript prefix;
102 prefix << OP_NAME_FIRSTUPDATE << name << rand << value
103 << OP_2DROP << OP_2DROP;
104
105 return AddNamePrefix (addr, prefix);
106 }
107
108 CScript
buildNameUpdate(const CScript & addr,const valtype & name,const valtype & value)109 CNameScript::buildNameUpdate (const CScript& addr, const valtype& name,
110 const valtype& value)
111 {
112 CScript prefix;
113 prefix << OP_NAME_UPDATE << name << value << OP_2DROP << OP_DROP;
114
115 return AddNamePrefix (addr, prefix);
116 }
117