LCOV - code coverage report
Current view: top level - src - pubkey.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 64 67 95.5 %
Date: 2025-02-23 09:33:43 Functions: 14 15 93.3 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 The Bitcoin developers
       3             : // Copyright (c) 2016-2021 The PIVX Core 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 PIVX_PUBKEY_H
       8             : #define PIVX_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    24181649 :     CKeyID() : uint160() {}
      24    12745114 :     explicit CKeyID(const uint160& in) : uint160(in) {}
      25             : };
      26             : 
      27             : /** A reference to a CKey: the Hash160 of its serialized public key, special case for exchange key */
      28             : 
      29             : class CExchangeKeyID : public uint160
      30             : {
      31             : public:
      32             :     CExchangeKeyID() : uint160() {}
      33          17 :     explicit CExchangeKeyID(const uint160& in) : uint160(in) {}
      34             : 
      35          15 :     operator CKeyID() const {
      36          15 :         return CKeyID(static_cast<const uint160&>(*this));
      37             :     }
      38             : };
      39             : 
      40             : typedef uint256 ChainCode;
      41             : 
      42             : /** An encapsulated public key. */
      43             : class CPubKey
      44             : {
      45             : public:
      46             :     /**
      47             :      * secp256k1:
      48             :      */
      49             :     static constexpr unsigned int PUBLIC_KEY_SIZE             = 65;
      50             :     static constexpr unsigned int COMPRESSED_PUBLIC_KEY_SIZE  = 33;
      51             :     static constexpr unsigned int SIGNATURE_SIZE              = 72;
      52             :     static constexpr unsigned int COMPACT_SIGNATURE_SIZE      = 65;
      53             :     /**
      54             :      * see www.keylength.com
      55             :      * script supports up to 75 for single byte push
      56             :      */
      57             :     static_assert(
      58             :         PUBLIC_KEY_SIZE >= COMPRESSED_PUBLIC_KEY_SIZE,
      59             :         "COMPRESSED_PUBLIC_KEY_SIZE is larger than PUBLIC_KEY_SIZE");
      60             : 
      61             : private:
      62             :     /**
      63             :      * Just store the serialized data.
      64             :      * Its length can very cheaply be computed from the first byte.
      65             :      */
      66             :     unsigned char vch[PUBLIC_KEY_SIZE];
      67             : 
      68             :     //! Compute the length of a pubkey with a given first byte.
      69    18290297 :     unsigned int static GetLen(unsigned char chHeader)
      70             :     {
      71    18290297 :         if (chHeader == 2 || chHeader == 3)
      72             :             return COMPRESSED_PUBLIC_KEY_SIZE;
      73       71979 :         if (chHeader == 4 || chHeader == 6 || chHeader == 7)
      74       47804 :             return PUBLIC_KEY_SIZE;
      75             :         return 0;
      76             :     }
      77             : 
      78             :     //! Set this key data to be invalid
      79     7460455 :     void Invalidate()
      80             :     {
      81     7460455 :         vch[0] = 0xFF;
      82          12 :     }
      83             : 
      84             : public:
      85             : 
      86       24838 :     bool static ValidSize(const std::vector<unsigned char> &vch) {
      87       26103 :       return vch.size() > 0 && GetLen(vch[0]) == vch.size();
      88             :     }
      89             : 
      90             :     //! Construct an invalid public key.
      91     7460443 :     CPubKey()
      92     7460443 :     {
      93     7441837 :         Invalidate();
      94             :     }
      95             : 
      96             :     //! Initialize a public key using begin/end iterators to byte data.
      97             :     template <typename T>
      98     1895121 :     void Set(const T pbegin, const T pend)
      99             :     {
     100     1895123 :         int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
     101     1895111 :         if (len && len == (pend - pbegin))
     102     1895109 :             memcpy(vch, (unsigned char*)&pbegin[0], len);
     103             :         else
     104     1895121 :             Invalidate();
     105     1895121 :     }
     106             : 
     107             :     //! Construct a public key using begin/end iterators to byte data.
     108             :     template <typename T>
     109        6708 :     CPubKey(const T pbegin, const T pend)
     110             :     {
     111        6708 :         Set(pbegin, pend);
     112             :     }
     113             : 
     114             :     //! Construct a public key from a byte vector.
     115     1863423 :     explicit CPubKey(const std::vector<unsigned char>& _vch)
     116     1863423 :     {
     117     1863423 :         Set(_vch.begin(), _vch.end());
     118     1863423 :     }
     119             : 
     120             :     //! Simple read-only vector-like interface to the pubkey data.
     121    19063587 :     unsigned int size() const { return GetLen(vch[0]); }
     122     1419420 :     const unsigned char* data() const { return vch; }
     123     7277903 :     const unsigned char* begin() const { return vch; }
     124     3576762 :     const unsigned char* end() const { return vch + size(); }
     125         923 :     const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
     126             : 
     127             :     //! Comparator implementation.
     128       18908 :     friend bool operator==(const CPubKey& a, const CPubKey& b)
     129             :     {
     130       18908 :         return a.vch[0] == b.vch[0] &&
     131        9838 :                memcmp(a.vch, b.vch, a.size()) == 0;
     132             :     }
     133             :     friend bool operator!=(const CPubKey& a, const CPubKey& b)
     134             :     {
     135             :         return !(a == b);
     136             :     }
     137             :     friend bool operator<(const CPubKey& a, const CPubKey& b)
     138             :     {
     139             :         return a.vch[0] < b.vch[0] ||
     140             :                (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
     141             :     }
     142             : 
     143             :     //! Implement serialization, as if this was a byte vector.
     144             :     template <typename Stream>
     145       43773 :     void Serialize(Stream& s) const
     146             :     {
     147       43773 :         unsigned int len = size();
     148       43773 :         ::WriteCompactSize(s, len);
     149       43773 :         s.write((char*)vch, len);
     150       43773 :     }
     151             :     template <typename Stream>
     152       26021 :     void Unserialize(Stream& s)
     153             :     {
     154       26021 :         unsigned int len = ::ReadCompactSize(s);
     155       26021 :         if (len <= PUBLIC_KEY_SIZE) {
     156       26021 :             s.read((char*)vch, len);
     157             :         } else {
     158             :             // invalid pubkey, skip available data
     159             :             char dummy;
     160           0 :             while (len--)
     161           0 :                 s.read(&dummy, 1);
     162           0 :             Invalidate();
     163             :         }
     164       26021 :     }
     165             : 
     166             :     //! Get the KeyID of this public key (hash of its serialization)
     167      299495 :     CKeyID GetID() const
     168             :     {
     169      308229 :         return CKeyID(Hash160(vch, vch + size()));
     170             :     }
     171             : 
     172             :     //! Get the 256-bit hash of this public key.
     173        4781 :     uint256 GetHash() const
     174             :     {
     175        4781 :         return Hash(vch, vch + size());
     176             :     }
     177             : 
     178             :     /*
     179             :      * Check syntactic correctness.
     180             :      *
     181             :      * Note that this is consensus critical as CheckSig() calls it!
     182             :      */
     183     6408985 :     bool IsValid() const
     184             :     {
     185     8270548 :         return size() > 0;
     186             :     }
     187             : 
     188             :     //! fully validate whether this is a valid public key (more expensive than IsValid())
     189             :     bool IsFullyValid() const;
     190             : 
     191             :     //! Check whether this is a compressed public key.
     192       27031 :     bool IsCompressed() const
     193             :     {
     194       27046 :         return size() == COMPRESSED_PUBLIC_KEY_SIZE;
     195             :     }
     196             : 
     197             :     /**
     198             :      * Verify a DER signature (~72 bytes).
     199             :      * If this public key is not fully valid, the return value will be false.
     200             :      */
     201             :     bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
     202             : 
     203             :     /**
     204             :      * Check whether a signature is normalized (lower-S).
     205             :      */
     206             :     static bool CheckLowS(const std::vector<unsigned char>& vchSig);
     207             : 
     208             :     //! Recover a public key from a compact signature.
     209             :     bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
     210             : 
     211             :     //! Turn this public key into an uncompressed public key.
     212             :     bool Decompress();
     213             : 
     214             :     //! Derive BIP32 child pubkey.
     215             :     bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
     216             : 
     217          20 :     std::vector<unsigned char> Raw() const
     218             :     {
     219          20 :         return std::vector<unsigned char>(vch, vch + size());
     220             :     }
     221             : 
     222             : };
     223             : 
     224       18200 : struct CExtPubKey {
     225             :     unsigned char nDepth;
     226             :     unsigned char vchFingerprint[4];
     227             :     unsigned int nChild;
     228             :     ChainCode chaincode;
     229             :     CPubKey pubkey;
     230             : 
     231          23 :     friend bool operator==(const CExtPubKey& a, const CExtPubKey& b)
     232             :     {
     233          46 :         return a.nDepth == b.nDepth &&
     234          23 :             memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], sizeof(vchFingerprint)) == 0 &&
     235          23 :             a.nChild == b.nChild &&
     236          46 :             a.chaincode == b.chaincode &&
     237          23 :             a.pubkey == b.pubkey;
     238             :     }
     239             : 
     240             :     void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
     241             :     void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
     242             :     bool Derive(CExtPubKey& out, unsigned int nChild) const;
     243             : 
     244             :     void Serialize(CSizeComputer& s) const
     245             :     {
     246             :         // Optimized implementation for ::GetSerializeSize that avoids copying.
     247             :         s.seek(BIP32_EXTKEY_SIZE + 1); // add one byte for the size (compact int)
     248             :     }
     249             :     template <typename Stream>
     250             :     void Serialize(Stream& s) const
     251             :     {
     252             :         unsigned int len = BIP32_EXTKEY_SIZE;
     253             :         ::WriteCompactSize(s, len);
     254             :         unsigned char code[BIP32_EXTKEY_SIZE];
     255             :         Encode(code);
     256             :         s.write((const char *)&code[0], len);
     257             :     }
     258             :     template <typename Stream>
     259             :     void Unserialize(Stream& s)
     260             :     {
     261             :         unsigned int len = ::ReadCompactSize(s);
     262             :         unsigned char code[BIP32_EXTKEY_SIZE];
     263             :         if (len != BIP32_EXTKEY_SIZE)
     264             :             throw std::runtime_error("Invalid extended key size\n");
     265             :         s.read((char *)&code[0], len);
     266             :         Decode(code);
     267             :     }
     268             : };
     269             : 
     270             : /** Users of this module must hold an ECCVerifyHandle. The constructor and
     271             :  *  destructor of these are not allowed to run in parallel, though. */
     272             : class ECCVerifyHandle
     273             : {
     274             :     static int refcount;
     275             : 
     276             : public:
     277             :     ECCVerifyHandle();
     278             :     ~ECCVerifyHandle();
     279             : };
     280             : 
     281             : #endif // PIVX_PUBKEY_H

Generated by: LCOV version 1.14