Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2014 The Bitcoin Core developers
3 : // Distributed under the MIT software license, see the accompanying
4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 :
6 : #include "script/standard.h"
7 :
8 : #include "pubkey.h"
9 : #include "script/script.h"
10 : #include "util.h"
11 : #include "utilstrencodings.h"
12 :
13 : #include <boost/foreach.hpp>
14 :
15 : using namespace std;
16 :
17 : typedef vector<unsigned char> valtype;
18 :
19 : unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
20 :
21 237 : CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
22 :
23 114 : const char* GetTxnOutputType(txnouttype t)
24 : {
25 114 : switch (t)
26 : {
27 : case TX_NONSTANDARD: return "nonstandard";
28 4 : case TX_PUBKEY: return "pubkey";
29 89 : case TX_PUBKEYHASH: return "pubkeyhash";
30 9 : case TX_SCRIPTHASH: return "scripthash";
31 3 : case TX_MULTISIG: return "multisig";
32 4 : case TX_NULL_DATA: return "nulldata";
33 : }
34 0 : return NULL;
35 : }
36 :
37 : /**
38 : * Return public keys or hashes from scriptPubKey, for 'standard' transaction types.
39 : */
40 37305 : bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsigned char> >& vSolutionsRet)
41 : {
42 : // Templates
43 37401 : static multimap<txnouttype, CScript> mTemplates;
44 37305 : if (mTemplates.empty())
45 : {
46 : // Standard tx, sender provides pubkey, receiver adds signature
47 576 : mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG));
48 :
49 : // Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
50 576 : mTemplates.insert(make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG));
51 :
52 : // Sender provides N pubkeys, receivers provides M signatures
53 576 : mTemplates.insert(make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG));
54 : }
55 :
56 : vSolutionsRet.clear();
57 :
58 : // Shortcut for pay-to-script-hash, which are more constrained than the other types:
59 : // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
60 37305 : if (scriptPubKey.IsPayToScriptHash())
61 : {
62 484 : typeRet = TX_SCRIPTHASH;
63 2904 : vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
64 484 : vSolutionsRet.push_back(hashBytes);
65 484 : return true;
66 : }
67 :
68 : // Provably prunable, data-carrying output
69 : //
70 : // So long as script passes the IsUnspendable() test and all but the first
71 : // byte passes the IsPushOnly() test we don't care what exactly is in the
72 : // script.
73 73678 : if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
74 17 : typeRet = TX_NULL_DATA;
75 17 : return true;
76 : }
77 :
78 : // Scan templates
79 36804 : const CScript& script1 = scriptPubKey;
80 396570 : BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates)
81 : {
82 53649 : const CScript& script2 = tplate.second;
83 : vSolutionsRet.clear();
84 :
85 : opcodetype opcode1, opcode2;
86 : vector<unsigned char> vch1, vch2;
87 :
88 : // Compare
89 107298 : CScript::const_iterator pc1 = script1.begin();
90 107298 : CScript::const_iterator pc2 = script2.begin();
91 : while (true)
92 : {
93 598999 : if (pc1 == script1.end() && pc2 == script2.end())
94 : {
95 : // Found a match
96 36537 : typeRet = tplate.first;
97 36537 : if (typeRet == TX_MULTISIG)
98 : {
99 : // Additional checks for TX_MULTISIG:
100 138 : unsigned char m = vSolutionsRet.front()[0];
101 138 : unsigned char n = vSolutionsRet.back()[0];
102 273 : if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n)
103 : return false;
104 : }
105 36533 : return true;
106 : }
107 138506 : if (!script1.GetOp(pc1, opcode1, vch1))
108 : break;
109 137979 : if (!script2.GetOp(pc2, opcode2, vch2))
110 : break;
111 :
112 : // Template matching opcodes:
113 137979 : if (opcode2 == OP_PUBKEYS)
114 : {
115 1032 : while (vch1.size() >= 33 && vch1.size() <= 65)
116 : {
117 372 : vSolutionsRet.push_back(vch1);
118 372 : if (!script1.GetOp(pc1, opcode1, vch1))
119 : break;
120 : }
121 145 : if (!script2.GetOp(pc2, opcode2, vch2))
122 : break;
123 : // Normal situation is to fall through
124 : // to other if/else statements
125 : }
126 :
127 137979 : if (opcode2 == OP_PUBKEY)
128 : {
129 73302 : if (vch1.size() < 33 || vch1.size() > 65)
130 : break;
131 20364 : vSolutionsRet.push_back(vch1);
132 : }
133 101328 : else if (opcode2 == OP_PUBKEYHASH)
134 : {
135 32070 : if (vch1.size() != sizeof(uint160))
136 : break;
137 16035 : vSolutionsRet.push_back(vch1);
138 : }
139 85293 : else if (opcode2 == OP_SMALLINTEGER)
140 : { // Single-byte small integer pushed onto vSolutions
141 397 : if (opcode1 == OP_0 ||
142 : (opcode1 >= OP_1 && opcode1 <= OP_16))
143 : {
144 353 : char n = (char)CScript::DecodeOP_N(opcode1);
145 1059 : vSolutionsRet.push_back(valtype(1, n));
146 : }
147 : else
148 : break;
149 : }
150 169538 : else if (opcode1 != opcode2 || vch1 != vch2)
151 : {
152 : // Others must match exactly
153 : break;
154 : }
155 : }
156 : }
157 :
158 : vSolutionsRet.clear();
159 267 : typeRet = TX_NONSTANDARD;
160 267 : return false;
161 : }
162 :
163 24 : int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions)
164 : {
165 24 : switch (t)
166 : {
167 : case TX_NONSTANDARD:
168 : case TX_NULL_DATA:
169 : return -1;
170 : case TX_PUBKEY:
171 6 : return 1;
172 : case TX_PUBKEYHASH:
173 9 : return 2;
174 : case TX_MULTISIG:
175 6 : if (vSolutions.size() < 1 || vSolutions[0].size() < 1)
176 : return -1;
177 2 : return vSolutions[0][0] + 1;
178 : case TX_SCRIPTHASH:
179 7 : return 1; // doesn't include args needed by the script
180 : }
181 : return -1;
182 : }
183 :
184 1545 : bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
185 : {
186 : vector<valtype> vSolutions;
187 : txnouttype whichType;
188 1545 : if (!Solver(scriptPubKey, whichType, vSolutions))
189 : return false;
190 :
191 1545 : if (whichType == TX_PUBKEY)
192 : {
193 992 : CPubKey pubKey(vSolutions[0]);
194 992 : if (!pubKey.IsValid())
195 : return false;
196 :
197 1984 : addressRet = pubKey.GetID();
198 992 : return true;
199 : }
200 553 : else if (whichType == TX_PUBKEYHASH)
201 : {
202 1076 : addressRet = CKeyID(uint160(vSolutions[0]));
203 538 : return true;
204 : }
205 15 : else if (whichType == TX_SCRIPTHASH)
206 : {
207 28 : addressRet = CScriptID(uint160(vSolutions[0]));
208 14 : return true;
209 : }
210 : // Multisig txns have more than one address...
211 1545 : return false;
212 : }
213 :
214 115 : bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vector<CTxDestination>& addressRet, int& nRequiredRet)
215 : {
216 115 : addressRet.clear();
217 115 : typeRet = TX_NONSTANDARD;
218 : vector<valtype> vSolutions;
219 115 : if (!Solver(scriptPubKey, typeRet, vSolutions))
220 : return false;
221 110 : if (typeRet == TX_NULL_DATA){
222 : // This is data, not addresses
223 : return false;
224 : }
225 :
226 106 : if (typeRet == TX_MULTISIG)
227 : {
228 4 : nRequiredRet = vSolutions.front()[0];
229 28 : for (unsigned int i = 1; i < vSolutions.size()-1; i++)
230 : {
231 20 : CPubKey pubKey(vSolutions[i]);
232 10 : if (!pubKey.IsValid())
233 0 : continue;
234 :
235 20 : CTxDestination address = pubKey.GetID();
236 10 : addressRet.push_back(address);
237 : }
238 :
239 4 : if (addressRet.empty())
240 : return false;
241 : }
242 : else
243 : {
244 102 : nRequiredRet = 1;
245 : CTxDestination address;
246 102 : if (!ExtractDestination(scriptPubKey, address))
247 0 : return false;
248 102 : addressRet.push_back(address);
249 : }
250 :
251 115 : return true;
252 : }
253 :
254 : namespace
255 : {
256 2542 : class CScriptVisitor : public boost::static_visitor<bool>
257 : {
258 : private:
259 : CScript *script;
260 : public:
261 2542 : CScriptVisitor(CScript *scriptin) { script = scriptin; }
262 :
263 0 : bool operator()(const CNoDestination &dest) const {
264 0 : script->clear();
265 0 : return false;
266 : }
267 :
268 2496 : bool operator()(const CKeyID &keyID) const {
269 2496 : script->clear();
270 4992 : *script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
271 2496 : return true;
272 : }
273 :
274 46 : bool operator()(const CScriptID &scriptID) const {
275 46 : script->clear();
276 92 : *script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
277 46 : return true;
278 : }
279 : };
280 : }
281 :
282 2542 : CScript GetScriptForDestination(const CTxDestination& dest)
283 : {
284 : CScript script;
285 :
286 2542 : boost::apply_visitor(CScriptVisitor(&script), dest);
287 2542 : return script;
288 : }
289 :
290 1394 : CScript GetScriptForRawPubKey(const CPubKey& pubKey)
291 : {
292 8364 : return CScript() << std::vector<unsigned char>(pubKey.begin(), pubKey.end()) << OP_CHECKSIG;
293 : }
294 :
295 15 : CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
296 : {
297 : CScript script;
298 :
299 15 : script << CScript::EncodeOP_N(nRequired);
300 255 : BOOST_FOREACH(const CPubKey& key, keys)
301 72 : script << ToByteVector(key);
302 30 : script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
303 15 : return script;
304 330 : }
|