depends: use new variable layout for qt sdk
[bitcoinplatinum.git] / src / script / standard.cpp
blob4b9bec9aa18a45738c8275ba112d2bd68bd6d769
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 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.
6 #include "script/standard.h"
8 #include "pubkey.h"
9 #include "script/script.h"
10 #include "util.h"
11 #include "utilstrencodings.h"
13 #include <boost/foreach.hpp>
15 using namespace std;
17 typedef vector<unsigned char> valtype;
19 bool fAcceptDatacarrier = DEFAULT_ACCEPT_DATACARRIER;
20 unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
22 CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
24 const char* GetTxnOutputType(txnouttype t)
26 switch (t)
28 case TX_NONSTANDARD: return "nonstandard";
29 case TX_PUBKEY: return "pubkey";
30 case TX_PUBKEYHASH: return "pubkeyhash";
31 case TX_SCRIPTHASH: return "scripthash";
32 case TX_MULTISIG: return "multisig";
33 case TX_NULL_DATA: return "nulldata";
34 case TX_WITNESS_V0_KEYHASH: return "witness_v0_keyhash";
35 case TX_WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash";
37 return NULL;
40 /**
41 * Return public keys or hashes from scriptPubKey, for 'standard' transaction types.
43 bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsigned char> >& vSolutionsRet)
45 // Templates
46 static multimap<txnouttype, CScript> mTemplates;
47 if (mTemplates.empty())
49 // Standard tx, sender provides pubkey, receiver adds signature
50 mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG));
52 // Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
53 mTemplates.insert(make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG));
55 // Sender provides N pubkeys, receivers provides M signatures
56 mTemplates.insert(make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG));
59 vSolutionsRet.clear();
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())
65 typeRet = TX_SCRIPTHASH;
66 vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
67 vSolutionsRet.push_back(hashBytes);
68 return true;
71 int witnessversion;
72 std::vector<unsigned char> witnessprogram;
73 if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
74 if (witnessversion == 0 && witnessprogram.size() == 20) {
75 typeRet = TX_WITNESS_V0_KEYHASH;
76 vSolutionsRet.push_back(witnessprogram);
77 return true;
79 if (witnessversion == 0 && witnessprogram.size() == 32) {
80 typeRet = TX_WITNESS_V0_SCRIPTHASH;
81 vSolutionsRet.push_back(witnessprogram);
82 return true;
84 return false;
87 // Provably prunable, data-carrying output
89 // So long as script passes the IsUnspendable() test and all but the first
90 // byte passes the IsPushOnly() test we don't care what exactly is in the
91 // script.
92 if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
93 typeRet = TX_NULL_DATA;
94 return true;
97 // Scan templates
98 const CScript& script1 = scriptPubKey;
99 BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates)
101 const CScript& script2 = tplate.second;
102 vSolutionsRet.clear();
104 opcodetype opcode1, opcode2;
105 vector<unsigned char> vch1, vch2;
107 // Compare
108 CScript::const_iterator pc1 = script1.begin();
109 CScript::const_iterator pc2 = script2.begin();
110 while (true)
112 if (pc1 == script1.end() && pc2 == script2.end())
114 // Found a match
115 typeRet = tplate.first;
116 if (typeRet == TX_MULTISIG)
118 // Additional checks for TX_MULTISIG:
119 unsigned char m = vSolutionsRet.front()[0];
120 unsigned char n = vSolutionsRet.back()[0];
121 if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n)
122 return false;
124 return true;
126 if (!script1.GetOp(pc1, opcode1, vch1))
127 break;
128 if (!script2.GetOp(pc2, opcode2, vch2))
129 break;
131 // Template matching opcodes:
132 if (opcode2 == OP_PUBKEYS)
134 while (vch1.size() >= 33 && vch1.size() <= 65)
136 vSolutionsRet.push_back(vch1);
137 if (!script1.GetOp(pc1, opcode1, vch1))
138 break;
140 if (!script2.GetOp(pc2, opcode2, vch2))
141 break;
142 // Normal situation is to fall through
143 // to other if/else statements
146 if (opcode2 == OP_PUBKEY)
148 if (vch1.size() < 33 || vch1.size() > 65)
149 break;
150 vSolutionsRet.push_back(vch1);
152 else if (opcode2 == OP_PUBKEYHASH)
154 if (vch1.size() != sizeof(uint160))
155 break;
156 vSolutionsRet.push_back(vch1);
158 else if (opcode2 == OP_SMALLINTEGER)
159 { // Single-byte small integer pushed onto vSolutions
160 if (opcode1 == OP_0 ||
161 (opcode1 >= OP_1 && opcode1 <= OP_16))
163 char n = (char)CScript::DecodeOP_N(opcode1);
164 vSolutionsRet.push_back(valtype(1, n));
166 else
167 break;
169 else if (opcode1 != opcode2 || vch1 != vch2)
171 // Others must match exactly
172 break;
177 vSolutionsRet.clear();
178 typeRet = TX_NONSTANDARD;
179 return false;
182 bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
184 vector<valtype> vSolutions;
185 txnouttype whichType;
186 if (!Solver(scriptPubKey, whichType, vSolutions))
187 return false;
189 if (whichType == TX_PUBKEY)
191 CPubKey pubKey(vSolutions[0]);
192 if (!pubKey.IsValid())
193 return false;
195 addressRet = pubKey.GetID();
196 return true;
198 else if (whichType == TX_PUBKEYHASH)
200 addressRet = CKeyID(uint160(vSolutions[0]));
201 return true;
203 else if (whichType == TX_SCRIPTHASH)
205 addressRet = CScriptID(uint160(vSolutions[0]));
206 return true;
208 // Multisig txns have more than one address...
209 return false;
212 bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vector<CTxDestination>& addressRet, int& nRequiredRet)
214 addressRet.clear();
215 typeRet = TX_NONSTANDARD;
216 vector<valtype> vSolutions;
217 if (!Solver(scriptPubKey, typeRet, vSolutions))
218 return false;
219 if (typeRet == TX_NULL_DATA){
220 // This is data, not addresses
221 return false;
224 if (typeRet == TX_MULTISIG)
226 nRequiredRet = vSolutions.front()[0];
227 for (unsigned int i = 1; i < vSolutions.size()-1; i++)
229 CPubKey pubKey(vSolutions[i]);
230 if (!pubKey.IsValid())
231 continue;
233 CTxDestination address = pubKey.GetID();
234 addressRet.push_back(address);
237 if (addressRet.empty())
238 return false;
240 else
242 nRequiredRet = 1;
243 CTxDestination address;
244 if (!ExtractDestination(scriptPubKey, address))
245 return false;
246 addressRet.push_back(address);
249 return true;
252 namespace
254 class CScriptVisitor : public boost::static_visitor<bool>
256 private:
257 CScript *script;
258 public:
259 CScriptVisitor(CScript *scriptin) { script = scriptin; }
261 bool operator()(const CNoDestination &dest) const {
262 script->clear();
263 return false;
266 bool operator()(const CKeyID &keyID) const {
267 script->clear();
268 *script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
269 return true;
272 bool operator()(const CScriptID &scriptID) const {
273 script->clear();
274 *script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
275 return true;
280 CScript GetScriptForDestination(const CTxDestination& dest)
282 CScript script;
284 boost::apply_visitor(CScriptVisitor(&script), dest);
285 return script;
288 CScript GetScriptForRawPubKey(const CPubKey& pubKey)
290 return CScript() << std::vector<unsigned char>(pubKey.begin(), pubKey.end()) << OP_CHECKSIG;
293 CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
295 CScript script;
297 script << CScript::EncodeOP_N(nRequired);
298 BOOST_FOREACH(const CPubKey& key, keys)
299 script << ToByteVector(key);
300 script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
301 return script;
304 CScript GetScriptForWitness(const CScript& redeemscript)
306 CScript ret;
308 txnouttype typ;
309 std::vector<std::vector<unsigned char> > vSolutions;
310 if (Solver(redeemscript, typ, vSolutions)) {
311 if (typ == TX_PUBKEY) {
312 unsigned char h160[20];
313 CHash160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160);
314 ret << OP_0 << std::vector<unsigned char>(&h160[0], &h160[20]);
315 return ret;
316 } else if (typ == TX_PUBKEYHASH) {
317 ret << OP_0 << vSolutions[0];
318 return ret;
321 uint256 hash;
322 CSHA256().Write(&redeemscript[0], redeemscript.size()).Finalize(hash.begin());
323 ret << OP_0 << ToByteVector(hash);
324 return ret;