Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto 2 : // Copyright (c) 2009-2021 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 <uint256.h> 13 : 14 : #include <array> 15 : #include <cstring> 16 : #include <vector> 17 : 18 : const unsigned int BIP32_EXTKEY_SIZE = 74; 19 : const unsigned int BIP32_EXTKEY_WITH_VERSION_SIZE = 78; 20 : 21 : /** A reference to a CKey: the Hash160 of its serialized public key */ 22 : class CKeyID : public uint160 23 : { 24 : public: 25 7830208 : CKeyID() : uint160() {} 26 15408459 : explicit CKeyID(const uint160& in) : uint160(in) {} 27 : }; 28 : 29 : typedef uint256 ChainCode; 30 : 31 : /** An encapsulated public key. */ 32 : class CPubKey 33 : { 34 : public: 35 : /** 36 : * secp256k1: 37 : */ 38 : static constexpr unsigned int SIZE = 65; 39 : static constexpr unsigned int COMPRESSED_SIZE = 33; 40 : static constexpr unsigned int SIGNATURE_SIZE = 72; 41 : static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65; 42 : /** 43 : * see www.keylength.com 44 : * script supports up to 75 for single byte push 45 : */ 46 : static_assert( 47 : SIZE >= COMPRESSED_SIZE, 48 : "COMPRESSED_SIZE is larger than SIZE"); 49 : 50 : private: 51 : 52 : /** 53 : * Just store the serialized data. 54 : * Its length can very cheaply be computed from the first byte. 55 : */ 56 : unsigned char vch[SIZE]; 57 : 58 : //! Compute the length of a pubkey with a given first byte. 59 17845718 : unsigned int static GetLen(unsigned char chHeader) 60 : { 61 17845718 : if (chHeader == 2 || chHeader == 3) 62 17599407 : return COMPRESSED_SIZE; 63 246311 : if (chHeader == 4 || chHeader == 6 || chHeader == 7) 64 245479 : return SIZE; 65 832 : return 0; 66 17845718 : } 67 : 68 : //! Set this key data to be invalid 69 5097203 : void Invalidate() 70 : { 71 5097203 : vch[0] = 0xFF; 72 5097203 : } 73 : 74 : public: 75 : 76 52630 : bool static ValidSize(const std::vector<unsigned char> &vch) { 77 52630 : return vch.size() > 0 && GetLen(vch[0]) == vch.size(); 78 : } 79 : 80 : //! Construct an invalid public key. 81 10193738 : CPubKey() 82 5096869 : { 83 5096869 : Invalidate(); 84 10193738 : } 85 : 86 : //! Initialize a public key using begin/end iterators to byte data. 87 : template <typename T> 88 935551 : void Set(const T pbegin, const T pend) 89 : { 90 935551 : int len = pend == pbegin ? 0 : GetLen(pbegin[0]); 91 935551 : if (len && len == (pend - pbegin)) 92 935088 : memcpy(vch, (unsigned char*)&pbegin[0], len); 93 : else 94 481 : Invalidate(); 95 935569 : } 96 : 97 : //! Construct a public key using begin/end iterators to byte data. 98 : template <typename T> 99 2266 : CPubKey(const T pbegin, const T pend) 100 1133 : { 101 1133 : Set(pbegin, pend); 102 2266 : } 103 : 104 : //! Construct a public key from a byte vector. 105 987213 : explicit CPubKey(Span<const uint8_t> _vch) 106 493616 : { 107 493597 : Set(_vch.begin(), _vch.end()); 108 987213 : } 109 : 110 : //! Simple read-only vector-like interface to the pubkey data. 111 16861404 : unsigned int size() const { return GetLen(vch[0]); } 112 430773 : const unsigned char* data() const { return vch; } 113 4161741 : const unsigned char* begin() const { return vch; } 114 951301 : const unsigned char* end() const { return vch + size(); } 115 69724 : const unsigned char& operator[](unsigned int pos) const { return vch[pos]; } 116 : 117 : //! Comparator implementation. 118 24881 : friend bool operator==(const CPubKey& a, const CPubKey& b) 119 : { 120 49762 : return a.vch[0] == b.vch[0] && 121 24881 : memcmp(a.vch, b.vch, a.size()) == 0; 122 : } 123 23941 : friend bool operator!=(const CPubKey& a, const CPubKey& b) 124 : { 125 23941 : return !(a == b); 126 : } 127 3936599 : friend bool operator<(const CPubKey& a, const CPubKey& b) 128 : { 129 7633133 : return a.vch[0] < b.vch[0] || 130 3696534 : (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0); 131 : } 132 8 : friend bool operator>(const CPubKey& a, const CPubKey& b) 133 : { 134 16 : return a.vch[0] > b.vch[0] || 135 8 : (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) > 0); 136 : } 137 : 138 : //! Implement serialization, as if this was a byte vector. 139 : template <typename Stream> 140 138572 : void Serialize(Stream& s) const 141 : { 142 138572 : unsigned int len = size(); 143 138572 : ::WriteCompactSize(s, len); 144 138572 : s.write(AsBytes(Span{vch, len})); 145 138572 : } 146 : template <typename Stream> 147 92506 : void Unserialize(Stream& s) 148 : { 149 92506 : const unsigned int len(::ReadCompactSize(s)); 150 92506 : if (len <= SIZE) { 151 92506 : s.read(AsWritableBytes(Span{vch, len})); 152 92506 : if (len != size()) { 153 6 : Invalidate(); 154 6 : } 155 92506 : } else { 156 : // invalid pubkey, skip available data 157 0 : s.ignore(len); 158 0 : Invalidate(); 159 : } 160 92506 : } 161 : 162 : //! Get the KeyID of this public key (hash of its serialization) 163 4649916 : CKeyID GetID() const 164 : { 165 4649916 : return CKeyID(Hash160(Span{vch}.first(size()))); 166 : } 167 : 168 : //! Get the 256-bit hash of this public key. 169 3851 : uint256 GetHash() const 170 : { 171 3851 : return Hash(Span{vch}.first(size())); 172 : } 173 : 174 : /* 175 : * Check syntactic correctness. 176 : * 177 : * Note that this is consensus critical as CheckSig() calls it! 178 : */ 179 3372806 : bool IsValid() const 180 : { 181 3372806 : return size() > 0; 182 : } 183 : 184 : //! fully validate whether this is a valid public key (more expensive than IsValid()) 185 : bool IsFullyValid() const; 186 : 187 : //! Check whether this is a compressed public key. 188 99960 : bool IsCompressed() const 189 : { 190 99960 : return size() == COMPRESSED_SIZE; 191 : } 192 : 193 : /** 194 : * Verify a DER signature (~72 bytes). 195 : * If this public key is not fully valid, the return value will be false. 196 : */ 197 : bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const; 198 : 199 : /** 200 : * Check whether a signature is normalized (lower-S). 201 : */ 202 : static bool CheckLowS(const std::vector<unsigned char>& vchSig); 203 : 204 : //! Recover a public key from a compact signature. 205 : bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig); 206 : 207 : //! Turn this public key into an uncompressed public key. 208 : bool Decompress(); 209 : 210 : //! Derive BIP32 child pubkey. 211 : [[nodiscard]] bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const; 212 : }; 213 : 214 : /** An ElligatorSwift-encoded public key. */ 215 : struct EllSwiftPubKey 216 : { 217 : private: 218 : static constexpr size_t SIZE = 64; 219 : std::array<std::byte, SIZE> m_pubkey; 220 : 221 : public: 222 : /** Default constructor creates all-zero pubkey (which is valid). */ 223 : EllSwiftPubKey() noexcept = default; 224 : 225 : /** Construct a new ellswift public key from a given serialization. */ 226 : EllSwiftPubKey(Span<const std::byte> ellswift) noexcept; 227 : 228 : /** Decode to normal compressed CPubKey (for debugging purposes). */ 229 : CPubKey Decode() const; 230 : 231 : // Read-only access for serialization. 232 1138 : const std::byte* data() const { return m_pubkey.data(); } 233 2805 : static constexpr size_t size() { return SIZE; } 234 366 : auto begin() const { return m_pubkey.cbegin(); } 235 366 : auto end() const { return m_pubkey.cend(); } 236 : 237 98 : bool friend operator==(const EllSwiftPubKey& a, const EllSwiftPubKey& b) 238 : { 239 98 : return a.m_pubkey == b.m_pubkey; 240 : } 241 : 242 : bool friend operator!=(const EllSwiftPubKey& a, const EllSwiftPubKey& b) 243 : { 244 : return a.m_pubkey != b.m_pubkey; 245 : } 246 : }; 247 : 248 : struct CExtPubKey { 249 : unsigned char version[4]; 250 : unsigned char nDepth; 251 : unsigned char vchFingerprint[4]; 252 : unsigned int nChild; 253 : ChainCode chaincode; 254 : CPubKey pubkey; 255 : 256 39 : friend bool operator==(const CExtPubKey &a, const CExtPubKey &b) 257 : { 258 78 : return a.nDepth == b.nDepth && 259 39 : memcmp(a.vchFingerprint, b.vchFingerprint, sizeof(vchFingerprint)) == 0 && 260 39 : a.nChild == b.nChild && 261 39 : a.chaincode == b.chaincode && 262 39 : a.pubkey == b.pubkey; 263 : } 264 : 265 12 : friend bool operator!=(const CExtPubKey &a, const CExtPubKey &b) 266 : { 267 12 : return !(a == b); 268 : } 269 : 270 16 : friend bool operator<(const CExtPubKey &a, const CExtPubKey &b) 271 : { 272 16 : if (a.pubkey < b.pubkey) { 273 8 : return true; 274 8 : } else if (a.pubkey > b.pubkey) { 275 8 : return false; 276 : } 277 0 : return a.chaincode < b.chaincode; 278 16 : } 279 : 280 : void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const; 281 : void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]); 282 : void EncodeWithVersion(unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]) const; 283 : void DecodeWithVersion(const unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]); 284 : [[nodiscard]] bool Derive(CExtPubKey& out, unsigned int nChild) const; 285 : 286 : void Serialize(CSizeComputer& s) const 287 : { 288 : // Optimized implementation for ::GetSerializeSize that avoids copying. 289 : s.seek(BIP32_EXTKEY_SIZE + 1); // add one byte for the size (compact int) 290 : } 291 : template <typename Stream> 292 31845 : void Serialize(Stream& s) const 293 : { 294 31845 : unsigned int len = BIP32_EXTKEY_SIZE; 295 31845 : ::WriteCompactSize(s, len); 296 : unsigned char code[BIP32_EXTKEY_SIZE]; 297 31845 : Encode(code); 298 31845 : s.write(AsBytes(Span{&code[0], len})); 299 31845 : } 300 : template <typename Stream> 301 23941 : void Unserialize(Stream& s) 302 : { 303 23941 : unsigned int len = ::ReadCompactSize(s); 304 : unsigned char code[BIP32_EXTKEY_SIZE]; 305 23941 : if (len != BIP32_EXTKEY_SIZE) 306 0 : throw std::runtime_error("Invalid extended key size\n"); 307 23941 : s.read(AsWritableBytes(Span{&code[0], len})); 308 23941 : Decode(code); 309 23941 : } 310 : }; 311 : 312 : #endif // BITCOIN_PUBKEY_H