Branch data Line data Source code
1 : : // Copyright (c) 2017-2022 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 <test/data/bip341_wallet_vectors.json.h>
6 : :
7 : : #include <addresstype.h>
8 : : #include <key.h>
9 : : #include <key_io.h>
10 : : #include <script/script.h>
11 : : #include <script/signingprovider.h>
12 : : #include <script/solver.h>
13 : : #include <test/util/setup_common.h>
14 : : #include <util/strencodings.h>
15 : :
16 : : #include <boost/test/unit_test.hpp>
17 : :
18 : : #include <univalue.h>
19 : :
20 : : using namespace util::hex_literals;
21 : :
22 : : BOOST_FIXTURE_TEST_SUITE(script_standard_tests, BasicTestingSetup)
23 : :
24 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(dest_default_is_no_dest)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
25 : : {
26 : 1 : CTxDestination dest;
27 [ + - + - : 2 : BOOST_CHECK(!IsValidDestination(dest));
+ - ]
28 : 1 : }
29 : :
30 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(script_standard_Solver_success)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
31 : : {
32 : 3 : CKey keys[3];
33 [ + + ]: 4 : CPubKey pubkeys[3];
34 [ + + ]: 4 : for (int i = 0; i < 3; i++) {
35 [ + - ]: 3 : keys[i].MakeNewKey(true);
36 [ + - ]: 3 : pubkeys[i] = keys[i].GetPubKey();
37 : : }
38 : :
39 : 1 : CScript s;
40 : 1 : std::vector<std::vector<unsigned char> > solutions;
41 : :
42 : : // TxoutType::PUBKEY
43 : 1 : s.clear();
44 [ + - + - ]: 1 : s << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
45 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::PUBKEY);
+ - ]
46 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(solutions.size(), 1U);
47 [ + - + - : 2 : BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0]));
+ - ]
48 : :
49 : : // TxoutType::PUBKEYHASH
50 : 1 : s.clear();
51 [ + - + - : 1 : s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+ - + - +
- + - ]
52 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::PUBKEYHASH);
+ - ]
53 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(solutions.size(), 1U);
54 [ + - + - : 2 : BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
+ - + - ]
55 : :
56 : : // TxoutType::SCRIPTHASH
57 : 1 : CScript redeemScript(s); // initialize with leftover P2PKH script
58 : 1 : s.clear();
59 [ + - + - : 1 : s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+ - + - ]
60 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::SCRIPTHASH);
+ - ]
61 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(solutions.size(), 1U);
62 [ + - + - : 2 : BOOST_CHECK(solutions[0] == ToByteVector(CScriptID(redeemScript)));
+ - + - ]
63 : :
64 : : // TxoutType::MULTISIG
65 : 1 : s.clear();
66 [ + - ]: 1 : s << OP_1 <<
67 [ + - ]: 1 : ToByteVector(pubkeys[0]) <<
68 [ + - ]: 2 : ToByteVector(pubkeys[1]) <<
69 [ + - + - ]: 1 : OP_2 << OP_CHECKMULTISIG;
70 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::MULTISIG);
+ - ]
71 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(solutions.size(), 4U);
72 [ + - + - : 2 : BOOST_CHECK(solutions[0] == std::vector<unsigned char>({1}));
+ - + - ]
73 [ + - + - : 2 : BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
+ - + - ]
74 [ + - + - : 2 : BOOST_CHECK(solutions[2] == ToByteVector(pubkeys[1]));
+ - + - ]
75 [ + - + - : 2 : BOOST_CHECK(solutions[3] == std::vector<unsigned char>({2}));
+ - ]
76 : :
77 : 1 : s.clear();
78 [ + - ]: 1 : s << OP_2 <<
79 [ + - ]: 1 : ToByteVector(pubkeys[0]) <<
80 [ + - ]: 2 : ToByteVector(pubkeys[1]) <<
81 [ + - ]: 2 : ToByteVector(pubkeys[2]) <<
82 [ + - + - ]: 1 : OP_3 << OP_CHECKMULTISIG;
83 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::MULTISIG);
+ - + - ]
84 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(solutions.size(), 5U);
85 [ + - + - : 2 : BOOST_CHECK(solutions[0] == std::vector<unsigned char>({2}));
+ - + - ]
86 [ + - + - : 2 : BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
+ - + - ]
87 [ + - + - : 2 : BOOST_CHECK(solutions[2] == ToByteVector(pubkeys[1]));
+ - + - ]
88 [ + - + - : 2 : BOOST_CHECK(solutions[3] == ToByteVector(pubkeys[2]));
+ - + - ]
89 [ + - + - : 2 : BOOST_CHECK(solutions[4] == std::vector<unsigned char>({3}));
+ - ]
90 : :
91 : : // TxoutType::NULL_DATA
92 : 1 : s.clear();
93 [ + - + - ]: 1 : s << OP_RETURN <<
94 [ + - + - : 2 : std::vector<unsigned char>({0}) <<
+ - ]
95 [ + - + - ]: 2 : std::vector<unsigned char>({75}) <<
96 [ + - ]: 1 : std::vector<unsigned char>({255});
97 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NULL_DATA);
+ - ]
98 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(solutions.size(), 0U);
99 : :
100 : : // TxoutType::WITNESS_V0_KEYHASH
101 : 1 : s.clear();
102 [ + - + - : 1 : s << OP_0 << ToByteVector(pubkeys[0].GetID());
+ - ]
103 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::WITNESS_V0_KEYHASH);
+ - ]
104 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(solutions.size(), 1U);
105 [ + - + - : 2 : BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
+ - + - +
- ]
106 : :
107 : : // TxoutType::WITNESS_V0_SCRIPTHASH
108 : 1 : uint256 scriptHash;
109 [ + - - + : 2 : CSHA256().Write(redeemScript.data(), redeemScript.size())
+ - + - ]
110 [ + - ]: 1 : .Finalize(scriptHash.begin());
111 : :
112 : 1 : s.clear();
113 [ + - + - ]: 1 : s << OP_0 << ToByteVector(scriptHash);
114 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::WITNESS_V0_SCRIPTHASH);
+ - ]
115 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(solutions.size(), 1U);
116 [ + - + - : 2 : BOOST_CHECK(solutions[0] == ToByteVector(scriptHash));
+ - ]
117 : :
118 : : // TxoutType::WITNESS_V1_TAPROOT
119 : 1 : s.clear();
120 [ + - + - ]: 1 : s << OP_1 << ToByteVector(uint256::ZERO);
121 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::WITNESS_V1_TAPROOT);
+ - ]
122 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(solutions.size(), 1U);
123 [ + - + - : 2 : BOOST_CHECK(solutions[0] == ToByteVector(uint256::ZERO));
+ - ]
124 : :
125 : : // TxoutType::WITNESS_UNKNOWN
126 : 1 : s.clear();
127 [ + - + - ]: 1 : s << OP_16 << ToByteVector(uint256::ONE);
128 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::WITNESS_UNKNOWN);
+ - ]
129 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(solutions.size(), 2U);
130 [ + - + - : 2 : BOOST_CHECK(solutions[0] == std::vector<unsigned char>{16});
+ - + - ]
131 [ + - + - : 2 : BOOST_CHECK(solutions[1] == ToByteVector(uint256::ONE));
+ - ]
132 : :
133 : : // TxoutType::ANCHOR
134 : 1 : s.clear();
135 [ + - ]: 1 : s << OP_1 << ANCHOR_BYTES;
136 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::ANCHOR);
+ - ]
137 [ + - + - : 2 : BOOST_CHECK(solutions.empty());
+ - ]
138 : :
139 : : // Sanity-check IsPayToAnchor
140 : 1 : int version{-1};
141 : 1 : std::vector<unsigned char> witness_program;
142 [ + - + - : 2 : BOOST_CHECK(s.IsPayToAnchor());
+ - + - ]
143 [ + - + - : 2 : BOOST_CHECK(s.IsWitnessProgram(version, witness_program));
+ - + - ]
144 [ + - + - : 2 : BOOST_CHECK(CScript::IsPayToAnchor(version, witness_program));
+ - ]
145 : :
146 : : // TxoutType::NONSTANDARD
147 : 1 : s.clear();
148 [ + - + - : 1 : s << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
+ - + - ]
149 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
+ - ]
150 [ + + - - ]: 5 : }
151 : :
152 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(script_standard_Solver_failure)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
153 : : {
154 : 1 : CKey key = GenerateRandomKey();
155 [ + - ]: 1 : CPubKey pubkey = key.GetPubKey();
156 : :
157 : 1 : CScript s;
158 : 1 : std::vector<std::vector<unsigned char> > solutions;
159 : :
160 : : // TxoutType::PUBKEY with incorrectly sized pubkey
161 : 1 : s.clear();
162 [ + - + - : 2 : s << std::vector<unsigned char>(30, 0x01) << OP_CHECKSIG;
+ - ]
163 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
+ - ]
164 : :
165 : : // TxoutType::PUBKEYHASH with incorrectly sized key hash
166 : 1 : s.clear();
167 [ + - + - : 1 : s << OP_DUP << OP_HASH160 << ToByteVector(pubkey) << OP_EQUALVERIFY << OP_CHECKSIG;
+ - + - +
- ]
168 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
+ - ]
169 : :
170 : : // TxoutType::SCRIPTHASH with incorrectly sized script hash
171 : 1 : s.clear();
172 [ + - + - : 2 : s << OP_HASH160 << std::vector<unsigned char>(21, 0x01) << OP_EQUAL;
+ - + - ]
173 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
+ - ]
174 : :
175 : : // TxoutType::MULTISIG 0/2
176 : 1 : s.clear();
177 [ + - + - : 1 : s << OP_0 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
+ - + - ]
178 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
+ - ]
179 : :
180 : : // TxoutType::MULTISIG 2/1
181 : 1 : s.clear();
182 [ + - + - : 1 : s << OP_2 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
+ - + - ]
183 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
+ - ]
184 : :
185 : : // TxoutType::MULTISIG n = 2 with 1 pubkey
186 : 1 : s.clear();
187 [ + - + - : 1 : s << OP_1 << ToByteVector(pubkey) << OP_2 << OP_CHECKMULTISIG;
+ - + - ]
188 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
+ - ]
189 : :
190 : : // TxoutType::MULTISIG n = 1 with 0 pubkeys
191 : 1 : s.clear();
192 [ + - + - : 1 : s << OP_1 << OP_1 << OP_CHECKMULTISIG;
+ - ]
193 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
+ - ]
194 : :
195 : : // TxoutType::NULL_DATA with other opcodes
196 : 1 : s.clear();
197 [ + - + - : 2 : s << OP_RETURN << std::vector<unsigned char>({75}) << OP_ADD;
+ - + - ]
198 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
+ - ]
199 : :
200 : : // TxoutType::WITNESS_V0_{KEY,SCRIPT}HASH with incorrect program size (-> consensus-invalid, i.e. non-standard)
201 : 1 : s.clear();
202 [ + - + - : 1 : s << OP_0 << std::vector<unsigned char>(19, 0x01);
+ - ]
203 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
+ - ]
204 : :
205 : : // TxoutType::WITNESS_V1_TAPROOT with incorrect program size (-> undefined, but still policy-valid)
206 : 1 : s.clear();
207 [ + - + - : 1 : s << OP_1 << std::vector<unsigned char>(31, 0x01);
+ - ]
208 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::WITNESS_UNKNOWN);
+ - ]
209 : 1 : s.clear();
210 [ + - + - : 1 : s << OP_1 << std::vector<unsigned char>(33, 0x01);
+ - ]
211 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::WITNESS_UNKNOWN);
+ - ]
212 : :
213 : : // TxoutType::ANCHOR but wrong witness version
214 : 1 : s.clear();
215 [ + - ]: 1 : s << OP_2 << ANCHOR_BYTES;
216 [ + - + - : 2 : BOOST_CHECK(!s.IsPayToAnchor());
+ - + - ]
217 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::WITNESS_UNKNOWN);
+ - ]
218 : :
219 : : // TxoutType::ANCHOR but wrong 2-byte data push
220 : 1 : s.clear();
221 [ + - + - : 1 : s << OP_1 << std::vector<unsigned char>{0xff, 0xff};
+ - ]
222 [ + - + - : 2 : BOOST_CHECK(!s.IsPayToAnchor());
+ - + - ]
223 [ + - + - : 1 : BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::WITNESS_UNKNOWN);
+ - ]
224 : 1 : }
225 : :
226 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
227 : : {
228 : 1 : CKey key = GenerateRandomKey();
229 [ + - ]: 1 : CPubKey pubkey = key.GetPubKey();
230 : :
231 : 1 : CScript s;
232 : 1 : CTxDestination address;
233 : :
234 : : // TxoutType::PUBKEY
235 : 1 : s.clear();
236 [ + - + - ]: 1 : s << ToByteVector(pubkey) << OP_CHECKSIG;
237 [ + - + - : 2 : BOOST_CHECK(!ExtractDestination(s, address));
+ - + - ]
238 [ + - - + : 2 : BOOST_CHECK(std::get<PubKeyDestination>(address) == PubKeyDestination(pubkey));
+ - ]
239 : :
240 : : // TxoutType::PUBKEYHASH
241 : 1 : s.clear();
242 [ + - + - : 1 : s << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+ - + - +
- + - ]
243 [ + - + - : 2 : BOOST_CHECK(ExtractDestination(s, address));
+ - + - ]
244 [ + - + - : 3 : BOOST_CHECK(std::get<PKHash>(address) == PKHash(pubkey));
+ - ]
245 : :
246 : : // TxoutType::SCRIPTHASH
247 : 1 : CScript redeemScript(s); // initialize with leftover P2PKH script
248 : 1 : s.clear();
249 [ + - + - : 1 : s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+ - + - ]
250 [ + - + - : 2 : BOOST_CHECK(ExtractDestination(s, address));
+ - + - ]
251 [ + - + - : 3 : BOOST_CHECK(std::get<ScriptHash>(address) == ScriptHash(redeemScript));
+ - ]
252 : :
253 : : // TxoutType::MULTISIG
254 : 1 : s.clear();
255 [ + - + - : 1 : s << OP_1 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
+ - + - ]
256 [ + - + - : 2 : BOOST_CHECK(!ExtractDestination(s, address));
+ - ]
257 : :
258 : : // TxoutType::NULL_DATA
259 : 1 : s.clear();
260 [ + - + - : 1 : s << OP_RETURN << std::vector<unsigned char>({75});
+ - ]
261 [ + - + - : 2 : BOOST_CHECK(!ExtractDestination(s, address));
+ - ]
262 : :
263 : : // TxoutType::WITNESS_V0_KEYHASH
264 : 1 : s.clear();
265 [ + - + - : 1 : s << OP_0 << ToByteVector(pubkey.GetID());
+ - ]
266 [ + - + - : 2 : BOOST_CHECK(ExtractDestination(s, address));
+ - + - ]
267 [ + - ]: 1 : WitnessV0KeyHash keyhash;
268 [ + - + - : 1 : CHash160().Write(pubkey).Finalize(keyhash);
+ - ]
269 [ + - - + : 2 : BOOST_CHECK(std::get<WitnessV0KeyHash>(address) == keyhash);
+ - ]
270 : :
271 : : // TxoutType::WITNESS_V0_SCRIPTHASH
272 : 1 : s.clear();
273 [ + - ]: 1 : WitnessV0ScriptHash scripthash;
274 [ + - - + : 2 : CSHA256().Write(redeemScript.data(), redeemScript.size()).Finalize(scripthash.begin());
+ - + - ]
275 [ + - + - ]: 1 : s << OP_0 << ToByteVector(scripthash);
276 [ + - + - : 2 : BOOST_CHECK(ExtractDestination(s, address));
+ - + - ]
277 [ + - - + : 2 : BOOST_CHECK(std::get<WitnessV0ScriptHash>(address) == scripthash);
+ - ]
278 : :
279 : : // TxoutType::WITNESS_V1_TAPROOT
280 : 1 : s.clear();
281 : 1 : auto xpk = XOnlyPubKey(pubkey);
282 [ + - + - ]: 1 : s << OP_1 << ToByteVector(xpk);
283 [ + - + - : 2 : BOOST_CHECK(ExtractDestination(s, address));
+ - + - ]
284 [ + - - + : 2 : BOOST_CHECK(std::get<WitnessV1Taproot>(address) == WitnessV1Taproot(xpk));
+ - ]
285 : :
286 : : // TxoutType::ANCHOR
287 : 1 : s.clear();
288 [ + - ]: 1 : s << OP_1 << ANCHOR_BYTES;
289 [ + - + - : 2 : BOOST_CHECK(ExtractDestination(s, address));
+ - + - ]
290 [ + - + - : 4 : BOOST_CHECK(std::get<PayToAnchor>(address) == PayToAnchor());
+ - + - ]
291 : :
292 : : // TxoutType::WITNESS_UNKNOWN with unknown version
293 : : // -> segwit version 1 with an undefined program size (33 bytes in this test case)
294 : 1 : s.clear();
295 [ + - + - ]: 1 : s << OP_1 << ToByteVector(pubkey);
296 [ + - + - : 2 : BOOST_CHECK(ExtractDestination(s, address));
+ - + - ]
297 [ + - ]: 2 : WitnessUnknown unk_v1{1, ToByteVector(pubkey)};
298 [ + - - + : 3 : BOOST_CHECK(std::get<WitnessUnknown>(address) == unk_v1);
+ - + - ]
299 : 1 : s.clear();
300 : : // -> segwit versions 2+ are not specified yet
301 [ + - + - ]: 1 : s << OP_2 << ToByteVector(xpk);
302 [ + - + - : 2 : BOOST_CHECK(ExtractDestination(s, address));
+ - + - ]
303 [ + - ]: 2 : WitnessUnknown unk_v2{2, ToByteVector(xpk)};
304 [ + - - + : 3 : BOOST_CHECK(std::get<WitnessUnknown>(address) == unk_v2);
+ - + - ]
305 : 1 : }
306 : :
307 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(script_standard_GetScriptFor_)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
308 : : {
309 : 3 : CKey keys[3];
310 [ + + ]: 4 : 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 [ + - + - ]: 2 : result = GetScriptForDestination(PKHash(pubkeys[0]));
322 [ + - + - ]: 2 : 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 [ + - + - ]: 2 : result = GetScriptForDestination(ScriptHash(redeemScript));
329 [ + - + - ]: 2 : BOOST_CHECK(result == expected);
330 : :
331 : : // CNoDestination
332 : 1 : expected.clear();
333 [ + - ]: 2 : result = GetScriptForDestination(CNoDestination());
334 [ + - + - ]: 2 : BOOST_CHECK(result == expected);
335 : :
336 : : // GetScriptForRawPubKey
337 : 1 : expected.clear();
338 [ + - + - ]: 1 : expected << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
339 [ + - ]: 2 : result = GetScriptForRawPubKey(pubkeys[0]);
340 [ + - + - ]: 2 : BOOST_CHECK(result == expected);
341 : :
342 : : // GetScriptForMultisig
343 : 1 : expected.clear();
344 [ + - ]: 1 : expected << OP_2 <<
345 [ + - ]: 1 : ToByteVector(pubkeys[0]) <<
346 [ + - ]: 2 : ToByteVector(pubkeys[1]) <<
347 [ + - ]: 2 : ToByteVector(pubkeys[2]) <<
348 [ + - + - ]: 1 : OP_3 << OP_CHECKMULTISIG;
349 [ + - + - : 2 : result = GetScriptForMultisig(2, std::vector<CPubKey>(pubkeys, pubkeys + 3));
+ - ]
350 [ + - + - ]: 2 : BOOST_CHECK(result == expected);
351 : :
352 : : // WitnessV0KeyHash
353 : 1 : expected.clear();
354 [ + - + - : 1 : expected << OP_0 << ToByteVector(pubkeys[0].GetID());
+ - ]
355 [ + - + - : 2 : result = GetScriptForDestination(WitnessV0KeyHash(Hash160(ToByteVector(pubkeys[0]))));
+ - ]
356 [ + - + - : 2 : BOOST_CHECK(result == expected);
+ - ]
357 [ + - + - ]: 2 : result = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0].GetID()));
358 [ + - + - : 2 : 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 [ + - + - : 3 : CSHA256().Write(witnessScript.data(), witnessScript.size())
+ - + - ]
366 [ + - ]: 1 : .Finalize(scriptHash.begin());
367 : :
368 : 1 : expected.clear();
369 [ + - + - ]: 1 : expected << OP_0 << ToByteVector(scriptHash);
370 [ + - + - ]: 2 : result = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
371 [ + - + - ]: 2 : BOOST_CHECK(result == expected);
372 : :
373 : : // WitnessV1Taproot
374 : 1 : auto xpk = XOnlyPubKey(pubkeys[0]);
375 : 1 : expected.clear();
376 [ + - + - ]: 1 : expected << OP_1 << ToByteVector(xpk);
377 [ + - ]: 2 : result = GetScriptForDestination(WitnessV1Taproot(xpk));
378 [ + - + - ]: 2 : BOOST_CHECK(result == expected);
379 : :
380 : : // PayToAnchor
381 : 1 : expected.clear();
382 [ + - ]: 1 : expected << OP_1 << ANCHOR_BYTES;
383 [ + - + - ]: 2 : result = GetScriptForDestination(PayToAnchor());
384 [ + - + - ]: 2 : BOOST_CHECK(result == expected);
385 [ + + - - ]: 5 : }
386 : :
387 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(script_standard_taproot_builder)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
388 : : {
389 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({}), true);
390 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({0}), true);
391 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({1}), false);
392 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({2}), false);
393 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({0,0}), false);
394 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({0,1}), false);
395 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({0,2}), false);
396 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({1,0}), false);
397 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({1,1}), true);
398 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({1,2}), false);
399 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({2,0}), false);
400 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({2,1}), false);
401 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({2,2}), false);
402 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({0,0,0}), false);
403 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({0,0,1}), false);
404 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({0,0,2}), false);
405 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({0,1,0}), false);
406 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({0,1,1}), false);
407 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({0,1,2}), false);
408 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({0,2,0}), false);
409 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({0,2,1}), false);
410 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({0,2,2}), false);
411 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({1,0,0}), false);
412 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({1,0,1}), false);
413 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({1,0,2}), false);
414 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({1,1,0}), false);
415 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({1,1,1}), false);
416 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({1,1,2}), false);
417 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({1,2,0}), false);
418 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({1,2,1}), false);
419 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({1,2,2}), true);
420 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({2,0,0}), false);
421 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({2,0,1}), false);
422 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({2,0,2}), false);
423 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({2,1,0}), false);
424 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({2,1,1}), false);
425 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({2,1,2}), false);
426 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({2,2,0}), false);
427 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({2,2,1}), true);
428 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({2,2,2}), false);
429 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({2,2,2,3,4,5,6,7,8,9,10,11,12,14,14,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,31,31,31,31,31,31,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,128}), true);
430 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({128,128,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1}), true);
431 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({129,129,128,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1}), false);
432 : :
433 : 1 : XOnlyPubKey key_inner{"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"_hex_u8};
434 : 1 : XOnlyPubKey key_1{"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5"_hex_u8};
435 : 1 : XOnlyPubKey key_2{"f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9"_hex_u8};
436 [ + - + - ]: 1 : CScript script_1 = CScript() << ToByteVector(key_1) << OP_CHECKSIG;
437 [ + - + - ]: 1 : CScript script_2 = CScript() << ToByteVector(key_2) << OP_CHECKSIG;
438 : 1 : constexpr uint256 hash_3{"31fe7061656bea2a36aa60a2f7ef940578049273746935d296426dc0afd86b68"};
439 : :
440 [ + - ]: 1 : TaprootBuilder builder;
441 [ + - + - : 2 : BOOST_CHECK(builder.IsValid() && builder.IsComplete());
- + + - +
- ]
442 [ + - + - ]: 2 : builder.Add(2, script_2, 0xc0);
443 [ + - + - : 2 : BOOST_CHECK(builder.IsValid() && !builder.IsComplete());
- + + - +
- ]
444 [ + - ]: 1 : builder.AddOmitted(2, hash_3);
445 [ + - + - : 2 : BOOST_CHECK(builder.IsValid() && !builder.IsComplete());
- + + - +
- ]
446 [ + - + - ]: 2 : builder.Add(1, script_1, 0xc0);
447 [ + - + - : 2 : BOOST_CHECK(builder.IsValid() && builder.IsComplete());
- + + - +
- ]
448 [ + - ]: 1 : builder.Finalize(key_inner);
449 [ + - + - : 2 : BOOST_CHECK(builder.IsValid() && builder.IsComplete());
- + + - +
- ]
450 [ + - + - : 1 : BOOST_CHECK_EQUAL(EncodeDestination(builder.GetOutput()), "bc1pj6gaw944fy0xpmzzu45ugqde4rz7mqj5kj0tg8kmr5f0pjq8vnaqgynnge");
+ - + - ]
451 : 1 : }
452 : :
453 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(bip341_spk_test_vectors)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
454 : : {
455 : 1 : using control_set = decltype(TaprootSpendData::scripts)::mapped_type;
456 : :
457 [ + - ]: 1 : UniValue tests;
458 [ + - ]: 1 : tests.read(json_tests::bip341_wallet_vectors);
459 : :
460 [ + - + - ]: 1 : const auto& vectors = tests["scriptPubKey"];
461 : :
462 [ + - + + ]: 8 : for (const auto& vec : vectors.getValues()) {
463 [ + - ]: 7 : TaprootBuilder spktest;
464 [ + - ]: 7 : std::map<std::pair<std::vector<unsigned char>, int>, int> scriptposes;
465 : 26 : std::function<void (const UniValue&, int)> parse_tree = [&](const UniValue& node, int depth) {
466 [ + + ]: 19 : if (node.isNull()) return;
467 [ + + ]: 18 : if (node.isObject()) {
468 [ + - + - : 12 : auto script = ParseHex(node["script"].get_str());
+ - ]
469 [ + - + - : 12 : int idx = node["id"].getInt<int>();
+ - ]
470 [ + - + - : 12 : int leaf_version = node["leafVersion"].getInt<int>();
+ - ]
471 [ + - + - ]: 12 : scriptposes[{script, leaf_version}] = idx;
472 [ + - ]: 12 : spktest.Add(depth, script, leaf_version);
473 : 12 : } else {
474 : 6 : parse_tree(node[0], depth + 1);
475 : 6 : parse_tree(node[1], depth + 1);
476 : : }
477 [ + - ]: 7 : };
478 [ + - + - : 14 : parse_tree(vec["given"]["scriptTree"], 0);
+ - + - +
- ]
479 [ + - + - : 14 : spktest.Finalize(XOnlyPubKey(ParseHex(vec["given"]["internalPubkey"].get_str())));
+ - + - +
- + - +
- ]
480 [ + - + - : 14 : BOOST_CHECK_EQUAL(HexStr(GetScriptForDestination(spktest.GetOutput())), vec["expected"]["scriptPubKey"].get_str());
+ - + - +
- + - + -
+ - + - +
- ]
481 [ + - + - : 7 : BOOST_CHECK_EQUAL(EncodeDestination(spktest.GetOutput()), vec["expected"]["bip350Address"].get_str());
+ - + - +
- + - + -
+ - + - ]
482 [ + - ]: 7 : auto spend_data = spktest.GetSpendData();
483 [ + - + - : 7 : BOOST_CHECK_EQUAL(vec["intermediary"]["merkleRoot"].isNull(), spend_data.merkle_root.IsNull());
+ - + - +
- + - ]
484 [ + + ]: 7 : if (!spend_data.merkle_root.IsNull()) {
485 [ + - + - : 6 : BOOST_CHECK_EQUAL(vec["intermediary"]["merkleRoot"].get_str(), HexStr(spend_data.merkle_root));
+ - + - +
- + - + -
+ - ]
486 : : }
487 [ + - + - ]: 7 : BOOST_CHECK_EQUAL(spend_data.scripts.size(), scriptposes.size());
488 [ + + ]: 19 : for (const auto& scriptpos : scriptposes) {
489 [ + - + - : 48 : BOOST_CHECK(spend_data.scripts[scriptpos.first] == control_set{ParseHex(vec["expected"]["scriptPathControlBlocks"][scriptpos.second].get_str())});
+ - + - +
- + - + -
+ - + - +
- + - + +
- - ]
490 : : }
491 : 7 : }
492 [ + - + - ]: 25 : }
493 : :
494 : : BOOST_AUTO_TEST_SUITE_END()
|