LCOV - code coverage report
Current view: top level - src - pubkey.h (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 0 104 0.0 %
Date: 2023-09-26 12:08:55 Functions: 0 64 0.0 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2022 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           0 :     CKeyID() : uint160() {}
      27           0 :     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           0 :     unsigned int static GetLen(unsigned char chHeader)
      61             :     {
      62           0 :         if (chHeader == 2 || chHeader == 3)
      63           0 :             return COMPRESSED_SIZE;
      64           0 :         if (chHeader == 4 || chHeader == 6 || chHeader == 7)
      65           0 :             return SIZE;
      66           0 :         return 0;
      67           0 :     }
      68             : 
      69             :     //! Set this key data to be invalid
      70           0 :     void Invalidate()
      71             :     {
      72           0 :         vch[0] = 0xFF;
      73           0 :     }
      74             : 
      75             : public:
      76             : 
      77           0 :     bool static ValidSize(const std::vector<unsigned char> &vch) {
      78           0 :       return vch.size() > 0 && GetLen(vch[0]) == vch.size();
      79             :     }
      80             : 
      81             :     //! Construct an invalid public key.
      82           0 :     CPubKey()
      83             :     {
      84           0 :         Invalidate();
      85           0 :     }
      86             : 
      87             :     //! Initialize a public key using begin/end iterators to byte data.
      88             :     template <typename T>
      89           0 :     void Set(const T pbegin, const T pend)
      90             :     {
      91           0 :         int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
      92           0 :         if (len && len == (pend - pbegin))
      93           0 :             memcpy(vch, (unsigned char*)&pbegin[0], len);
      94             :         else
      95           0 :             Invalidate();
      96           0 :     }
      97             : 
      98             :     //! Construct a public key using begin/end iterators to byte data.
      99             :     template <typename T>
     100           0 :     CPubKey(const T pbegin, const T pend)
     101             :     {
     102           0 :         Set(pbegin, pend);
     103           0 :     }
     104             : 
     105             :     //! Construct a public key from a byte vector.
     106           0 :     explicit CPubKey(Span<const uint8_t> _vch)
     107             :     {
     108           0 :         Set(_vch.begin(), _vch.end());
     109           0 :     }
     110             : 
     111             :     //! Simple read-only vector-like interface to the pubkey data.
     112           0 :     unsigned int size() const { return GetLen(vch[0]); }
     113           0 :     const unsigned char* data() const { return vch; }
     114           0 :     const unsigned char* begin() const { return vch; }
     115           0 :     const unsigned char* end() const { return vch + size(); }
     116           0 :     const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
     117             : 
     118             :     //! Comparator implementation.
     119           0 :     friend bool operator==(const CPubKey& a, const CPubKey& b)
     120             :     {
     121           0 :         return a.vch[0] == b.vch[0] &&
     122           0 :                memcmp(a.vch, b.vch, a.size()) == 0;
     123             :     }
     124           0 :     friend bool operator!=(const CPubKey& a, const CPubKey& b)
     125             :     {
     126           0 :         return !(a == b);
     127             :     }
     128           0 :     friend bool operator<(const CPubKey& a, const CPubKey& b)
     129             :     {
     130           0 :         return a.vch[0] < b.vch[0] ||
     131           0 :                (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
     132             :     }
     133           0 :     friend bool operator>(const CPubKey& a, const CPubKey& b)
     134             :     {
     135           0 :         return a.vch[0] > b.vch[0] ||
     136           0 :                (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           0 :     void Serialize(Stream& s) const
     142             :     {
     143           0 :         unsigned int len = size();
     144           0 :         ::WriteCompactSize(s, len);
     145           0 :         s << Span{vch, len};
     146           0 :     }
     147             :     template <typename Stream>
     148           0 :     void Unserialize(Stream& s)
     149             :     {
     150           0 :         const unsigned int len(::ReadCompactSize(s));
     151           0 :         if (len <= SIZE) {
     152           0 :             s >> Span{vch, len};
     153           0 :             if (len != size()) {
     154           0 :                 Invalidate();
     155           0 :             }
     156           0 :         } else {
     157             :             // invalid pubkey, skip available data
     158           0 :             s.ignore(len);
     159           0 :             Invalidate();
     160             :         }
     161           0 :     }
     162             : 
     163             :     //! Get the KeyID of this public key (hash of its serialization)
     164           0 :     CKeyID GetID() const
     165             :     {
     166           0 :         return CKeyID(Hash160(Span{vch}.first(size())));
     167             :     }
     168             : 
     169             :     //! Get the 256-bit hash of this public key.
     170           0 :     uint256 GetHash() const
     171             :     {
     172           0 :         return Hash(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           0 :     bool IsValid() const
     190             :     {
     191           0 :         return size() > 0;
     192             :     }
     193             : 
     194             :     //! fully validate whether this is a valid public key (more expensive than IsValid())
     195             :     bool IsFullyValid() const;
     196             : 
     197             :     //! Check whether this is a compressed public key.
     198           0 :     bool IsCompressed() const
     199             :     {
     200           0 :         return size() == COMPRESSED_SIZE;
     201             :     }
     202             : 
     203             :     /**
     204             :      * Verify a DER signature (~72 bytes).
     205             :      * If this public key is not fully valid, the return value will be false.
     206             :      */
     207             :     bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
     208             : 
     209             :     /**
     210             :      * Check whether a signature is normalized (lower-S).
     211             :      */
     212             :     static bool CheckLowS(const std::vector<unsigned char>& vchSig);
     213             : 
     214             :     //! Recover a public key from a compact signature.
     215             :     bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
     216             : 
     217             :     //! Turn this public key into an uncompressed public key.
     218             :     bool Decompress();
     219             : 
     220             :     //! Derive BIP32 child pubkey.
     221             :     [[nodiscard]] bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
     222             : };
     223             : 
     224             : class XOnlyPubKey
     225             : {
     226             : private:
     227             :     uint256 m_keydata;
     228             : 
     229             : public:
     230             :     /** Construct an empty x-only pubkey. */
     231           0 :     XOnlyPubKey() = default;
     232             : 
     233             :     XOnlyPubKey(const XOnlyPubKey&) = default;
     234             :     XOnlyPubKey& operator=(const XOnlyPubKey&) = default;
     235             : 
     236             :     /** Determine if this pubkey is fully valid. This is true for approximately 50% of all
     237             :      *  possible 32-byte arrays. If false, VerifySchnorr, CheckTapTweak and CreateTapTweak
     238             :      *  will always fail. */
     239             :     bool IsFullyValid() const;
     240             : 
     241             :     /** Test whether this is the 0 key (the result of default construction). This implies
     242             :      *  !IsFullyValid(). */
     243           0 :     bool IsNull() const { return m_keydata.IsNull(); }
     244             : 
     245             :     /** Construct an x-only pubkey from exactly 32 bytes. */
     246             :     explicit XOnlyPubKey(Span<const unsigned char> bytes);
     247             : 
     248             :     /** Construct an x-only pubkey from a normal pubkey. */
     249           0 :     explicit XOnlyPubKey(const CPubKey& pubkey) : XOnlyPubKey(Span{pubkey}.subspan(1, 32)) {}
     250             : 
     251             :     /** Verify a Schnorr signature against this public key.
     252             :      *
     253             :      * sigbytes must be exactly 64 bytes.
     254             :      */
     255             :     bool VerifySchnorr(const uint256& msg, Span<const unsigned char> sigbytes) const;
     256             : 
     257             :     /** Compute the Taproot tweak as specified in BIP341, with *this as internal
     258             :      * key:
     259             :      *  - if merkle_root == nullptr: H_TapTweak(xonly_pubkey)
     260             :      *  - otherwise:                 H_TapTweak(xonly_pubkey || *merkle_root)
     261             :      *
     262             :      * Note that the behavior of this function with merkle_root != nullptr is
     263             :      * consensus critical.
     264             :      */
     265             :     uint256 ComputeTapTweakHash(const uint256* merkle_root) const;
     266             : 
     267             :     /** Verify that this is a Taproot tweaked output point, against a specified internal key,
     268             :      *  Merkle root, and parity. */
     269             :     bool CheckTapTweak(const XOnlyPubKey& internal, const uint256& merkle_root, bool parity) const;
     270             : 
     271             :     /** Construct a Taproot tweaked output point with this point as internal key. */
     272             :     std::optional<std::pair<XOnlyPubKey, bool>> CreateTapTweak(const uint256* merkle_root) const;
     273             : 
     274             :     /** Returns a list of CKeyIDs for the CPubKeys that could have been used to create this XOnlyPubKey.
     275             :      * This is needed for key lookups since keys are indexed by CKeyID.
     276             :      */
     277             :     std::vector<CKeyID> GetKeyIDs() const;
     278             : 
     279             :     const unsigned char& operator[](int pos) const { return *(m_keydata.begin() + pos); }
     280           0 :     const unsigned char* data() const { return m_keydata.begin(); }
     281           0 :     static constexpr size_t size() { return decltype(m_keydata)::size(); }
     282           0 :     const unsigned char* begin() const { return m_keydata.begin(); }
     283           0 :     const unsigned char* end() const { return m_keydata.end(); }
     284           0 :     unsigned char* begin() { return m_keydata.begin(); }
     285             :     unsigned char* end() { return m_keydata.end(); }
     286           0 :     bool operator==(const XOnlyPubKey& other) const { return m_keydata == other.m_keydata; }
     287           0 :     bool operator!=(const XOnlyPubKey& other) const { return m_keydata != other.m_keydata; }
     288           0 :     bool operator<(const XOnlyPubKey& other) const { return m_keydata < other.m_keydata; }
     289             : 
     290             :     //! Implement serialization without length prefixes since it is a fixed length
     291           0 :     SERIALIZE_METHODS(XOnlyPubKey, obj) { READWRITE(obj.m_keydata); }
     292             : };
     293             : 
     294             : /** An ElligatorSwift-encoded public key. */
     295             : struct EllSwiftPubKey
     296             : {
     297             : private:
     298             :     static constexpr size_t SIZE = 64;
     299             :     std::array<std::byte, SIZE> m_pubkey;
     300             : 
     301             : public:
     302             :     /** Default constructor creates all-zero pubkey (which is valid). */
     303             :     EllSwiftPubKey() noexcept = default;
     304             : 
     305             :     /** Construct a new ellswift public key from a given serialization. */
     306             :     EllSwiftPubKey(Span<const std::byte> ellswift) noexcept;
     307             : 
     308             :     /** Decode to normal compressed CPubKey (for debugging purposes). */
     309             :     CPubKey Decode() const;
     310             : 
     311             :     // Read-only access for serialization.
     312           0 :     const std::byte* data() const { return m_pubkey.data(); }
     313           0 :     static constexpr size_t size() { return SIZE; }
     314           0 :     auto begin() const { return m_pubkey.cbegin(); }
     315           0 :     auto end() const { return m_pubkey.cend(); }
     316             : 
     317           0 :     bool friend operator==(const EllSwiftPubKey& a, const EllSwiftPubKey& b)
     318             :     {
     319           0 :         return a.m_pubkey == b.m_pubkey;
     320             :     }
     321             : 
     322           0 :     bool friend operator!=(const EllSwiftPubKey& a, const EllSwiftPubKey& b)
     323             :     {
     324           0 :         return a.m_pubkey != b.m_pubkey;
     325             :     }
     326             : };
     327             : 
     328             : struct CExtPubKey {
     329             :     unsigned char version[4];
     330             :     unsigned char nDepth;
     331             :     unsigned char vchFingerprint[4];
     332             :     unsigned int nChild;
     333             :     ChainCode chaincode;
     334             :     CPubKey pubkey;
     335             : 
     336           0 :     friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
     337             :     {
     338           0 :         return a.nDepth == b.nDepth &&
     339           0 :             memcmp(a.vchFingerprint, b.vchFingerprint, sizeof(vchFingerprint)) == 0 &&
     340           0 :             a.nChild == b.nChild &&
     341           0 :             a.chaincode == b.chaincode &&
     342           0 :             a.pubkey == b.pubkey;
     343             :     }
     344             : 
     345           0 :     friend bool operator!=(const CExtPubKey &a, const CExtPubKey &b)
     346             :     {
     347           0 :         return !(a == b);
     348             :     }
     349             : 
     350           0 :     friend bool operator<(const CExtPubKey &a, const CExtPubKey &b)
     351             :     {
     352           0 :         if (a.pubkey < b.pubkey) {
     353           0 :             return true;
     354           0 :         } else if (a.pubkey > b.pubkey) {
     355           0 :             return false;
     356             :         }
     357           0 :         return a.chaincode < b.chaincode;
     358           0 :     }
     359             : 
     360             :     void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
     361             :     void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
     362             :     void EncodeWithVersion(unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]) const;
     363             :     void DecodeWithVersion(const unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]);
     364             :     [[nodiscard]] bool Derive(CExtPubKey& out, unsigned int nChild) const;
     365             : };
     366             : 
     367             : #endif // BITCOIN_PUBKEY_H

Generated by: LCOV version 1.14