Branch data Line data Source code
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 [ + + + + : 541122 : CKeyID() : uint160() {}
+ + + ]
32 [ + + ]: 6381102 : explicit CKeyID(const uint160& in) : uint160(in) {}
[ + - + - ]
33 : 2685497 : KeyFingerprint fingerprint() const
34 : : {
35 : 2685497 : KeyFingerprint ret;
36 : 2685497 : std::copy_n(begin(), ret.size(), ret.begin());
37 : 2685497 : return ret;
38 : : }
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 : 25250392 : unsigned int static GetLen(unsigned char chHeader)
70 : : {
71 [ + + ]: 25250392 : if (chHeader == 2 || chHeader == 3)
72 : : return COMPRESSED_SIZE;
73 [ + + + + ]: 99653 : if (chHeader == 4 || chHeader == 6 || chHeader == 7)
74 : 36180 : return SIZE;
75 : : return 0;
76 : : }
77 : :
78 : : //! Set this key data to be invalid
79 : 3186960 : void Invalidate()
80 : : {
81 : 3186960 : vch[0] = 0xFF;
82 : 22224 : }
83 : :
84 : : public:
85 : :
86 : 28727 : bool static ValidSize(const std::vector<unsigned char> &vch) {
87 [ - + + + : 28727 : return vch.size() > 0 && GetLen(vch[0]) == vch.size();
+ + ]
88 : : }
89 : :
90 : : //! Construct an invalid public key.
91 : 3164736 : CPubKey()
92 : 3030737 : {
93 [ + + + + ]: 3054132 : Invalidate();
[ + - + -
+ - + - +
- ][ + - +
- + - + -
+ - + + +
- + + ][ +
- + - - -
- - - - ]
[ + + + +
+ + + - +
- + + - +
+ + ]
94 : : }
95 : :
96 : : //! Initialize a public key using begin/end iterators to byte data.
97 : : template <typename T>
98 [ + + ]: 2015984 : void Set(const T pbegin, const T pend)
99 : : {
100 [ + + ]: 2015984 : int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
101 [ + + + + ]: 2013840 : if (len && len == (pend - pbegin))
102 : 1993766 : memcpy(vch, (unsigned char*)&pbegin[0], len);
103 : : else
104 : 22218 : Invalidate();
105 : 2015984 : }
106 : :
107 : : //! Construct a public key using begin/end iterators to byte data.
108 : : template <typename T>
109 : 4712 : CPubKey(const T pbegin, const T pend)
110 : : {
111 : 4621 : Set(pbegin, pend);
112 : : }
113 : :
114 : : //! Construct a public key from a byte vector.
115 : 402727 : explicit CPubKey(std::span<const uint8_t> _vch)
116 : 402727 : {
117 : 402727 : Set(_vch.begin(), _vch.end());
118 : 402727 : }
119 : :
120 : : //! Simple read-only vector-like interface to the pubkey data.
121 [ + + + + ]: 14384864 : unsigned int size() const { return GetLen(vch[0]); }
[ + - + -
+ - + - ]
[ + + - +
# # # # ]
[ + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - ][ # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
122 [ + - + - : 1808236 : const unsigned char* data() const { return vch; }
+ - + - ]
[ + - # # ]
[ + - + -
# # # # ]
[ + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - ][ # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
123 [ - + ]: 339506 : const unsigned char* begin() const { return vch; }
124 [ + - # # ]: 162795 : const unsigned char* end() const { return vch + size(); }
[ + - + - ]
125 [ + - ]: 13223 : const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
126 : :
127 : : //! Comparator implementation.
128 : 74869 : friend bool operator==(const CPubKey& a, const CPubKey& b)
129 : : {
130 [ + + ]: 74869 : return a.vch[0] == b.vch[0] &&
131 [ + + ]: 74435 : memcmp(a.vch, b.vch, a.size()) == 0;
132 : : }
133 : 13103504 : friend bool operator<(const CPubKey& a, const CPubKey& b)
134 : : {
135 [ + + + + ]: 13103504 : return a.vch[0] < b.vch[0] ||
136 [ + + ]: 12112107 : (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
137 : : }
138 : 1282 : friend bool operator>(const CPubKey& a, const CPubKey& b)
139 : : {
140 [ + + + - ]: 1282 : return a.vch[0] > b.vch[0] ||
141 [ + + ]: 1257 : (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) > 0);
142 : : }
143 : :
144 : : //! Implement serialization, as if this was a byte vector.
145 : : template <typename Stream>
146 : 6714 : void Serialize(Stream& s) const
147 : : {
148 : 6714 : unsigned int len = size();
149 : 6714 : ::WriteCompactSize(s, len);
150 : 6714 : s << std::span{vch, len};
151 : 6714 : }
152 : : template <typename Stream>
153 : 3714 : void Unserialize(Stream& s)
154 : : {
155 : 3714 : const unsigned int len(::ReadCompactSize(s));
156 [ + - ]: 3714 : if (len <= SIZE) {
157 : 3714 : s >> std::span{vch, len};
158 [ + + ]: 3714 : if (len != size()) {
159 : 6 : Invalidate();
160 : : }
161 : : } else {
162 : : // invalid pubkey, skip available data
163 : 0 : s.ignore(len);
164 : 0 : Invalidate();
165 : : }
166 : 3714 : }
167 : :
168 : : //! Get the KeyID of this public key (hash of its serialization)
169 : 6028907 : CKeyID GetID() const
170 : : {
171 : 6028907 : return CKeyID(Hash160(std::span{vch}.first(size())));
172 : : }
173 : :
174 : : //! Get the 256-bit hash of this public key.
175 : 4094 : uint256 GetHash() const
176 : : {
177 : 4094 : return Hash(std::span{vch}.first(size()));
178 : : }
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 : 1184217 : bool IsValid() const
195 : : {
196 [ + + + - ]: 1515390 : return size() > 0;
[ + + + -
+ + + - ]
[ + + + +
+ + ][ + +
+ - + + +
- ][ - + -
+ - + - +
- + ][ + +
+ + - + +
+ - + +
+ ]
197 : : }
198 : :
199 : : /** Check if a public key is a syntactically valid compressed or uncompressed key. */
200 : 277529 : bool IsValidNonHybrid() const noexcept
201 : : {
202 [ + + + + ]: 277529 : return size() > 0 && (vch[0] == 0x02 || vch[0] == 0x03 || vch[0] == 0x04);
203 : : }
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 : 203709 : bool IsCompressed() const
210 : : {
211 [ + + ][ + + : 203709 : return size() == COMPRESSED_SIZE;
+ + + + ]
[ + + + +
+ + + - +
- ]
[ - + + + ]
212 : : }
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 [ + - + + ]: 763830 : 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 [ + + + + ]: 118167 : bool IsNull() const { return m_keydata.IsNull(); }
[ + + - +
+ + + + -
+ + + +
+ ][ + + +
+ + + +
+ ]
260 : :
261 : : /** Construct an x-only pubkey from exactly 32 bytes. */
262 [ + + - + : 1690245 : constexpr explicit XOnlyPubKey(std::span<const unsigned char> bytes) : m_keydata{bytes} {}
+ + + + ]
[ + - + + ]
[ - + - +
- + + + ]
263 : :
264 : : /** Construct an x-only pubkey from a normal pubkey. */
265 : 1426040 : 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 : : const unsigned char& operator[](int pos) const { return *(m_keydata.begin() + pos); }
302 : : static constexpr size_t size() { return decltype(m_keydata)::size(); }
303 [ + - ][ + - : 307650 : const unsigned char* data() const { return m_keydata.begin(); }
+ - + - +
- + - ][ #
# # # # #
# # # # ]
304 [ + - ]: 1365063 : const unsigned char* begin() const { return m_keydata.begin(); }
305 [ + - ]: 1365063 : const unsigned char* end() const { return m_keydata.end(); }
306 [ + - ]: 7 : unsigned char* data() { return m_keydata.begin(); }
307 [ + - ]: 286113 : unsigned char* begin() { return m_keydata.begin(); }
308 [ + - ]: 6 : unsigned char* end() { return m_keydata.end(); }
309 [ + + ]: 20399 : bool operator==(const XOnlyPubKey& other) const { return m_keydata == other.m_keydata; }
[ + + + + ]
310 : 2938032 : 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 : 20313 : 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 [ + - + - : 512 : const std::byte* data() const { return m_pubkey.data(); }
+ - + - +
- + - +
- ]
335 : : static constexpr size_t size() { return SIZE; }
336 : 278 : auto begin() const { return m_pubkey.cbegin(); }
337 : 278 : auto end() const { return m_pubkey.cend(); }
338 : :
339 : 98 : bool friend operator==(const EllSwiftPubKey& a, const EllSwiftPubKey& b)
340 : : {
341 [ + - + - ]: 98 : return a.m_pubkey == b.m_pubkey;
342 : : }
343 : : };
344 : :
345 [ + + + + : 18191017 : 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 : 51 : friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
354 : : {
355 [ + - ]: 51 : return a.nDepth == b.nDepth &&
356 [ + - ]: 51 : a.fingerprint == b.fingerprint &&
357 [ + - ]: 51 : a.nChild == b.nChild &&
358 [ + - + - ]: 102 : a.chaincode == b.chaincode &&
359 [ - + ]: 51 : a.pubkey == b.pubkey;
360 : : }
361 : :
362 : 1410 : friend bool operator<(const CExtPubKey &a, const CExtPubKey &b)
363 : : {
364 [ + + ]: 1410 : if (a.pubkey < b.pubkey) {
365 : : return true;
366 [ + + ]: 1282 : } else if (a.pubkey > b.pubkey) {
367 : : return false;
368 : : }
369 : 1244 : return a.chaincode < b.chaincode;
370 : : }
371 : :
372 : 1523058 : KeyFingerprint id_key_fingerprint() const
373 : : {
374 : 1523058 : return pubkey.GetID().fingerprint();
375 : : }
376 : :
377 : : //! BIP32 serialization without the version bytes (BIP32_EXTKEY_SIZE bytes)
378 : : template <typename Stream>
379 : 155558 : void Serialize(Stream& s) const
380 : : {
381 [ - + ]: 155558 : assert(pubkey.size() == CPubKey::COMPRESSED_SIZE);
382 : 155558 : s << nDepth << fingerprint << Using<BigEndianFormatter<4>>(nChild) << chaincode << std::span{pubkey.data(), CPubKey::COMPRESSED_SIZE};
383 : 155558 : }
384 : : template <typename Stream>
385 : 14347 : void Unserialize(Stream& s)
386 : : {
387 : : std::array<unsigned char, CPubKey::COMPRESSED_SIZE> ser_pubkey;
388 : 14347 : s >> nDepth >> fingerprint >> Using<BigEndianFormatter<4>>(nChild) >> chaincode >> ser_pubkey;
389 : 14273 : pubkey.Set(ser_pubkey.begin(), ser_pubkey.end());
390 [ + + + + : 14273 : if ((nDepth == 0 && (nChild != 0 || fingerprint != KeyFingerprint{})) || !pubkey.IsFullyValid()) pubkey = CPubKey();
+ + + + ]
391 : 14273 : }
392 : : [[nodiscard]] bool Derive(CExtPubKey& out, unsigned int nChild, uint256* bip32_tweak_out = nullptr) const;
393 : : };
394 : :
395 : : #endif // BITCOIN_PUBKEY_H
|