]> Git Repo - VerusCoin.git/blame - src/script/standard.cpp
test
[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
56 if (GetBoolArg("-datacarrier", true))
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)
c4408a6c 147 break;
148 }
149 else if (opcode1 != opcode2 || vch1 != vch2)
150 {
151 // Others must match exactly
152 break;
153 }
154 }
155 }
156
157 vSolutionsRet.clear();
158 typeRet = TX_NONSTANDARD;
159 return false;
160}
161
162int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions)
163{
164 switch (t)
165 {
166 case TX_NONSTANDARD:
167 case TX_NULL_DATA:
168 return -1;
169 case TX_PUBKEY:
170 return 1;
171 case TX_PUBKEYHASH:
172 return 2;
173 case TX_MULTISIG:
174 if (vSolutions.size() < 1 || vSolutions[0].size() < 1)
175 return -1;
176 return vSolutions[0][0] + 1;
177 case TX_SCRIPTHASH:
178 return 1; // doesn't include args needed by the script
179 }
180 return -1;
181}
182
183bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
184{
185 vector<valtype> vSolutions;
186 if (!Solver(scriptPubKey, whichType, vSolutions))
187 return false;
188
189 if (whichType == TX_MULTISIG)
190 {
191 unsigned char m = vSolutions.front()[0];
192 unsigned char n = vSolutions.back()[0];
193 // Support up to x-of-3 multisig txns as standard
194 if (n < 1 || n > 3)
195 return false;
196 if (m < 1 || m > n)
197 return false;
198 }
199
200 return whichType != TX_NONSTANDARD;
201}
202
203bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
204{
205 vector<valtype> vSolutions;
206 txnouttype whichType;
207 if (!Solver(scriptPubKey, whichType, vSolutions))
208 return false;
209
210 if (whichType == TX_PUBKEY)
211 {
9d7cd4c5
AA
212 CPubKey pubKey(vSolutions[0]);
213 if (!pubKey.IsValid())
b62d7030 214 {
215 fprintf(stderr,"TX_PUBKEY invalid pubkey\n");
9d7cd4c5 216 return false;
b62d7030 217 }
9d7cd4c5
AA
218
219 addressRet = pubKey.GetID();
c4408a6c 220 return true;
221 }
222 else if (whichType == TX_PUBKEYHASH)
223 {
224 addressRet = CKeyID(uint160(vSolutions[0]));
225 return true;
226 }
227 else if (whichType == TX_SCRIPTHASH)
228 {
229 addressRet = CScriptID(uint160(vSolutions[0]));
230 return true;
231 }
232 // Multisig txns have more than one address...
233 return false;
234}
235
236bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vector<CTxDestination>& addressRet, int& nRequiredRet)
237{
238 addressRet.clear();
239 typeRet = TX_NONSTANDARD;
240 vector<valtype> vSolutions;
241 if (!Solver(scriptPubKey, typeRet, vSolutions))
242 return false;
243 if (typeRet == TX_NULL_DATA){
244 // This is data, not addresses
245 return false;
246 }
247
248 if (typeRet == TX_MULTISIG)
249 {
250 nRequiredRet = vSolutions.front()[0];
251 for (unsigned int i = 1; i < vSolutions.size()-1; i++)
252 {
9d7cd4c5
AA
253 CPubKey pubKey(vSolutions[i]);
254 if (!pubKey.IsValid())
255 continue;
256
257 CTxDestination address = pubKey.GetID();
c4408a6c 258 addressRet.push_back(address);
259 }
9d7cd4c5
AA
260
261 if (addressRet.empty())
262 return false;
c4408a6c 263 }
264 else
265 {
266 nRequiredRet = 1;
267 CTxDestination address;
268 if (!ExtractDestination(scriptPubKey, address))
269 return false;
270 addressRet.push_back(address);
271 }
272
273 return true;
274}
0be990ba
PW
275
276namespace
277{
278class CScriptVisitor : public boost::static_visitor<bool>
279{
280private:
281 CScript *script;
282public:
283 CScriptVisitor(CScript *scriptin) { script = scriptin; }
284
285 bool operator()(const CNoDestination &dest) const {
286 script->clear();
287 return false;
288 }
289
290 bool operator()(const CKeyID &keyID) const {
291 script->clear();
e9ca4280 292 *script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
0be990ba
PW
293 return true;
294 }
295
296 bool operator()(const CScriptID &scriptID) const {
297 script->clear();
e9ca4280 298 *script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
0be990ba
PW
299 return true;
300 }
301};
302}
303
304CScript GetScriptForDestination(const CTxDestination& dest)
305{
306 CScript script;
307
308 boost::apply_visitor(CScriptVisitor(&script), dest);
309 return script;
310}
311
312CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
313{
314 CScript script;
315
316 script << CScript::EncodeOP_N(nRequired);
317 BOOST_FOREACH(const CPubKey& key, keys)
e9ca4280 318 script << ToByteVector(key);
0be990ba
PW
319 script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
320 return script;
321}
This page took 0.159319 seconds and 4 git commands to generate.