/tmp/bitcoin/src/pubkey.h
Line | Count | Source |
1 | | // Copyright (c) 2009-2010 Satoshi Nakamoto |
2 | | // Copyright (c) 2009-present The Bitcoin Core developers |
3 | | // Copyright (c) 2017 The Zcash developers |
4 | | // Distributed under the MIT software license, see the accompanying |
5 | | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
6 | | |
7 | | #ifndef BITCOIN_PUBKEY_H |
8 | | #define BITCOIN_PUBKEY_H |
9 | | |
10 | | #include <hash.h> |
11 | | #include <serialize.h> |
12 | | #include <span.h> |
13 | | #include <uint256.h> |
14 | | |
15 | | #include <array> |
16 | | #include <cassert> |
17 | | #include <cstring> |
18 | | #include <optional> |
19 | | #include <span> |
20 | | #include <vector> |
21 | | |
22 | | inline constexpr unsigned int BIP32_EXTKEY_SIZE = 74; |
23 | | inline constexpr unsigned int BIP32_EXTKEY_WITH_VERSION_SIZE = 78; |
24 | | |
25 | | using KeyFingerprint = std::array<unsigned char, 4>; |
26 | | |
27 | | /** A reference to a CKey: the Hash160 of its serialized public key */ |
28 | | class CKeyID : public uint160 |
29 | | { |
30 | | public: |
31 | 519k | CKeyID() : uint160() {} |
32 | 6.39M | explicit CKeyID(const uint160& in) : uint160(in) {} |
33 | | KeyFingerprint fingerprint() const |
34 | 2.68M | { |
35 | 2.68M | KeyFingerprint ret; |
36 | 2.68M | std::copy_n(begin(), ret.size(), ret.begin()); |
37 | 2.68M | return ret; |
38 | 2.68M | } |
39 | | }; |
40 | | |
41 | | /** An encapsulated public key. */ |
42 | | class CPubKey |
43 | | { |
44 | | public: |
45 | | /** |
46 | | * secp256k1: |
47 | | */ |
48 | | static constexpr unsigned int SIZE = 65; |
49 | | static constexpr unsigned int COMPRESSED_SIZE = 33; |
50 | | static constexpr unsigned int SIGNATURE_SIZE = 72; |
51 | | static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65; |
52 | | /** |
53 | | * see www.keylength.com |
54 | | * script supports up to 75 for single byte push |
55 | | */ |
56 | | static_assert( |
57 | | SIZE >= COMPRESSED_SIZE, |
58 | | "COMPRESSED_SIZE is larger than SIZE"); |
59 | | |
60 | | private: |
61 | | |
62 | | /** |
63 | | * Just store the serialized data. |
64 | | * Its length can very cheaply be computed from the first byte. |
65 | | */ |
66 | | unsigned char vch[SIZE]; |
67 | | |
68 | | //! Compute the length of a pubkey with a given first byte. |
69 | | unsigned int static GetLen(unsigned char chHeader) |
70 | 26.5M | { |
71 | 26.5M | if (chHeader == 2 || chHeader == 3) |
72 | 26.4M | return COMPRESSED_SIZE; |
73 | 125k | if (chHeader == 4 || chHeader == 6 || chHeader == 7) |
74 | 59.6k | return SIZE; |
75 | 65.3k | return 0; |
76 | 125k | } |
77 | | |
78 | | //! Set this key data to be invalid |
79 | | void Invalidate() |
80 | 3.20M | { |
81 | 3.20M | vch[0] = 0xFF; |
82 | 3.20M | } |
83 | | |
84 | | public: |
85 | | |
86 | 28.9k | bool static ValidSize(const std::vector<unsigned char> &vch) { |
87 | 28.9k | return vch.size() > 0 && GetLen(vch[0]) == vch.size(); |
88 | 28.9k | } |
89 | | |
90 | | //! Construct an invalid public key. |
91 | | CPubKey() |
92 | 3.17M | { |
93 | 3.17M | Invalidate(); |
94 | 3.17M | } |
95 | | |
96 | | //! Initialize a public key using begin/end iterators to byte data. |
97 | | template <typename T> |
98 | | void Set(const T pbegin, const T pend) |
99 | 2.04M | { |
100 | 2.04M | int len = pend == pbegin ? 0 : GetLen(pbegin[0]); |
101 | 2.04M | if (len && len == (pend - pbegin)) |
102 | 2.01M | memcpy(vch, (unsigned char*)&pbegin[0], len); |
103 | 24.0k | else |
104 | 24.0k | Invalidate(); |
105 | 2.04M | } void CPubKey::Set<__gnu_cxx::__normal_iterator<unsigned char const*, std::span<unsigned char const, 18446744073709551615ul>::__iter_tag>>(__gnu_cxx::__normal_iterator<unsigned char const*, std::span<unsigned char const, 18446744073709551615ul>::__iter_tag>, __gnu_cxx::__normal_iterator<unsigned char const*, std::span<unsigned char const, 18446744073709551615ul>::__iter_tag>) Line | Count | Source | 99 | 426k | { | 100 | 426k | int len = pend == pbegin ? 0 : GetLen(pbegin[0]); | 101 | 426k | if (len && len == (pend - pbegin)) | 102 | 402k | memcpy(vch, (unsigned char*)&pbegin[0], len); | 103 | 24.0k | else | 104 | 24.0k | Invalidate(); | 105 | 426k | } |
void CPubKey::Set<unsigned char*>(unsigned char*, unsigned char*) Line | Count | Source | 99 | 1.59M | { | 100 | 1.59M | int len = pend == pbegin ? 0 : GetLen(pbegin[0]); | 101 | 1.59M | if (len && len == (pend - pbegin)) | 102 | 1.59M | memcpy(vch, (unsigned char*)&pbegin[0], len); | 103 | 8 | else | 104 | 8 | Invalidate(); | 105 | 1.59M | } |
void CPubKey::Set<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char>>>>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char>>>, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char>>>) Line | Count | Source | 99 | 2.72k | { | 100 | 2.72k | int len = pend == pbegin ? 0 : GetLen(pbegin[0]); | 101 | 2.72k | if (len && len == (pend - pbegin)) | 102 | 2.72k | memcpy(vch, (unsigned char*)&pbegin[0], len); | 103 | 4 | else | 104 | 4 | Invalidate(); | 105 | 2.72k | } |
void CPubKey::Set<__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char>>>>(__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char>>>, __gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char>>>) Line | Count | Source | 99 | 931 | { | 100 | 931 | int len = pend == pbegin ? 0 : GetLen(pbegin[0]); | 101 | 931 | if (len && len == (pend - pbegin)) | 102 | 931 | memcpy(vch, (unsigned char*)&pbegin[0], len); | 103 | 0 | else | 104 | 0 | Invalidate(); | 105 | 931 | } |
void CPubKey::Set<unsigned char const*>(unsigned char const*, unsigned char const*) Line | Count | Source | 99 | 13.2k | { | 100 | 13.2k | int len = pend == pbegin ? 0 : GetLen(pbegin[0]); | 101 | 13.2k | if (len && len == (pend - pbegin)) | 102 | 13.2k | memcpy(vch, (unsigned char*)&pbegin[0], len); | 103 | 0 | else | 104 | 0 | Invalidate(); | 105 | 13.2k | } |
|
106 | | |
107 | | //! Construct a public key using begin/end iterators to byte data. |
108 | | template <typename T> |
109 | | CPubKey(const T pbegin, const T pend) |
110 | 4.57k | { |
111 | 4.57k | Set(pbegin, pend); |
112 | 4.57k | } CPubKey::CPubKey<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char>>>>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char>>>, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char>>>) Line | Count | Source | 110 | 2.72k | { | 111 | 2.72k | Set(pbegin, pend); | 112 | 2.72k | } |
CPubKey::CPubKey<__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char>>>>(__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char>>>, __gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char>>>) Line | Count | Source | 110 | 931 | { | 111 | 931 | Set(pbegin, pend); | 112 | 931 | } |
CPubKey::CPubKey<unsigned char*>(unsigned char*, unsigned char*) Line | Count | Source | 110 | 922 | { | 111 | 922 | Set(pbegin, pend); | 112 | 922 | } |
|
113 | | |
114 | | //! Construct a public key from a byte vector. |
115 | | explicit CPubKey(std::span<const uint8_t> _vch) |
116 | 426k | { |
117 | 426k | Set(_vch.begin(), _vch.end()); |
118 | 426k | } |
119 | | |
120 | | //! Simple read-only vector-like interface to the pubkey data. |
121 | 24.4M | unsigned int size() const { return GetLen(vch[0]); } |
122 | 2.35M | const unsigned char* data() const { return vch; } |
123 | 2.03M | const unsigned char* begin() const { return vch; } |
124 | 163k | const unsigned char* end() const { return vch + size(); } |
125 | 40.5k | const unsigned char& operator[](unsigned int pos) const { return vch[pos]; } |
126 | | |
127 | | //! Comparator implementation. |
128 | | friend bool operator==(const CPubKey& a, const CPubKey& b) |
129 | 74.0k | { |
130 | 74.0k | return a.vch[0] == b.vch[0] && |
131 | 74.0k | memcmp(a.vch, b.vch, a.size()) == 0; |
132 | 74.0k | } |
133 | | friend bool operator<(const CPubKey& a, const CPubKey& b) |
134 | 13.0M | { |
135 | 13.0M | return a.vch[0] < b.vch[0] || |
136 | 13.0M | (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0); |
137 | 13.0M | } |
138 | | friend bool operator>(const CPubKey& a, const CPubKey& b) |
139 | 1.28k | { |
140 | 1.28k | return a.vch[0] > b.vch[0] || |
141 | 1.28k | (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) > 0); |
142 | 1.28k | } |
143 | | |
144 | | //! Implement serialization, as if this was a byte vector. |
145 | | template <typename Stream> |
146 | | void Serialize(Stream& s) const |
147 | 6.75k | { |
148 | 6.75k | unsigned int len = size(); |
149 | 6.75k | ::WriteCompactSize(s, len); |
150 | 6.75k | s << std::span{vch, len}; |
151 | 6.75k | } void CPubKey::Serialize<DataStream>(DataStream&) const Line | Count | Source | 147 | 5.88k | { | 148 | 5.88k | unsigned int len = size(); | 149 | 5.88k | ::WriteCompactSize(s, len); | 150 | 5.88k | s << std::span{vch, len}; | 151 | 5.88k | } |
void CPubKey::Serialize<HashWriter>(HashWriter&) const Line | Count | Source | 147 | 870 | { | 148 | 870 | unsigned int len = size(); | 149 | 870 | ::WriteCompactSize(s, len); | 150 | 870 | s << std::span{vch, len}; | 151 | 870 | } |
|
152 | | template <typename Stream> |
153 | | void Unserialize(Stream& s) |
154 | 3.85k | { |
155 | 3.85k | const unsigned int len(::ReadCompactSize(s)); |
156 | 3.85k | if (len <= SIZE) { |
157 | 3.85k | s >> std::span{vch, len}; |
158 | 3.85k | if (len != size()) { |
159 | 6 | Invalidate(); |
160 | 6 | } |
161 | 3.85k | } else { |
162 | | // invalid pubkey, skip available data |
163 | 0 | s.ignore(len); |
164 | 0 | Invalidate(); |
165 | 0 | } |
166 | 3.85k | } |
167 | | |
168 | | //! Get the KeyID of this public key (hash of its serialization) |
169 | | CKeyID GetID() const |
170 | 6.02M | { |
171 | 6.02M | return CKeyID(Hash160(std::span{vch}.first(size()))); |
172 | 6.02M | } |
173 | | |
174 | | //! Get the 256-bit hash of this public key. |
175 | | uint256 GetHash() const |
176 | 4.34k | { |
177 | 4.34k | return Hash(std::span{vch}.first(size())); |
178 | 4.34k | } |
179 | | |
180 | | /* |
181 | | * Check syntactic correctness. |
182 | | * |
183 | | * When setting a pubkey (Set()) or deserializing fails (its header bytes |
184 | | * don't match the length of the data), the size is set to 0. Thus, |
185 | | * by checking size, one can observe whether Set() or deserialization has |
186 | | * failed. |
187 | | * |
188 | | * This does not check for more than that. In particular, it does not verify |
189 | | * that the coordinates correspond to a point on the curve (see IsFullyValid() |
190 | | * for that instead). |
191 | | * |
192 | | * Note that this is consensus critical as CheckECDSASignature() calls it! |
193 | | */ |
194 | | bool IsValid() const |
195 | 1.54M | { |
196 | 1.54M | return size() > 0; |
197 | 1.54M | } |
198 | | |
199 | | /** Check if a public key is a syntactically valid compressed or uncompressed key. */ |
200 | | bool IsValidNonHybrid() const noexcept |
201 | 277k | { |
202 | 277k | return size() > 0 && (vch[0] == 0x02 || vch[0] == 0x03 || vch[0] == 0x04); |
203 | 277k | } |
204 | | |
205 | | //! fully validate whether this is a valid public key (more expensive than IsValid()) |
206 | | bool IsFullyValid() const; |
207 | | |
208 | | //! Check whether this is a compressed public key. |
209 | | bool IsCompressed() const |
210 | 204k | { |
211 | 204k | return size() == COMPRESSED_SIZE; |
212 | 204k | } |
213 | | |
214 | | /** |
215 | | * Verify a DER signature (~72 bytes). |
216 | | * If this public key is not fully valid, the return value will be false. |
217 | | */ |
218 | | bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const; |
219 | | |
220 | | /** |
221 | | * Check whether a signature is normalized (lower-S). |
222 | | */ |
223 | | static bool CheckLowS(const std::vector<unsigned char>& vchSig); |
224 | | |
225 | | //! Recover a public key from a compact signature. |
226 | | bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig); |
227 | | |
228 | | //! Turn this public key into an uncompressed public key. |
229 | | bool Decompress(); |
230 | | |
231 | | //! Derive BIP32 child pubkey. |
232 | | [[nodiscard]] bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc, uint256* bip32_tweak_out = nullptr) const; |
233 | | }; |
234 | | |
235 | | class XOnlyPubKey |
236 | | { |
237 | | private: |
238 | | uint256 m_keydata; |
239 | | |
240 | | public: |
241 | | /** Nothing Up My Sleeve point H |
242 | | * Used as an internal key for provably disabling the key path spend |
243 | | * see BIP341 for more details */ |
244 | | static const XOnlyPubKey NUMS_H; |
245 | | |
246 | | /** Construct an empty x-only pubkey. */ |
247 | 1.50M | XOnlyPubKey() = default; |
248 | | |
249 | | XOnlyPubKey(const XOnlyPubKey&) = default; |
250 | | XOnlyPubKey& operator=(const XOnlyPubKey&) = default; |
251 | | |
252 | | /** Determine if this pubkey is fully valid. This is true for approximately 50% of all |
253 | | * possible 32-byte arrays. If false, VerifySchnorr, CheckTapTweak and CreateTapTweak |
254 | | * will always fail. */ |
255 | | bool IsFullyValid() const; |
256 | | |
257 | | /** Test whether this is the 0 key (the result of default construction). This implies |
258 | | * !IsFullyValid(). */ |
259 | 57.6k | bool IsNull() const { return m_keydata.IsNull(); } |
260 | | |
261 | | /** Construct an x-only pubkey from exactly 32 bytes. */ |
262 | 2.06M | constexpr explicit XOnlyPubKey(std::span<const unsigned char> bytes) : m_keydata{bytes} {} |
263 | | |
264 | | /** Construct an x-only pubkey from a normal pubkey. */ |
265 | 1.42M | explicit XOnlyPubKey(const CPubKey& pubkey) : XOnlyPubKey(std::span{pubkey}.subspan(1, 32)) {} |
266 | | |
267 | | /** Verify a Schnorr signature against this public key. |
268 | | * |
269 | | * sigbytes must be exactly 64 bytes. |
270 | | */ |
271 | | bool VerifySchnorr(const uint256& msg, std::span<const unsigned char> sigbytes) const; |
272 | | |
273 | | /** Compute the Taproot tweak as specified in BIP341, with *this as internal |
274 | | * key: |
275 | | * - if merkle_root == nullptr: H_TapTweak(xonly_pubkey) |
276 | | * - otherwise: H_TapTweak(xonly_pubkey || *merkle_root) |
277 | | * |
278 | | * Note that the behavior of this function with merkle_root != nullptr is |
279 | | * consensus critical. |
280 | | */ |
281 | | uint256 ComputeTapTweakHash(const uint256* merkle_root) const; |
282 | | |
283 | | /** Verify that this is a Taproot tweaked output point, against a specified internal key, |
284 | | * Merkle root, and parity. */ |
285 | | bool CheckTapTweak(const XOnlyPubKey& internal, const uint256& merkle_root, bool parity) const; |
286 | | |
287 | | /** Construct a Taproot tweaked output point with this point as internal key. */ |
288 | | std::optional<std::pair<XOnlyPubKey, bool>> CreateTapTweak(const uint256* merkle_root) const; |
289 | | |
290 | | /** Returns a list of CKeyIDs for the CPubKeys that could have been used to create this XOnlyPubKey. |
291 | | * As the CKeyID is the Hash160(full pubkey), the produced CKeyIDs are for the versions of this |
292 | | * XOnlyPubKey with 0x02 and 0x03 prefixes. |
293 | | * This is needed for key lookups since keys are indexed by CKeyID. |
294 | | */ |
295 | | std::vector<CKeyID> GetKeyIDs() const; |
296 | | /** Returns this XOnlyPubKey with 0x02 and 0x03 prefixes */ |
297 | | std::vector<CPubKey> GetCPubKeys() const; |
298 | | |
299 | | CPubKey GetEvenCorrespondingCPubKey() const; |
300 | | |
301 | 0 | const unsigned char& operator[](int pos) const { return *(m_keydata.begin() + pos); } |
302 | 294k | static constexpr size_t size() { return decltype(m_keydata)::size(); } |
303 | 561k | const unsigned char* data() const { return m_keydata.begin(); } |
304 | 1.36M | const unsigned char* begin() const { return m_keydata.begin(); } |
305 | 1.36M | const unsigned char* end() const { return m_keydata.end(); } |
306 | 7 | unsigned char* data() { return m_keydata.begin(); } |
307 | 286k | unsigned char* begin() { return m_keydata.begin(); } |
308 | 6 | unsigned char* end() { return m_keydata.end(); } |
309 | 19.8k | bool operator==(const XOnlyPubKey& other) const { return m_keydata == other.m_keydata; } |
310 | 2.96M | bool operator<(const XOnlyPubKey& other) const { return m_keydata < other.m_keydata; } |
311 | | |
312 | | //! Implement serialization without length prefixes since it is a fixed length |
313 | 20.4k | SERIALIZE_METHODS(XOnlyPubKey, obj) { READWRITE(obj.m_keydata); }void XOnlyPubKey::SerializationOps<SpanReader, XOnlyPubKey, ActionUnserialize>(XOnlyPubKey&, SpanReader&, ActionUnserialize) Line | Count | Source | 313 | 8.33k | SERIALIZE_METHODS(XOnlyPubKey, obj) { READWRITE(obj.m_keydata); } |
Unexecuted instantiation: void XOnlyPubKey::SerializationOps<DataStream, XOnlyPubKey, ActionUnserialize>(XOnlyPubKey&, DataStream&, ActionUnserialize) void XOnlyPubKey::SerializationOps<SizeComputer, XOnlyPubKey const, ActionSerialize>(XOnlyPubKey const&, SizeComputer&, ActionSerialize) Line | Count | Source | 313 | 6.03k | SERIALIZE_METHODS(XOnlyPubKey, obj) { READWRITE(obj.m_keydata); } |
void XOnlyPubKey::SerializationOps<DataStream, XOnlyPubKey const, ActionSerialize>(XOnlyPubKey const&, DataStream&, ActionSerialize) Line | Count | Source | 313 | 6.03k | SERIALIZE_METHODS(XOnlyPubKey, obj) { READWRITE(obj.m_keydata); } |
|
314 | | }; |
315 | | |
316 | | /** An ElligatorSwift-encoded public key. */ |
317 | | struct EllSwiftPubKey |
318 | | { |
319 | | private: |
320 | | static constexpr size_t SIZE = 64; |
321 | | std::array<std::byte, SIZE> m_pubkey; |
322 | | |
323 | | public: |
324 | | /** Default constructor creates all-zero pubkey (which is valid). */ |
325 | | EllSwiftPubKey() noexcept = default; |
326 | | |
327 | | /** Construct a new ellswift public key from a given serialization. */ |
328 | | EllSwiftPubKey(std::span<const std::byte> ellswift) noexcept; |
329 | | |
330 | | /** Decode to normal compressed CPubKey (for debugging purposes). */ |
331 | | CPubKey Decode() const; |
332 | | |
333 | | // Read-only access for serialization. |
334 | 951 | const std::byte* data() const { return m_pubkey.data(); } |
335 | 2.22k | static constexpr size_t size() { return SIZE; } |
336 | 276 | auto begin() const { return m_pubkey.cbegin(); } |
337 | 276 | auto end() const { return m_pubkey.cend(); } |
338 | | |
339 | | bool friend operator==(const EllSwiftPubKey& a, const EllSwiftPubKey& b) |
340 | 98 | { |
341 | 98 | return a.m_pubkey == b.m_pubkey; |
342 | 98 | } |
343 | | }; |
344 | | |
345 | | struct CExtPubKey { |
346 | | unsigned char version[4]; |
347 | | unsigned char nDepth; |
348 | | KeyFingerprint fingerprint; |
349 | | unsigned int nChild; |
350 | | ChainCode chaincode; |
351 | | CPubKey pubkey; |
352 | | |
353 | | friend bool operator==(const CExtPubKey &a, const CExtPubKey &b) |
354 | 51 | { |
355 | 51 | return a.nDepth == b.nDepth && |
356 | 51 | a.fingerprint == b.fingerprint && |
357 | 51 | a.nChild == b.nChild && |
358 | 51 | a.chaincode == b.chaincode && |
359 | 51 | a.pubkey == b.pubkey; |
360 | 51 | } |
361 | | |
362 | | friend bool operator<(const CExtPubKey &a, const CExtPubKey &b) |
363 | 1.40k | { |
364 | 1.40k | if (a.pubkey < b.pubkey) { |
365 | 112 | return true; |
366 | 1.28k | } else if (a.pubkey > b.pubkey) { |
367 | 45 | return false; |
368 | 45 | } |
369 | 1.24k | return a.chaincode < b.chaincode; |
370 | 1.40k | } |
371 | | |
372 | | KeyFingerprint id_key_fingerprint() const |
373 | 1.52M | { |
374 | 1.52M | return pubkey.GetID().fingerprint(); |
375 | 1.52M | } |
376 | | |
377 | | //! BIP32 serialization without the version bytes (BIP32_EXTKEY_SIZE bytes) |
378 | | template <typename Stream> |
379 | | void Serialize(Stream& s) const |
380 | 155k | { |
381 | 155k | assert(pubkey.size() == CPubKey::COMPRESSED_SIZE); |
382 | 155k | s << nDepth << fingerprint << Using<BigEndianFormatter<4>>(nChild) << chaincode << std::span{pubkey.data(), CPubKey::COMPRESSED_SIZE}; |
383 | 155k | } void CExtPubKey::Serialize<DataStream>(DataStream&) const Line | Count | Source | 380 | 22 | { | 381 | 22 | assert(pubkey.size() == CPubKey::COMPRESSED_SIZE); | 382 | 22 | s << nDepth << fingerprint << Using<BigEndianFormatter<4>>(nChild) << chaincode << std::span{pubkey.data(), CPubKey::COMPRESSED_SIZE}; | 383 | 22 | } |
void CExtPubKey::Serialize<SizeComputer>(SizeComputer&) const Line | Count | Source | 380 | 4 | { | 381 | 4 | assert(pubkey.size() == CPubKey::COMPRESSED_SIZE); | 382 | 4 | s << nDepth << fingerprint << Using<BigEndianFormatter<4>>(nChild) << chaincode << std::span{pubkey.data(), CPubKey::COMPRESSED_SIZE}; | 383 | 4 | } |
void CExtPubKey::Serialize<VectorWriter>(VectorWriter&) const Line | Count | Source | 380 | 155k | { | 381 | 155k | assert(pubkey.size() == CPubKey::COMPRESSED_SIZE); | 382 | 155k | s << nDepth << fingerprint << Using<BigEndianFormatter<4>>(nChild) << chaincode << std::span{pubkey.data(), CPubKey::COMPRESSED_SIZE}; | 383 | 155k | } |
|
384 | | template <typename Stream> |
385 | | void Unserialize(Stream& s) |
386 | 14.3k | { |
387 | 14.3k | std::array<unsigned char, CPubKey::COMPRESSED_SIZE> ser_pubkey; |
388 | 14.3k | s >> nDepth >> fingerprint >> Using<BigEndianFormatter<4>>(nChild) >> chaincode >> ser_pubkey; |
389 | 14.3k | pubkey.Set(ser_pubkey.begin(), ser_pubkey.end()); |
390 | 14.3k | if ((nDepth == 0 && (nChild != 0 || fingerprint != KeyFingerprint{})) || !pubkey.IsFullyValid()) pubkey = CPubKey(); |
391 | 14.3k | } void CExtPubKey::Unserialize<DataStream>(DataStream&) Line | Count | Source | 386 | 5.90k | { | 387 | 5.90k | std::array<unsigned char, CPubKey::COMPRESSED_SIZE> ser_pubkey; | 388 | 5.90k | s >> nDepth >> fingerprint >> Using<BigEndianFormatter<4>>(nChild) >> chaincode >> ser_pubkey; | 389 | 5.90k | pubkey.Set(ser_pubkey.begin(), ser_pubkey.end()); | 390 | 5.90k | if ((nDepth == 0 && (nChild != 0 || fingerprint != KeyFingerprint{})) || !pubkey.IsFullyValid()) pubkey = CPubKey(); | 391 | 5.90k | } |
void CExtPubKey::Unserialize<SpanReader>(SpanReader&) Line | Count | Source | 386 | 8.44k | { | 387 | 8.44k | std::array<unsigned char, CPubKey::COMPRESSED_SIZE> ser_pubkey; | 388 | 8.44k | s >> nDepth >> fingerprint >> Using<BigEndianFormatter<4>>(nChild) >> chaincode >> ser_pubkey; | 389 | 8.44k | pubkey.Set(ser_pubkey.begin(), ser_pubkey.end()); | 390 | 8.44k | if ((nDepth == 0 && (nChild != 0 || fingerprint != KeyFingerprint{})) || !pubkey.IsFullyValid()) pubkey = CPubKey(); | 391 | 8.44k | } |
|
392 | | [[nodiscard]] bool Derive(CExtPubKey& out, unsigned int nChild, uint256* bip32_tweak_out = nullptr) const; |
393 | | }; |
394 | | |
395 | | #endif // BITCOIN_PUBKEY_H |