Bitcoin Core  29.1.0
P2P Digital Currency
ismine_tests.cpp
Go to the documentation of this file.
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 <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 {
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;
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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]));
593 
594  // Test P2PKH
595  result = spk_manager->IsMine(GetScriptForDestination(PKHash(pubkeys[0])));
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);
603 
604  // Test P2WPKH
605  scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
606  result = spk_manager->IsMine(scriptPubKey);
608 
609  // P2SH-P2WPKH output
610  redeemScript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
611  scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
612  result = spk_manager->IsMine(scriptPubKey);
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);
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);
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);
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);
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);
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);
701  BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
702  }
703 }
704 
706 } // namespace wallet
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
Definition: solver.cpp:218
std::unique_ptr< interfaces::Chain > chain
Definition: context.h:76
wallet::ScriptPubKeyMan * CreateDescriptor(CWallet &keystore, const std::string &desc_str, const bool success)
Definition: util.cpp:196
BOOST_AUTO_TEST_CASE(ismine_standard)
node::NodeContext m_node
Definition: bitcoin-gui.cpp:42
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:182
Definition: script.h:161
Definition: script.h:76
Basic testing setup.
Definition: setup_common.h:64
CKey GenerateRandomKey(bool compressed) noexcept
Definition: key.cpp:352
Definition: script.h:94
void SetupLegacyScriptPubKeyMan()
Make a Legacy(Data)SPKM and set it for all types, internal, and external.
Definition: wallet.cpp:3700
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
#define LOCK(cs)
Definition: sync.h:257
BOOST_AUTO_TEST_SUITE_END()
TaprootBuilder & Finalize(const XOnlyPubKey &internal_key)
Finalize the construction.
An encapsulated public key.
Definition: pubkey.h:33
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
Definition: types.h:41
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
Definition: key.cpp:161
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:299
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
Definition: strencodings.h:427
is a home for public enum and struct type definitions that are used by internally by wallet code...
bool IsFullyValid() const
Determine if this pubkey is fully valid.
Definition: pubkey.cpp:224
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Utility class to construct Taproot outputs from internal key and script tree.
std::vector< unsigned char > ToByteVector(const T &in)
Definition: script.h:67
std::unique_ptr< WalletDatabase > CreateMockableWalletDatabase(MockableData records)
Definition: util.cpp:186
auto result
Definition: common-types.h:74
Definition: script.h:92
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:414
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: solver.cpp:213
Definition: script.h:99
An encapsulated private key.
Definition: key.h:34
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:231
void clear()
Definition: script.h:576
#define Assert(val)
Identity function.
Definition: check.h:85
#define BOOST_CHECK(expr)
Definition: object.cpp:17