Line data Source code
1 : // Copyright (c) 2017-2021 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 <script/script.h>
7 : #include <script/script_error.h>
8 : #include <script/standard.h>
9 : #include <test/util/setup_common.h>
10 : #include <wallet/ismine.h>
11 : #include <wallet/wallet.h>
12 :
13 : #include <boost/test/unit_test.hpp>
14 :
15 : using node::NodeContext;
16 :
17 : namespace wallet {
18 146 : BOOST_FIXTURE_TEST_SUITE(ismine_tests, BasicTestingSetup)
19 :
20 149 : BOOST_AUTO_TEST_CASE(ismine_standard)
21 : {
22 1 : CKey keys[2];
23 2 : CPubKey pubkeys[2];
24 3 : for (int i = 0; i < 2; i++) {
25 2 : keys[i].MakeNewKey(true);
26 2 : pubkeys[i] = keys[i].GetPubKey();
27 2 : }
28 :
29 1 : CKey uncompressedKey = GenerateRandomKey(/*compressed=*/false);
30 1 : CPubKey uncompressedPubkey = uncompressedKey.GetPubKey();
31 1 : NodeContext node;
32 1 : auto& chain = m_node.chain;
33 :
34 1 : CScript scriptPubKey;
35 : isminetype result;
36 :
37 : // P2PK compressed
38 : {
39 1 : CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase());
40 1 : keystore.SetupLegacyScriptPubKeyMan();
41 1 : LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
42 1 : scriptPubKey = GetScriptForRawPubKey(pubkeys[0]);
43 :
44 : // Keystore does not have key
45 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
46 1 : BOOST_CHECK_EQUAL(result, ISMINE_NO);
47 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
48 :
49 : // Keystore has key
50 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
51 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
52 1 : BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
53 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
54 1 : }
55 :
56 : // P2PK uncompressed
57 : {
58 1 : CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase());
59 1 : keystore.SetupLegacyScriptPubKeyMan();
60 1 : LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
61 1 : scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey);
62 :
63 : // Keystore does not have key
64 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
65 1 : BOOST_CHECK_EQUAL(result, ISMINE_NO);
66 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
67 :
68 : // Keystore has key
69 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
70 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
71 1 : BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
72 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
73 1 : }
74 :
75 : // P2PKH compressed
76 : {
77 1 : CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase());
78 1 : keystore.SetupLegacyScriptPubKeyMan();
79 1 : LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
80 1 : scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0]));
81 :
82 : // Keystore does not have key
83 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
84 1 : BOOST_CHECK_EQUAL(result, ISMINE_NO);
85 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
86 :
87 : // Keystore has key
88 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
89 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
90 1 : BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
91 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
92 1 : }
93 :
94 : // P2PKH uncompressed
95 : {
96 1 : CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase());
97 1 : keystore.SetupLegacyScriptPubKeyMan();
98 1 : LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
99 1 : scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey));
100 :
101 : // Keystore does not have key
102 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
103 1 : BOOST_CHECK_EQUAL(result, ISMINE_NO);
104 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
105 :
106 : // Keystore has key
107 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
108 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
109 1 : BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
110 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
111 1 : }
112 :
113 : // P2SH
114 : {
115 1 : CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase());
116 1 : keystore.SetupLegacyScriptPubKeyMan();
117 1 : LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
118 :
119 1 : CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
120 1 : scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
121 :
122 : // Keystore does not have redeemScript or key
123 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
124 1 : BOOST_CHECK_EQUAL(result, ISMINE_NO);
125 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
126 :
127 : // Keystore has redeemScript but no key
128 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
129 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
130 1 : BOOST_CHECK_EQUAL(result, ISMINE_NO);
131 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
132 :
133 : // Keystore has redeemScript and key
134 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
135 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
136 1 : BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
137 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
138 1 : }
139 :
140 : // (P2PKH inside) P2SH inside P2SH (invalid)
141 : {
142 1 : CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase());
143 1 : keystore.SetupLegacyScriptPubKeyMan();
144 1 : LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
145 :
146 1 : CScript redeemscript_inner = GetScriptForDestination(PKHash(pubkeys[0]));
147 1 : CScript redeemscript = GetScriptForDestination(ScriptHash(redeemscript_inner));
148 1 : scriptPubKey = GetScriptForDestination(ScriptHash(redeemscript));
149 :
150 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript));
151 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript_inner));
152 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
153 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
154 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
155 1 : BOOST_CHECK_EQUAL(result, ISMINE_NO);
156 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
157 1 : }
158 :
159 : // scriptPubKey multisig
160 : {
161 1 : CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase());
162 1 : keystore.SetupLegacyScriptPubKeyMan();
163 1 : LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
164 :
165 1 : scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
166 :
167 : // Keystore does not have any keys
168 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
169 1 : BOOST_CHECK_EQUAL(result, ISMINE_NO);
170 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
171 :
172 : // Keystore has 1/2 keys
173 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
174 :
175 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
176 1 : BOOST_CHECK_EQUAL(result, ISMINE_NO);
177 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
178 :
179 : // Keystore has 2/2 keys
180 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
181 :
182 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
183 1 : BOOST_CHECK_EQUAL(result, ISMINE_NO);
184 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
185 :
186 : // Keystore has 2/2 keys and the script
187 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
188 :
189 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
190 1 : BOOST_CHECK_EQUAL(result, ISMINE_NO);
191 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
192 1 : }
193 :
194 : // P2SH multisig
195 : {
196 1 : CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase());
197 1 : keystore.SetupLegacyScriptPubKeyMan();
198 1 : LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
199 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
200 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
201 :
202 1 : CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
203 1 : scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
204 :
205 : // Keystore has no redeemScript
206 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
207 1 : BOOST_CHECK_EQUAL(result, ISMINE_NO);
208 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
209 :
210 : // Keystore has redeemScript
211 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
212 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
213 1 : BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
214 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
215 1 : }
216 :
217 : // OP_RETURN
218 : {
219 1 : CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase());
220 1 : keystore.SetupLegacyScriptPubKeyMan();
221 1 : LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
222 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
223 :
224 1 : scriptPubKey.clear();
225 1 : scriptPubKey << OP_RETURN << ToByteVector(pubkeys[0]);
226 :
227 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
228 1 : BOOST_CHECK_EQUAL(result, ISMINE_NO);
229 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
230 1 : }
231 :
232 : // Nonstandard
233 : {
234 1 : CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase());
235 1 : keystore.SetupLegacyScriptPubKeyMan();
236 1 : LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
237 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
238 :
239 1 : scriptPubKey.clear();
240 1 : scriptPubKey << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
241 :
242 1 : result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
243 1 : BOOST_CHECK_EQUAL(result, ISMINE_NO);
244 1 : BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
245 1 : }
246 1 : }
247 :
248 146 : BOOST_AUTO_TEST_SUITE_END()
249 : } // namespace wallet
|