1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2018 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 <crypto/sha256.h>
9 #include <pubkey.h>
10 #include <script/script.h>
11 #include <util/system.h>
12 #include <util/strencodings.h>
13 
14 
15 typedef std::vector<unsigned char> valtype;
16 
17 bool fAcceptDatacarrier = DEFAULT_ACCEPT_DATACARRIER;
18 unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
19 
CScriptID(const CScript & in)20 CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
21 
WitnessV0ScriptHash(const CScript & in)22 WitnessV0ScriptHash::WitnessV0ScriptHash(const CScript& in)
23 {
24     CSHA256().Write(in.data(), in.size()).Finalize(begin());
25 }
26 
GetTxnOutputType(txnouttype t)27 const char* GetTxnOutputType(txnouttype t)
28 {
29     switch (t)
30     {
31     case TX_NONSTANDARD: return "nonstandard";
32     case TX_PUBKEY: return "pubkey";
33     case TX_PUBKEYHASH: return "pubkeyhash";
34     case TX_SCRIPTHASH: return "scripthash";
35     case TX_MULTISIG: return "multisig";
36     case TX_NULL_DATA: return "nulldata";
37     case TX_WITNESS_V0_KEYHASH: return "witness_v0_keyhash";
38     case TX_WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash";
39     case TX_WITNESS_UNKNOWN: return "witness_unknown";
40     }
41     return nullptr;
42 }
43 
MatchPayToPubkey(const CScript & script,valtype & pubkey)44 static bool MatchPayToPubkey(const CScript& script, valtype& pubkey)
45 {
46     if (script.size() == CPubKey::PUBLIC_KEY_SIZE + 2 && script[0] == CPubKey::PUBLIC_KEY_SIZE && script.back() == OP_CHECKSIG) {
47         pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::PUBLIC_KEY_SIZE + 1);
48         return CPubKey::ValidSize(pubkey);
49     }
50     if (script.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 2 && script[0] == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE && script.back() == OP_CHECKSIG) {
51         pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1);
52         return CPubKey::ValidSize(pubkey);
53     }
54     return false;
55 }
56 
MatchPayToPubkeyHash(const CScript & script,valtype & pubkeyhash)57 static bool MatchPayToPubkeyHash(const CScript& script, valtype& pubkeyhash)
58 {
59     if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160 && script[2] == 20 && script[23] == OP_EQUALVERIFY && script[24] == OP_CHECKSIG) {
60         pubkeyhash = valtype(script.begin () + 3, script.begin() + 23);
61         return true;
62     }
63     return false;
64 }
65 
66 /** Test for "small positive integer" script opcodes - OP_1 through OP_16. */
IsSmallInteger(opcodetype opcode)67 static constexpr bool IsSmallInteger(opcodetype opcode)
68 {
69     return opcode >= OP_1 && opcode <= OP_16;
70 }
71 
MatchMultisig(const CScript & script,unsigned int & required,std::vector<valtype> & pubkeys)72 static bool MatchMultisig(const CScript& script, unsigned int& required, std::vector<valtype>& pubkeys)
73 {
74     opcodetype opcode;
75     valtype data;
76     CScript::const_iterator it = script.begin();
77     if (script.size() < 1 || script.back() != OP_CHECKMULTISIG) return false;
78 
79     if (!script.GetOp(it, opcode, data) || !IsSmallInteger(opcode)) return false;
80     required = CScript::DecodeOP_N(opcode);
81     while (script.GetOp(it, opcode, data) && CPubKey::ValidSize(data)) {
82         pubkeys.emplace_back(std::move(data));
83     }
84     if (!IsSmallInteger(opcode)) return false;
85     unsigned int keys = CScript::DecodeOP_N(opcode);
86     if (pubkeys.size() != keys || keys < required) return false;
87     return (it + 1 == script.end());
88 }
89 
Solver(const CScript & scriptPubKey,std::vector<std::vector<unsigned char>> & vSolutionsRet)90 txnouttype Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned char>>& vSolutionsRet)
91 {
92     vSolutionsRet.clear();
93 
94     // Shortcut for pay-to-script-hash, which are more constrained than the other types:
95     // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
96     if (scriptPubKey.IsPayToScriptHash())
97     {
98         std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
99         vSolutionsRet.push_back(hashBytes);
100         return TX_SCRIPTHASH;
101     }
102 
103     int witnessversion;
104     std::vector<unsigned char> witnessprogram;
105     if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
106         if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_KEYHASH_SIZE) {
107             vSolutionsRet.push_back(witnessprogram);
108             return TX_WITNESS_V0_KEYHASH;
109         }
110         if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_SCRIPTHASH_SIZE) {
111             vSolutionsRet.push_back(witnessprogram);
112             return TX_WITNESS_V0_SCRIPTHASH;
113         }
114         if (witnessversion != 0) {
115             vSolutionsRet.push_back(std::vector<unsigned char>{(unsigned char)witnessversion});
116             vSolutionsRet.push_back(std::move(witnessprogram));
117             return TX_WITNESS_UNKNOWN;
118         }
119         return TX_NONSTANDARD;
120     }
121 
122     // Provably prunable, data-carrying output
123     //
124     // So long as script passes the IsUnspendable() test and all but the first
125     // byte passes the IsPushOnly() test we don't care what exactly is in the
126     // script.
127     if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
128         return TX_NULL_DATA;
129     }
130 
131     std::vector<unsigned char> data;
132     if (MatchPayToPubkey(scriptPubKey, data)) {
133         vSolutionsRet.push_back(std::move(data));
134         return TX_PUBKEY;
135     }
136 
137     if (MatchPayToPubkeyHash(scriptPubKey, data)) {
138         vSolutionsRet.push_back(std::move(data));
139         return TX_PUBKEYHASH;
140     }
141 
142     unsigned int required;
143     std::vector<std::vector<unsigned char>> keys;
144     if (MatchMultisig(scriptPubKey, required, keys)) {
145         vSolutionsRet.push_back({static_cast<unsigned char>(required)}); // safe as required is in range 1..16
146         vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end());
147         vSolutionsRet.push_back({static_cast<unsigned char>(keys.size())}); // safe as size is in range 1..16
148         return TX_MULTISIG;
149     }
150 
151     vSolutionsRet.clear();
152     return TX_NONSTANDARD;
153 }
154 
ExtractDestination(const CScript & scriptPubKey,CTxDestination & addressRet)155 bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
156 {
157     std::vector<valtype> vSolutions;
158     txnouttype whichType = Solver(scriptPubKey, vSolutions);
159 
160     if (whichType == TX_PUBKEY) {
161         CPubKey pubKey(vSolutions[0]);
162         if (!pubKey.IsValid())
163             return false;
164 
165         addressRet = pubKey.GetID();
166         return true;
167     }
168     else if (whichType == TX_PUBKEYHASH)
169     {
170         addressRet = CKeyID(uint160(vSolutions[0]));
171         return true;
172     }
173     else if (whichType == TX_SCRIPTHASH)
174     {
175         addressRet = CScriptID(uint160(vSolutions[0]));
176         return true;
177     } else if (whichType == TX_WITNESS_V0_KEYHASH) {
178         WitnessV0KeyHash hash;
179         std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
180         addressRet = hash;
181         return true;
182     } else if (whichType == TX_WITNESS_V0_SCRIPTHASH) {
183         WitnessV0ScriptHash hash;
184         std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
185         addressRet = hash;
186         return true;
187     } else if (whichType == TX_WITNESS_UNKNOWN) {
188         WitnessUnknown unk;
189         unk.version = vSolutions[0][0];
190         std::copy(vSolutions[1].begin(), vSolutions[1].end(), unk.program);
191         unk.length = vSolutions[1].size();
192         addressRet = unk;
193         return true;
194     }
195     // Multisig txns have more than one address...
196     return false;
197 }
198 
ExtractDestinations(const CScript & scriptPubKey,txnouttype & typeRet,std::vector<CTxDestination> & addressRet,int & nRequiredRet)199 bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet)
200 {
201     addressRet.clear();
202     std::vector<valtype> vSolutions;
203     typeRet = Solver(scriptPubKey, vSolutions);
204     if (typeRet == TX_NONSTANDARD) {
205         return false;
206     } else if (typeRet == TX_NULL_DATA) {
207         // This is data, not addresses
208         return false;
209     }
210 
211     if (typeRet == TX_MULTISIG)
212     {
213         nRequiredRet = vSolutions.front()[0];
214         for (unsigned int i = 1; i < vSolutions.size()-1; i++)
215         {
216             CPubKey pubKey(vSolutions[i]);
217             if (!pubKey.IsValid())
218                 continue;
219 
220             CTxDestination address = pubKey.GetID();
221             addressRet.push_back(address);
222         }
223 
224         if (addressRet.empty())
225             return false;
226     }
227     else
228     {
229         nRequiredRet = 1;
230         CTxDestination address;
231         if (!ExtractDestination(scriptPubKey, address))
232            return false;
233         addressRet.push_back(address);
234     }
235 
236     return true;
237 }
238 
239 namespace
240 {
241 class CScriptVisitor : public boost::static_visitor<bool>
242 {
243 private:
244     CScript *script;
245 public:
CScriptVisitor(CScript * scriptin)246     explicit CScriptVisitor(CScript *scriptin) { script = scriptin; }
247 
operator ()(const CNoDestination & dest) const248     bool operator()(const CNoDestination &dest) const {
249         script->clear();
250         return false;
251     }
252 
operator ()(const CKeyID & keyID) const253     bool operator()(const CKeyID &keyID) const {
254         script->clear();
255         *script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
256         return true;
257     }
258 
operator ()(const CScriptID & scriptID) const259     bool operator()(const CScriptID &scriptID) const {
260         script->clear();
261         *script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
262         return true;
263     }
264 
operator ()(const WitnessV0KeyHash & id) const265     bool operator()(const WitnessV0KeyHash& id) const
266     {
267         script->clear();
268         *script << OP_0 << ToByteVector(id);
269         return true;
270     }
271 
operator ()(const WitnessV0ScriptHash & id) const272     bool operator()(const WitnessV0ScriptHash& id) const
273     {
274         script->clear();
275         *script << OP_0 << ToByteVector(id);
276         return true;
277     }
278 
operator ()(const WitnessUnknown & id) const279     bool operator()(const WitnessUnknown& id) const
280     {
281         script->clear();
282         *script << CScript::EncodeOP_N(id.version) << std::vector<unsigned char>(id.program, id.program + id.length);
283         return true;
284     }
285 };
286 } // namespace
287 
GetScriptForDestination(const CTxDestination & dest)288 CScript GetScriptForDestination(const CTxDestination& dest)
289 {
290     CScript script;
291 
292     boost::apply_visitor(CScriptVisitor(&script), dest);
293     return script;
294 }
295 
GetScriptForRawPubKey(const CPubKey & pubKey)296 CScript GetScriptForRawPubKey(const CPubKey& pubKey)
297 {
298     return CScript() << std::vector<unsigned char>(pubKey.begin(), pubKey.end()) << OP_CHECKSIG;
299 }
300 
GetScriptForMultisig(int nRequired,const std::vector<CPubKey> & keys)301 CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
302 {
303     CScript script;
304 
305     script << CScript::EncodeOP_N(nRequired);
306     for (const CPubKey& key : keys)
307         script << ToByteVector(key);
308     script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
309     return script;
310 }
311 
GetScriptForWitness(const CScript & redeemscript)312 CScript GetScriptForWitness(const CScript& redeemscript)
313 {
314     std::vector<std::vector<unsigned char> > vSolutions;
315     txnouttype typ = Solver(redeemscript, vSolutions);
316     if (typ == TX_PUBKEY) {
317         return GetScriptForDestination(WitnessV0KeyHash(Hash160(vSolutions[0].begin(), vSolutions[0].end())));
318     } else if (typ == TX_PUBKEYHASH) {
319         return GetScriptForDestination(WitnessV0KeyHash(vSolutions[0]));
320     }
321     return GetScriptForDestination(WitnessV0ScriptHash(redeemscript));
322 }
323 
IsValidDestination(const CTxDestination & dest)324 bool IsValidDestination(const CTxDestination& dest) {
325     return dest.which() != 0;
326 }
327