LCOV - code coverage report
Current view: top level - src - pubkey.h (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 110 122 90.2 %
Date: 2023-09-07 14:00:19 Functions: 53 57 93.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 54 76 71.1 %

           Branch data     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                 :     458680 :     CKeyID() : uint160() {}
#      27                 :    5894800 :     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                 :            :     unsigned int static GetLen(unsigned char chHeader)
#      61                 :   21552658 :     {
#      62 [ +  + ][ +  + ]:   21552658 :         if (chHeader == 2 || chHeader == 3)
#      63                 :   21494548 :             return COMPRESSED_SIZE;
#      64 [ +  + ][ +  + ]:      58110 :         if (chHeader == 4 || chHeader == 6 || chHeader == 7)
#                 [ +  + ]
#      65                 :      18992 :             return SIZE;
#      66                 :      39118 :         return 0;
#      67                 :      58110 :     }
#      68                 :            : 
#      69                 :            :     //! Set this key data to be invalid
#      70                 :            :     void Invalidate()
#      71                 :    4220810 :     {
#      72                 :    4220810 :         vch[0] = 0xFF;
#      73                 :    4220810 :     }
#      74                 :            : 
#      75                 :            : public:
#      76                 :            : 
#      77                 :      26924 :     bool static ValidSize(const std::vector<unsigned char> &vch) {
#      78 [ +  + ][ +  + ]:      26924 :       return vch.size() > 0 && GetLen(vch[0]) == vch.size();
#      79                 :      26924 :     }
#      80                 :            : 
#      81                 :            :     //! Construct an invalid public key.
#      82                 :            :     CPubKey()
#      83                 :    4201588 :     {
#      84                 :    4201588 :         Invalidate();
#      85                 :    4201588 :     }
#      86                 :            : 
#      87                 :            :     //! Initialize a public key using begin/end iterators to byte data.
#      88                 :            :     template <typename T>
#      89                 :            :     void Set(const T pbegin, const T pend)
#      90                 :    1689852 :     {
#      91 [ -  + ][ -  + ]:    1689852 :         int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
#         [ +  + ][ -  + ]
#      92 [ +  - ][ +  + ]:    1689852 :         if (len && len == (pend - pbegin))
#         [ +  + ][ +  - ]
#         [ +  - ][ +  - ]
#         [ +  + ][ +  - ]
#      93                 :    1670737 :             memcpy(vch, (unsigned char*)&pbegin[0], len);
#      94                 :      19115 :         else
#      95                 :      19115 :             Invalidate();
#      96                 :    1689852 :     }
#      97                 :            : 
#      98                 :            :     //! Construct a public key using begin/end iterators to byte data.
#      99                 :            :     template <typename T>
#     100                 :            :     CPubKey(const T pbegin, const T pend)
#     101                 :       2134 :     {
#     102                 :       2134 :         Set(pbegin, pend);
#     103                 :       2134 :     }
#     104                 :            : 
#     105                 :            :     //! Construct a public key from a byte vector.
#     106                 :            :     explicit CPubKey(Span<const uint8_t> _vch)
#     107                 :     386380 :     {
#     108                 :     386380 :         Set(_vch.begin(), _vch.end());
#     109                 :     386380 :     }
#     110                 :            : 
#     111                 :            :     //! Simple read-only vector-like interface to the pubkey data.
#     112                 :   19838311 :     unsigned int size() const { return GetLen(vch[0]); }
#     113                 :    1736618 :     const unsigned char* data() const { return vch; }
#     114                 :    1897350 :     const unsigned char* begin() const { return vch; }
#     115                 :     165078 :     const unsigned char* end() const { return vch + size(); }
#     116                 :      42080 :     const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
#     117                 :            : 
#     118                 :            :     //! Comparator implementation.
#     119                 :            :     friend bool operator==(const CPubKey& a, const CPubKey& b)
#     120                 :       6519 :     {
#     121         [ +  - ]:       6519 :         return a.vch[0] == b.vch[0] &&
#     122         [ +  - ]:       6519 :                memcmp(a.vch, b.vch, a.size()) == 0;
#     123                 :       6519 :     }
#     124                 :            :     friend bool operator!=(const CPubKey& a, const CPubKey& b)
#     125                 :          0 :     {
#     126                 :          0 :         return !(a == b);
#     127                 :          0 :     }
#     128                 :            :     friend bool operator<(const CPubKey& a, const CPubKey& b)
#     129                 :   10028787 :     {
#     130         [ +  + ]:   10028787 :         return a.vch[0] < b.vch[0] ||
#     131 [ +  + ][ +  + ]:   10028787 :                (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
#     132                 :   10028787 :     }
#     133                 :            :     friend bool operator>(const CPubKey& a, const CPubKey& b)
#     134                 :          2 :     {
#     135         [ -  + ]:          2 :         return a.vch[0] > b.vch[0] ||
#     136 [ +  - ][ +  - ]:          2 :                (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) > 0);
#     137                 :          2 :     }
#     138                 :            : 
#     139                 :            :     //! Implement serialization, as if this was a byte vector.
#     140                 :            :     template <typename Stream>
#     141                 :            :     void Serialize(Stream& s) const
#     142                 :      19000 :     {
#     143                 :      19000 :         unsigned int len = size();
#     144                 :      19000 :         ::WriteCompactSize(s, len);
#     145                 :      19000 :         s << Span{vch, len};
#     146                 :      19000 :     }
#     147                 :            :     template <typename Stream>
#     148                 :            :     void Unserialize(Stream& s)
#     149                 :      21760 :     {
#     150                 :      21760 :         const unsigned int len(::ReadCompactSize(s));
#     151 [ +  - ][ +  - ]:      21760 :         if (len <= SIZE) {
#     152                 :      21760 :             s >> Span{vch, len};
#     153 [ +  + ][ -  + ]:      21760 :             if (len != size()) {
#     154                 :         12 :                 Invalidate();
#     155                 :         12 :             }
#     156                 :      21760 :         } else {
#     157                 :            :             // invalid pubkey, skip available data
#     158                 :          0 :             s.ignore(len);
#     159                 :          0 :             Invalidate();
#     160                 :          0 :         }
#     161                 :      21760 :     }
#     162                 :            : 
#     163                 :            :     //! Get the KeyID of this public key (hash of its serialization)
#     164                 :            :     CKeyID GetID() const
#     165                 :    5547867 :     {
#     166                 :    5547867 :         return CKeyID(Hash160(Span{vch}.first(size())));
#     167                 :    5547867 :     }
#     168                 :            : 
#     169                 :            :     //! Get the 256-bit hash of this public key.
#     170                 :            :     uint256 GetHash() const
#     171                 :       8202 :     {
#     172                 :       8202 :         return Hash(Span{vch}.first(size()));
#     173                 :       8202 :     }
#     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                 :            :     bool IsValid() const
#     190                 :    1233655 :     {
#     191                 :    1233655 :         return size() > 0;
#     192                 :    1233655 :     }
#     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                 :            :     bool IsCompressed() const
#     199                 :      47310 :     {
#     200                 :      47310 :         return size() == COMPRESSED_SIZE;
#     201                 :      47310 :     }
#     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                 :    1219938 :     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                 :      31400 :     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                 :    1130479 :     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                 :          0 :     const unsigned char& operator[](int pos) const { return *(m_keydata.begin() + pos); }
#     280                 :     189735 :     const unsigned char* data() const { return m_keydata.begin(); }
#     281                 :      14148 :     static constexpr size_t size() { return decltype(m_keydata)::size(); }
#     282                 :    1291740 :     const unsigned char* begin() const { return m_keydata.begin(); }
#     283                 :    1291740 :     const unsigned char* end() const { return m_keydata.end(); }
#     284                 :     149829 :     unsigned char* begin() { return m_keydata.begin(); }
#     285                 :          8 :     unsigned char* end() { return m_keydata.end(); }
#     286                 :          0 :     bool operator==(const XOnlyPubKey& other) const { return m_keydata == other.m_keydata; }
#     287                 :       3897 :     bool operator!=(const XOnlyPubKey& other) const { return m_keydata != other.m_keydata; }
#     288                 :     376131 :     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                 :       6865 :     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                 :     493694 :     const std::byte* data() const { return m_pubkey.data(); }
#     313                 :    2416370 :     static constexpr size_t size() { return SIZE; }
#     314                 :     340200 :     auto begin() const { return m_pubkey.cbegin(); }
#     315                 :     340200 :     auto end() const { return m_pubkey.cend(); }
#     316                 :            : 
#     317                 :            :     bool friend operator==(const EllSwiftPubKey& a, const EllSwiftPubKey& b)
#     318                 :        196 :     {
#     319                 :        196 :         return a.m_pubkey == b.m_pubkey;
#     320                 :        196 :     }
#     321                 :            : 
#     322                 :            :     bool friend operator!=(const EllSwiftPubKey& a, const EllSwiftPubKey& b)
#     323                 :          0 :     {
#     324                 :          0 :         return a.m_pubkey != b.m_pubkey;
#     325                 :          0 :     }
#     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                 :            :     friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
#     337                 :         60 :     {
#     338         [ +  - ]:         60 :         return a.nDepth == b.nDepth &&
#     339         [ +  - ]:         60 :             memcmp(a.vchFingerprint, b.vchFingerprint, sizeof(vchFingerprint)) == 0 &&
#     340         [ +  - ]:         60 :             a.nChild == b.nChild &&
#     341         [ +  - ]:         60 :             a.chaincode == b.chaincode &&
#     342         [ +  - ]:         60 :             a.pubkey == b.pubkey;
#     343                 :         60 :     }
#     344                 :            : 
#     345                 :            :     friend bool operator!=(const CExtPubKey &a, const CExtPubKey &b)
#     346                 :          6 :     {
#     347                 :          6 :         return !(a == b);
#     348                 :          6 :     }
#     349                 :            : 
#     350                 :            :     friend bool operator<(const CExtPubKey &a, const CExtPubKey &b)
#     351                 :          4 :     {
#     352         [ +  + ]:          4 :         if (a.pubkey < b.pubkey) {
#     353                 :          2 :             return true;
#     354         [ +  - ]:          2 :         } else if (a.pubkey > b.pubkey) {
#     355                 :          2 :             return false;
#     356                 :          2 :         }
#     357                 :          0 :         return a.chaincode < b.chaincode;
#     358                 :          4 :     }
#     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 3.1-eol-3983-g6fec45e53af6