Bitcoin Core 28.0.0
P2P Digital Currency
Loading...
Searching...
No Matches
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
18
19namespace wallet {
20BOOST_FIXTURE_TEST_SUITE(ismine_tests, BasicTestingSetup)
21
22wallet::ScriptPubKeyMan* CreateDescriptor(CWallet& keystore, const std::string& desc_str, const bool success)
23{
24 keystore.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
25
27 std::string error;
28 std::unique_ptr<Descriptor> parsed_desc = Parse(desc_str, keys, error, false);
29 BOOST_CHECK(success == (parsed_desc != nullptr));
30 if (!success) return nullptr;
31
32 const int64_t range_start = 0, range_end = 1, next_index = 0, timestamp = 1;
33
34 WalletDescriptor w_desc(std::move(parsed_desc), timestamp, range_start, range_end, next_index);
35
36 LOCK(keystore.cs_wallet);
37
38 return Assert(keystore.AddWalletDescriptor(w_desc, keys,/*label=*/"", /*internal=*/false));
39};
40
41BOOST_AUTO_TEST_CASE(ismine_standard)
42{
43 CKey keys[2];
44 CPubKey pubkeys[2];
45 for (int i = 0; i < 2; i++) {
46 keys[i].MakeNewKey(true);
47 pubkeys[i] = keys[i].GetPubKey();
48 }
49
50 CKey uncompressedKey = GenerateRandomKey(/*compressed=*/false);
51 CPubKey uncompressedPubkey = uncompressedKey.GetPubKey();
52 std::unique_ptr<interfaces::Chain>& chain = m_node.chain;
53
54 CScript scriptPubKey;
55 isminetype result;
56
57 // P2PK compressed - Legacy
58 {
59 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
62 scriptPubKey = GetScriptForRawPubKey(pubkeys[0]);
63
64 // Keystore does not have key
65 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
66 BOOST_CHECK_EQUAL(result, ISMINE_NO);
67 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
68
69 // Keystore has key
70 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
71 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
72 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
73 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
74 }
75
76 // P2PK compressed - Descriptor
77 {
78 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
79 std::string desc_str = "pk(" + EncodeSecret(keys[0]) + ")";
80
81 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
82
83 scriptPubKey = GetScriptForRawPubKey(pubkeys[0]);
84 result = spk_manager->IsMine(scriptPubKey);
85 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
86 }
87
88 // P2PK uncompressed - Legacy
89 {
90 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
93 scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey);
94
95 // Keystore does not have key
96 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
97 BOOST_CHECK_EQUAL(result, ISMINE_NO);
98 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
99
100 // Keystore has key
101 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
102 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
103 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
104 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
105 }
106
107 // P2PK uncompressed - Descriptor
108 {
109 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
110 std::string desc_str = "pk(" + EncodeSecret(uncompressedKey) + ")";
111
112 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
113
114 scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey);
115 result = spk_manager->IsMine(scriptPubKey);
116 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
117 }
118
119 // P2PKH compressed - Legacy
120 {
121 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
124 scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0]));
125
126 // Keystore does not have key
127 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
128 BOOST_CHECK_EQUAL(result, ISMINE_NO);
129 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
130
131 // Keystore has key
132 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
133 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
134 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
135 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
136 }
137
138 // P2PKH compressed - Descriptor
139 {
140 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
141 std::string desc_str = "pkh(" + EncodeSecret(keys[0]) + ")";
142
143 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
144
145 scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0]));
146 result = spk_manager->IsMine(scriptPubKey);
147 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
148 }
149
150 // P2PKH uncompressed - Legacy
151 {
152 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
155 scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey));
156
157 // Keystore does not have key
158 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
159 BOOST_CHECK_EQUAL(result, ISMINE_NO);
160 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
161
162 // Keystore has key
163 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
164 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
165 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
166 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
167 }
168
169 // P2PKH uncompressed - Descriptor
170 {
171 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
172 std::string desc_str = "pkh(" + EncodeSecret(uncompressedKey) + ")";
173
174 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
175
176 scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey));
177 result = spk_manager->IsMine(scriptPubKey);
178 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
179 }
180
181 // P2SH - Legacy
182 {
183 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
186
187 CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
188 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
189
190 // Keystore does not have redeemScript or key
191 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
192 BOOST_CHECK_EQUAL(result, ISMINE_NO);
193 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
194
195 // Keystore has redeemScript but no key
196 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
197 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
198 BOOST_CHECK_EQUAL(result, ISMINE_NO);
199 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
200
201 // Keystore has redeemScript and key
202 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
203 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
204 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
205 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
206 }
207
208 // P2SH - Descriptor
209 {
210 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
211 std::string desc_str = "sh(pkh(" + EncodeSecret(keys[0]) + "))";
212
213 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
214
215 CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
216 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
217 result = spk_manager->IsMine(scriptPubKey);
218 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
219 }
220
221 // (P2PKH inside) P2SH inside P2SH (invalid) - Legacy
222 {
223 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
226
227 CScript redeemscript_inner = GetScriptForDestination(PKHash(pubkeys[0]));
228 CScript redeemscript = GetScriptForDestination(ScriptHash(redeemscript_inner));
229 scriptPubKey = GetScriptForDestination(ScriptHash(redeemscript));
230
231 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript));
232 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript_inner));
233 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
234 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
235 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
236 BOOST_CHECK_EQUAL(result, ISMINE_NO);
237 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
238 }
239
240 // (P2PKH inside) P2SH inside P2SH (invalid) - Descriptor
241 {
242 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
243 std::string desc_str = "sh(sh(" + EncodeSecret(keys[0]) + "))";
244
245 auto spk_manager = CreateDescriptor(keystore, desc_str, false);
246 BOOST_CHECK_EQUAL(spk_manager, nullptr);
247 }
248
249 // (P2PKH inside) P2SH inside P2WSH (invalid) - Legacy
250 {
251 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
254
255 CScript redeemscript = GetScriptForDestination(PKHash(pubkeys[0]));
256 CScript witnessscript = GetScriptForDestination(ScriptHash(redeemscript));
257 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
258
259 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript));
260 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript));
261 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
262 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
263 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
264 BOOST_CHECK_EQUAL(result, ISMINE_NO);
265 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
266 }
267
268 // (P2PKH inside) P2SH inside P2WSH (invalid) - Descriptor
269 {
270 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
271 std::string desc_str = "wsh(sh(" + EncodeSecret(keys[0]) + "))";
272
273 auto spk_manager = CreateDescriptor(keystore, desc_str, false);
274 BOOST_CHECK_EQUAL(spk_manager, nullptr);
275 }
276
277 // P2WPKH inside P2WSH (invalid) - Legacy
278 {
279 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
282
283 CScript witnessscript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
284 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
285
286 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript));
287 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
288 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
289 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
290 BOOST_CHECK_EQUAL(result, ISMINE_NO);
291 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
292 }
293
294 // P2WPKH inside P2WSH (invalid) - Descriptor
295 {
296 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
297 std::string desc_str = "wsh(wpkh(" + EncodeSecret(keys[0]) + "))";
298
299 auto spk_manager = CreateDescriptor(keystore, desc_str, false);
300 BOOST_CHECK_EQUAL(spk_manager, nullptr);
301 }
302
303 // (P2PKH inside) P2WSH inside P2WSH (invalid) - Legacy
304 {
305 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
308
309 CScript witnessscript_inner = GetScriptForDestination(PKHash(pubkeys[0]));
310 CScript witnessscript = GetScriptForDestination(WitnessV0ScriptHash(witnessscript_inner));
311 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
312
313 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript_inner));
314 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript));
315 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
316 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
317 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
318 BOOST_CHECK_EQUAL(result, ISMINE_NO);
319 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
320 }
321
322 // (P2PKH inside) P2WSH inside P2WSH (invalid) - Descriptor
323 {
324 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
325 std::string desc_str = "wsh(wsh(" + EncodeSecret(keys[0]) + "))";
326
327 auto spk_manager = CreateDescriptor(keystore, desc_str, false);
328 BOOST_CHECK_EQUAL(spk_manager, nullptr);
329 }
330
331 // P2WPKH compressed - Legacy
332 {
333 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
336 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
337
338 scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
339
340 // Keystore implicitly has key and P2SH redeemScript
341 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
342 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
343 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
344 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
345 }
346
347 // P2WPKH compressed - Descriptor
348 {
349 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
350 std::string desc_str = "wpkh(" + EncodeSecret(keys[0]) + ")";
351
352 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
353
354 scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
355 result = spk_manager->IsMine(scriptPubKey);
356 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
357 }
358
359 // P2WPKH uncompressed - Legacy
360 {
361 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
364 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
365
366 scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(uncompressedPubkey));
367
368 // Keystore has key, but no P2SH redeemScript
369 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
370 BOOST_CHECK_EQUAL(result, ISMINE_NO);
371 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
372
373 // Keystore has key and P2SH redeemScript
374 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
375 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
376 BOOST_CHECK_EQUAL(result, ISMINE_NO);
377 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
378 }
379
380 // P2WPKH uncompressed (invalid) - Descriptor
381 {
382 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
383 std::string desc_str = "wpkh(" + EncodeSecret(uncompressedKey) + ")";
384
385 auto spk_manager = CreateDescriptor(keystore, desc_str, false);
386 BOOST_CHECK_EQUAL(spk_manager, nullptr);
387 }
388
389 // scriptPubKey multisig - Legacy
390 {
391 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
394
395 scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
396
397 // Keystore does not have any keys
398 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
399 BOOST_CHECK_EQUAL(result, ISMINE_NO);
400 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
401
402 // Keystore has 1/2 keys
403 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
404
405 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
406 BOOST_CHECK_EQUAL(result, ISMINE_NO);
407 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
408
409 // Keystore has 2/2 keys
410 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
411
412 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
413 BOOST_CHECK_EQUAL(result, ISMINE_NO);
414 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
415
416 // Keystore has 2/2 keys and the script
417 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
418
419 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
420 BOOST_CHECK_EQUAL(result, ISMINE_NO);
421 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
422 }
423
424 // scriptPubKey multisig - Descriptor
425 {
426 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
427 std::string desc_str = "multi(2, " + EncodeSecret(uncompressedKey) + ", " + EncodeSecret(keys[1]) + ")";
428
429 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
430
431 scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
432 result = spk_manager->IsMine(scriptPubKey);
433 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
434 }
435
436 // P2SH multisig - Legacy
437 {
438 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
441 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
442 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
443
444 CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
445 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
446
447 // Keystore has no redeemScript
448 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
449 BOOST_CHECK_EQUAL(result, ISMINE_NO);
450 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
451
452 // Keystore has redeemScript
453 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
454 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
455 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
456 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
457 }
458
459 // P2SH multisig - Descriptor
460 {
461 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
462
463 std::string desc_str = "sh(multi(2, " + EncodeSecret(uncompressedKey) + ", " + EncodeSecret(keys[1]) + "))";
464
465 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
466
467 CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
468 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
469 result = spk_manager->IsMine(scriptPubKey);
470 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
471 }
472
473 // P2WSH multisig with compressed keys - Legacy
474 {
475 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
478 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
479 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
480
481 CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
482 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
483
484 // Keystore has keys, but no witnessScript or P2SH redeemScript
485 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
486 BOOST_CHECK_EQUAL(result, ISMINE_NO);
487 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
488
489 // Keystore has keys and witnessScript, but no P2SH redeemScript
490 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
491 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
492 BOOST_CHECK_EQUAL(result, ISMINE_NO);
493 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
494
495 // Keystore has keys, witnessScript, P2SH redeemScript
496 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
497 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
498 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
499 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
500 }
501
502 // P2WSH multisig with compressed keys - Descriptor
503 {
504 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
505
506 std::string desc_str = "wsh(multi(2, " + EncodeSecret(keys[0]) + ", " + EncodeSecret(keys[1]) + "))";
507
508 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
509
510 CScript redeemScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
511 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(redeemScript));
512 result = spk_manager->IsMine(scriptPubKey);
513 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
514 }
515
516 // P2WSH multisig with uncompressed key - Legacy
517 {
518 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
521 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
522 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
523
524 CScript witnessScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
525 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
526
527 // Keystore has keys, but no witnessScript or P2SH redeemScript
528 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
529 BOOST_CHECK_EQUAL(result, ISMINE_NO);
530 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
531
532 // Keystore has keys and witnessScript, but no P2SH redeemScript
533 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
534 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
535 BOOST_CHECK_EQUAL(result, ISMINE_NO);
536 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
537
538 // Keystore has keys, witnessScript, P2SH redeemScript
539 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
540 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
541 BOOST_CHECK_EQUAL(result, ISMINE_NO);
542 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
543 }
544
545 // P2WSH multisig with uncompressed key (invalid) - Descriptor
546 {
547 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
548
549 std::string desc_str = "wsh(multi(2, " + EncodeSecret(uncompressedKey) + ", " + EncodeSecret(keys[1]) + "))";
550
551 auto spk_manager = CreateDescriptor(keystore, desc_str, false);
552 BOOST_CHECK_EQUAL(spk_manager, nullptr);
553 }
554
555 // P2WSH multisig wrapped in P2SH - Legacy
556 {
557 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
560
561 CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
562 CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
563 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
564
565 // Keystore has no witnessScript, P2SH redeemScript, or keys
566 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
567 BOOST_CHECK_EQUAL(result, ISMINE_NO);
568 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
569
570 // Keystore has witnessScript and P2SH redeemScript, but no keys
571 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
572 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
573 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
574 BOOST_CHECK_EQUAL(result, ISMINE_NO);
575 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
576
577 // Keystore has keys, witnessScript, P2SH redeemScript
578 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
579 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
580 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
581 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
582 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
583 }
584
585 // P2WSH multisig wrapped in P2SH - Descriptor
586 {
587 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
588
589 std::string desc_str = "sh(wsh(multi(2, " + EncodeSecret(keys[0]) + ", " + EncodeSecret(keys[1]) + ")))";
590
591 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
592
593 CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
594 CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
595 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
596 result = spk_manager->IsMine(scriptPubKey);
597 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
598 }
599
600 // Combo - Descriptor
601 {
602 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
603
604 std::string desc_str = "combo(" + EncodeSecret(keys[0]) + ")";
605
606 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
607
608 // Test P2PK
609 result = spk_manager->IsMine(GetScriptForRawPubKey(pubkeys[0]));
610 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
611
612 // Test P2PKH
613 result = spk_manager->IsMine(GetScriptForDestination(PKHash(pubkeys[0])));
614 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
615
616 // Test P2SH (combo descriptor does not describe P2SH)
617 CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
618 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
619 result = spk_manager->IsMine(scriptPubKey);
620 BOOST_CHECK_EQUAL(result, ISMINE_NO);
621
622 // Test P2WPKH
623 scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
624 result = spk_manager->IsMine(scriptPubKey);
625 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
626
627 // P2SH-P2WPKH output
628 redeemScript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
629 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
630 result = spk_manager->IsMine(scriptPubKey);
631 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
632
633 // Test P2TR (combo descriptor does not describe P2TR)
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_NO);
642 }
643
644 // Taproot - Descriptor
645 {
646 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
647
648 std::string desc_str = "tr(" + EncodeSecret(keys[0]) + ")";
649
650 auto spk_manager = CreateDescriptor(keystore, desc_str, true);
651
652 XOnlyPubKey xpk(pubkeys[0]);
653 Assert(xpk.IsFullyValid());
654 TaprootBuilder builder;
655 builder.Finalize(xpk);
656 WitnessV1Taproot output = builder.GetOutput();
657 scriptPubKey = GetScriptForDestination(output);
658 result = spk_manager->IsMine(scriptPubKey);
659 BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
660 }
661
662 // OP_RETURN
663 {
664 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
667 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
668
669 scriptPubKey.clear();
670 scriptPubKey << OP_RETURN << ToByteVector(pubkeys[0]);
671
672 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
673 BOOST_CHECK_EQUAL(result, ISMINE_NO);
674 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
675 }
676
677 // witness unspendable
678 {
679 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
682 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
683
684 scriptPubKey.clear();
685 scriptPubKey << OP_0 << ToByteVector(ParseHex("aabb"));
686
687 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
688 BOOST_CHECK_EQUAL(result, ISMINE_NO);
689 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
690 }
691
692 // witness unknown
693 {
694 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
697 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
698
699 scriptPubKey.clear();
700 scriptPubKey << OP_16 << ToByteVector(ParseHex("aabb"));
701
702 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
703 BOOST_CHECK_EQUAL(result, ISMINE_NO);
704 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
705 }
706
707 // Nonstandard
708 {
709 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
712 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
713
714 scriptPubKey.clear();
715 scriptPubKey << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
716
717 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
718 BOOST_CHECK_EQUAL(result, ISMINE_NO);
719 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
720 }
721}
722
724} // namespace wallet
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
node::NodeContext m_node
#define Assert(val)
Identity function.
Definition check.h:77
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:414
void clear()
Definition script.h:565
virtual bool AddKey(const CKey &key)
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:226
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:3617
void SetupLegacyScriptPubKeyMan()
Make a Legacy(Data)SPKM and set it for all types, internal, and external.
Definition wallet.cpp:3661
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:321
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
wallet::ScriptPubKeyMan * CreateDescriptor(CWallet &keystore, const std::string &desc_str, const bool success)
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
Definition types.h:41
BOOST_AUTO_TEST_CASE(bnb_search_test)
#define BOOST_CHECK_EQUAL(v1, v2)
Definition object.cpp:18
#define BOOST_CHECK(expr)
Definition object.cpp:17
@ OP_16
Definition script.h:98
@ OP_EQUAL
Definition script.h:145
@ OP_ADD
Definition script.h:160
@ OP_9
Definition script.h:91
@ OP_11
Definition script.h:93
@ OP_0
Definition script.h:75
@ OP_RETURN
Definition script.h:110
std::vector< unsigned char > ToByteVector(const T &in)
Definition script.h:66
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
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
Basic testing setup.
std::unique_ptr< interfaces::Chain > chain
Definition context.h:73
#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,...