Bitcoin Core 28.99.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>
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
18using namespace util::hex_literals;
19
20namespace wallet {
22
23wallet::ScriptPubKeyMan* CreateDescriptor(CWallet& keystore, const std::string& desc_str, const bool success)
24{
25 keystore.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
26
28 std::string error;
29 auto parsed_descs = Parse(desc_str, keys, error, false);
30 BOOST_CHECK(success == (!parsed_descs.empty()));
31 if (!success) return nullptr;
32 auto& desc = parsed_descs.at(0);
33
34 const int64_t range_start = 0, range_end = 1, next_index = 0, timestamp = 1;
35
36 WalletDescriptor w_desc(std::move(desc), timestamp, range_start, range_end, next_index);
37
38 LOCK(keystore.cs_wallet);
39
40 return Assert(keystore.AddWalletDescriptor(w_desc, keys,/*label=*/"", /*internal=*/false));
41};
42
43BOOST_AUTO_TEST_CASE(ismine_standard)
44{
45 CKey keys[2];
46 CPubKey pubkeys[2];
47 for (int i = 0; i < 2; i++) {
48 keys[i].MakeNewKey(true);
49 pubkeys[i] = keys[i].GetPubKey();
50 }
51
52 CKey uncompressedKey = GenerateRandomKey(/*compressed=*/false);
53 CPubKey uncompressedPubkey = uncompressedKey.GetPubKey();
54 std::unique_ptr<interfaces::Chain>& chain = m_node.chain;
55
56 CScript scriptPubKey;
57 isminetype result;
58
59 // P2PK compressed - Legacy
60 {
61 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
64 scriptPubKey = GetScriptForRawPubKey(pubkeys[0]);
65
66 // Keystore does not have key
67 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
69 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
70
71 // Keystore has key
72 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
73 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
75 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
76 }
77
78 // P2PK compressed - Descriptor
79 {
80 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
81 std::string desc_str = "pk(" + EncodeSecret(keys[0]) + ")";
82
83 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
84
85 scriptPubKey = GetScriptForRawPubKey(pubkeys[0]);
86 result = spk_manager->IsMine(scriptPubKey);
88 }
89
90 // P2PK uncompressed - Legacy
91 {
92 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
95 scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey);
96
97 // Keystore does not have key
98 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
100 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
101
102 // Keystore has key
103 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
104 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
106 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
107 }
108
109 // P2PK uncompressed - Descriptor
110 {
111 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
112 std::string desc_str = "pk(" + EncodeSecret(uncompressedKey) + ")";
113
114 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
115
116 scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey);
117 result = spk_manager->IsMine(scriptPubKey);
119 }
120
121 // P2PKH compressed - Legacy
122 {
123 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
126 scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0]));
127
128 // Keystore does not have key
129 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
131 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
132
133 // Keystore has key
134 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
135 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
137 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
138 }
139
140 // P2PKH compressed - Descriptor
141 {
142 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
143 std::string desc_str = "pkh(" + EncodeSecret(keys[0]) + ")";
144
145 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
146
147 scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0]));
148 result = spk_manager->IsMine(scriptPubKey);
150 }
151
152 // P2PKH uncompressed - Legacy
153 {
154 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
157 scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey));
158
159 // Keystore does not have key
160 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
162 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
163
164 // Keystore has key
165 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
166 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
168 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
169 }
170
171 // P2PKH uncompressed - Descriptor
172 {
173 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
174 std::string desc_str = "pkh(" + EncodeSecret(uncompressedKey) + ")";
175
176 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
177
178 scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey));
179 result = spk_manager->IsMine(scriptPubKey);
181 }
182
183 // P2SH - Legacy
184 {
185 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
188
189 CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
190 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
191
192 // Keystore does not have redeemScript or key
193 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
195 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
196
197 // Keystore has redeemScript but no key
198 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
199 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
201 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
202
203 // Keystore has redeemScript and key
204 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
205 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
207 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
208 }
209
210 // P2SH - Descriptor
211 {
212 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
213 std::string desc_str = "sh(pkh(" + EncodeSecret(keys[0]) + "))";
214
215 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
216
217 CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
218 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
219 result = spk_manager->IsMine(scriptPubKey);
221 }
222
223 // (P2PKH inside) P2SH inside P2SH (invalid) - Legacy
224 {
225 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
228
229 CScript redeemscript_inner = GetScriptForDestination(PKHash(pubkeys[0]));
230 CScript redeemscript = GetScriptForDestination(ScriptHash(redeemscript_inner));
231 scriptPubKey = GetScriptForDestination(ScriptHash(redeemscript));
232
233 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript));
234 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript_inner));
235 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
236 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
237 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
239 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
240 }
241
242 // (P2PKH inside) P2SH inside P2SH (invalid) - Descriptor
243 {
244 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
245 std::string desc_str = "sh(sh(" + EncodeSecret(keys[0]) + "))";
246
247 auto spk_manager = CreateDescriptor(keystore, desc_str, false);
248 BOOST_CHECK_EQUAL(spk_manager, nullptr);
249 }
250
251 // (P2PKH inside) P2SH inside P2WSH (invalid) - Legacy
252 {
253 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
256
257 CScript redeemscript = GetScriptForDestination(PKHash(pubkeys[0]));
258 CScript witnessscript = GetScriptForDestination(ScriptHash(redeemscript));
259 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
260
261 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript));
262 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript));
263 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
264 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
265 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
267 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
268 }
269
270 // (P2PKH inside) P2SH inside P2WSH (invalid) - Descriptor
271 {
272 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
273 std::string desc_str = "wsh(sh(" + EncodeSecret(keys[0]) + "))";
274
275 auto spk_manager = CreateDescriptor(keystore, desc_str, false);
276 BOOST_CHECK_EQUAL(spk_manager, nullptr);
277 }
278
279 // P2WPKH inside P2WSH (invalid) - Legacy
280 {
281 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
284
285 CScript witnessscript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
286 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
287
288 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript));
289 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
290 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
291 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
293 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
294 }
295
296 // P2WPKH inside P2WSH (invalid) - Descriptor
297 {
298 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
299 std::string desc_str = "wsh(wpkh(" + EncodeSecret(keys[0]) + "))";
300
301 auto spk_manager = CreateDescriptor(keystore, desc_str, false);
302 BOOST_CHECK_EQUAL(spk_manager, nullptr);
303 }
304
305 // (P2PKH inside) P2WSH inside P2WSH (invalid) - Legacy
306 {
307 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
310
311 CScript witnessscript_inner = GetScriptForDestination(PKHash(pubkeys[0]));
312 CScript witnessscript = GetScriptForDestination(WitnessV0ScriptHash(witnessscript_inner));
313 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
314
315 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript_inner));
316 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript));
317 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
318 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
319 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
321 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
322 }
323
324 // (P2PKH inside) P2WSH inside P2WSH (invalid) - Descriptor
325 {
326 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
327 std::string desc_str = "wsh(wsh(" + EncodeSecret(keys[0]) + "))";
328
329 auto spk_manager = CreateDescriptor(keystore, desc_str, false);
330 BOOST_CHECK_EQUAL(spk_manager, nullptr);
331 }
332
333 // P2WPKH compressed - Legacy
334 {
335 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
338 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
339
340 scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
341
342 // Keystore implicitly has key and P2SH redeemScript
343 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
344 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
346 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
347 }
348
349 // P2WPKH compressed - Descriptor
350 {
351 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
352 std::string desc_str = "wpkh(" + EncodeSecret(keys[0]) + ")";
353
354 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
355
356 scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
357 result = spk_manager->IsMine(scriptPubKey);
359 }
360
361 // P2WPKH uncompressed - Legacy
362 {
363 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
366 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
367
368 scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(uncompressedPubkey));
369
370 // Keystore has key, but no P2SH redeemScript
371 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
373 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
374
375 // Keystore has key and P2SH redeemScript
376 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
377 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
379 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
380 }
381
382 // P2WPKH uncompressed (invalid) - Descriptor
383 {
384 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
385 std::string desc_str = "wpkh(" + EncodeSecret(uncompressedKey) + ")";
386
387 auto spk_manager = CreateDescriptor(keystore, desc_str, false);
388 BOOST_CHECK_EQUAL(spk_manager, nullptr);
389 }
390
391 // scriptPubKey multisig - Legacy
392 {
393 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
396
397 scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
398
399 // Keystore does not have any keys
400 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
402 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
403
404 // Keystore has 1/2 keys
405 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
406
407 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
409 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
410
411 // Keystore has 2/2 keys
412 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
413
414 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
416 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
417
418 // Keystore has 2/2 keys and the script
419 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
420
421 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
423 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
424 }
425
426 // scriptPubKey multisig - Descriptor
427 {
428 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
429 std::string desc_str = "multi(2, " + EncodeSecret(uncompressedKey) + ", " + EncodeSecret(keys[1]) + ")";
430
431 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
432
433 scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
434 result = spk_manager->IsMine(scriptPubKey);
436 }
437
438 // P2SH multisig - Legacy
439 {
440 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
443 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
444 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
445
446 CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
447 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
448
449 // Keystore has no redeemScript
450 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
452 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
453
454 // Keystore has redeemScript
455 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
456 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
458 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
459 }
460
461 // P2SH multisig - Descriptor
462 {
463 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
464
465 std::string desc_str = "sh(multi(2, " + EncodeSecret(uncompressedKey) + ", " + EncodeSecret(keys[1]) + "))";
466
467 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
468
469 CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
470 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
471 result = spk_manager->IsMine(scriptPubKey);
473 }
474
475 // P2WSH multisig with compressed keys - Legacy
476 {
477 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
480 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
481 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
482
483 CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
484 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
485
486 // Keystore has keys, but no witnessScript or P2SH redeemScript
487 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
489 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
490
491 // Keystore has keys and witnessScript, but no P2SH redeemScript
492 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
493 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
495 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
496
497 // Keystore has keys, witnessScript, P2SH redeemScript
498 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
499 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
501 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
502 }
503
504 // P2WSH multisig with compressed keys - Descriptor
505 {
506 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
507
508 std::string desc_str = "wsh(multi(2, " + EncodeSecret(keys[0]) + ", " + EncodeSecret(keys[1]) + "))";
509
510 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
511
512 CScript redeemScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
513 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(redeemScript));
514 result = spk_manager->IsMine(scriptPubKey);
516 }
517
518 // P2WSH multisig with uncompressed key - Legacy
519 {
520 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
523 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
524 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
525
526 CScript witnessScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
527 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
528
529 // Keystore has keys, but no witnessScript or P2SH redeemScript
530 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
532 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
533
534 // Keystore has keys and witnessScript, but no P2SH redeemScript
535 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
536 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
538 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
539
540 // Keystore has keys, witnessScript, P2SH redeemScript
541 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
542 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
544 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
545 }
546
547 // P2WSH multisig with uncompressed key (invalid) - Descriptor
548 {
549 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
550
551 std::string desc_str = "wsh(multi(2, " + EncodeSecret(uncompressedKey) + ", " + EncodeSecret(keys[1]) + "))";
552
553 auto spk_manager = CreateDescriptor(keystore, desc_str, false);
554 BOOST_CHECK_EQUAL(spk_manager, nullptr);
555 }
556
557 // P2WSH multisig wrapped in P2SH - Legacy
558 {
559 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
562
563 CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
564 CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
565 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
566
567 // Keystore has no witnessScript, P2SH redeemScript, or keys
568 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
570 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
571
572 // Keystore has witnessScript and P2SH redeemScript, but no keys
573 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
574 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
575 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
577 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
578
579 // Keystore has keys, witnessScript, P2SH redeemScript
580 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
581 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
582 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
584 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
585 }
586
587 // P2WSH multisig wrapped in P2SH - Descriptor
588 {
589 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
590
591 std::string desc_str = "sh(wsh(multi(2, " + EncodeSecret(keys[0]) + ", " + EncodeSecret(keys[1]) + ")))";
592
593 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
594
595 CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
596 CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
597 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
598 result = spk_manager->IsMine(scriptPubKey);
600 }
601
602 // Combo - Descriptor
603 {
604 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
605
606 std::string desc_str = "combo(" + EncodeSecret(keys[0]) + ")";
607
608 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
609
610 // Test P2PK
611 result = spk_manager->IsMine(GetScriptForRawPubKey(pubkeys[0]));
613
614 // Test P2PKH
615 result = spk_manager->IsMine(GetScriptForDestination(PKHash(pubkeys[0])));
617
618 // Test P2SH (combo descriptor does not describe P2SH)
619 CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
620 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
621 result = spk_manager->IsMine(scriptPubKey);
623
624 // Test P2WPKH
625 scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
626 result = spk_manager->IsMine(scriptPubKey);
628
629 // P2SH-P2WPKH output
630 redeemScript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
631 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
632 result = spk_manager->IsMine(scriptPubKey);
634
635 // Test P2TR (combo descriptor does not describe P2TR)
636 XOnlyPubKey xpk(pubkeys[0]);
637 Assert(xpk.IsFullyValid());
638 TaprootBuilder builder;
639 builder.Finalize(xpk);
640 WitnessV1Taproot output = builder.GetOutput();
641 scriptPubKey = GetScriptForDestination(output);
642 result = spk_manager->IsMine(scriptPubKey);
644 }
645
646 // Taproot - Descriptor
647 {
648 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
649
650 std::string desc_str = "tr(" + EncodeSecret(keys[0]) + ")";
651
652 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
653
654 XOnlyPubKey xpk(pubkeys[0]);
655 Assert(xpk.IsFullyValid());
656 TaprootBuilder builder;
657 builder.Finalize(xpk);
658 WitnessV1Taproot output = builder.GetOutput();
659 scriptPubKey = GetScriptForDestination(output);
660 result = spk_manager->IsMine(scriptPubKey);
662 }
663
664 // OP_RETURN
665 {
666 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
669 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
670
671 scriptPubKey.clear();
672 scriptPubKey << OP_RETURN << ToByteVector(pubkeys[0]);
673
674 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
676 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
677 }
678
679 // witness unspendable
680 {
681 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
684 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
685
686 scriptPubKey.clear();
687 scriptPubKey << OP_0 << "aabb"_hex;
688
689 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
691 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
692 }
693
694 // witness unknown
695 {
696 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
699 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
700
701 scriptPubKey.clear();
702 scriptPubKey << OP_16 << "aabb"_hex;
703
704 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
706 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
707 }
708
709 // Nonstandard
710 {
711 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
714 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
715
716 scriptPubKey.clear();
717 scriptPubKey << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
718
719 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
721 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
722 }
723}
724
726} // namespace wallet
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
node::NodeContext m_node
Definition: bitcoin-gui.cpp:42
#define Assert(val)
Identity function.
Definition: check.h:85
An encapsulated private key.
Definition: key.h:35
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
Definition: key.cpp:161
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:182
An encapsulated public key.
Definition: pubkey.h:34
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:415
void clear()
Definition: script.h:576
virtual bool AddKey(const CKey &key)
RecursiveMutex cs_KeyStore
Utility class to construct Taproot outputs from internal key and script tree.
WitnessV1Taproot GetOutput()
Compute scriptPubKey (after Finalize()).
TaprootBuilder & Finalize(const XOnlyPubKey &internal_key)
Finalize the construction.
bool IsFullyValid() const
Determine if this pubkey is fully valid.
Definition: pubkey.cpp:224
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:300
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
Definition: wallet.cpp:3636
void SetupLegacyScriptPubKeyMan()
Make a Legacy(Data)SPKM and set it for all types, internal, and external.
Definition: wallet.cpp:3680
isminetype IsMine(const CScript &script) const override
std::unordered_set< CScript, SaltedSipHasher > GetScriptPubKeys() const override
Returns a set of all the scriptPubKeys that this ScriptPubKeyMan watches.
bool AddCScript(const CScript &redeemScript) override
Descriptor with some wallet metadata.
Definition: walletutil.h:85
static UniValue Parse(std::string_view raw)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
Definition: client.cpp:327
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
CKey GenerateRandomKey(bool compressed) noexcept
Definition: key.cpp:352
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:231
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
Definition: strencodings.h:427
wallet::ScriptPubKeyMan * CreateDescriptor(CWallet &keystore, const std::string &desc_str, const bool success)
std::unique_ptr< WalletDatabase > CreateMockableWalletDatabase(MockableData records)
Definition: util.cpp:186
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
Definition: types.h:41
@ ISMINE_NO
Definition: types.h:42
@ ISMINE_SPENDABLE
Definition: types.h:44
BOOST_AUTO_TEST_CASE(bnb_search_test)
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:74
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
#define BOOST_CHECK(expr)
Definition: object.cpp:17
@ OP_16
Definition: script.h:99
@ OP_EQUAL
Definition: script.h:146
@ OP_ADD
Definition: script.h:161
@ OP_9
Definition: script.h:92
@ OP_11
Definition: script.h:94
@ OP_0
Definition: script.h:76
@ OP_RETURN
Definition: script.h:111
std::vector< unsigned char > ToByteVector(const T &in)
Definition: script.h:67
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
Definition: solver.cpp:218
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: solver.cpp:213
Basic testing setup.
Definition: setup_common.h:63
std::unique_ptr< interfaces::Chain > chain
Definition: context.h:76
#define LOCK(cs)
Definition: sync.h:257
is a home for public enum and struct type definitions that are used by internally by wallet code,...