Bitcoin Core 22.99.0
P2P Digital Currency
key.cpp
Go to the documentation of this file.
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>
17#include <script/standard.h>
18#include <streams.h>
19#include <test/fuzz/fuzz.h>
20#include <util/strencodings.h>
21
22#include <cassert>
23#include <cstdint>
24#include <numeric>
25#include <string>
26#include <vector>
27
29{
30 static const ECCVerifyHandle ecc_verify_handle;
31 ECC_Start();
33}
34
36{
37 const CKey key = [&] {
38 CKey k;
39 k.Set(buffer.begin(), buffer.end(), true);
40 return k;
41 }();
42 if (!key.IsValid()) {
43 return;
44 }
45
46 {
47 assert(key.begin() + key.size() == key.end());
48 assert(key.IsCompressed());
49 assert(key.size() == 32);
50 assert(DecodeSecret(EncodeSecret(key)) == key);
51 }
52
53 {
54 CKey invalid_key;
55 assert(!(invalid_key == key));
56 assert(!invalid_key.IsCompressed());
57 assert(!invalid_key.IsValid());
58 assert(invalid_key.size() == 0);
59 }
60
61 {
62 CKey uncompressed_key;
63 uncompressed_key.Set(buffer.begin(), buffer.end(), false);
64 assert(!(uncompressed_key == key));
65 assert(!uncompressed_key.IsCompressed());
66 assert(key.size() == 32);
67 assert(uncompressed_key.begin() + uncompressed_key.size() == uncompressed_key.end());
68 assert(uncompressed_key.IsValid());
69 }
70
71 {
72 CKey copied_key;
73 copied_key.Set(key.begin(), key.end(), key.IsCompressed());
74 assert(copied_key == key);
75 }
76
77 {
78 CKey negated_key = key;
79 negated_key.Negate();
80 assert(negated_key.IsValid());
81 assert(!(negated_key == key));
82
83 negated_key.Negate();
84 assert(negated_key == key);
85 }
86
87 const uint256 random_uint256 = Hash(buffer);
88
89 {
90 CKey child_key;
91 ChainCode child_chaincode;
92 const bool ok = key.Derive(child_key, child_chaincode, 0, random_uint256);
93 assert(ok);
94 assert(child_key.IsValid());
95 assert(!(child_key == key));
96 assert(child_chaincode != random_uint256);
97 }
98
99 const CPubKey pubkey = key.GetPubKey();
100
101 {
102 assert(pubkey.size() == 33);
103 assert(key.VerifyPubKey(pubkey));
104 assert(pubkey.GetHash() != random_uint256);
105 assert(pubkey.begin() + pubkey.size() == pubkey.end());
106 assert(pubkey.data() == pubkey.begin());
107 assert(pubkey.IsCompressed());
108 assert(pubkey.IsValid());
109 assert(pubkey.IsFullyValid());
110 assert(HexToPubKey(HexStr(pubkey)) == pubkey);
111 assert(GetAllDestinationsForKey(pubkey).size() == 3);
112 }
113
114 {
116 pubkey.Serialize(data_stream);
117
118 CPubKey pubkey_deserialized;
119 pubkey_deserialized.Unserialize(data_stream);
120 assert(pubkey_deserialized == pubkey);
121 }
122
123 {
124 const CScript tx_pubkey_script = GetScriptForRawPubKey(pubkey);
125 assert(!tx_pubkey_script.IsPayToScriptHash());
126 assert(!tx_pubkey_script.IsPayToWitnessScriptHash());
127 assert(!tx_pubkey_script.IsPushOnly());
128 assert(!tx_pubkey_script.IsUnspendable());
129 assert(tx_pubkey_script.HasValidOps());
130 assert(tx_pubkey_script.size() == 35);
131
132 const CScript tx_multisig_script = GetScriptForMultisig(1, {pubkey});
133 assert(!tx_multisig_script.IsPayToScriptHash());
134 assert(!tx_multisig_script.IsPayToWitnessScriptHash());
135 assert(!tx_multisig_script.IsPushOnly());
136 assert(!tx_multisig_script.IsUnspendable());
137 assert(tx_multisig_script.HasValidOps());
138 assert(tx_multisig_script.size() == 37);
139
140 FillableSigningProvider fillable_signing_provider;
141 assert(IsSolvable(fillable_signing_provider, tx_pubkey_script));
142 assert(IsSolvable(fillable_signing_provider, tx_multisig_script));
143 assert(!IsSegWitOutput(fillable_signing_provider, tx_pubkey_script));
144 assert(!IsSegWitOutput(fillable_signing_provider, tx_multisig_script));
145 assert(fillable_signing_provider.GetKeys().size() == 0);
146 assert(!fillable_signing_provider.HaveKey(pubkey.GetID()));
147
148 const bool ok_add_key = fillable_signing_provider.AddKey(key);
149 assert(ok_add_key);
150 assert(fillable_signing_provider.HaveKey(pubkey.GetID()));
151
152 FillableSigningProvider fillable_signing_provider_pub;
153 assert(!fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
154
155 const bool ok_add_key_pubkey = fillable_signing_provider_pub.AddKeyPubKey(key, pubkey);
156 assert(ok_add_key_pubkey);
157 assert(fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
158
159 TxoutType which_type_tx_pubkey;
160 const bool is_standard_tx_pubkey = IsStandard(tx_pubkey_script, which_type_tx_pubkey);
161 assert(is_standard_tx_pubkey);
162 assert(which_type_tx_pubkey == TxoutType::PUBKEY);
163
164 TxoutType which_type_tx_multisig;
165 const bool is_standard_tx_multisig = IsStandard(tx_multisig_script, which_type_tx_multisig);
166 assert(is_standard_tx_multisig);
167 assert(which_type_tx_multisig == TxoutType::MULTISIG);
168
169 std::vector<std::vector<unsigned char>> v_solutions_ret_tx_pubkey;
170 const TxoutType outtype_tx_pubkey = Solver(tx_pubkey_script, v_solutions_ret_tx_pubkey);
171 assert(outtype_tx_pubkey == TxoutType::PUBKEY);
172 assert(v_solutions_ret_tx_pubkey.size() == 1);
173 assert(v_solutions_ret_tx_pubkey[0].size() == 33);
174
175 std::vector<std::vector<unsigned char>> v_solutions_ret_tx_multisig;
176 const TxoutType outtype_tx_multisig = Solver(tx_multisig_script, v_solutions_ret_tx_multisig);
177 assert(outtype_tx_multisig == TxoutType::MULTISIG);
178 assert(v_solutions_ret_tx_multisig.size() == 3);
179 assert(v_solutions_ret_tx_multisig[0].size() == 1);
180 assert(v_solutions_ret_tx_multisig[1].size() == 33);
181 assert(v_solutions_ret_tx_multisig[2].size() == 1);
182
183 OutputType output_type{};
184 const CTxDestination tx_destination = GetDestinationForKey(pubkey, output_type);
185 assert(output_type == OutputType::LEGACY);
186 assert(IsValidDestination(tx_destination));
187 assert(CTxDestination{PKHash{pubkey}} == tx_destination);
188
189 const CScript script_for_destination = GetScriptForDestination(tx_destination);
190 assert(script_for_destination.size() == 25);
191
192 const std::string destination_address = EncodeDestination(tx_destination);
193 assert(DecodeDestination(destination_address) == tx_destination);
194
195 const CPubKey pubkey_from_address_string = AddrToPubKey(fillable_signing_provider, destination_address);
196 assert(pubkey_from_address_string == pubkey);
197
198 CKeyID key_id = pubkey.GetID();
199 assert(!key_id.IsNull());
200 assert(key_id == CKeyID{key_id});
201 assert(key_id == GetKeyForDestination(fillable_signing_provider, tx_destination));
202
203 CPubKey pubkey_out;
204 const bool ok_get_pubkey = fillable_signing_provider.GetPubKey(key_id, pubkey_out);
205 assert(ok_get_pubkey);
206
207 CKey key_out;
208 const bool ok_get_key = fillable_signing_provider.GetKey(key_id, key_out);
209 assert(ok_get_key);
210 assert(fillable_signing_provider.GetKeys().size() == 1);
211 assert(fillable_signing_provider.HaveKey(key_id));
212
213 KeyOriginInfo key_origin_info;
214 const bool ok_get_key_origin = fillable_signing_provider.GetKeyOrigin(key_id, key_origin_info);
215 assert(!ok_get_key_origin);
216 }
217
218 {
219 const std::vector<unsigned char> vch_pubkey{pubkey.begin(), pubkey.end()};
220 assert(CPubKey::ValidSize(vch_pubkey));
221 assert(!CPubKey::ValidSize({pubkey.begin(), pubkey.begin() + pubkey.size() - 1}));
222
223 const CPubKey pubkey_ctor_1{vch_pubkey};
224 assert(pubkey == pubkey_ctor_1);
225
226 const CPubKey pubkey_ctor_2{vch_pubkey.begin(), vch_pubkey.end()};
227 assert(pubkey == pubkey_ctor_2);
228
229 CPubKey pubkey_set;
230 pubkey_set.Set(vch_pubkey.begin(), vch_pubkey.end());
231 assert(pubkey == pubkey_set);
232 }
233
234 {
235 const CPubKey invalid_pubkey{};
236 assert(!invalid_pubkey.IsValid());
237 assert(!invalid_pubkey.IsFullyValid());
238 assert(!(pubkey == invalid_pubkey));
239 assert(pubkey != invalid_pubkey);
240 assert(pubkey < invalid_pubkey);
241 }
242
243 {
244 // Cover CPubKey's operator[](unsigned int pos)
245 unsigned int sum = 0;
246 for (size_t i = 0; i < pubkey.size(); ++i) {
247 sum += pubkey[i];
248 }
249 assert(std::accumulate(pubkey.begin(), pubkey.end(), 0U) == sum);
250 }
251
252 {
253 CPubKey decompressed_pubkey = pubkey;
254 assert(decompressed_pubkey.IsCompressed());
255
256 const bool ok = decompressed_pubkey.Decompress();
257 assert(ok);
258 assert(!decompressed_pubkey.IsCompressed());
259 assert(decompressed_pubkey.size() == 65);
260 }
261
262 {
263 std::vector<unsigned char> vch_sig;
264 const bool ok = key.Sign(random_uint256, vch_sig, false);
265 assert(ok);
266 assert(pubkey.Verify(random_uint256, vch_sig));
267 assert(CPubKey::CheckLowS(vch_sig));
268
269 const std::vector<unsigned char> vch_invalid_sig{vch_sig.begin(), vch_sig.begin() + vch_sig.size() - 1};
270 assert(!pubkey.Verify(random_uint256, vch_invalid_sig));
271 assert(!CPubKey::CheckLowS(vch_invalid_sig));
272 }
273
274 {
275 std::vector<unsigned char> vch_compact_sig;
276 const bool ok_sign_compact = key.SignCompact(random_uint256, vch_compact_sig);
277 assert(ok_sign_compact);
278
279 CPubKey recover_pubkey;
280 const bool ok_recover_compact = recover_pubkey.RecoverCompact(random_uint256, vch_compact_sig);
281 assert(ok_recover_compact);
282 assert(recover_pubkey == pubkey);
283 }
284
285 {
286 CPubKey child_pubkey;
287 ChainCode child_chaincode;
288 const bool ok = pubkey.Derive(child_pubkey, child_chaincode, 0, random_uint256);
289 assert(ok);
290 assert(child_pubkey != pubkey);
291 assert(child_pubkey.IsCompressed());
292 assert(child_pubkey.IsFullyValid());
293 assert(child_pubkey.IsValid());
294 assert(child_pubkey.size() == 33);
295 assert(child_chaincode != random_uint256);
296 }
297
298 const CPrivKey priv_key = key.GetPrivKey();
299
300 {
301 for (const bool skip_check : {true, false}) {
302 CKey loaded_key;
303 const bool ok = loaded_key.Load(priv_key, pubkey, skip_check);
304 assert(ok);
305 assert(key == loaded_key);
306 }
307 }
308}
void SelectParams(const std::string &network)
Sets the params returned by Params() to those for the given chain name.
static const std::string REGTEST
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:205
An encapsulated private key.
Definition: key.h:27
const unsigned char * begin() const
Definition: key.h:89
bool Negate()
Negate private key.
Definition: key.cpp:168
unsigned int size() const
Simple read-only vector-like interface.
Definition: key.h:87
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:93
bool Sign(const uint256 &hash, std::vector< unsigned char > &vchSig, bool grind=true, uint32_t test_case=0) const
Create a DER-serialized signature.
Definition: key.cpp:213
CPrivKey GetPrivKey() const
Convert the private key to a CPrivKey (serialized OpenSSL private key data).
Definition: key.cpp:174
const unsigned char * end() const
Definition: key.h:90
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:96
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:187
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:73
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
Definition: key.cpp:235
bool Load(const CPrivKey &privkey, const CPubKey &vchPubKey, bool fSkipCheck)
Load private key and check that public key matches.
Definition: key.cpp:282
bool Derive(CKey &keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode &cc) const
Derive BIP32 child key.
Definition: key.cpp:294
bool SignCompact(const uint256 &hash, std::vector< unsigned char > &vchSig) const
Create a compact signature (65 bytes), which allows reconstructing the used public key.
Definition: key.cpp:249
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:23
An encapsulated public key.
Definition: pubkey.h:33
const unsigned char * data() const
Definition: pubkey.h:112
bool RecoverCompact(const uint256 &hash, const std::vector< unsigned char > &vchSig)
Recover a public key from a compact signature.
Definition: pubkey.cpp:271
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:194
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:160
static bool CheckLowS(const std::vector< unsigned char > &vchSig)
Check whether a signature is normalized (lower-S).
Definition: pubkey.cpp:363
bool IsValid() const
Definition: pubkey.h:185
bool Decompress()
Turn this public key into an uncompressed public key.
Definition: pubkey.cpp:300
const unsigned char * end() const
Definition: pubkey.h:114
bool Verify(const uint256 &hash, const std::vector< unsigned char > &vchSig) const
Verify a DER signature (~72 bytes).
Definition: pubkey.cpp:253
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
Definition: pubkey.cpp:292
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:111
const unsigned char * begin() const
Definition: pubkey.h:113
static bool ValidSize(const std::vector< unsigned char > &vch)
Definition: pubkey.h:76
void Serialize(Stream &s) const
Implement serialization, as if this was a byte vector.
Definition: pubkey.h:135
void Unserialize(Stream &s)
Definition: pubkey.h:142
uint256 GetHash() const
Get the 256-bit hash of this public key.
Definition: pubkey.h:166
bool Derive(CPubKey &pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode &cc) const
Derive BIP32 child pubkey.
Definition: pubkey.cpp:315
void Set(const T pbegin, const T pend)
Initialize a public key using begin/end iterators to byte data.
Definition: pubkey.h:88
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:406
bool IsPushOnly(const_iterator pc) const
Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical).
Definition: script.cpp:236
bool IsPayToScriptHash() const
Definition: script.cpp:201
bool IsUnspendable() const
Returns whether the script is guaranteed to fail at execution, regardless of the initial stack.
Definition: script.h:544
bool IsPayToWitnessScriptHash() const
Definition: script.cpp:210
bool HasValidOps() const
Check if the script contains valid OP_CODES.
Definition: script.cpp:270
Users of this module must hold an ECCVerifyHandle.
Definition: pubkey.h:316
Fillable signing provider that keeps keys in an address->secret map.
virtual bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey)
virtual bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const override
virtual bool GetKey(const CKeyID &address, CKey &keyOut) const override
virtual std::set< CKeyID > GetKeys() const
virtual bool AddKey(const CKey &key)
virtual bool HaveKey(const CKeyID &address) const override
virtual bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const
bool IsNull() const
Definition: uint256.h:31
size_type size() const
Definition: prevector.h:282
256-bit opaque blob.
Definition: uint256.h:124
volatile double sum
Definition: examples.cpp:10
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
Definition: hash.h:75
void ECC_Start()
Initialize the elliptic curve support.
Definition: key.cpp:370
std::vector< unsigned char, secure_allocator< unsigned char > > CPrivKey
CPrivKey is a serialized private key, with all parameters included (SIZE bytes)
Definition: key.h:23
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:196
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:256
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:178
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg)
Definition: key_io.cpp:261
CTxDestination GetDestinationForKey(const CPubKey &key, OutputType type)
Get a destination of the requested type (if possible) to the specified key.
Definition: outputtype.cpp:49
std::vector< CTxDestination > GetAllDestinationsForKey(const CPubKey &key)
Get all destinations (potentially) supported by the wallet for the given key.
Definition: outputtype.cpp:69
OutputType
Definition: outputtype.h:18
bool IsStandard(const CScript &scriptPubKey, TxoutType &whichType)
Definition: policy.cpp:58
CPubKey HexToPubKey(const std::string &hex_in)
Definition: util.cpp:192
CPubKey AddrToPubKey(const FillableSigningProvider &keystore, const std::string &addr_in)
Definition: util.cpp:205
@ SER_NETWORK
Definition: serialize.h:138
bool IsSegWitOutput(const SigningProvider &provider, const CScript &script)
Check whether a scriptPubKey is known to be segwit.
Definition: sign.cpp:600
bool IsSolvable(const SigningProvider &provider, const CScript &script)
Definition: sign.cpp:581
CKeyID GetKeyForDestination(const SigningProvider &store, const CTxDestination &dest)
Return the CKeyID of the key involved in a script (if there is a unique one).
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char > > &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
Definition: standard.cpp:144
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
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:332
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:310
TxoutType
Definition: standard.h:59
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:157
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
void initialize_key()
Definition: key.cpp:28
FUZZ_TARGET_INIT(key, initialize_key)
Definition: key.cpp:35
assert(!tx.IsCoinBase())
static const int INIT_PROTO_VERSION
initial proto version, to be increased after version/verack negotiation
Definition: version.h:15