]> Git Repo - VerusCoin.git/blame - src/script/standard.cpp
Merge branch 'dev' into jl777
[VerusCoin.git] / src / script / standard.cpp
CommitLineData
c4408a6c 1// Copyright (c) 2009-2010 Satoshi Nakamoto
f914f1a7 2// Copyright (c) 2009-2014 The Bitcoin Core developers
2d79bba3 3// Distributed under the MIT software license, see the accompanying
c4408a6c 4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#include "script/standard.h"
7
d2e74c55 8#include "pubkey.h"
c4408a6c 9#include "script/script.h"
10#include "util.h"
85c579e3 11#include "utilstrencodings.h"
c4408a6c 12
13#include <boost/foreach.hpp>
14
15using namespace std;
16
17typedef vector<unsigned char> valtype;
18
2aa63292
LD
19unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
20
d78f0daf 21CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
066e2a14 22
c4408a6c 23const char* GetTxnOutputType(txnouttype t)
24{
25 switch (t)
26 {
27 case TX_NONSTANDARD: return "nonstandard";
28 case TX_PUBKEY: return "pubkey";
29 case TX_PUBKEYHASH: return "pubkeyhash";
30 case TX_SCRIPTHASH: return "scripthash";
31 case TX_MULTISIG: return "multisig";
32 case TX_NULL_DATA: return "nulldata";
33 }
34 return NULL;
35}
36
b9a36b15
MF
37/**
38 * Return public keys or hashes from scriptPubKey, for 'standard' transaction types.
39 */
c4408a6c 40bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsigned char> >& vSolutionsRet)
41{
42 // Templates
43 static multimap<txnouttype, CScript> mTemplates;
44 if (mTemplates.empty())
45 {
46 // Standard tx, sender provides pubkey, receiver adds signature
47 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 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 mTemplates.insert(make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG));
54
55 // Empty, provably prunable, data-carrying output
4aa2c64e 56 if (GetBoolArg("-datacarrier", true))
c4408a6c 57 mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN << OP_SMALLDATA));
58 mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN));
59 }
60
61 // Shortcut for pay-to-script-hash, which are more constrained than the other types:
62 // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
63 if (scriptPubKey.IsPayToScriptHash())
64 {
65 typeRet = TX_SCRIPTHASH;
66 vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
67 vSolutionsRet.push_back(hashBytes);
68 return true;
69 }
70
71 // Scan templates
72 const CScript& script1 = scriptPubKey;
73 BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates)
74 {
75 const CScript& script2 = tplate.second;
76 vSolutionsRet.clear();
77
78 opcodetype opcode1, opcode2;
79 vector<unsigned char> vch1, vch2;
80
81 // Compare
82 CScript::const_iterator pc1 = script1.begin();
83 CScript::const_iterator pc2 = script2.begin();
84 while (true)
85 {
86 if (pc1 == script1.end() && pc2 == script2.end())
87 {
88 // Found a match
89 typeRet = tplate.first;
90 if (typeRet == TX_MULTISIG)
91 {
92 // Additional checks for TX_MULTISIG:
93 unsigned char m = vSolutionsRet.front()[0];
94 unsigned char n = vSolutionsRet.back()[0];
95 if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n)
96 return false;
97 }
98 return true;
99 }
100 if (!script1.GetOp(pc1, opcode1, vch1))
101 break;
102 if (!script2.GetOp(pc2, opcode2, vch2))
103 break;
104
105 // Template matching opcodes:
106 if (opcode2 == OP_PUBKEYS)
107 {
108 while (vch1.size() >= 33 && vch1.size() <= 65)
109 {
110 vSolutionsRet.push_back(vch1);
111 if (!script1.GetOp(pc1, opcode1, vch1))
112 break;
113 }
114 if (!script2.GetOp(pc2, opcode2, vch2))
115 break;
116 // Normal situation is to fall through
117 // to other if/else statements
118 }
119
120 if (opcode2 == OP_PUBKEY)
121 {
122 if (vch1.size() < 33 || vch1.size() > 65)
123 break;
124 vSolutionsRet.push_back(vch1);
125 }
126 else if (opcode2 == OP_PUBKEYHASH)
127 {
128 if (vch1.size() != sizeof(uint160))
129 break;
130 vSolutionsRet.push_back(vch1);
131 }
132 else if (opcode2 == OP_SMALLINTEGER)
133 { // Single-byte small integer pushed onto vSolutions
134 if (opcode1 == OP_0 ||
135 (opcode1 >= OP_1 && opcode1 <= OP_16))
136 {
137 char n = (char)CScript::DecodeOP_N(opcode1);
138 vSolutionsRet.push_back(valtype(1, n));
139 }
140 else
141 break;
142 }
143 else if (opcode2 == OP_SMALLDATA)
144 {
2aa63292
LD
145 // small pushdata, <= nMaxDatacarrierBytes
146 if (vch1.size() > nMaxDatacarrierBytes)
cc0f93da 147 {
148 fprintf(stderr,"size.%d > nMaxDatacarrier.%d\n",(int32_t)vch1.size(),(int32_t)nMaxDatacarrierBytes);
c4408a6c 149 break;
cc0f93da 150 }
c4408a6c 151 }
152 else if (opcode1 != opcode2 || vch1 != vch2)
153 {
154 // Others must match exactly
155 break;
156 }
157 }
158 }
159
160 vSolutionsRet.clear();
161 typeRet = TX_NONSTANDARD;
162 return false;
163}
164
165int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions)
166{
167 switch (t)
168 {
169 case TX_NONSTANDARD:
170 case TX_NULL_DATA:
171 return -1;
172 case TX_PUBKEY:
173 return 1;
174 case TX_PUBKEYHASH:
175 return 2;
176 case TX_MULTISIG:
177 if (vSolutions.size() < 1 || vSolutions[0].size() < 1)
178 return -1;
179 return vSolutions[0][0] + 1;
180 case TX_SCRIPTHASH:
181 return 1; // doesn't include args needed by the script
182 }
183 return -1;
184}
185
186bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
187{
188 vector<valtype> vSolutions;
189 if (!Solver(scriptPubKey, whichType, vSolutions))
cf9538e0 190 {
191 int32_t i; uint8_t *ptr = (uint8_t *)scriptPubKey.data();
192 for (i=0; i<scriptPubKey.size(); i++)
193 fprintf(stderr,"%02x",ptr[i]);
194 fprintf(stderr," non-standard scriptPubKey\n");
c4408a6c 195 return false;
cf9538e0 196 }
c4408a6c 197
198 if (whichType == TX_MULTISIG)
199 {
200 unsigned char m = vSolutions.front()[0];
201 unsigned char n = vSolutions.back()[0];
cf9538e0 202 // Support up to x-of-9 multisig txns as standard
203 if (n < 1 || n > 9)
c4408a6c 204 return false;
205 if (m < 1 || m > n)
206 return false;
207 }
c4408a6c 208 return whichType != TX_NONSTANDARD;
209}
210
211bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
212{
213 vector<valtype> vSolutions;
214 txnouttype whichType;
215 if (!Solver(scriptPubKey, whichType, vSolutions))
216 return false;
217
218 if (whichType == TX_PUBKEY)
219 {
9d7cd4c5
AA
220 CPubKey pubKey(vSolutions[0]);
221 if (!pubKey.IsValid())
b62d7030 222 {
223 fprintf(stderr,"TX_PUBKEY invalid pubkey\n");
9d7cd4c5 224 return false;
b62d7030 225 }
9d7cd4c5
AA
226
227 addressRet = pubKey.GetID();
c4408a6c 228 return true;
229 }
230 else if (whichType == TX_PUBKEYHASH)
231 {
232 addressRet = CKeyID(uint160(vSolutions[0]));
233 return true;
234 }
235 else if (whichType == TX_SCRIPTHASH)
236 {
237 addressRet = CScriptID(uint160(vSolutions[0]));
238 return true;
239 }
240 // Multisig txns have more than one address...
241 return false;
242}
243
244bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vector<CTxDestination>& addressRet, int& nRequiredRet)
245{
246 addressRet.clear();
247 typeRet = TX_NONSTANDARD;
248 vector<valtype> vSolutions;
249 if (!Solver(scriptPubKey, typeRet, vSolutions))
250 return false;
251 if (typeRet == TX_NULL_DATA){
252 // This is data, not addresses
253 return false;
254 }
255
256 if (typeRet == TX_MULTISIG)
257 {
258 nRequiredRet = vSolutions.front()[0];
259 for (unsigned int i = 1; i < vSolutions.size()-1; i++)
260 {
9d7cd4c5
AA
261 CPubKey pubKey(vSolutions[i]);
262 if (!pubKey.IsValid())
263 continue;
264
265 CTxDestination address = pubKey.GetID();
c4408a6c 266 addressRet.push_back(address);
267 }
9d7cd4c5
AA
268
269 if (addressRet.empty())
270 return false;
c4408a6c 271 }
272 else
273 {
274 nRequiredRet = 1;
275 CTxDestination address;
276 if (!ExtractDestination(scriptPubKey, address))
277 return false;
278 addressRet.push_back(address);
279 }
280
281 return true;
282}
0be990ba
PW
283
284namespace
285{
286class CScriptVisitor : public boost::static_visitor<bool>
287{
288private:
289 CScript *script;
290public:
291 CScriptVisitor(CScript *scriptin) { script = scriptin; }
292
293 bool operator()(const CNoDestination &dest) const {
294 script->clear();
295 return false;
296 }
297
298 bool operator()(const CKeyID &keyID) const {
299 script->clear();
e9ca4280 300 *script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
0be990ba
PW
301 return true;
302 }
303
304 bool operator()(const CScriptID &scriptID) const {
305 script->clear();
e9ca4280 306 *script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
0be990ba
PW
307 return true;
308 }
309};
310}
311
312CScript GetScriptForDestination(const CTxDestination& dest)
313{
314 CScript script;
315
316 boost::apply_visitor(CScriptVisitor(&script), dest);
317 return script;
318}
319
320CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
321{
322 CScript script;
323
324 script << CScript::EncodeOP_N(nRequired);
325 BOOST_FOREACH(const CPubKey& key, keys)
e9ca4280 326 script << ToByteVector(key);
0be990ba
PW
327 script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
328 return script;
329}
This page took 0.278332 seconds and 4 git commands to generate.