Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2014 The Bitcoin developers
3 : // Copyright (c) 2017-2021 The PIVX Core developers
4 : // Distributed under the MIT software license, see the accompanying
5 : // file COPYING or https://www.opensource.org/licenses/mit-license.php.
6 :
7 : #include "script/standard.h"
8 :
9 : #include "pubkey.h"
10 : #include "script/script.h"
11 :
12 : typedef std::vector<unsigned char> valtype;
13 :
14 : unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
15 :
16 1818 : CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
17 :
18 1599 : const char* GetTxnOutputType(txnouttype t)
19 : {
20 1599 : switch (t)
21 : {
22 : case TX_NONSTANDARD: return "nonstandard";
23 1 : case TX_PUBKEY: return "pubkey";
24 1490 : case TX_PUBKEYHASH: return "pubkeyhash";
25 0 : case TX_EXCHANGEADDR: return "exchangeaddress";
26 15 : case TX_SCRIPTHASH: return "scripthash";
27 4 : case TX_MULTISIG: return "multisig";
28 52 : case TX_COLDSTAKE: return "coldstake";
29 4 : case TX_NULL_DATA: return "nulldata";
30 : }
31 0 : return nullptr;
32 : }
33 :
34 14634285 : static bool MatchPayToPubkey(const CScript& script, valtype& pubkey)
35 : {
36 14662217 : if (script.size() == CPubKey::PUBLIC_KEY_SIZE + 2 && script[0] == CPubKey::PUBLIC_KEY_SIZE && script.back() == OP_CHECKSIG) {
37 2478 : pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::PUBLIC_KEY_SIZE + 1);
38 1239 : return CPubKey::ValidSize(pubkey);
39 : }
40 14674526 : if (script.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 2 && script[0] == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE && script.back() == OP_CHECKSIG) {
41 41446 : pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1);
42 20723 : return CPubKey::ValidSize(pubkey);
43 : }
44 : return false;
45 : }
46 :
47 14612345 : static bool MatchPayToPubkeyHash(const CScript& script, valtype& pubkeyhash)
48 : {
49 87483141 : if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160 && script[2] == 20 && script[23] == OP_EQUALVERIFY && script[24] == OP_CHECKSIG) {
50 29146932 : pubkeyhash = valtype(script.begin () + 3, script.begin() + 23);
51 14573466 : return true;
52 : }
53 : return false;
54 : }
55 :
56 38429 : static bool MatchPayToColdStaking(const CScript& script, valtype& stakerPubKeyHash, valtype& ownerPubKeyHash)
57 : {
58 38429 : if (script.IsPayToColdStaking()) {
59 8139 : stakerPubKeyHash = valtype(script.begin () + 6, script.begin() + 26);
60 8139 : ownerPubKeyHash = valtype(script.begin () + 28, script.begin() + 48);
61 2713 : return true;
62 : }
63 : return false;
64 : }
65 :
66 : /** Test for "small positive integer" script opcodes - OP_1 through OP_16. */
67 1402 : static constexpr bool IsSmallInteger(opcodetype opcode)
68 : {
69 1402 : return opcode >= OP_1 && opcode <= OP_16;
70 : }
71 :
72 35716 : static bool MatchMultisig(const CScript& script, unsigned int& required, std::vector<valtype>& pubkeys)
73 : {
74 35716 : opcodetype opcode;
75 71432 : valtype data;
76 35716 : CScript::const_iterator it = script.begin();
77 72171 : if (script.size() < 1 || script.back() != OP_CHECKMULTISIG) return false;
78 :
79 702 : if (!script.GetOp(it, opcode, data) || !IsSmallInteger(opcode)) return false;
80 700 : required = CScript::DecodeOP_N(opcode);
81 2876 : while (script.GetOp(it, opcode, data) && CPubKey::ValidSize(data)) {
82 2176 : pubkeys.emplace_back(std::move(data));
83 : }
84 700 : if (!IsSmallInteger(opcode)) return false;
85 698 : unsigned int keys = CScript::DecodeOP_N(opcode);
86 698 : if (pubkeys.size() != keys || keys < required) return false;
87 1386 : return (it + 1 == script.end());
88 : }
89 :
90 15076754 : bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet)
91 : {
92 15116367 : if (scriptPubKey.empty())
93 : return false;
94 :
95 14780358 : vSolutionsRet.clear();
96 :
97 : // Shortcut for pay-to-script-hash, which are more constrained than the other types:
98 : // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
99 14780358 : if (scriptPubKey.IsPayToScriptHash())
100 : {
101 131785 : typeRet = TX_SCRIPTHASH;
102 395355 : std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
103 131785 : vSolutionsRet.push_back(hashBytes);
104 131785 : return true;
105 : }
106 :
107 : // Provably prunable, data-carrying output
108 : //
109 : // So long as script passes the IsUnspendable() test and all but the first
110 : // byte passes the IsPushOnly() test we don't care what exactly is in the
111 : // script.
112 29336817 : if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
113 14274 : typeRet = TX_NULL_DATA;
114 14274 : return true;
115 : }
116 :
117 29711039 : std::vector<unsigned char> data;
118 14634285 : if (MatchPayToPubkey(scriptPubKey, data)) {
119 21962 : typeRet = TX_PUBKEY;
120 21962 : vSolutionsRet.push_back(std::move(data));
121 : return true;
122 : }
123 :
124 14612345 : if (MatchPayToPubkeyHash(scriptPubKey, data)) {
125 14573466 : typeRet = TX_PUBKEYHASH;
126 14573466 : vSolutionsRet.push_back(std::move(data));
127 : return true;
128 : }
129 :
130 38895 : if (scriptPubKey.IsPayToExchangeAddress())
131 : {
132 466 : typeRet = TX_EXCHANGEADDR;
133 1398 : std::vector<unsigned char> hashBytes(scriptPubKey.begin()+4, scriptPubKey.begin()+24);
134 466 : vSolutionsRet.push_back(hashBytes);
135 466 : return true;
136 : }
137 :
138 :
139 14672760 : std::vector<unsigned char> data1;
140 38429 : if (MatchPayToColdStaking(scriptPubKey, data, data1)) {
141 2713 : typeRet = TX_COLDSTAKE;
142 2713 : vSolutionsRet.push_back(std::move(data));
143 38429 : vSolutionsRet.push_back(std::move(data1));
144 : return true;
145 : }
146 :
147 35716 : unsigned int required;
148 71432 : std::vector<std::vector<unsigned char>> keys;
149 35716 : if (MatchMultisig(scriptPubKey, required, keys)) {
150 693 : typeRet = TX_MULTISIG;
151 1386 : vSolutionsRet.push_back({static_cast<unsigned char>(required)}); // safe as required is in range 1..16
152 693 : vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end());
153 1386 : vSolutionsRet.push_back({static_cast<unsigned char>(keys.size())}); // safe as size is in range 1..16
154 693 : return true;
155 : }
156 :
157 35023 : vSolutionsRet.clear();
158 35023 : typeRet = TX_NONSTANDARD;
159 35023 : return false;
160 : }
161 :
162 3122441 : bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet, bool fColdStake)
163 : {
164 6244882 : std::vector<valtype> vSolutions;
165 3122441 : txnouttype whichType;
166 3122441 : if (!Solver(scriptPubKey, whichType, vSolutions))
167 : return false;
168 :
169 3121059 : if (whichType == TX_PUBKEY) {
170 1328 : CPubKey pubKey(vSolutions[0]);
171 2656 : if (!pubKey.IsValid())
172 : return false;
173 :
174 1328 : addressRet = pubKey.GetID();
175 1328 : return true;
176 :
177 3119732 : } else if (whichType == TX_PUBKEYHASH) {
178 3119403 : addressRet = CKeyID(uint160(vSolutions[0]));
179 3119403 : return true;
180 :
181 333 : } else if (whichType == TX_SCRIPTHASH) {
182 81 : addressRet = CScriptID(uint160(vSolutions[0]));
183 81 : return true;
184 252 : } else if (whichType == TX_EXCHANGEADDR) {
185 12 : addressRet = CExchangeKeyID(uint160(vSolutions[0]));
186 12 : return true;
187 240 : } else if (whichType == TX_COLDSTAKE) {
188 203 : addressRet = CKeyID(uint160(vSolutions[!fColdStake]));
189 203 : return true;
190 : }
191 : // Multisig txns have more than one address...
192 : return false;
193 : }
194 :
195 1136701 : bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet)
196 : {
197 1136701 : addressRet.clear();
198 1136701 : typeRet = TX_NONSTANDARD;
199 2273392 : std::vector<valtype> vSolutions;
200 1136701 : if (!Solver(scriptPubKey, typeRet, vSolutions))
201 : return false;
202 1134299 : if (typeRet == TX_NULL_DATA){
203 : // This is data, not addresses
204 : return false;
205 : }
206 :
207 1134248 : if (typeRet == TX_MULTISIG)
208 : {
209 19 : nRequiredRet = vSolutions.front()[0];
210 69 : for (unsigned int i = 1; i < vSolutions.size()-1; i++)
211 : {
212 50 : CPubKey pubKey(vSolutions[i]);
213 50 : if (!pubKey.IsValid())
214 0 : continue;
215 :
216 100 : CTxDestination address = pubKey.GetID();
217 50 : addressRet.push_back(address);
218 : }
219 :
220 19 : if (addressRet.empty())
221 0 : return false;
222 :
223 1134226 : } else if (typeRet == TX_COLDSTAKE)
224 : {
225 222 : if (vSolutions.size() < 2)
226 : return false;
227 222 : nRequiredRet = 2;
228 222 : addressRet.push_back(CKeyID(uint160(vSolutions[0])));
229 222 : addressRet.push_back(CKeyID(uint160(vSolutions[1])));
230 222 : return true;
231 :
232 : } else
233 : {
234 1134005 : nRequiredRet = 1;
235 2268010 : CTxDestination address;
236 1134005 : if (!ExtractDestination(scriptPubKey, address))
237 0 : return false;
238 1134005 : addressRet.push_back(address);
239 : }
240 :
241 : return true;
242 : }
243 :
244 : namespace
245 : {
246 : class CScriptVisitor : public boost::static_visitor<bool>
247 : {
248 : private:
249 : CScript *script;
250 : public:
251 46990 : explicit CScriptVisitor(CScript *scriptin) { script = scriptin; }
252 :
253 23 : bool operator()(const CNoDestination &dest) const {
254 23 : script->clear();
255 23 : return false;
256 : }
257 :
258 46851 : bool operator()(const CKeyID &keyID) const {
259 46851 : script->clear();
260 46851 : *script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
261 46851 : return true;
262 : }
263 :
264 6 : bool operator()(const CExchangeKeyID &keyID) const {
265 6 : script->clear();
266 6 : *script << OP_EXCHANGEADDR << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
267 6 : return true;
268 : }
269 :
270 110 : bool operator()(const CScriptID &scriptID) const {
271 110 : script->clear();
272 110 : *script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
273 110 : return true;
274 : }
275 : };
276 : }
277 :
278 46990 : CScript GetScriptForDestination(const CTxDestination& dest)
279 : {
280 46990 : CScript script;
281 :
282 46990 : boost::apply_visitor(CScriptVisitor(&script), dest);
283 46990 : return script;
284 : }
285 :
286 26911 : CScript GetScriptForRawPubKey(const CPubKey& pubKey)
287 : {
288 80733 : return CScript() << std::vector<unsigned char>(pubKey.begin(), pubKey.end()) << OP_CHECKSIG;
289 : }
290 :
291 4 : CScript GetScriptForStakeDelegation(const CKeyID& stakingKey, const CKeyID& spendingKey)
292 : {
293 4 : CScript script;
294 4 : script << OP_DUP << OP_HASH160 << OP_ROT <<
295 4 : OP_IF << OP_CHECKCOLDSTAKEVERIFY << ToByteVector(stakingKey) <<
296 8 : OP_ELSE << ToByteVector(spendingKey) << OP_ENDIF <<
297 4 : OP_EQUALVERIFY << OP_CHECKSIG;
298 4 : return script;
299 : }
300 :
301 32 : CScript GetScriptForStakeDelegationLOF(const CKeyID& stakingKey, const CKeyID& spendingKey)
302 : {
303 32 : CScript script;
304 32 : script << OP_DUP << OP_HASH160 << OP_ROT <<
305 32 : OP_IF << OP_CHECKCOLDSTAKEVERIFY_LOF << ToByteVector(stakingKey) <<
306 64 : OP_ELSE << ToByteVector(spendingKey) << OP_ENDIF <<
307 32 : OP_EQUALVERIFY << OP_CHECKSIG;
308 32 : return script;
309 : }
310 :
311 25 : CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
312 : {
313 25 : CScript script;
314 :
315 50 : script << CScript::EncodeOP_N(nRequired);
316 127 : for (const CPubKey& key : keys)
317 204 : script << ToByteVector(key);
318 50 : script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
319 25 : return script;
320 : }
321 :
322 0 : CScript GetScriptForOpReturn(const uint256& message)
323 : {
324 0 : CScript script;
325 0 : script << OP_RETURN << ToByteVector(message);
326 0 : return script;
327 : }
328 :
329 16799 : bool IsValidDestination(const CTxDestination& dest) {
330 16799 : return dest.which() != 0;
331 : }
332 :
|