LCOV - code coverage report
Current view: top level - src - pubkey.h (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 102 111 91.9 %
Date: 2022-04-21 14:51:19 Functions: 41 44 93.2 %
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: 52 72 72.2 %

           Branch data     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 <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                 :    3362339 :     CKeyID() : uint160() {}
#      27                 :    8283458 :     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                 :   21556340 :     {
#      62 [ +  + ][ +  + ]:   21556340 :         if (chHeader == 2 || chHeader == 3)
#      63                 :   21468906 :             return COMPRESSED_SIZE;
#      64 [ +  + ][ +  + ]:      87434 :         if (chHeader == 4 || chHeader == 6 || chHeader == 7)
#                 [ +  + ]
#      65                 :      44264 :             return SIZE;
#      66                 :      43170 :         return 0;
#      67                 :      87434 :     }
#      68                 :            : 
#      69                 :            :     //! Set this key data to be invalid
#      70                 :            :     void Invalidate()
#      71                 :    6183844 :     {
#      72                 :    6183844 :         vch[0] = 0xFF;
#      73                 :    6183844 :     }
#      74                 :            : 
#      75                 :            : public:
#      76                 :            : 
#      77                 :      94824 :     bool static ValidSize(const std::vector<unsigned char> &vch) {
#      78 [ +  + ][ +  + ]:      94824 :       return vch.size() > 0 && GetLen(vch[0]) == vch.size();
#      79                 :      94824 :     }
#      80                 :            : 
#      81                 :            :     //! Construct an invalid public key.
#      82                 :            :     CPubKey()
#      83                 :    6162593 :     {
#      84                 :    6162593 :         Invalidate();
#      85                 :    6162593 :     }
#      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                 :    1073463 :     {
#      91 [ -  + ][ -  + ]:    1073463 :         int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
#         [ -  + ][ +  + ]
#      92 [ +  - ][ +  + ]:    1073463 :         if (len && len == (pend - pbegin))
#         [ +  - ][ +  + ]
#         [ +  - ][ +  + ]
#         [ +  - ][ +  - ]
#      93                 :    1052542 :             memcpy(vch, (unsigned char*)&pbegin[0], len);
#      94                 :      20921 :         else
#      95                 :      20921 :             Invalidate();
#      96                 :    1073463 :     }
#      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                 :       1503 :     {
#     102                 :       1503 :         Set(pbegin, pend);
#     103                 :       1503 :     }
#     104                 :            : 
#     105                 :            :     //! Construct a public key from a byte vector.
#     106                 :            :     explicit CPubKey(Span<const uint8_t> _vch)
#     107                 :     409400 :     {
#     108                 :     409400 :         Set(_vch.begin(), _vch.end());
#     109                 :     409400 :     }
#     110                 :            : 
#     111                 :            :     //! Simple read-only vector-like interface to the pubkey data.
#     112                 :   20404636 :     unsigned int size() const { return GetLen(vch[0]); }
#     113                 :    2385467 :     const unsigned char* data() const { return vch; }
#     114                 :    3699946 :     const unsigned char* begin() const { return vch; }
#     115                 :    1022484 :     const unsigned char* end() const { return vch + size(); }
#     116                 :      43305 :     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                 :       6175 :     {
#     121         [ +  - ]:       6175 :         return a.vch[0] == b.vch[0] &&
#     122         [ +  - ]:       6175 :                memcmp(a.vch, b.vch, a.size()) == 0;
#     123                 :       6175 :     }
#     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                 :    4970772 :     {
#     130         [ +  + ]:    4970772 :         return a.vch[0] < b.vch[0] ||
#     131 [ +  + ][ +  + ]:    4970772 :                (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
#     132                 :    4970772 :     }
#     133                 :            :     friend bool operator>(const CPubKey& a, const CPubKey& b)
#     134                 :          4 :     {
#     135         [ -  + ]:          4 :         return a.vch[0] > b.vch[0] ||
#     136 [ +  - ][ +  - ]:          4 :                (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) > 0);
#     137                 :          4 :     }
#     138                 :            : 
#     139                 :            :     //! Implement serialization, as if this was a byte vector.
#     140                 :            :     template <typename Stream>
#     141                 :            :     void Serialize(Stream& s) const
#     142                 :      66354 :     {
#     143                 :      66354 :         unsigned int len = size();
#     144                 :      66354 :         ::WriteCompactSize(s, len);
#     145                 :      66354 :         s.write(AsBytes(Span{vch, len}));
#     146                 :      66354 :     }
#     147                 :            :     template <typename Stream>
#     148                 :            :     void Unserialize(Stream& s)
#     149                 :      44661 :     {
#     150                 :      44661 :         const unsigned int len(::ReadCompactSize(s));
#     151         [ +  - ]:      44661 :         if (len <= SIZE) {
#     152                 :      44661 :             s.read(AsWritableBytes(Span{vch, len}));
#     153         [ +  + ]:      44661 :             if (len != size()) {
#     154                 :         12 :                 Invalidate();
#     155                 :         12 :             }
#     156                 :      44661 :         } else {
#     157                 :            :             // invalid pubkey, skip available data
#     158                 :          0 :             s.ignore(len);
#     159                 :          0 :             Invalidate();
#     160                 :          0 :         }
#     161                 :      44661 :     }
#     162                 :            : 
#     163                 :            :     //! Get the KeyID of this public key (hash of its serialization)
#     164                 :            :     CKeyID GetID() const
#     165                 :    6245692 :     {
#     166                 :    6245692 :         return CKeyID(Hash160(Span{vch}.first(size())));
#     167                 :    6245692 :     }
#     168                 :            : 
#     169                 :            :     //! Get the 256-bit hash of this public key.
#     170                 :            :     uint256 GetHash() const
#     171                 :       6454 :     {
#     172                 :       6454 :         return Hash(Span{vch}.first(size()));
#     173                 :       6454 :     }
#     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                 :    2476680 :     {
#     191                 :    2476680 :         return size() > 0;
#     192                 :    2476680 :     }
#     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                 :     706202 :     {
#     200                 :     706202 :         return size() == COMPRESSED_SIZE;
#     201                 :     706202 :     }
#     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                 :            :     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                 :    2283730 :     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                 :     128168 :     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                 :    1172660 :     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                 :     121741 :     const unsigned char* data() const { return m_keydata.begin(); }
#     281                 :      13386 :     static constexpr size_t size() { return decltype(m_keydata)::size(); }
#     282                 :    1228839 :     const unsigned char* begin() const { return m_keydata.begin(); }
#     283                 :    1228839 :     const unsigned char* end() const { return m_keydata.end(); }
#     284                 :      74729 :     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                 :        117 :     bool operator!=(const XOnlyPubKey& other) const { return m_keydata != other.m_keydata; }
#     288                 :      34801 :     bool operator<(const XOnlyPubKey& other) const { return m_keydata < other.m_keydata; }
#     289                 :            : };
#     290                 :            : 
#     291                 :            : struct CExtPubKey {
#     292                 :            :     unsigned char version[4];
#     293                 :            :     unsigned char nDepth;
#     294                 :            :     unsigned char vchFingerprint[4];
#     295                 :            :     unsigned int nChild;
#     296                 :            :     ChainCode chaincode;
#     297                 :            :     CPubKey pubkey;
#     298                 :            : 
#     299                 :            :     friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
#     300                 :         60 :     {
#     301         [ +  - ]:         60 :         return a.nDepth == b.nDepth &&
#     302         [ +  - ]:         60 :             memcmp(a.vchFingerprint, b.vchFingerprint, sizeof(vchFingerprint)) == 0 &&
#     303         [ +  - ]:         60 :             a.nChild == b.nChild &&
#     304         [ +  - ]:         60 :             a.chaincode == b.chaincode &&
#     305         [ +  - ]:         60 :             a.pubkey == b.pubkey;
#     306                 :         60 :     }
#     307                 :            : 
#     308                 :            :     friend bool operator!=(const CExtPubKey &a, const CExtPubKey &b)
#     309                 :          6 :     {
#     310                 :          6 :         return !(a == b);
#     311                 :          6 :     }
#     312                 :            : 
#     313                 :            :     friend bool operator<(const CExtPubKey &a, const CExtPubKey &b)
#     314                 :          8 :     {
#     315         [ +  + ]:          8 :         if (a.pubkey < b.pubkey) {
#     316                 :          4 :             return true;
#     317         [ +  - ]:          4 :         } else if (a.pubkey > b.pubkey) {
#     318                 :          4 :             return false;
#     319                 :          4 :         }
#     320                 :          0 :         return a.chaincode < b.chaincode;
#     321                 :          8 :     }
#     322                 :            : 
#     323                 :            :     void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
#     324                 :            :     void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
#     325                 :            :     void EncodeWithVersion(unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]) const;
#     326                 :            :     void DecodeWithVersion(const unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]);
#     327                 :            :     bool Derive(CExtPubKey& out, unsigned int nChild) const;
#     328                 :            : };
#     329                 :            : 
#     330                 :            : /** Users of this module must hold an ECCVerifyHandle. The constructor and
#     331                 :            :  *  destructor of these are not allowed to run in parallel, though. */
#     332                 :            : class ECCVerifyHandle
#     333                 :            : {
#     334                 :            :     static int refcount;
#     335                 :            : 
#     336                 :            : public:
#     337                 :            :     ECCVerifyHandle();
#     338                 :            :     ~ECCVerifyHandle();
#     339                 :            : };
#     340                 :            : 
#     341                 :            : typedef struct secp256k1_context_struct secp256k1_context;
#     342                 :            : 
#     343                 :            : /** Access to the internal secp256k1 context used for verification. Only intended to be used
#     344                 :            :  *  by key.cpp. */
#     345                 :            : const secp256k1_context* GetVerifyContext();
#     346                 :            : 
#     347                 :            : #endif // BITCOIN_PUBKEY_H

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a