LCOV - code coverage report
Current view: top level - src - pubkey.h (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 79 91 86.8 %
Date: 2021-06-29 14:35:33 Functions: 29 32 90.6 %
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: 45 64 70.3 %

           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

Generated by: LCOV version 1.14