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