/ src / wallet / test / ismine_tests.cpp
ismine_tests.cpp
  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