ismine_tests.cpp raw

   1  // Copyright (c) 2017-2022 The Limenka 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      isminetype result;
  38  
  39      // P2PK compressed - Legacy
  40      {
  41          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
  42          keystore.SetupLegacyScriptPubKeyMan();
  43          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
  44          scriptPubKey = GetScriptForRawPubKey(pubkeys[0]);
  45  
  46          // Keystore does not have key
  47          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
  48          BOOST_CHECK_EQUAL(result, ISMINE_NO);
  49          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
  50  
  51          // Keystore has key
  52          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
  53          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
  54          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
  55          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
  56      }
  57  
  58      // P2PK compressed - Descriptor
  59      {
  60          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
  61          std::string desc_str = "pk(" + EncodeSecret(keys[0]) + ")";
  62  
  63          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
  64  
  65          scriptPubKey = GetScriptForRawPubKey(pubkeys[0]);
  66          result = spk_manager->IsMine(scriptPubKey);
  67          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
  68      }
  69  
  70      // P2PK uncompressed - Legacy
  71      {
  72          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
  73          keystore.SetupLegacyScriptPubKeyMan();
  74          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
  75          scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey);
  76  
  77          // Keystore does not have key
  78          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
  79          BOOST_CHECK_EQUAL(result, ISMINE_NO);
  80          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
  81  
  82          // Keystore has key
  83          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
  84          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
  85          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
  86          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
  87      }
  88  
  89      // P2PK uncompressed - Descriptor
  90      {
  91          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
  92          std::string desc_str = "pk(" + EncodeSecret(uncompressedKey) + ")";
  93  
  94          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
  95  
  96          scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey);
  97          result = spk_manager->IsMine(scriptPubKey);
  98          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
  99      }
 100  
 101      // P2PKH compressed - Legacy
 102      {
 103          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 104          keystore.SetupLegacyScriptPubKeyMan();
 105          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 106          scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0]));
 107  
 108          // Keystore does not have key
 109          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 110          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 111          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 112  
 113          // Keystore has key
 114          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
 115          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 116          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 117          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
 118      }
 119  
 120      // P2PKH compressed - Descriptor
 121      {
 122          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 123          std::string desc_str = "pkh(" + EncodeSecret(keys[0]) + ")";
 124  
 125          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 126  
 127          scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0]));
 128          result = spk_manager->IsMine(scriptPubKey);
 129          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 130      }
 131  
 132      // P2PKH uncompressed - Legacy
 133      {
 134          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 135          keystore.SetupLegacyScriptPubKeyMan();
 136          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 137          scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey));
 138  
 139          // Keystore does not have key
 140          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 141          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 142          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 143  
 144          // Keystore has key
 145          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
 146          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 147          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 148          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
 149      }
 150  
 151      // P2PKH uncompressed - Descriptor
 152      {
 153          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 154          std::string desc_str = "pkh(" + EncodeSecret(uncompressedKey) + ")";
 155  
 156          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 157  
 158          scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey));
 159          result = spk_manager->IsMine(scriptPubKey);
 160          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 161      }
 162  
 163      // P2SH - Legacy
 164      {
 165          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 166          keystore.SetupLegacyScriptPubKeyMan();
 167          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 168  
 169          CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
 170          scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
 171  
 172          // Keystore does not have redeemScript or key
 173          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 174          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 175          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 176  
 177          // Keystore has redeemScript but no key
 178          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
 179          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 180          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 181          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 182  
 183          // Keystore has redeemScript and key
 184          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
 185          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 186          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 187          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
 188      }
 189  
 190      // P2SH - Descriptor
 191      {
 192          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 193          std::string desc_str = "sh(pkh(" + EncodeSecret(keys[0]) + "))";
 194  
 195          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 196  
 197          CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
 198          scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
 199          result = spk_manager->IsMine(scriptPubKey);
 200          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 201      }
 202  
 203      // (P2PKH inside) P2SH inside P2SH (invalid) - Legacy
 204      {
 205          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 206          keystore.SetupLegacyScriptPubKeyMan();
 207          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 208  
 209          CScript redeemscript_inner = GetScriptForDestination(PKHash(pubkeys[0]));
 210          CScript redeemscript = GetScriptForDestination(ScriptHash(redeemscript_inner));
 211          scriptPubKey = GetScriptForDestination(ScriptHash(redeemscript));
 212  
 213          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript));
 214          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript_inner));
 215          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
 216          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
 217          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 218          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 219          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 220      }
 221  
 222      // (P2PKH inside) P2SH inside P2SH (invalid) - Descriptor
 223      {
 224          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 225          std::string desc_str = "sh(sh(" + EncodeSecret(keys[0]) + "))";
 226  
 227          auto spk_manager = CreateDescriptor(keystore, desc_str, false);
 228          BOOST_CHECK_EQUAL(spk_manager, nullptr);
 229      }
 230  
 231      // (P2PKH inside) P2SH inside P2WSH (invalid) - Legacy
 232      {
 233          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 234          keystore.SetupLegacyScriptPubKeyMan();
 235          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 236  
 237          CScript redeemscript = GetScriptForDestination(PKHash(pubkeys[0]));
 238          CScript witnessscript = GetScriptForDestination(ScriptHash(redeemscript));
 239          scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
 240  
 241          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript));
 242          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript));
 243          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
 244          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
 245          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 246          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 247          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 248      }
 249  
 250      // (P2PKH inside) P2SH inside P2WSH (invalid) - Descriptor
 251      {
 252          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 253          std::string desc_str = "wsh(sh(" + EncodeSecret(keys[0]) + "))";
 254  
 255          auto spk_manager = CreateDescriptor(keystore, desc_str, false);
 256          BOOST_CHECK_EQUAL(spk_manager, nullptr);
 257      }
 258  
 259      // P2WPKH inside P2WSH (invalid) - Legacy
 260      {
 261          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 262          keystore.SetupLegacyScriptPubKeyMan();
 263          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 264  
 265          CScript witnessscript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
 266          scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
 267  
 268          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript));
 269          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
 270          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
 271          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 272          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 273          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 274      }
 275  
 276      // P2WPKH inside P2WSH (invalid) - Descriptor
 277      {
 278          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 279          std::string desc_str = "wsh(wpkh(" + EncodeSecret(keys[0]) + "))";
 280  
 281          auto spk_manager = CreateDescriptor(keystore, desc_str, false);
 282          BOOST_CHECK_EQUAL(spk_manager, nullptr);
 283      }
 284  
 285      // (P2PKH inside) P2WSH inside P2WSH (invalid) - Legacy
 286      {
 287          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 288          keystore.SetupLegacyScriptPubKeyMan();
 289          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 290  
 291          CScript witnessscript_inner = GetScriptForDestination(PKHash(pubkeys[0]));
 292          CScript witnessscript = GetScriptForDestination(WitnessV0ScriptHash(witnessscript_inner));
 293          scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
 294  
 295          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript_inner));
 296          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript));
 297          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
 298          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
 299          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 300          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 301          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 302      }
 303  
 304      // (P2PKH inside) P2WSH inside P2WSH (invalid) - Descriptor
 305      {
 306          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 307          std::string desc_str = "wsh(wsh(" + EncodeSecret(keys[0]) + "))";
 308  
 309          auto spk_manager = CreateDescriptor(keystore, desc_str, false);
 310          BOOST_CHECK_EQUAL(spk_manager, nullptr);
 311      }
 312  
 313      // P2WPKH compressed - Legacy
 314      {
 315          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 316          keystore.SetupLegacyScriptPubKeyMan();
 317          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 318          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
 319  
 320          scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
 321  
 322          // Keystore implicitly has key and P2SH redeemScript
 323          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
 324          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 325          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 326          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
 327      }
 328  
 329      // P2WPKH compressed - Descriptor
 330      {
 331          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 332          std::string desc_str = "wpkh(" + EncodeSecret(keys[0]) + ")";
 333  
 334          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 335  
 336          scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
 337          result = spk_manager->IsMine(scriptPubKey);
 338          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 339      }
 340  
 341      // P2WPKH uncompressed - Legacy
 342      {
 343          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 344          keystore.SetupLegacyScriptPubKeyMan();
 345          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 346          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
 347  
 348          scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(uncompressedPubkey));
 349  
 350          // Keystore has key, but no P2SH redeemScript
 351          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 352          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 353          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 354  
 355          // Keystore has key and P2SH redeemScript
 356          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
 357          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 358          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 359          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 360      }
 361  
 362      // P2WPKH uncompressed (invalid) - Descriptor
 363      {
 364          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 365          std::string desc_str = "wpkh(" + EncodeSecret(uncompressedKey) + ")";
 366  
 367          auto spk_manager = CreateDescriptor(keystore, desc_str, false);
 368          BOOST_CHECK_EQUAL(spk_manager, nullptr);
 369      }
 370  
 371      // scriptPubKey multisig - Legacy
 372      {
 373          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 374          keystore.SetupLegacyScriptPubKeyMan();
 375          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 376  
 377          scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
 378  
 379          // Keystore does not have any keys
 380          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 381          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 382          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 383  
 384          // Keystore has 1/2 keys
 385          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
 386  
 387          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 388          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 389          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 390  
 391          // Keystore has 2/2 keys
 392          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
 393  
 394          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 395          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 396          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 397  
 398          // Keystore has 2/2 keys and the script
 399          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
 400  
 401          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 402          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 403          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 404      }
 405  
 406      // scriptPubKey multisig - Descriptor
 407      {
 408          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 409          std::string desc_str = "multi(2, " + EncodeSecret(uncompressedKey) + ", " + EncodeSecret(keys[1]) + ")";
 410  
 411          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 412  
 413          scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
 414          result = spk_manager->IsMine(scriptPubKey);
 415          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 416      }
 417  
 418      // P2SH multisig - Legacy
 419      {
 420          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 421          keystore.SetupLegacyScriptPubKeyMan();
 422          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 423          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
 424          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
 425  
 426          CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
 427          scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
 428  
 429          // Keystore has no redeemScript
 430          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 431          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 432          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 433  
 434          // Keystore has redeemScript
 435          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
 436          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 437          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 438          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
 439      }
 440  
 441      // P2SH multisig - Descriptor
 442      {
 443          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 444  
 445          std::string desc_str = "sh(multi(2, " + EncodeSecret(uncompressedKey) + ", " + EncodeSecret(keys[1]) + "))";
 446  
 447          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 448  
 449          CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
 450          scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
 451          result = spk_manager->IsMine(scriptPubKey);
 452          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 453      }
 454  
 455      // P2WSH multisig with compressed keys - Legacy
 456      {
 457          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 458          keystore.SetupLegacyScriptPubKeyMan();
 459          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 460          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
 461          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
 462  
 463          CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
 464          scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
 465  
 466          // Keystore has keys, but no witnessScript or P2SH redeemScript
 467          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 468          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 469          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 470  
 471          // Keystore has keys and witnessScript, but no P2SH redeemScript
 472          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
 473          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 474          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 475          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 476  
 477          // Keystore has keys, witnessScript, P2SH redeemScript
 478          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
 479          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 480          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 481          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
 482      }
 483  
 484      // P2WSH multisig with compressed keys - Descriptor
 485      {
 486          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 487  
 488          std::string desc_str = "wsh(multi(2, " + EncodeSecret(keys[0]) + ", " + EncodeSecret(keys[1]) + "))";
 489  
 490          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 491  
 492          CScript redeemScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
 493          scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(redeemScript));
 494          result = spk_manager->IsMine(scriptPubKey);
 495          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 496      }
 497  
 498      // P2WSH multisig with uncompressed key - Legacy
 499      {
 500          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 501          keystore.SetupLegacyScriptPubKeyMan();
 502          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 503          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
 504          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
 505  
 506          CScript witnessScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
 507          scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
 508  
 509          // Keystore has keys, but no witnessScript or P2SH redeemScript
 510          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 511          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 512          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 513  
 514          // Keystore has keys and witnessScript, but no P2SH redeemScript
 515          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
 516          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 517          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 518          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 519  
 520          // Keystore has keys, witnessScript, P2SH redeemScript
 521          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
 522          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 523          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 524          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 525      }
 526  
 527      // P2WSH multisig with uncompressed key (invalid) - Descriptor
 528      {
 529          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 530  
 531          std::string desc_str = "wsh(multi(2, " + EncodeSecret(uncompressedKey) + ", " + EncodeSecret(keys[1]) + "))";
 532  
 533          auto spk_manager = CreateDescriptor(keystore, desc_str, false);
 534          BOOST_CHECK_EQUAL(spk_manager, nullptr);
 535      }
 536  
 537      // P2WSH multisig wrapped in P2SH - Legacy
 538      {
 539          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 540          keystore.SetupLegacyScriptPubKeyMan();
 541          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 542  
 543          CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
 544          CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
 545          scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
 546  
 547          // Keystore has no witnessScript, P2SH redeemScript, or keys
 548          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 549          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 550          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 551  
 552          // Keystore has witnessScript and P2SH redeemScript, but no keys
 553          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
 554          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
 555          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 556          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 557          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 558  
 559          // Keystore has keys, witnessScript, P2SH redeemScript
 560          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
 561          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
 562          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 563          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 564          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
 565      }
 566  
 567      // P2WSH multisig wrapped in P2SH - Descriptor
 568      {
 569          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 570  
 571          std::string desc_str = "sh(wsh(multi(2, " + EncodeSecret(keys[0]) + ", " + EncodeSecret(keys[1]) + ")))";
 572  
 573          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 574  
 575          CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
 576          CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
 577          scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
 578          result = spk_manager->IsMine(scriptPubKey);
 579          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 580      }
 581  
 582      // Combo - Descriptor
 583      {
 584          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 585  
 586          std::string desc_str = "combo(" + EncodeSecret(keys[0]) + ")";
 587  
 588          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 589  
 590          // Test P2PK
 591          result = spk_manager->IsMine(GetScriptForRawPubKey(pubkeys[0]));
 592          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 593  
 594          // Test P2PKH
 595          result = spk_manager->IsMine(GetScriptForDestination(PKHash(pubkeys[0])));
 596          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 597  
 598          // Test P2SH (combo descriptor does not describe P2SH)
 599          CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
 600          scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
 601          result = spk_manager->IsMine(scriptPubKey);
 602          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 603  
 604          // Test P2WPKH
 605          scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
 606          result = spk_manager->IsMine(scriptPubKey);
 607          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 608  
 609          // P2SH-P2WPKH output
 610          redeemScript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
 611          scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
 612          result = spk_manager->IsMine(scriptPubKey);
 613          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 614  
 615          // Test P2TR (combo descriptor does not describe P2TR)
 616          XOnlyPubKey xpk(pubkeys[0]);
 617          Assert(xpk.IsFullyValid());
 618          TaprootBuilder builder;
 619          builder.Finalize(xpk);
 620          WitnessV1Taproot output = builder.GetOutput();
 621          scriptPubKey = GetScriptForDestination(output);
 622          result = spk_manager->IsMine(scriptPubKey);
 623          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 624      }
 625  
 626      // Taproot - Descriptor
 627      {
 628          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 629  
 630          std::string desc_str = "tr(" + EncodeSecret(keys[0]) + ")";
 631  
 632          auto spk_manager = CreateDescriptor(keystore, desc_str, true);
 633  
 634          XOnlyPubKey xpk(pubkeys[0]);
 635          Assert(xpk.IsFullyValid());
 636          TaprootBuilder builder;
 637          builder.Finalize(xpk);
 638          WitnessV1Taproot output = builder.GetOutput();
 639          scriptPubKey = GetScriptForDestination(output);
 640          result = spk_manager->IsMine(scriptPubKey);
 641          BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
 642      }
 643  
 644      // OP_RETURN
 645      {
 646          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 647          keystore.SetupLegacyScriptPubKeyMan();
 648          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 649          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
 650  
 651          scriptPubKey.clear();
 652          scriptPubKey << OP_RETURN << ToByteVector(pubkeys[0]);
 653  
 654          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 655          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 656          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 657      }
 658  
 659      // witness unspendable
 660      {
 661          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 662          keystore.SetupLegacyScriptPubKeyMan();
 663          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 664          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
 665  
 666          scriptPubKey.clear();
 667          scriptPubKey << OP_0 << "aabb"_hex;
 668  
 669          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 670          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 671          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 672      }
 673  
 674      // witness unknown
 675      {
 676          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 677          keystore.SetupLegacyScriptPubKeyMan();
 678          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 679          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
 680  
 681          scriptPubKey.clear();
 682          scriptPubKey << OP_16 << "aabb"_hex;
 683  
 684          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 685          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 686          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 687      }
 688  
 689      // Nonstandard
 690      {
 691          CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
 692          keystore.SetupLegacyScriptPubKeyMan();
 693          LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
 694          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
 695  
 696          scriptPubKey.clear();
 697          scriptPubKey << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
 698  
 699          result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
 700          BOOST_CHECK_EQUAL(result, ISMINE_NO);
 701          BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
 702      }
 703  }
 704  
 705  BOOST_AUTO_TEST_SUITE_END()
 706  } // namespace wallet
 707