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