LCOV - code coverage report
Current view: top level - src - pubkey.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 71 78 91.0 %
Date: 2020-09-26 01:30:44 Functions: 37 38 97.4 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2019 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 <uint256.h>
      13             : 
      14             : #include <stdexcept>
      15             : #include <vector>
      16             : 
      17             : const unsigned int BIP32_EXTKEY_SIZE = 74;
      18             : 
      19             : /** A reference to a CKey: the Hash160 of its serialized public key */
      20             : class CKeyID : public uint160
      21             : {
      22             : public:
      23     5923986 :     CKeyID() : uint160() {}
      24     6526018 :     explicit CKeyID(const uint160& in) : uint160(in) {}
      25             : };
      26             : 
      27             : typedef uint256 ChainCode;
      28             : 
      29             : /** An encapsulated public key. */
      30             : class CPubKey
      31             : {
      32             : public:
      33             :     /**
      34             :      * secp256k1:
      35             :      */
      36             :     static constexpr unsigned int SIZE                   = 65;
      37             :     static constexpr unsigned int COMPRESSED_SIZE        = 33;
      38             :     static constexpr unsigned int SIGNATURE_SIZE         = 72;
      39             :     static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65;
      40             :     /**
      41             :      * see www.keylength.com
      42             :      * script supports up to 75 for single byte push
      43             :      */
      44             :     static_assert(
      45             :         SIZE >= COMPRESSED_SIZE,
      46             :         "COMPRESSED_SIZE is larger than SIZE");
      47             : 
      48             : private:
      49             : 
      50             :     /**
      51             :      * Just store the serialized data.
      52             :      * Its length can very cheaply be computed from the first byte.
      53             :      */
      54             :     unsigned char vch[SIZE];
      55             : 
      56             :     //! Compute the length of a pubkey with a given first byte.
      57     6494104 :     unsigned int static GetLen(unsigned char chHeader)
      58             :     {
      59     6494104 :         if (chHeader == 2 || chHeader == 3)
      60     6370464 :             return COMPRESSED_SIZE;
      61      123749 :         if (chHeader == 4 || chHeader == 6 || chHeader == 7)
      62      122400 :             return SIZE;
      63        1349 :         return 0;
      64     6494203 :     }
      65             : 
      66             :     //! Set this key data to be invalid
      67     2575454 :     void Invalidate()
      68             :     {
      69     2575454 :         vch[0] = 0xFF;
      70     2575454 :     }
      71             : 
      72             : public:
      73             : 
      74       61464 :     bool static ValidSize(const std::vector<unsigned char> &vch) {
      75       61464 :       return vch.size() > 0 && GetLen(vch[0]) == vch.size();
      76             :     }
      77             : 
      78             :     //! Construct an invalid public key.
      79     5150364 :     CPubKey()
      80     2575182 :     {
      81     2575182 :         Invalidate();
      82     5150364 :     }
      83             : 
      84             :     //! Initialize a public key using begin/end iterators to byte data.
      85             :     template <typename T>
      86      348383 :     void Set(const T pbegin, const T pend)
      87             :     {
      88      348383 :         int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
      89      348384 :         if (len && len == (pend - pbegin))
      90      348148 :             memcpy(vch, (unsigned char*)&pbegin[0], len);
      91             :         else
      92         266 :             Invalidate();
      93      348437 :     }
      94             : 
      95             :     //! Construct a public key using begin/end iterators to byte data.
      96             :     template <typename T>
      97       51634 :     CPubKey(const T pbegin, const T pend)
      98       25817 :     {
      99       25817 :         Set(pbegin, pend);
     100       51634 :     }
     101             : 
     102             :     //! Construct a public key from a byte vector.
     103      515200 :     explicit CPubKey(const std::vector<unsigned char>& _vch)
     104      257687 :     {
     105      257513 :         Set(_vch.begin(), _vch.end());
     106      515200 :     }
     107             : 
     108             :     //! Simple read-only vector-like interface to the pubkey data.
     109     6095477 :     unsigned int size() const { return GetLen(vch[0]); }
     110      115192 :     const unsigned char* data() const { return vch; }
     111     1741450 :     const unsigned char* begin() const { return vch; }
     112      642140 :     const unsigned char* end() const { return vch + size(); }
     113      209787 :     const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
     114             : 
     115             :     //! Comparator implementation.
     116        1998 :     friend bool operator==(const CPubKey& a, const CPubKey& b)
     117             :     {
     118        3996 :         return a.vch[0] == b.vch[0] &&
     119        1998 :                memcmp(a.vch, b.vch, a.size()) == 0;
     120             :     }
     121             :     friend bool operator!=(const CPubKey& a, const CPubKey& b)
     122             :     {
     123             :         return !(a == b);
     124             :     }
     125      158190 :     friend bool operator<(const CPubKey& a, const CPubKey& b)
     126             :     {
     127      300658 :         return a.vch[0] < b.vch[0] ||
     128      142468 :                (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
     129             :     }
     130             : 
     131             :     //! Implement serialization, as if this was a byte vector.
     132             :     template <typename Stream>
     133       80156 :     void Serialize(Stream& s) const
     134             :     {
     135       80156 :         unsigned int len = size();
     136       80156 :         ::WriteCompactSize(s, len);
     137       80156 :         s.write((char*)vch, len);
     138       80156 :     }
     139             :     template <typename Stream>
     140       41158 :     void Unserialize(Stream& s)
     141             :     {
     142       41158 :         unsigned int len = ::ReadCompactSize(s);
     143       41158 :         if (len <= SIZE) {
     144       41158 :             s.read((char*)vch, len);
     145       41158 :             if (len != size()) {
     146           6 :                 Invalidate();
     147           6 :             }
     148             :         } else {
     149             :             // invalid pubkey, skip available data
     150           0 :             char dummy;
     151           0 :             while (len--)
     152           0 :                 s.read(&dummy, 1);
     153           0 :             Invalidate();
     154           0 :         }
     155       41158 :     }
     156             : 
     157             :     //! Get the KeyID of this public key (hash of its serialization)
     158     1649894 :     CKeyID GetID() const
     159             :     {
     160     1649894 :         return CKeyID(Hash160(MakeSpan(vch).first(size())));
     161             :     }
     162             : 
     163             :     //! Get the 256-bit hash of this public key.
     164        3268 :     uint256 GetHash() const
     165             :     {
     166        3268 :         return Hash(MakeSpan(vch).first(size()));
     167             :     }
     168             : 
     169             :     /*
     170             :      * Check syntactic correctness.
     171             :      *
     172             :      * Note that this is consensus critical as CheckSig() calls it!
     173             :      */
     174     1521658 :     bool IsValid() const
     175             :     {
     176     1521658 :         return size() > 0;
     177             :     }
     178             : 
     179             :     //! fully validate whether this is a valid public key (more expensive than IsValid())
     180             :     bool IsFullyValid() const;
     181             : 
     182             :     //! Check whether this is a compressed public key.
     183      433207 :     bool IsCompressed() const
     184             :     {
     185      433207 :         return size() == COMPRESSED_SIZE;
     186             :     }
     187             : 
     188             :     /**
     189             :      * Verify a DER signature (~72 bytes).
     190             :      * If this public key is not fully valid, the return value will be false.
     191             :      */
     192             :     bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
     193             : 
     194             :     /**
     195             :      * Check whether a signature is normalized (lower-S).
     196             :      */
     197             :     static bool CheckLowS(const std::vector<unsigned char>& vchSig);
     198             : 
     199             :     //! Recover a public key from a compact signature.
     200             :     bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
     201             : 
     202             :     //! Turn this public key into an uncompressed public key.
     203             :     bool Decompress();
     204             : 
     205             :     //! Derive BIP32 child pubkey.
     206             :     bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
     207             : };
     208             : 
     209       38494 : struct CExtPubKey {
     210             :     unsigned char nDepth;
     211             :     unsigned char vchFingerprint[4];
     212             :     unsigned int nChild;
     213             :     ChainCode chaincode;
     214             :     CPubKey pubkey;
     215             : 
     216          23 :     friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
     217             :     {
     218          46 :         return a.nDepth == b.nDepth &&
     219          23 :             memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], sizeof(vchFingerprint)) == 0 &&
     220          23 :             a.nChild == b.nChild &&
     221          23 :             a.chaincode == b.chaincode &&
     222          23 :             a.pubkey == b.pubkey;
     223             :     }
     224             : 
     225           0 :     friend bool operator!=(const CExtPubKey &a, const CExtPubKey &b)
     226             :     {
     227           0 :         return !(a == b);
     228             :     }
     229             : 
     230             :     void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
     231             :     void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
     232             :     bool Derive(CExtPubKey& out, unsigned int nChild) const;
     233             : };
     234             : 
     235             : /** Users of this module must hold an ECCVerifyHandle. The constructor and
     236             :  *  destructor of these are not allowed to run in parallel, though. */
     237             : class ECCVerifyHandle
     238             : {
     239             :     static int refcount;
     240             : 
     241             : public:
     242             :     ECCVerifyHandle();
     243             :     ~ECCVerifyHandle();
     244             : };
     245             : 
     246             : #endif // BITCOIN_PUBKEY_H

Generated by: LCOV version 1.15