ismine_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 <key.h>
   6  #include <key_io.h>
   7  #include <node/context.h>
   8  #include <script/script.h>
   9  #include <script/solver.h>
  10  #include <script/signingprovider.h>
  11  #include <test/util/setup_common.h>
  12  #include <wallet/types.h>
  13  #include <wallet/wallet.h>
  14  #include <wallet/test/util.h>
  15  
  16  #include <boost/test/unit_test.hpp>
  17  
  18  using namespace util::hex_literals;
  19  
  20  namespace wallet {
  21  BOOST_FIXTURE_TEST_SUITE(ismine_tests, BasicTestingSetup)
  22  
  23  BOOST_AUTO_TEST_CASE(ismine_standard)
  24  {
  25      CKey keys[2];
  26      CPubKey pubkeys[2];
  27      for (int i = 0; i < 2; i++) {
  28          keys[i].MakeNewKey(true);
  29          pubkeys[i] = keys[i].GetPubKey();
  30      }
  31  
  32      CKey uncompressedKey = GenerateRandomKey(/*compressed=*/false);
  33      CPubKey uncompressedPubkey = uncompressedKey.GetPubKey();
  34      std::unique_ptr<interfaces::Chain>& chain = m_node.chain;
  35  
  36      CScript scriptPubKey;
  37      bool result;
  38  
  39      // P2PK compressed - Descriptor
  40      {
  41          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
  42          std::string desc_str = "pk(" + EncodeSecret(keys[0]) + ")";
  43  
  44          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
  45  
  46          scriptPubKey = GetScriptForRawPubKey(pubkeys[0]);
  47          result = spk_manager->IsMine(scriptPubKey);
  48          BOOST_CHECK(result);
  49      }
  50  
  51      // P2PK uncompressed - Descriptor
  52      {
  53          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
  54          std::string desc_str = "pk(" + EncodeSecret(uncompressedKey) + ")";
  55  
  56          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
  57  
  58          scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey);
  59          result = spk_manager->IsMine(scriptPubKey);
  60          BOOST_CHECK(result);
  61      }
  62  
  63      // P2PKH compressed - Descriptor
  64      {
  65          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
  66          std::string desc_str = "pkh(" + EncodeSecret(keys[0]) + ")";
  67  
  68          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
  69  
  70          scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0]));
  71          result = spk_manager->IsMine(scriptPubKey);
  72          BOOST_CHECK(result);
  73      }
  74  
  75      // P2PKH uncompressed - Descriptor
  76      {
  77          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
  78          std::string desc_str = "pkh(" + EncodeSecret(uncompressedKey) + ")";
  79  
  80          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
  81  
  82          scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey));
  83          result = spk_manager->IsMine(scriptPubKey);
  84          BOOST_CHECK(result);
  85      }
  86  
  87      // P2SH - Descriptor
  88      {
  89          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
  90          std::string desc_str = "sh(pkh(" + EncodeSecret(keys[0]) + "))";
  91  
  92          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
  93  
  94          CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
  95          scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
  96          result = spk_manager->IsMine(scriptPubKey);
  97          BOOST_CHECK(result);
  98      }
  99  
 100      // (P2PKH inside) P2SH inside P2SH (invalid) - Descriptor
 101      {
 102          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 103          std::string desc_str = "sh(sh(" + EncodeSecret(keys[0]) + "))";
 104  
 105          auto spk_manager = CreateDescriptor(keystore, desc_str, false);
 106          BOOST_CHECK_EQUAL(spk_manager, nullptr);
 107      }
 108  
 109      // (P2PKH inside) P2SH inside P2WSH (invalid) - Descriptor
 110      {
 111          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 112          std::string desc_str = "wsh(sh(" + EncodeSecret(keys[0]) + "))";
 113  
 114          auto spk_manager = CreateDescriptor(keystore, desc_str, false);
 115          BOOST_CHECK_EQUAL(spk_manager, nullptr);
 116      }
 117  
 118      // P2WPKH inside P2WSH (invalid) - Descriptor
 119      {
 120          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 121          std::string desc_str = "wsh(wpkh(" + EncodeSecret(keys[0]) + "))";
 122  
 123          auto spk_manager = CreateDescriptor(keystore, desc_str, false);
 124          BOOST_CHECK_EQUAL(spk_manager, nullptr);
 125      }
 126  
 127      // (P2PKH inside) P2WSH inside P2WSH (invalid) - Descriptor
 128      {
 129          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 130          std::string desc_str = "wsh(wsh(" + EncodeSecret(keys[0]) + "))";
 131  
 132          auto spk_manager = CreateDescriptor(keystore, desc_str, false);
 133          BOOST_CHECK_EQUAL(spk_manager, nullptr);
 134      }
 135  
 136      // P2WPKH compressed - Descriptor
 137      {
 138          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 139          std::string desc_str = "wpkh(" + EncodeSecret(keys[0]) + ")";
 140  
 141          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 142  
 143          scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
 144          result = spk_manager->IsMine(scriptPubKey);
 145          BOOST_CHECK(result);
 146      }
 147  
 148      // P2WPKH uncompressed (invalid) - Descriptor
 149      {
 150          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 151          std::string desc_str = "wpkh(" + EncodeSecret(uncompressedKey) + ")";
 152  
 153          auto spk_manager = CreateDescriptor(keystore, desc_str, false);
 154          BOOST_CHECK_EQUAL(spk_manager, nullptr);
 155      }
 156  
 157      // scriptPubKey multisig - Descriptor
 158      {
 159          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 160          std::string desc_str = "multi(2," + EncodeSecret(uncompressedKey) + "," + EncodeSecret(keys[1]) + ")";
 161  
 162          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 163  
 164          scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
 165          result = spk_manager->IsMine(scriptPubKey);
 166          BOOST_CHECK(result);
 167      }
 168  
 169      // P2SH multisig - Descriptor
 170      {
 171          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 172  
 173          std::string desc_str = "sh(multi(2," + EncodeSecret(uncompressedKey) + "," + EncodeSecret(keys[1]) + "))";
 174  
 175          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 176  
 177          CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
 178          scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
 179          result = spk_manager->IsMine(scriptPubKey);
 180          BOOST_CHECK(result);
 181      }
 182  
 183      // P2WSH multisig with compressed keys - Descriptor
 184      {
 185          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 186  
 187          std::string desc_str = "wsh(multi(2," + EncodeSecret(keys[0]) + "," + EncodeSecret(keys[1]) + "))";
 188  
 189          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 190  
 191          CScript redeemScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
 192          scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(redeemScript));
 193          result = spk_manager->IsMine(scriptPubKey);
 194          BOOST_CHECK(result);
 195      }
 196  
 197      // P2WSH multisig with uncompressed key (invalid) - Descriptor
 198      {
 199          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 200  
 201          std::string desc_str = "wsh(multi(2," + EncodeSecret(uncompressedKey) + "," + EncodeSecret(keys[1]) + "))";
 202  
 203          auto spk_manager = CreateDescriptor(keystore, desc_str, false);
 204          BOOST_CHECK_EQUAL(spk_manager, nullptr);
 205      }
 206  
 207      // P2WSH multisig wrapped in P2SH - Descriptor
 208      {
 209          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 210  
 211          std::string desc_str = "sh(wsh(multi(2," + EncodeSecret(keys[0]) + "," + EncodeSecret(keys[1]) + ")))";
 212  
 213          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 214  
 215          CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
 216          CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
 217          scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
 218          result = spk_manager->IsMine(scriptPubKey);
 219          BOOST_CHECK(result);
 220      }
 221  
 222      // Combo - Descriptor
 223      {
 224          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 225  
 226          std::string desc_str = "combo(" + EncodeSecret(keys[0]) + ")";
 227  
 228          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 229  
 230          // Test P2PK
 231          result = spk_manager->IsMine(GetScriptForRawPubKey(pubkeys[0]));
 232          BOOST_CHECK(result);
 233  
 234          // Test P2PKH
 235          result = spk_manager->IsMine(GetScriptForDestination(PKHash(pubkeys[0])));
 236          BOOST_CHECK(result);
 237  
 238          // Test P2SH (combo descriptor does not describe P2SH)
 239          CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
 240          scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
 241          result = spk_manager->IsMine(scriptPubKey);
 242          BOOST_CHECK(!result);
 243  
 244          // Test P2WPKH
 245          scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
 246          result = spk_manager->IsMine(scriptPubKey);
 247          BOOST_CHECK(result);
 248  
 249          // P2SH-P2WPKH output
 250          redeemScript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
 251          scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
 252          result = spk_manager->IsMine(scriptPubKey);
 253          BOOST_CHECK(result);
 254  
 255          // Test P2TR (combo descriptor does not describe P2TR)
 256          XOnlyPubKey xpk(pubkeys[0]);
 257          Assert(xpk.IsFullyValid());
 258          TaprootBuilder builder;
 259          builder.Finalize(xpk);
 260          WitnessV1Taproot output = builder.GetOutput();
 261          scriptPubKey = GetScriptForDestination(output);
 262          result = spk_manager->IsMine(scriptPubKey);
 263          BOOST_CHECK(!result);
 264      }
 265  
 266      // Taproot - Descriptor
 267      {
 268          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 269  
 270          std::string desc_str = "tr(" + EncodeSecret(keys[0]) + ")";
 271  
 272          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 273  
 274          XOnlyPubKey xpk(pubkeys[0]);
 275          Assert(xpk.IsFullyValid());
 276          TaprootBuilder builder;
 277          builder.Finalize(xpk);
 278          WitnessV1Taproot output = builder.GetOutput();
 279          scriptPubKey = GetScriptForDestination(output);
 280          result = spk_manager->IsMine(scriptPubKey);
 281          BOOST_CHECK(result);
 282      }
 283  }
 284  
 285  BOOST_AUTO_TEST_SUITE_END()
 286  } // namespace wallet
 287