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