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 <cstring>
16 : : #include <optional>
17 : : #include <vector>
18 : :
19 : : const unsigned int BIP32_EXTKEY_SIZE = 74;
20 : : const unsigned int BIP32_EXTKEY_WITH_VERSION_SIZE = 78;
21 : :
22 : : /** A reference to a CKey: the Hash160 of its serialized public key */
23 : : class CKeyID : public uint160
24 : : {
25 : : public:
26 [ + + + + : 457964 : CKeyID() : uint160() {}
+ + + ]
27 [ + + ]: 5998337 : explicit CKeyID(const uint160& in) : uint160(in) {}
[ + - + - ]
28 : : };
29 : :
30 : : typedef uint256 ChainCode;
31 : :
32 : : /** An encapsulated public key. */
33 : : class CPubKey
34 : : {
35 : : public:
36 : : /**
37 : : * secp256k1:
38 : : */
39 : : static constexpr unsigned int SIZE = 65;
40 : : static constexpr unsigned int COMPRESSED_SIZE = 33;
41 : : static constexpr unsigned int SIGNATURE_SIZE = 72;
42 : : static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65;
43 : : /**
44 : : * see www.keylength.com
45 : : * script supports up to 75 for single byte push
46 : : */
47 : : static_assert(
48 : : SIZE >= COMPRESSED_SIZE,
49 : : "COMPRESSED_SIZE is larger than SIZE");
50 : :
51 : : private:
52 : :
53 : : /**
54 : : * Just store the serialized data.
55 : : * Its length can very cheaply be computed from the first byte.
56 : : */
57 : : unsigned char vch[SIZE];
58 : :
59 : : //! Compute the length of a pubkey with a given first byte.
60 : 22905189 : unsigned int static GetLen(unsigned char chHeader)
61 : : {
62 [ + + ]: 22905189 : if (chHeader == 2 || chHeader == 3)
63 : : return COMPRESSED_SIZE;
64 [ + + + + ]: 67090 : if (chHeader == 4 || chHeader == 6 || chHeader == 7)
65 : 9189 : return SIZE;
66 : : return 0;
67 : : }
68 : :
69 : : //! Set this key data to be invalid
70 : 2783658 : void Invalidate()
71 : : {
72 : 2783658 : vch[0] = 0xFF;
73 : 18881 : }
74 : :
75 : : public:
76 : :
77 : 28246 : bool static ValidSize(const std::vector<unsigned char> &vch) {
78 [ + + + + ]: 28246 : return vch.size() > 0 && GetLen(vch[0]) == vch.size();
79 : : }
80 : :
81 : : //! Construct an invalid public key.
82 : 2764777 : CPubKey()
83 : 2764777 : {
84 [ + + + + ]: 3027981 : Invalidate();
[ + + + -
+ - ][ + -
+ - - - +
- + - ][ +
- + - + -
- - - - ]
[ + - + -
+ - + - +
- + - + +
+ + + + ]
85 : : }
86 : :
87 : : //! Initialize a public key using begin/end iterators to byte data.
88 : : template <typename T>
89 [ + + ]: 1857515 : void Set(const T pbegin, const T pend)
90 : : {
91 [ + + ]: 1857515 : int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
92 [ + + + + ]: 1857292 : if (len && len == (pend - pbegin))
93 : 1838640 : memcpy(vch, (unsigned char*)&pbegin[0], len);
94 : : else
95 : 18875 : Invalidate();
96 : 1857515 : }
97 : :
98 : : //! Construct a public key using begin/end iterators to byte data.
99 : : template <typename T>
100 : 3357 : CPubKey(const T pbegin, const T pend)
101 : : {
102 : 3357 : Set(pbegin, pend);
103 : : }
104 : :
105 : : //! Construct a public key from a byte vector.
106 : 348447 : explicit CPubKey(std::span<const uint8_t> _vch)
107 : 348447 : {
108 : 348447 : Set(_vch.begin(), _vch.end());
109 : 348447 : }
110 : :
111 : : //! Simple read-only vector-like interface to the pubkey data.
112 [ + + + + ]: 8919877 : unsigned int size() const { return GetLen(vch[0]); }
[ + - + -
+ - + - ]
[ + + - + ]
[ + - + -
+ - - - ]
[ - - - -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - ]
113 [ + - + - : 1770309 : const unsigned char* data() const { return vch; }
+ - + - ]
[ + - + -
+ - ]
[ + - # # ]
[ - - - -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - ][ # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
114 [ - + ]: 376741 : const unsigned char* begin() const { return vch; }
115 [ + - + - : 164048 : const unsigned char* end() const { return vch + size(); }
+ - - - ]
[ + - - -
+ - - - ]
116 [ + - ]: 12688 : const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
117 : :
118 : : //! Comparator implementation.
119 : 70428 : friend bool operator==(const CPubKey& a, const CPubKey& b)
120 : : {
121 [ + - ]: 70428 : return a.vch[0] == b.vch[0] &&
122 [ - + ]: 70428 : memcmp(a.vch, b.vch, a.size()) == 0;
123 : : }
124 : : friend bool operator!=(const CPubKey& a, const CPubKey& b)
125 : : {
126 : : return !(a == b);
127 : : }
128 : 11388678 : friend bool operator<(const CPubKey& a, const CPubKey& b)
129 : : {
130 [ + + + + ]: 11388678 : return a.vch[0] < b.vch[0] ||
131 [ + + ]: 10586999 : (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
132 : : }
133 : 569 : friend bool operator>(const CPubKey& a, const CPubKey& b)
134 : : {
135 [ + + + - ]: 569 : return a.vch[0] > b.vch[0] ||
136 [ + + ]: 561 : (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) > 0);
137 : : }
138 : :
139 : : //! Implement serialization, as if this was a byte vector.
140 : : template <typename Stream>
141 : 4040 : void Serialize(Stream& s) const
142 : : {
143 : 4040 : unsigned int len = size();
144 : 4040 : ::WriteCompactSize(s, len);
145 : 4040 : s << std::span{vch, len};
146 : 4040 : }
147 : : template <typename Stream>
148 : 2792 : void Unserialize(Stream& s)
149 : : {
150 : 2792 : const unsigned int len(::ReadCompactSize(s));
151 [ + - ]: 2792 : if (len <= SIZE) {
152 : 2792 : s >> std::span{vch, len};
153 [ + + ]: 2792 : if (len != size()) {
154 : 6 : Invalidate();
155 : : }
156 : : } else {
157 : : // invalid pubkey, skip available data
158 : 0 : s.ignore(len);
159 : 0 : Invalidate();
160 : : }
161 : 2792 : }
162 : :
163 : : //! Get the KeyID of this public key (hash of its serialization)
164 : 5642614 : CKeyID GetID() const
165 : : {
166 : 5642614 : return CKeyID(Hash160(std::span{vch}.first(size())));
167 : : }
168 : :
169 : : //! Get the 256-bit hash of this public key.
170 : 3304 : uint256 GetHash() const
171 : : {
172 : 3304 : return Hash(std::span{vch}.first(size()));
173 : : }
174 : :
175 : : /*
176 : : * Check syntactic correctness.
177 : : *
178 : : * When setting a pubkey (Set()) or deserializing fails (its header bytes
179 : : * don't match the length of the data), the size is set to 0. Thus,
180 : : * by checking size, one can observe whether Set() or deserialization has
181 : : * failed.
182 : : *
183 : : * This does not check for more than that. In particular, it does not verify
184 : : * that the coordinates correspond to a point on the curve (see IsFullyValid()
185 : : * for that instead).
186 : : *
187 : : * Note that this is consensus critical as CheckECDSASignature() calls it!
188 : : */
189 : 1072443 : bool IsValid() const
190 : : {
191 [ + + + - : 1041834 : return size() > 0;
+ - ][ + +
- + - - -
+ - + ][ -
+ + + + +
+ - - - ]
[ + + + -
+ + + - ]
[ + + + +
- - - + -
+ + + ][ +
+ + + - +
+ - - + +
+ ]
192 : : }
193 : :
194 : : /** Check if a public key is a syntactically valid compressed or uncompressed key. */
195 : 320276 : bool IsValidNonHybrid() const noexcept
196 : : {
197 [ + + + + ]: 320276 : return size() > 0 && (vch[0] == 0x02 || vch[0] == 0x03 || vch[0] == 0x04);
198 : : }
199 : :
200 : : //! fully validate whether this is a valid public key (more expensive than IsValid())
201 : : bool IsFullyValid() const;
202 : :
203 : : //! Check whether this is a compressed public key.
204 : 217587 : bool IsCompressed() const
205 : : {
206 [ + + ][ + + : 217587 : return size() == COMPRESSED_SIZE;
+ + + + ]
[ + + + + ]
207 : : }
208 : :
209 : : /**
210 : : * Verify a DER signature (~72 bytes).
211 : : * If this public key is not fully valid, the return value will be false.
212 : : */
213 : : bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
214 : :
215 : : /**
216 : : * Check whether a signature is normalized (lower-S).
217 : : */
218 : : static bool CheckLowS(const std::vector<unsigned char>& vchSig);
219 : :
220 : : //! Recover a public key from a compact signature.
221 : : bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
222 : :
223 : : //! Turn this public key into an uncompressed public key.
224 : : bool Decompress();
225 : :
226 : : //! Derive BIP32 child pubkey.
227 : : [[nodiscard]] bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
228 : : };
229 : :
230 : : class XOnlyPubKey
231 : : {
232 : : private:
233 : : uint256 m_keydata;
234 : :
235 : : public:
236 : : /** Nothing Up My Sleeve point H
237 : : * Used as an internal key for provably disabling the key path spend
238 : : * see BIP341 for more details */
239 : : static const XOnlyPubKey NUMS_H;
240 : :
241 : : /** Construct an empty x-only pubkey. */
242 [ + - # # ]: 806316 : XOnlyPubKey() = default;
[ + + + +
+ - ][ + +
- + + - ]
243 : :
244 : : XOnlyPubKey(const XOnlyPubKey&) = default;
245 : : XOnlyPubKey& operator=(const XOnlyPubKey&) = default;
246 : :
247 : : /** Determine if this pubkey is fully valid. This is true for approximately 50% of all
248 : : * possible 32-byte arrays. If false, VerifySchnorr, CheckTapTweak and CreateTapTweak
249 : : * will always fail. */
250 : : bool IsFullyValid() const;
251 : :
252 : : /** Test whether this is the 0 key (the result of default construction). This implies
253 : : * !IsFullyValid(). */
254 [ - + - + ]: 37712 : bool IsNull() const { return m_keydata.IsNull(); }
[ + + + +
+ + + + ]
[ + + - +
+ + + + -
+ + + +
+ ][ + + +
- + - # #
# # # # #
# ]
255 : :
256 : : /** Construct an x-only pubkey from exactly 32 bytes. */
257 [ + + + + ]: 1601365 : constexpr explicit XOnlyPubKey(std::span<const unsigned char> bytes) : m_keydata{bytes} {}
[ + + + - ]
258 : :
259 : : /** Construct an x-only pubkey from a normal pubkey. */
260 : 1393324 : explicit XOnlyPubKey(const CPubKey& pubkey) : XOnlyPubKey(std::span{pubkey}.subspan(1, 32)) {}
261 : :
262 : : /** Verify a Schnorr signature against this public key.
263 : : *
264 : : * sigbytes must be exactly 64 bytes.
265 : : */
266 : : bool VerifySchnorr(const uint256& msg, std::span<const unsigned char> sigbytes) const;
267 : :
268 : : /** Compute the Taproot tweak as specified in BIP341, with *this as internal
269 : : * key:
270 : : * - if merkle_root == nullptr: H_TapTweak(xonly_pubkey)
271 : : * - otherwise: H_TapTweak(xonly_pubkey || *merkle_root)
272 : : *
273 : : * Note that the behavior of this function with merkle_root != nullptr is
274 : : * consensus critical.
275 : : */
276 : : uint256 ComputeTapTweakHash(const uint256* merkle_root) const;
277 : :
278 : : /** Verify that this is a Taproot tweaked output point, against a specified internal key,
279 : : * Merkle root, and parity. */
280 : : bool CheckTapTweak(const XOnlyPubKey& internal, const uint256& merkle_root, bool parity) const;
281 : :
282 : : /** Construct a Taproot tweaked output point with this point as internal key. */
283 : : std::optional<std::pair<XOnlyPubKey, bool>> CreateTapTweak(const uint256* merkle_root) const;
284 : :
285 : : /** Returns a list of CKeyIDs for the CPubKeys that could have been used to create this XOnlyPubKey.
286 : : * As the CKeyID is the Hash160(full pubkey), the produced CKeyIDs are for the versions of this
287 : : * XOnlyPubKey with 0x02 and 0x03 prefixes.
288 : : * This is needed for key lookups since keys are indexed by CKeyID.
289 : : */
290 : : std::vector<CKeyID> GetKeyIDs() const;
291 : : /** Returns this XOnlyPubKey with 0x02 and 0x03 prefixes */
292 : : std::vector<CPubKey> GetCPubKeys() const;
293 : :
294 : : CPubKey GetEvenCorrespondingCPubKey() const;
295 : :
296 : : const unsigned char& operator[](int pos) const { return *(m_keydata.begin() + pos); }
297 : : static constexpr size_t size() { return decltype(m_keydata)::size(); }
298 [ + - + - : 226152 : const unsigned char* data() const { return m_keydata.begin(); }
+ - + - +
- ][ + - #
# # # # #
# # ]
299 [ + - ]: 1320977 : const unsigned char* begin() const { return m_keydata.begin(); }
300 [ + - ]: 1320977 : const unsigned char* end() const { return m_keydata.end(); }
301 [ + - ]: 7 : unsigned char* data() { return m_keydata.begin(); }
302 [ + - ]: 276120 : unsigned char* begin() { return m_keydata.begin(); }
303 [ + - ]: 6 : unsigned char* end() { return m_keydata.end(); }
304 [ + - ]: 2 : bool operator==(const XOnlyPubKey& other) const { return m_keydata == other.m_keydata; }
305 [ - + ]: 5626 : bool operator!=(const XOnlyPubKey& other) const { return m_keydata != other.m_keydata; }
306 [ + + - + : 2443838 : bool operator<(const XOnlyPubKey& other) const { return m_keydata < other.m_keydata; }
+ + + - +
- + - - -
+ + + + +
- + - + +
+ + - + +
+ + + - -
- - - - -
- - + - +
+ - + - ]
[ + + + +
+ - + - -
- - - + +
+ + + + +
+ + - - -
- - - - -
- - - - -
- - - - -
- + + - -
+ - ][ + +
- - - - -
- + + # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ][ + -
- + + + -
- - - - -
- + + + +
- - - - -
+ + + + +
- + + + +
+ - + - +
- - - + +
+ - + - ]
[ + - - -
- - - - -
+ ][ # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
307 : :
308 : : //! Implement serialization without length prefixes since it is a fixed length
309 : 7448 : SERIALIZE_METHODS(XOnlyPubKey, obj) { READWRITE(obj.m_keydata); }
310 : : };
311 : :
312 : : /** An ElligatorSwift-encoded public key. */
313 : : struct EllSwiftPubKey
314 : : {
315 : : private:
316 : : static constexpr size_t SIZE = 64;
317 : : std::array<std::byte, SIZE> m_pubkey;
318 : :
319 : : public:
320 : : /** Default constructor creates all-zero pubkey (which is valid). */
321 : : EllSwiftPubKey() noexcept = default;
322 : :
323 : : /** Construct a new ellswift public key from a given serialization. */
324 : : EllSwiftPubKey(std::span<const std::byte> ellswift) noexcept;
325 : :
326 : : /** Decode to normal compressed CPubKey (for debugging purposes). */
327 : : CPubKey Decode() const;
328 : :
329 : : // Read-only access for serialization.
330 [ + - + - : 508 : const std::byte* data() const { return m_pubkey.data(); }
+ - + - +
- + - +
- ]
331 : : static constexpr size_t size() { return SIZE; }
332 : 269 : auto begin() const { return m_pubkey.cbegin(); }
333 : 269 : auto end() const { return m_pubkey.cend(); }
334 : :
335 : 98 : bool friend operator==(const EllSwiftPubKey& a, const EllSwiftPubKey& b)
336 : : {
337 [ + - + - ]: 196 : return a.m_pubkey == b.m_pubkey;
338 : : }
339 : :
340 : : bool friend operator!=(const EllSwiftPubKey& a, const EllSwiftPubKey& b)
341 : : {
342 : : return a.m_pubkey != b.m_pubkey;
343 : : }
344 : : };
345 : :
346 [ + + + - ]: 827474 : struct CExtPubKey {
[ + - + - ]
[ + - + -
+ - + - +
+ + + ]
347 : : unsigned char version[4];
348 : : unsigned char nDepth;
349 : : unsigned char vchFingerprint[4];
350 : : unsigned int nChild;
351 : : ChainCode chaincode;
352 : : CPubKey pubkey;
353 : :
354 : 89 : friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
355 : : {
356 : 178 : return a.nDepth == b.nDepth &&
357 [ + - ]: 89 : memcmp(a.vchFingerprint, b.vchFingerprint, sizeof(vchFingerprint)) == 0 &&
358 [ + - + - ]: 89 : a.nChild == b.nChild &&
359 [ + - + - ]: 178 : a.chaincode == b.chaincode &&
360 [ - + ]: 89 : a.pubkey == b.pubkey;
361 : : }
362 : :
363 : 62 : friend bool operator!=(const CExtPubKey &a, const CExtPubKey &b)
364 : : {
365 [ - + - + : 62 : return !(a == b);
- - ]
366 : : }
367 : :
368 : 597 : friend bool operator<(const CExtPubKey &a, const CExtPubKey &b)
369 : : {
370 [ + + ]: 597 : if (a.pubkey < b.pubkey) {
371 : : return true;
372 [ + + ]: 569 : } else if (a.pubkey > b.pubkey) {
373 : : return false;
374 : : }
375 : 542 : return a.chaincode < b.chaincode;
376 : : }
377 : :
378 : : void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
379 : : void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
380 : : void EncodeWithVersion(unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]) const;
381 : : void DecodeWithVersion(const unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]);
382 : : [[nodiscard]] bool Derive(CExtPubKey& out, unsigned int nChild) const;
383 : : };
384 : :
385 : : #endif // BITCOIN_PUBKEY_H
|