script_standard_tests.cpp raw

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