Line data Source code
1 : // Copyright (c) 2017-2019 The Bitcoin Core developers
2 : // Distributed under the MIT software license, see the accompanying
3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 :
5 : #include <key.h>
6 : #include <script/script.h>
7 : #include <script/signingprovider.h>
8 : #include <script/standard.h>
9 : #include <test/util/setup_common.h>
10 :
11 : #include <boost/test/unit_test.hpp>
12 :
13 :
14 89 : BOOST_FIXTURE_TEST_SUITE(script_standard_tests, BasicTestingSetup)
15 :
16 95 : BOOST_AUTO_TEST_CASE(dest_default_is_no_dest)
17 : {
18 1 : CTxDestination dest;
19 1 : BOOST_CHECK(!IsValidDestination(dest));
20 1 : }
21 :
22 95 : BOOST_AUTO_TEST_CASE(script_standard_Solver_success)
23 : {
24 3 : CKey keys[3];
25 3 : CPubKey pubkeys[3];
26 4 : for (int i = 0; i < 3; i++) {
27 3 : keys[i].MakeNewKey(true);
28 3 : pubkeys[i] = keys[i].GetPubKey();
29 : }
30 :
31 1 : CScript s;
32 1 : std::vector<std::vector<unsigned char> > solutions;
33 :
34 : // TxoutType::PUBKEY
35 1 : s.clear();
36 1 : s << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
37 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::PUBKEY);
38 1 : BOOST_CHECK_EQUAL(solutions.size(), 1U);
39 1 : BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0]));
40 :
41 : // TxoutType::PUBKEYHASH
42 1 : s.clear();
43 1 : s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
44 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::PUBKEYHASH);
45 1 : BOOST_CHECK_EQUAL(solutions.size(), 1U);
46 1 : BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
47 :
48 : // TxoutType::SCRIPTHASH
49 1 : CScript redeemScript(s); // initialize with leftover P2PKH script
50 1 : s.clear();
51 1 : s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
52 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::SCRIPTHASH);
53 1 : BOOST_CHECK_EQUAL(solutions.size(), 1U);
54 1 : BOOST_CHECK(solutions[0] == ToByteVector(CScriptID(redeemScript)));
55 :
56 : // TxoutType::MULTISIG
57 1 : s.clear();
58 3 : s << OP_1 <<
59 2 : ToByteVector(pubkeys[0]) <<
60 2 : ToByteVector(pubkeys[1]) <<
61 1 : OP_2 << OP_CHECKMULTISIG;
62 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::MULTISIG);
63 1 : BOOST_CHECK_EQUAL(solutions.size(), 4U);
64 1 : BOOST_CHECK(solutions[0] == std::vector<unsigned char>({1}));
65 1 : BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
66 1 : BOOST_CHECK(solutions[2] == ToByteVector(pubkeys[1]));
67 1 : BOOST_CHECK(solutions[3] == std::vector<unsigned char>({2}));
68 :
69 1 : s.clear();
70 3 : s << OP_2 <<
71 2 : ToByteVector(pubkeys[0]) <<
72 2 : ToByteVector(pubkeys[1]) <<
73 2 : ToByteVector(pubkeys[2]) <<
74 1 : OP_3 << OP_CHECKMULTISIG;
75 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::MULTISIG);
76 1 : BOOST_CHECK_EQUAL(solutions.size(), 5U);
77 1 : BOOST_CHECK(solutions[0] == std::vector<unsigned char>({2}));
78 1 : BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
79 1 : BOOST_CHECK(solutions[2] == ToByteVector(pubkeys[1]));
80 1 : BOOST_CHECK(solutions[3] == ToByteVector(pubkeys[2]));
81 1 : BOOST_CHECK(solutions[4] == std::vector<unsigned char>({3}));
82 :
83 : // TxoutType::NULL_DATA
84 1 : s.clear();
85 3 : s << OP_RETURN <<
86 2 : std::vector<unsigned char>({0}) <<
87 2 : std::vector<unsigned char>({75}) <<
88 1 : std::vector<unsigned char>({255});
89 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NULL_DATA);
90 1 : BOOST_CHECK_EQUAL(solutions.size(), 0U);
91 :
92 : // TxoutType::WITNESS_V0_KEYHASH
93 1 : s.clear();
94 1 : s << OP_0 << ToByteVector(pubkeys[0].GetID());
95 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::WITNESS_V0_KEYHASH);
96 1 : BOOST_CHECK_EQUAL(solutions.size(), 1U);
97 1 : BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
98 :
99 : // TxoutType::WITNESS_V0_SCRIPTHASH
100 1 : uint256 scriptHash;
101 2 : CSHA256().Write(&redeemScript[0], redeemScript.size())
102 1 : .Finalize(scriptHash.begin());
103 :
104 1 : s.clear();
105 1 : s << OP_0 << ToByteVector(scriptHash);
106 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::WITNESS_V0_SCRIPTHASH);
107 1 : BOOST_CHECK_EQUAL(solutions.size(), 1U);
108 1 : BOOST_CHECK(solutions[0] == ToByteVector(scriptHash));
109 :
110 : // TxoutType::NONSTANDARD
111 1 : s.clear();
112 1 : s << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
113 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
114 3 : }
115 :
116 95 : BOOST_AUTO_TEST_CASE(script_standard_Solver_failure)
117 : {
118 1 : CKey key;
119 1 : CPubKey pubkey;
120 1 : key.MakeNewKey(true);
121 1 : pubkey = key.GetPubKey();
122 :
123 1 : CScript s;
124 1 : std::vector<std::vector<unsigned char> > solutions;
125 :
126 : // TxoutType::PUBKEY with incorrectly sized pubkey
127 1 : s.clear();
128 1 : s << std::vector<unsigned char>(30, 0x01) << OP_CHECKSIG;
129 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
130 :
131 : // TxoutType::PUBKEYHASH with incorrectly sized key hash
132 1 : s.clear();
133 1 : s << OP_DUP << OP_HASH160 << ToByteVector(pubkey) << OP_EQUALVERIFY << OP_CHECKSIG;
134 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
135 :
136 : // TxoutType::SCRIPTHASH with incorrectly sized script hash
137 1 : s.clear();
138 1 : s << OP_HASH160 << std::vector<unsigned char>(21, 0x01) << OP_EQUAL;
139 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
140 :
141 : // TxoutType::MULTISIG 0/2
142 1 : s.clear();
143 1 : s << OP_0 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
144 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
145 :
146 : // TxoutType::MULTISIG 2/1
147 1 : s.clear();
148 1 : s << OP_2 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
149 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
150 :
151 : // TxoutType::MULTISIG n = 2 with 1 pubkey
152 1 : s.clear();
153 1 : s << OP_1 << ToByteVector(pubkey) << OP_2 << OP_CHECKMULTISIG;
154 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
155 :
156 : // TxoutType::MULTISIG n = 1 with 0 pubkeys
157 1 : s.clear();
158 1 : s << OP_1 << OP_1 << OP_CHECKMULTISIG;
159 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
160 :
161 : // TxoutType::NULL_DATA with other opcodes
162 1 : s.clear();
163 1 : s << OP_RETURN << std::vector<unsigned char>({75}) << OP_ADD;
164 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
165 :
166 : // TxoutType::WITNESS_UNKNOWN with incorrect program size
167 1 : s.clear();
168 1 : s << OP_0 << std::vector<unsigned char>(19, 0x01);
169 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
170 1 : }
171 :
172 95 : BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
173 : {
174 1 : CKey key;
175 1 : CPubKey pubkey;
176 1 : key.MakeNewKey(true);
177 1 : pubkey = key.GetPubKey();
178 :
179 1 : CScript s;
180 1 : CTxDestination address;
181 :
182 : // TxoutType::PUBKEY
183 1 : s.clear();
184 1 : s << ToByteVector(pubkey) << OP_CHECKSIG;
185 1 : BOOST_CHECK(ExtractDestination(s, address));
186 1 : BOOST_CHECK(boost::get<PKHash>(&address) &&
187 : *boost::get<PKHash>(&address) == PKHash(pubkey));
188 :
189 : // TxoutType::PUBKEYHASH
190 1 : s.clear();
191 1 : s << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
192 1 : BOOST_CHECK(ExtractDestination(s, address));
193 1 : BOOST_CHECK(boost::get<PKHash>(&address) &&
194 : *boost::get<PKHash>(&address) == PKHash(pubkey));
195 :
196 : // TxoutType::SCRIPTHASH
197 1 : CScript redeemScript(s); // initialize with leftover P2PKH script
198 1 : s.clear();
199 1 : s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
200 1 : BOOST_CHECK(ExtractDestination(s, address));
201 1 : BOOST_CHECK(boost::get<ScriptHash>(&address) &&
202 : *boost::get<ScriptHash>(&address) == ScriptHash(redeemScript));
203 :
204 : // TxoutType::MULTISIG
205 1 : s.clear();
206 1 : s << OP_1 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
207 1 : BOOST_CHECK(!ExtractDestination(s, address));
208 :
209 : // TxoutType::NULL_DATA
210 1 : s.clear();
211 1 : s << OP_RETURN << std::vector<unsigned char>({75});
212 1 : BOOST_CHECK(!ExtractDestination(s, address));
213 :
214 : // TxoutType::WITNESS_V0_KEYHASH
215 1 : s.clear();
216 1 : s << OP_0 << ToByteVector(pubkey.GetID());
217 1 : BOOST_CHECK(ExtractDestination(s, address));
218 1 : WitnessV0KeyHash keyhash;
219 1 : CHash160().Write(pubkey).Finalize(keyhash);
220 1 : BOOST_CHECK(boost::get<WitnessV0KeyHash>(&address) && *boost::get<WitnessV0KeyHash>(&address) == keyhash);
221 :
222 : // TxoutType::WITNESS_V0_SCRIPTHASH
223 1 : s.clear();
224 1 : WitnessV0ScriptHash scripthash;
225 1 : CSHA256().Write(redeemScript.data(), redeemScript.size()).Finalize(scripthash.begin());
226 1 : s << OP_0 << ToByteVector(scripthash);
227 1 : BOOST_CHECK(ExtractDestination(s, address));
228 1 : BOOST_CHECK(boost::get<WitnessV0ScriptHash>(&address) && *boost::get<WitnessV0ScriptHash>(&address) == scripthash);
229 :
230 : // TxoutType::WITNESS_UNKNOWN with unknown version
231 1 : s.clear();
232 1 : s << OP_1 << ToByteVector(pubkey);
233 1 : BOOST_CHECK(ExtractDestination(s, address));
234 1 : WitnessUnknown unk;
235 1 : unk.length = 33;
236 1 : unk.version = 1;
237 1 : std::copy(pubkey.begin(), pubkey.end(), unk.program);
238 1 : BOOST_CHECK(boost::get<WitnessUnknown>(&address) && *boost::get<WitnessUnknown>(&address) == unk);
239 1 : }
240 :
241 95 : BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations)
242 : {
243 3 : CKey keys[3];
244 3 : CPubKey pubkeys[3];
245 4 : for (int i = 0; i < 3; i++) {
246 3 : keys[i].MakeNewKey(true);
247 3 : pubkeys[i] = keys[i].GetPubKey();
248 : }
249 :
250 1 : CScript s;
251 1 : TxoutType whichType;
252 1 : std::vector<CTxDestination> addresses;
253 1 : int nRequired;
254 :
255 : // TxoutType::PUBKEY
256 1 : s.clear();
257 1 : s << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
258 1 : BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
259 1 : BOOST_CHECK_EQUAL(whichType, TxoutType::PUBKEY);
260 1 : BOOST_CHECK_EQUAL(addresses.size(), 1U);
261 1 : BOOST_CHECK_EQUAL(nRequired, 1);
262 1 : BOOST_CHECK(boost::get<PKHash>(&addresses[0]) &&
263 : *boost::get<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
264 :
265 : // TxoutType::PUBKEYHASH
266 1 : s.clear();
267 1 : s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
268 1 : BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
269 1 : BOOST_CHECK_EQUAL(whichType, TxoutType::PUBKEYHASH);
270 1 : BOOST_CHECK_EQUAL(addresses.size(), 1U);
271 1 : BOOST_CHECK_EQUAL(nRequired, 1);
272 1 : BOOST_CHECK(boost::get<PKHash>(&addresses[0]) &&
273 : *boost::get<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
274 :
275 : // TxoutType::SCRIPTHASH
276 1 : CScript redeemScript(s); // initialize with leftover P2PKH script
277 1 : s.clear();
278 1 : s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
279 1 : BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
280 1 : BOOST_CHECK_EQUAL(whichType, TxoutType::SCRIPTHASH);
281 1 : BOOST_CHECK_EQUAL(addresses.size(), 1U);
282 1 : BOOST_CHECK_EQUAL(nRequired, 1);
283 1 : BOOST_CHECK(boost::get<ScriptHash>(&addresses[0]) &&
284 : *boost::get<ScriptHash>(&addresses[0]) == ScriptHash(redeemScript));
285 :
286 : // TxoutType::MULTISIG
287 1 : s.clear();
288 3 : s << OP_2 <<
289 2 : ToByteVector(pubkeys[0]) <<
290 2 : ToByteVector(pubkeys[1]) <<
291 1 : OP_2 << OP_CHECKMULTISIG;
292 1 : BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
293 1 : BOOST_CHECK_EQUAL(whichType, TxoutType::MULTISIG);
294 1 : BOOST_CHECK_EQUAL(addresses.size(), 2U);
295 1 : BOOST_CHECK_EQUAL(nRequired, 2);
296 1 : BOOST_CHECK(boost::get<PKHash>(&addresses[0]) &&
297 : *boost::get<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
298 1 : BOOST_CHECK(boost::get<PKHash>(&addresses[1]) &&
299 : *boost::get<PKHash>(&addresses[1]) == PKHash(pubkeys[1]));
300 :
301 : // TxoutType::NULL_DATA
302 1 : s.clear();
303 1 : s << OP_RETURN << std::vector<unsigned char>({75});
304 1 : BOOST_CHECK(!ExtractDestinations(s, whichType, addresses, nRequired));
305 3 : }
306 :
307 95 : BOOST_AUTO_TEST_CASE(script_standard_GetScriptFor_)
308 : {
309 3 : CKey keys[3];
310 3 : CPubKey pubkeys[3];
311 4 : for (int i = 0; i < 3; i++) {
312 3 : keys[i].MakeNewKey(true);
313 3 : pubkeys[i] = keys[i].GetPubKey();
314 : }
315 :
316 1 : CScript expected, result;
317 :
318 : // PKHash
319 1 : expected.clear();
320 1 : expected << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
321 1 : result = GetScriptForDestination(PKHash(pubkeys[0]));
322 1 : BOOST_CHECK(result == expected);
323 :
324 : // CScriptID
325 1 : CScript redeemScript(result);
326 1 : expected.clear();
327 1 : expected << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
328 1 : result = GetScriptForDestination(ScriptHash(redeemScript));
329 1 : BOOST_CHECK(result == expected);
330 :
331 : // CNoDestination
332 1 : expected.clear();
333 1 : result = GetScriptForDestination(CNoDestination());
334 1 : BOOST_CHECK(result == expected);
335 :
336 : // GetScriptForRawPubKey
337 1 : expected.clear();
338 1 : expected << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
339 1 : result = GetScriptForRawPubKey(pubkeys[0]);
340 1 : BOOST_CHECK(result == expected);
341 :
342 : // GetScriptForMultisig
343 1 : expected.clear();
344 3 : expected << OP_2 <<
345 2 : ToByteVector(pubkeys[0]) <<
346 2 : ToByteVector(pubkeys[1]) <<
347 2 : ToByteVector(pubkeys[2]) <<
348 1 : OP_3 << OP_CHECKMULTISIG;
349 1 : result = GetScriptForMultisig(2, std::vector<CPubKey>(pubkeys, pubkeys + 3));
350 1 : BOOST_CHECK(result == expected);
351 :
352 : // WitnessV0KeyHash
353 1 : expected.clear();
354 1 : expected << OP_0 << ToByteVector(pubkeys[0].GetID());
355 1 : result = GetScriptForDestination(WitnessV0KeyHash(Hash160(ToByteVector(pubkeys[0]))));
356 1 : BOOST_CHECK(result == expected);
357 1 : result = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0].GetID()));
358 1 : BOOST_CHECK(result == expected);
359 :
360 : // WitnessV0ScriptHash (multisig)
361 1 : CScript witnessScript;
362 1 : witnessScript << OP_1 << ToByteVector(pubkeys[0]) << OP_1 << OP_CHECKMULTISIG;
363 :
364 1 : uint256 scriptHash;
365 2 : CSHA256().Write(&witnessScript[0], witnessScript.size())
366 1 : .Finalize(scriptHash.begin());
367 :
368 1 : expected.clear();
369 1 : expected << OP_0 << ToByteVector(scriptHash);
370 1 : result = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
371 1 : BOOST_CHECK(result == expected);
372 3 : }
373 :
374 89 : BOOST_AUTO_TEST_SUITE_END()
|