1 // Copyright (c) 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 <chainparams.h>
6 #include <chainparamsbase.h>
7 #include <key.h>
8 #include <key_io.h>
9 #include <outputtype.h>
10 #include <policy/policy.h>
11 #include <pubkey.h>
12 #include <rpc/util.h>
13 #include <script/keyorigin.h>
14 #include <script/script.h>
15 #include <script/sign.h>
16 #include <script/signingprovider.h>
17 #include <script/standard.h>
18 #include <streams.h>
19 #include <test/fuzz/fuzz.h>
20 #include <util/memory.h>
21 #include <util/strencodings.h>
22
23 #include <cassert>
24 #include <cstdint>
25 #include <numeric>
26 #include <string>
27 #include <vector>
28
initialize()29 void initialize()
30 {
31 static const ECCVerifyHandle ecc_verify_handle;
32 ECC_Start();
33 SelectParams(CBaseChainParams::REGTEST);
34 }
35
test_one_input(const std::vector<uint8_t> & buffer)36 void test_one_input(const std::vector<uint8_t>& buffer)
37 {
38 const CKey key = [&] {
39 CKey k;
40 k.Set(buffer.begin(), buffer.end(), true);
41 return k;
42 }();
43 if (!key.IsValid()) {
44 return;
45 }
46
47 {
48 assert(key.begin() + key.size() == key.end());
49 assert(key.IsCompressed());
50 assert(key.size() == 32);
51 assert(DecodeSecret(EncodeSecret(key)) == key);
52 }
53
54 {
55 CKey invalid_key;
56 assert(!(invalid_key == key));
57 assert(!invalid_key.IsCompressed());
58 assert(!invalid_key.IsValid());
59 assert(invalid_key.size() == 0);
60 }
61
62 {
63 CKey uncompressed_key;
64 uncompressed_key.Set(buffer.begin(), buffer.end(), false);
65 assert(!(uncompressed_key == key));
66 assert(!uncompressed_key.IsCompressed());
67 assert(key.size() == 32);
68 assert(uncompressed_key.begin() + uncompressed_key.size() == uncompressed_key.end());
69 assert(uncompressed_key.IsValid());
70 }
71
72 {
73 CKey copied_key;
74 copied_key.Set(key.begin(), key.end(), key.IsCompressed());
75 assert(copied_key == key);
76 }
77
78 {
79 CKey negated_key = key;
80 negated_key.Negate();
81 assert(negated_key.IsValid());
82 assert(!(negated_key == key));
83
84 negated_key.Negate();
85 assert(negated_key == key);
86 }
87
88 const uint256 random_uint256 = Hash(buffer);
89
90 {
91 CKey child_key;
92 ChainCode child_chaincode;
93 const bool ok = key.Derive(child_key, child_chaincode, 0, random_uint256);
94 assert(ok);
95 assert(child_key.IsValid());
96 assert(!(child_key == key));
97 assert(child_chaincode != random_uint256);
98 }
99
100 const CPubKey pubkey = key.GetPubKey();
101
102 {
103 assert(pubkey.size() == 33);
104 assert(key.VerifyPubKey(pubkey));
105 assert(pubkey.GetHash() != random_uint256);
106 assert(pubkey.begin() + pubkey.size() == pubkey.end());
107 assert(pubkey.data() == pubkey.begin());
108 assert(pubkey.IsCompressed());
109 assert(pubkey.IsValid());
110 assert(pubkey.IsFullyValid());
111 assert(HexToPubKey(HexStr(pubkey)) == pubkey);
112 assert(GetAllDestinationsForKey(pubkey).size() == 3);
113 }
114
115 {
116 CDataStream data_stream{SER_NETWORK, INIT_PROTO_VERSION};
117 pubkey.Serialize(data_stream);
118
119 CPubKey pubkey_deserialized;
120 pubkey_deserialized.Unserialize(data_stream);
121 assert(pubkey_deserialized == pubkey);
122 }
123
124 {
125 const CScript tx_pubkey_script = GetScriptForRawPubKey(pubkey);
126 assert(!tx_pubkey_script.IsPayToScriptHash());
127 assert(!tx_pubkey_script.IsPayToWitnessScriptHash());
128 assert(!tx_pubkey_script.IsPushOnly());
129 assert(!tx_pubkey_script.IsUnspendable());
130 assert(tx_pubkey_script.HasValidOps());
131 assert(tx_pubkey_script.size() == 35);
132
133 const CScript tx_multisig_script = GetScriptForMultisig(1, {pubkey});
134 assert(!tx_multisig_script.IsPayToScriptHash());
135 assert(!tx_multisig_script.IsPayToWitnessScriptHash());
136 assert(!tx_multisig_script.IsPushOnly());
137 assert(!tx_multisig_script.IsUnspendable());
138 assert(tx_multisig_script.HasValidOps());
139 assert(tx_multisig_script.size() == 37);
140
141 FillableSigningProvider fillable_signing_provider;
142 assert(IsSolvable(fillable_signing_provider, tx_pubkey_script));
143 assert(IsSolvable(fillable_signing_provider, tx_multisig_script));
144 assert(!IsSegWitOutput(fillable_signing_provider, tx_pubkey_script));
145 assert(!IsSegWitOutput(fillable_signing_provider, tx_multisig_script));
146 assert(fillable_signing_provider.GetKeys().size() == 0);
147 assert(!fillable_signing_provider.HaveKey(pubkey.GetID()));
148
149 const bool ok_add_key = fillable_signing_provider.AddKey(key);
150 assert(ok_add_key);
151 assert(fillable_signing_provider.HaveKey(pubkey.GetID()));
152
153 FillableSigningProvider fillable_signing_provider_pub;
154 assert(!fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
155
156 const bool ok_add_key_pubkey = fillable_signing_provider_pub.AddKeyPubKey(key, pubkey);
157 assert(ok_add_key_pubkey);
158 assert(fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
159
160 TxoutType which_type_tx_pubkey;
161 const bool is_standard_tx_pubkey = IsStandard(tx_pubkey_script, which_type_tx_pubkey);
162 assert(is_standard_tx_pubkey);
163 assert(which_type_tx_pubkey == TxoutType::PUBKEY);
164
165 TxoutType which_type_tx_multisig;
166 const bool is_standard_tx_multisig = IsStandard(tx_multisig_script, which_type_tx_multisig);
167 assert(is_standard_tx_multisig);
168 assert(which_type_tx_multisig == TxoutType::MULTISIG);
169
170 std::vector<std::vector<unsigned char>> v_solutions_ret_tx_pubkey;
171 const TxoutType outtype_tx_pubkey = Solver(tx_pubkey_script, v_solutions_ret_tx_pubkey);
172 assert(outtype_tx_pubkey == TxoutType::PUBKEY);
173 assert(v_solutions_ret_tx_pubkey.size() == 1);
174 assert(v_solutions_ret_tx_pubkey[0].size() == 33);
175
176 std::vector<std::vector<unsigned char>> v_solutions_ret_tx_multisig;
177 const TxoutType outtype_tx_multisig = Solver(tx_multisig_script, v_solutions_ret_tx_multisig);
178 assert(outtype_tx_multisig == TxoutType::MULTISIG);
179 assert(v_solutions_ret_tx_multisig.size() == 3);
180 assert(v_solutions_ret_tx_multisig[0].size() == 1);
181 assert(v_solutions_ret_tx_multisig[1].size() == 33);
182 assert(v_solutions_ret_tx_multisig[2].size() == 1);
183
184 OutputType output_type{};
185 const CTxDestination tx_destination = GetDestinationForKey(pubkey, output_type);
186 assert(output_type == OutputType::LEGACY);
187 assert(IsValidDestination(tx_destination));
188 assert(CTxDestination{PKHash{pubkey}} == tx_destination);
189
190 const CScript script_for_destination = GetScriptForDestination(tx_destination);
191 assert(script_for_destination.size() == 25);
192
193 const std::string destination_address = EncodeDestination(tx_destination);
194 assert(DecodeDestination(destination_address) == tx_destination);
195
196 const CPubKey pubkey_from_address_string = AddrToPubKey(fillable_signing_provider, destination_address);
197 assert(pubkey_from_address_string == pubkey);
198
199 CKeyID key_id = pubkey.GetID();
200 assert(!key_id.IsNull());
201 assert(key_id == CKeyID{key_id});
202 assert(key_id == GetKeyForDestination(fillable_signing_provider, tx_destination));
203
204 CPubKey pubkey_out;
205 const bool ok_get_pubkey = fillable_signing_provider.GetPubKey(key_id, pubkey_out);
206 assert(ok_get_pubkey);
207
208 CKey key_out;
209 const bool ok_get_key = fillable_signing_provider.GetKey(key_id, key_out);
210 assert(ok_get_key);
211 assert(fillable_signing_provider.GetKeys().size() == 1);
212 assert(fillable_signing_provider.HaveKey(key_id));
213
214 KeyOriginInfo key_origin_info;
215 const bool ok_get_key_origin = fillable_signing_provider.GetKeyOrigin(key_id, key_origin_info);
216 assert(!ok_get_key_origin);
217 }
218
219 {
220 const std::vector<unsigned char> vch_pubkey{pubkey.begin(), pubkey.end()};
221 assert(CPubKey::ValidSize(vch_pubkey));
222 assert(!CPubKey::ValidSize({pubkey.begin(), pubkey.begin() + pubkey.size() - 1}));
223
224 const CPubKey pubkey_ctor_1{vch_pubkey};
225 assert(pubkey == pubkey_ctor_1);
226
227 const CPubKey pubkey_ctor_2{vch_pubkey.begin(), vch_pubkey.end()};
228 assert(pubkey == pubkey_ctor_2);
229
230 CPubKey pubkey_set;
231 pubkey_set.Set(vch_pubkey.begin(), vch_pubkey.end());
232 assert(pubkey == pubkey_set);
233 }
234
235 {
236 const CPubKey invalid_pubkey{};
237 assert(!invalid_pubkey.IsValid());
238 assert(!invalid_pubkey.IsFullyValid());
239 assert(!(pubkey == invalid_pubkey));
240 assert(pubkey != invalid_pubkey);
241 assert(pubkey < invalid_pubkey);
242 }
243
244 {
245 // Cover CPubKey's operator[](unsigned int pos)
246 unsigned int sum = 0;
247 for (size_t i = 0; i < pubkey.size(); ++i) {
248 sum += pubkey[i];
249 }
250 assert(std::accumulate(pubkey.begin(), pubkey.end(), 0U) == sum);
251 }
252
253 {
254 CPubKey decompressed_pubkey = pubkey;
255 assert(decompressed_pubkey.IsCompressed());
256
257 const bool ok = decompressed_pubkey.Decompress();
258 assert(ok);
259 assert(!decompressed_pubkey.IsCompressed());
260 assert(decompressed_pubkey.size() == 65);
261 }
262
263 {
264 std::vector<unsigned char> vch_sig;
265 const bool ok = key.Sign(random_uint256, vch_sig, false);
266 assert(ok);
267 assert(pubkey.Verify(random_uint256, vch_sig));
268 assert(CPubKey::CheckLowS(vch_sig));
269
270 const std::vector<unsigned char> vch_invalid_sig{vch_sig.begin(), vch_sig.begin() + vch_sig.size() - 1};
271 assert(!pubkey.Verify(random_uint256, vch_invalid_sig));
272 assert(!CPubKey::CheckLowS(vch_invalid_sig));
273 }
274
275 {
276 std::vector<unsigned char> vch_compact_sig;
277 const bool ok_sign_compact = key.SignCompact(random_uint256, vch_compact_sig);
278 assert(ok_sign_compact);
279
280 CPubKey recover_pubkey;
281 const bool ok_recover_compact = recover_pubkey.RecoverCompact(random_uint256, vch_compact_sig);
282 assert(ok_recover_compact);
283 assert(recover_pubkey == pubkey);
284 }
285
286 {
287 CPubKey child_pubkey;
288 ChainCode child_chaincode;
289 const bool ok = pubkey.Derive(child_pubkey, child_chaincode, 0, random_uint256);
290 assert(ok);
291 assert(child_pubkey != pubkey);
292 assert(child_pubkey.IsCompressed());
293 assert(child_pubkey.IsFullyValid());
294 assert(child_pubkey.IsValid());
295 assert(child_pubkey.size() == 33);
296 assert(child_chaincode != random_uint256);
297 }
298
299 const CPrivKey priv_key = key.GetPrivKey();
300
301 {
302 for (const bool skip_check : {true, false}) {
303 CKey loaded_key;
304 const bool ok = loaded_key.Load(priv_key, pubkey, skip_check);
305 assert(ok);
306 assert(key == loaded_key);
307 }
308 }
309 }
310