Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2020 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 <vector>
# 17 : :
# 18 : : const unsigned int BIP32_EXTKEY_SIZE = 74;
# 19 : :
# 20 : : /** A reference to a CKey: the Hash160 of its serialized public key */
# 21 : : class CKeyID : public uint160
# 22 : : {
# 23 : : public:
# 24 : 3920749 : CKeyID() : uint160() {}
# 25 : 5734170 : explicit CKeyID(const uint160& in) : uint160(in) {}
# 26 : : };
# 27 : :
# 28 : : typedef uint256 ChainCode;
# 29 : :
# 30 : : /** An encapsulated public key. */
# 31 : : class CPubKey
# 32 : : {
# 33 : : public:
# 34 : : /**
# 35 : : * secp256k1:
# 36 : : */
# 37 : : static constexpr unsigned int SIZE = 65;
# 38 : : static constexpr unsigned int COMPRESSED_SIZE = 33;
# 39 : : static constexpr unsigned int SIGNATURE_SIZE = 72;
# 40 : : static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65;
# 41 : : /**
# 42 : : * see www.keylength.com
# 43 : : * script supports up to 75 for single byte push
# 44 : : */
# 45 : : static_assert(
# 46 : : SIZE >= COMPRESSED_SIZE,
# 47 : : "COMPRESSED_SIZE is larger than SIZE");
# 48 : :
# 49 : : private:
# 50 : :
# 51 : : /**
# 52 : : * Just store the serialized data.
# 53 : : * Its length can very cheaply be computed from the first byte.
# 54 : : */
# 55 : : unsigned char vch[SIZE];
# 56 : :
# 57 : : //! Compute the length of a pubkey with a given first byte.
# 58 : : unsigned int static GetLen(unsigned char chHeader)
# 59 : 12830462 : {
# 60 [ + + ][ + + ]: 12830462 : if (chHeader == 2 || chHeader == 3)
# 61 : 12746650 : return COMPRESSED_SIZE;
# 62 [ + + ][ + + ]: 83812 : if (chHeader == 4 || chHeader == 6 || chHeader == 7)
# [ + + ]
# 63 : 79898 : return SIZE;
# 64 : 3914 : return 0;
# 65 : 3914 : }
# 66 : :
# 67 : : //! Set this key data to be invalid
# 68 : : void Invalidate()
# 69 : 4524649 : {
# 70 : 4524649 : vch[0] = 0xFF;
# 71 : 4524649 : }
# 72 : :
# 73 : : public:
# 74 : :
# 75 : 83779 : bool static ValidSize(const std::vector<unsigned char> &vch) {
# 76 [ + + ][ + + ]: 83779 : return vch.size() > 0 && GetLen(vch[0]) == vch.size();
# 77 : 83779 : }
# 78 : :
# 79 : : //! Construct an invalid public key.
# 80 : : CPubKey()
# 81 : 4523940 : {
# 82 : 4523940 : Invalidate();
# 83 : 4523940 : }
# 84 : :
# 85 : : //! Initialize a public key using begin/end iterators to byte data.
# 86 : : template <typename T>
# 87 : : void Set(const T pbegin, const T pend)
# 88 : 840632 : {
# 89 [ - + ][ - + ]: 840632 : int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
# [ - + ][ + + ]
# 90 [ + - ][ + - ]: 840632 : if (len && len == (pend - pbegin))
# [ + - ][ + + ]
# [ + - ][ + + ]
# [ + - ][ + - ]
# 91 : 840195 : memcpy(vch, (unsigned char*)&pbegin[0], len);
# 92 : 437 : else
# 93 : 437 : Invalidate();
# 94 : 840632 : }
# 95 : :
# 96 : : //! Construct a public key using begin/end iterators to byte data.
# 97 : : template <typename T>
# 98 : : CPubKey(const T pbegin, const T pend)
# 99 : 994 : {
# 100 : 994 : Set(pbegin, pend);
# 101 : 994 : }
# 102 : :
# 103 : : //! Construct a public key from a byte vector.
# 104 : : explicit CPubKey(Span<const uint8_t> _vch)
# 105 : 480415 : {
# 106 : 480415 : Set(_vch.begin(), _vch.end());
# 107 : 480415 : }
# 108 : :
# 109 : : //! Simple read-only vector-like interface to the pubkey data.
# 110 : 11918402 : unsigned int size() const { return GetLen(vch[0]); }
# 111 : 468166 : const unsigned char* data() const { return vch; }
# 112 : 3425538 : const unsigned char* begin() const { return vch; }
# 113 : 1161488 : const unsigned char* end() const { return vch + size(); }
# 114 : 45966 : const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
# 115 : :
# 116 : : //! Comparator implementation.
# 117 : : friend bool operator==(const CPubKey& a, const CPubKey& b)
# 118 : 5677 : {
# 119 [ + - ]: 5677 : return a.vch[0] == b.vch[0] &&
# 120 [ + - ]: 5677 : memcmp(a.vch, b.vch, a.size()) == 0;
# 121 : 5677 : }
# 122 : : friend bool operator!=(const CPubKey& a, const CPubKey& b)
# 123 : 0 : {
# 124 : 0 : return !(a == b);
# 125 : 0 : }
# 126 : : friend bool operator<(const CPubKey& a, const CPubKey& b)
# 127 : 735340 : {
# 128 [ + + ]: 735340 : return a.vch[0] < b.vch[0] ||
# 129 [ + + ][ + + ]: 735340 : (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
# 130 : 735340 : }
# 131 : :
# 132 : : //! Implement serialization, as if this was a byte vector.
# 133 : : template <typename Stream>
# 134 : : void Serialize(Stream& s) const
# 135 : 84668 : {
# 136 : 84668 : unsigned int len = size();
# 137 : 84668 : ::WriteCompactSize(s, len);
# 138 : 84668 : s.write((char*)vch, len);
# 139 : 84668 : }
# 140 : : template <typename Stream>
# 141 : : void Unserialize(Stream& s)
# 142 : 43265 : {
# 143 : 43265 : unsigned int len = ::ReadCompactSize(s);
# 144 [ + - ]: 43265 : if (len <= SIZE) {
# 145 : 43265 : s.read((char*)vch, len);
# 146 [ + + ]: 43265 : if (len != size()) {
# 147 : 12 : Invalidate();
# 148 : 12 : }
# 149 : 43265 : } else {
# 150 : : // invalid pubkey, skip available data
# 151 : 0 : char dummy;
# 152 [ # # ]: 0 : while (len--)
# 153 : 0 : s.read(&dummy, 1);
# 154 : 0 : Invalidate();
# 155 : 0 : }
# 156 : 43265 : }
# 157 : :
# 158 : : //! Get the KeyID of this public key (hash of its serialization)
# 159 : : CKeyID GetID() const
# 160 : 3377433 : {
# 161 : 3377433 : return CKeyID(Hash160(MakeSpan(vch).first(size())));
# 162 : 3377433 : }
# 163 : :
# 164 : : //! Get the 256-bit hash of this public key.
# 165 : : uint256 GetHash() const
# 166 : 6897 : {
# 167 : 6897 : return Hash(MakeSpan(vch).first(size()));
# 168 : 6897 : }
# 169 : :
# 170 : : /*
# 171 : : * Check syntactic correctness.
# 172 : : *
# 173 : : * When setting a pubkey (Set()) or deserializing fails (its header bytes
# 174 : : * don't match the length of the data), the size is set to 0. Thus,
# 175 : : * by checking size, one can observe whether Set() or deserialization has
# 176 : : * failed.
# 177 : : *
# 178 : : * This does not check for more than that. In particular, it does not verify
# 179 : : * that the coordinates correspond to a point on the curve (see IsFullyValid()
# 180 : : * for that instead).
# 181 : : *
# 182 : : * Note that this is consensus critical as CheckECDSASignature() calls it!
# 183 : : */
# 184 : : bool IsValid() const
# 185 : 2838208 : {
# 186 : 2838208 : return size() > 0;
# 187 : 2838208 : }
# 188 : :
# 189 : : //! fully validate whether this is a valid public key (more expensive than IsValid())
# 190 : : bool IsFullyValid() const;
# 191 : :
# 192 : : //! Check whether this is a compressed public key.
# 193 : : bool IsCompressed() const
# 194 : 768294 : {
# 195 : 768294 : return size() == COMPRESSED_SIZE;
# 196 : 768294 : }
# 197 : :
# 198 : : /**
# 199 : : * Verify a DER signature (~72 bytes).
# 200 : : * If this public key is not fully valid, the return value will be false.
# 201 : : */
# 202 : : bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
# 203 : :
# 204 : : /**
# 205 : : * Check whether a signature is normalized (lower-S).
# 206 : : */
# 207 : : static bool CheckLowS(const std::vector<unsigned char>& vchSig);
# 208 : :
# 209 : : //! Recover a public key from a compact signature.
# 210 : : bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
# 211 : :
# 212 : : //! Turn this public key into an uncompressed public key.
# 213 : : bool Decompress();
# 214 : :
# 215 : : //! Derive BIP32 child pubkey.
# 216 : : bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
# 217 : : };
# 218 : :
# 219 : : class XOnlyPubKey
# 220 : : {
# 221 : : private:
# 222 : : uint256 m_keydata;
# 223 : :
# 224 : : public:
# 225 : : /** Construct an x-only pubkey from exactly 32 bytes. */
# 226 : : explicit XOnlyPubKey(Span<const unsigned char> bytes);
# 227 : :
# 228 : : /** Verify a Schnorr signature against this public key.
# 229 : : *
# 230 : : * sigbytes must be exactly 64 bytes.
# 231 : : */
# 232 : : bool VerifySchnorr(const uint256& msg, Span<const unsigned char> sigbytes) const;
# 233 : : bool CheckPayToContract(const XOnlyPubKey& base, const uint256& hash, bool parity) const;
# 234 : :
# 235 : 0 : const unsigned char& operator[](int pos) const { return *(m_keydata.begin() + pos); }
# 236 : 19951 : const unsigned char* data() const { return m_keydata.begin(); }
# 237 : 12698 : size_t size() const { return m_keydata.size(); }
# 238 : : };
# 239 : :
# 240 : : struct CExtPubKey {
# 241 : : unsigned char nDepth;
# 242 : : unsigned char vchFingerprint[4];
# 243 : : unsigned int nChild;
# 244 : : ChainCode chaincode;
# 245 : : CPubKey pubkey;
# 246 : :
# 247 : : friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
# 248 : 54 : {
# 249 [ + - ]: 54 : return a.nDepth == b.nDepth &&
# 250 [ + - ]: 54 : memcmp(a.vchFingerprint, b.vchFingerprint, sizeof(vchFingerprint)) == 0 &&
# 251 [ + - ]: 54 : a.nChild == b.nChild &&
# 252 [ + - ]: 54 : a.chaincode == b.chaincode &&
# 253 [ + - ]: 54 : a.pubkey == b.pubkey;
# 254 : 54 : }
# 255 : :
# 256 : : friend bool operator!=(const CExtPubKey &a, const CExtPubKey &b)
# 257 : 0 : {
# 258 : 0 : return !(a == b);
# 259 : 0 : }
# 260 : :
# 261 : : void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
# 262 : : void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
# 263 : : bool Derive(CExtPubKey& out, unsigned int nChild) const;
# 264 : : };
# 265 : :
# 266 : : /** Users of this module must hold an ECCVerifyHandle. The constructor and
# 267 : : * destructor of these are not allowed to run in parallel, though. */
# 268 : : class ECCVerifyHandle
# 269 : : {
# 270 : : static int refcount;
# 271 : :
# 272 : : public:
# 273 : : ECCVerifyHandle();
# 274 : : ~ECCVerifyHandle();
# 275 : : };
# 276 : :
# 277 : : #endif // BITCOIN_PUBKEY_H
|