Bitcoin Core 22.99.0
P2P Digital Currency
ismine_tests.cpp
Go to the documentation of this file.
1// Copyright (c) 2017-2020 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 <node/context.h>
7#include <script/script.h>
8#include <script/standard.h>
10#include <wallet/ismine.h>
11#include <wallet/wallet.h>
12
13#include <boost/test/unit_test.hpp>
14
15
17
18BOOST_AUTO_TEST_CASE(ismine_standard)
19{
20 CKey keys[2];
21 CPubKey pubkeys[2];
22 for (int i = 0; i < 2; i++) {
23 keys[i].MakeNewKey(true);
24 pubkeys[i] = keys[i].GetPubKey();
25 }
26
27 CKey uncompressedKey;
28 uncompressedKey.MakeNewKey(false);
29 CPubKey uncompressedPubkey = uncompressedKey.GetPubKey();
30 std::unique_ptr<interfaces::Chain>& chain = m_node.chain;
31
32 CScript scriptPubKey;
33 isminetype result;
34
35 // P2PK compressed
36 {
37 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
40 scriptPubKey = GetScriptForRawPubKey(pubkeys[0]);
41
42 // Keystore does not have key
43 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
45
46 // Keystore has key
47 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
48 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
50 }
51
52 // P2PK uncompressed
53 {
54 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
57 scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey);
58
59 // Keystore does not have key
60 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
62
63 // Keystore has key
64 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
65 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
67 }
68
69 // P2PKH compressed
70 {
71 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
74 scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0]));
75
76 // Keystore does not have key
77 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
79
80 // Keystore has key
81 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
82 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
84 }
85
86 // P2PKH uncompressed
87 {
88 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
91 scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey));
92
93 // Keystore does not have key
94 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
96
97 // Keystore has key
98 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
99 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
101 }
102
103 // P2SH
104 {
105 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
108
109 CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
110 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
111
112 // Keystore does not have redeemScript or key
113 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
115
116 // Keystore has redeemScript but no key
117 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
118 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
120
121 // Keystore has redeemScript and key
122 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
123 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
125 }
126
127 // (P2PKH inside) P2SH inside P2SH (invalid)
128 {
129 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
132
133 CScript redeemscript_inner = GetScriptForDestination(PKHash(pubkeys[0]));
134 CScript redeemscript = GetScriptForDestination(ScriptHash(redeemscript_inner));
135 scriptPubKey = GetScriptForDestination(ScriptHash(redeemscript));
136
137 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript));
138 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript_inner));
139 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
140 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
141 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
143 }
144
145 // (P2PKH inside) P2SH inside P2WSH (invalid)
146 {
147 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
150
151 CScript redeemscript = GetScriptForDestination(PKHash(pubkeys[0]));
152 CScript witnessscript = GetScriptForDestination(ScriptHash(redeemscript));
153 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
154
155 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript));
156 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript));
157 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
158 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
159 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
161 }
162
163 // P2WPKH inside P2WSH (invalid)
164 {
165 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
168
169 CScript witnessscript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
170 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
171
172 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript));
173 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
174 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
175 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
177 }
178
179 // (P2PKH inside) P2WSH inside P2WSH (invalid)
180 {
181 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
184
185 CScript witnessscript_inner = GetScriptForDestination(PKHash(pubkeys[0]));
186 CScript witnessscript = GetScriptForDestination(WitnessV0ScriptHash(witnessscript_inner));
187 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
188
189 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript_inner));
190 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript));
191 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
192 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
193 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
195 }
196
197 // P2WPKH compressed
198 {
199 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
202 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
203
204 scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
205
206 // Keystore implicitly has key and P2SH redeemScript
207 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
208 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
210 }
211
212 // P2WPKH uncompressed
213 {
214 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
217 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
218
219 scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(uncompressedPubkey));
220
221 // Keystore has key, but no P2SH redeemScript
222 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
224
225 // Keystore has key and P2SH redeemScript
226 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
227 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
229 }
230
231 // scriptPubKey multisig
232 {
233 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
236
237 scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
238
239 // Keystore does not have any keys
240 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
242
243 // Keystore has 1/2 keys
244 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
245
246 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
248
249 // Keystore has 2/2 keys
250 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
251
252 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
254
255 // Keystore has 2/2 keys and the script
256 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
257
258 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
260 }
261
262 // P2SH multisig
263 {
264 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
267 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
268 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
269
270 CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
271 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
272
273 // Keystore has no redeemScript
274 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
276
277 // Keystore has redeemScript
278 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
279 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
281 }
282
283 // P2WSH multisig with compressed keys
284 {
285 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
288 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
289 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
290
291 CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
292 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
293
294 // Keystore has keys, but no witnessScript or P2SH redeemScript
295 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
297
298 // Keystore has keys and witnessScript, but no P2SH redeemScript
299 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
300 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
302
303 // Keystore has keys, witnessScript, P2SH redeemScript
304 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
305 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
307 }
308
309 // P2WSH multisig with uncompressed key
310 {
311 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
314 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
315 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
316
317 CScript witnessScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
318 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
319
320 // Keystore has keys, but no witnessScript or P2SH redeemScript
321 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
323
324 // Keystore has keys and witnessScript, but no P2SH redeemScript
325 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
326 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
328
329 // Keystore has keys, witnessScript, P2SH redeemScript
330 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
331 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
333 }
334
335 // P2WSH multisig wrapped in P2SH
336 {
337 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
340
341 CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
342 CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
343 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
344
345 // Keystore has no witnessScript, P2SH redeemScript, or keys
346 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
348
349 // Keystore has witnessScript and P2SH redeemScript, but no keys
350 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
351 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
352 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
354
355 // Keystore has keys, witnessScript, P2SH redeemScript
356 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
357 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
358 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
360 }
361
362 // OP_RETURN
363 {
364 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
367 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
368
369 scriptPubKey.clear();
370 scriptPubKey << OP_RETURN << ToByteVector(pubkeys[0]);
371
372 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
374 }
375
376 // witness unspendable
377 {
378 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
381 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
382
383 scriptPubKey.clear();
384 scriptPubKey << OP_0 << ToByteVector(ParseHex("aabb"));
385
386 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
388 }
389
390 // witness unknown
391 {
392 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
395 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
396
397 scriptPubKey.clear();
398 scriptPubKey << OP_16 << ToByteVector(ParseHex("aabb"));
399
400 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
402 }
403
404 // Nonstandard
405 {
406 CWallet keystore(chain.get(), "", CreateDummyWalletDatabase());
409 BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
410
411 scriptPubKey.clear();
412 scriptPubKey << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
413
414 result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
416 }
417}
418
NodeContext m_node
Definition: bitcoin-gui.cpp:36
An encapsulated private key.
Definition: key.h:27
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
Definition: key.cpp:160
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:187
An encapsulated public key.
Definition: pubkey.h:33
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:406
void clear()
Definition: script.h:549
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:229
void SetupLegacyScriptPubKeyMan()
Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
Definition: wallet.cpp:3107
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
Definition: wallet.cpp:3089
virtual bool AddKey(const CKey &key)
RecursiveMutex cs_KeyStore
isminetype IsMine(const CScript &script) const override
bool AddCScript(const CScript &redeemScript) override
BOOST_AUTO_TEST_SUITE_END()
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
Definition: ismine.h:39
@ ISMINE_SPENDABLE
Definition: ismine.h:42
@ ISMINE_NO
Definition: ismine.h:40
BOOST_AUTO_TEST_CASE(ismine_standard)
#define BOOST_FIXTURE_TEST_SUITE(a, b)
Definition: object.cpp:14
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
#define BOOST_CHECK(expr)
Definition: object.cpp:17
@ OP_16
Definition: script.h:92
@ OP_EQUAL
Definition: script.h:139
@ OP_ADD
Definition: script.h:154
@ OP_9
Definition: script.h:85
@ OP_11
Definition: script.h:87
@ OP_0
Definition: script.h:69
@ OP_RETURN
Definition: script.h:104
std::vector< unsigned char > ToByteVector(const T &in)
Definition: script.h:60
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
Definition: standard.cpp:320
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: standard.cpp:315
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:310
std::vector< unsigned char > ParseHex(const char *psz)
Basic testing setup.
Definition: setup_common.h:76
std::unique_ptr< interfaces::Chain > chain
Definition: context.h:50
#define LOCK(cs)
Definition: sync.h:226
std::unique_ptr< WalletDatabase > CreateDummyWalletDatabase()
Return object for accessing dummy database with no read/write capabilities.
Definition: walletdb.cpp:1183