LCOV - code coverage report
Current view: top level - src/primitives - block.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 116 116 100.0 %
Date: 2026-06-25 07:23:43 Functions: 106 109 97.2 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2020 The Bitcoin Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #ifndef BITCOIN_PRIMITIVES_BLOCK_H
       7             : #define BITCOIN_PRIMITIVES_BLOCK_H
       8             : 
       9             : #include <list>
      10             : #include <primitives/transaction.h>
      11             : #include <serialize.h>
      12             : #include <uint256.h>
      13             : #include <cstddef>
      14             : #include <type_traits>
      15             : 
      16             : /** Nodes collect new transactions into a block, hash them into a hash tree,
      17             :  * and scan through nonce values to make the block's hash satisfy proof-of-work
      18             :  * requirements.  When they solve the proof-of-work, they broadcast the block
      19             :  * to everyone and the block is added to the block chain.  The first transaction
      20             :  * in the block is a special one that creates a new coin owned by the creator
      21             :  * of the block.
      22             :  */
      23             : class CBlockHeader
      24             : {
      25             : public:
      26             :     // header
      27             :     int32_t nVersion;
      28             :     uint256 hashPrevBlock;
      29             :     uint256 hashMerkleRoot;
      30             :     uint32_t nTime;
      31             :     uint32_t nBits;
      32             :     uint32_t nNonce;
      33             : 
      34     3029885 :     CBlockHeader()
      35      640145 :     {
      36     2389740 :         SetNull();
      37     3029885 :     }
      38             : 
      39    28806638 :     SERIALIZE_METHODS(CBlockHeader, obj) { READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot, obj.nTime, obj.nBits, obj.nNonce); }
      40             : 
      41     4591451 :     void SetNull()
      42             :     {
      43     4591451 :         nVersion = 0;
      44     4591451 :         hashPrevBlock.SetNull();
      45     4591451 :         hashMerkleRoot.SetNull();
      46     4591451 :         nTime = 0;
      47     4591451 :         nBits = 0;
      48     4591451 :         nNonce = 0;
      49     4591451 :     }
      50             : 
      51      631647 :     bool IsNull() const
      52             :     {
      53      631647 :         return (nBits == 0);
      54             :     }
      55             : 
      56             :     uint256 GetHash() const;
      57             : 
      58     1501609 :     int64_t GetBlockTime() const
      59             :     {
      60     1501609 :         return (int64_t)nTime;
      61             :     }
      62             : };
      63             : 
      64      357972 : class CompressedHeaderBitField
      65             : {
      66      357972 :     std::byte bit_field{0};
      67             : 
      68             : public:
      69             :     enum class Flag : std::underlying_type_t<std::byte> {
      70             :         VERSION_BIT_0 = (1 << 0),
      71             :         VERSION_BIT_1 = (1 << 1),
      72             :         VERSION_BIT_2 = (1 << 2),
      73             :         PREV_BLOCK_HASH = (1 << 3),
      74             :         TIMESTAMP = (1 << 4),
      75             :         NBITS = (1 << 5),
      76             :     };
      77             : 
      78     1352436 :     inline bool IsCompressed(Flag flag) const
      79             :     {
      80     1352436 :         return (bit_field & to_byte(flag)) == to_byte(0);
      81             :     }
      82             : 
      83      536175 :     inline void MarkAsUncompressed(Flag flag)
      84             :     {
      85      536175 :         bit_field |= to_byte(flag);
      86      536175 :     }
      87             : 
      88      277389 :     inline void MarkAsCompressed(Flag flag)
      89             :     {
      90      277389 :         bit_field &= ~to_byte(flag);
      91      277389 :     }
      92             : 
      93      450812 :     inline bool IsVersionCompressed() const
      94             :     {
      95      450812 :         return GetVersionOffset() != 0;
      96             :     }
      97             : 
      98      270309 :     inline void SetVersionOffset(uint8_t version)
      99             :     {
     100      270309 :         bit_field &= ~VERSION_BIT_MASK;
     101      270309 :         bit_field |= to_byte(version) & VERSION_BIT_MASK;
     102      270309 :     }
     103             : 
     104      542779 :     inline uint8_t GetVersionOffset() const
     105             :     {
     106      542779 :         return to_uint8(bit_field & VERSION_BIT_MASK);
     107             :     }
     108             : 
     109             :     template <typename Stream>
     110      178725 :     void Serialize(Stream& s) const
     111             :     {
     112      178725 :         ::Serialize(s, to_uint8(bit_field));
     113      178725 :     }
     114             : 
     115             :     template <typename Stream>
     116      179247 :     void Unserialize(Stream& s)
     117             :     {
     118             :         uint8_t new_bit_field_value;
     119      179247 :         ::Unserialize(s, new_bit_field_value);
     120      179247 :         bit_field = to_byte(new_bit_field_value);
     121      179247 :     }
     122             : 
     123             : private:
     124      721504 :     static constexpr uint8_t to_uint8(const std::byte value)
     125             :     {
     126      721504 :         return std::to_integer<uint8_t>(value);
     127             :     }
     128             : 
     129     1801992 :     static constexpr std::byte to_byte(const uint8_t value)
     130             :     {
     131     1801992 :         return std::byte{value};
     132             :     }
     133             : 
     134     2166000 :     static constexpr std::byte to_byte(const Flag flag)
     135             :     {
     136     2166000 :         return static_cast<std::byte>(flag);
     137             :     }
     138             : 
     139             :     static constexpr std::byte VERSION_BIT_MASK = static_cast<std::byte>(Flag::VERSION_BIT_0) | static_cast<std::byte>(Flag::VERSION_BIT_1) | static_cast<std::byte>(Flag::VERSION_BIT_2);
     140             : };
     141             : 
     142             : struct CompressibleBlockHeader : CBlockHeader {
     143             :     CompressedHeaderBitField bit_field;
     144      357972 :     int16_t time_offset{0};
     145             : 
     146      537741 :     CompressibleBlockHeader() = default;
     147             : 
     148      357450 :     explicit CompressibleBlockHeader(CBlockHeader&& block_header)
     149      178725 :     {
     150             :         static_assert(std::is_trivially_copyable_v<CBlockHeader>, "If CBlockHeader is not trivially copyable, please consider using std::move on the next line");
     151      178725 :         *static_cast<CBlockHeader*>(this) = block_header;
     152             : 
     153             :         // When we create this from a block header, mark everything as uncompressed
     154      178725 :         bit_field.SetVersionOffset(0);
     155      178725 :         bit_field.MarkAsUncompressed(CompressedHeaderBitField::Flag::PREV_BLOCK_HASH);
     156      178725 :         bit_field.MarkAsUncompressed(CompressedHeaderBitField::Flag::TIMESTAMP);
     157      178725 :         bit_field.MarkAsUncompressed(CompressedHeaderBitField::Flag::NBITS);
     158      357450 :     }
     159             : 
     160     1073916 :     SERIALIZE_METHODS(CompressibleBlockHeader, obj)
     161             :     {
     162      357972 :         READWRITE(obj.bit_field);
     163      357972 :         if (!obj.bit_field.IsVersionCompressed()) {
     164      174421 :             READWRITE(obj.nVersion);
     165      174421 :         }
     166      357972 :         if (!obj.bit_field.IsCompressed(CompressedHeaderBitField::Flag::PREV_BLOCK_HASH)) {
     167      172669 :             READWRITE(obj.hashPrevBlock);
     168      172669 :         }
     169      357972 :         READWRITE(obj.hashMerkleRoot);
     170      357972 :         if (!obj.bit_field.IsCompressed(CompressedHeaderBitField::Flag::TIMESTAMP)) {
     171      172669 :             READWRITE(obj.nTime);
     172      172669 :         } else {
     173      185303 :             READWRITE(obj.time_offset);
     174             :         }
     175      357972 :         if (!obj.bit_field.IsCompressed(CompressedHeaderBitField::Flag::NBITS)) {
     176      172669 :             READWRITE(obj.nBits);
     177      172669 :         }
     178      357972 :         READWRITE(obj.nNonce);
     179      357972 :     }
     180             : 
     181             :     void Compress(const std::vector<CompressibleBlockHeader>& previous_blocks, std::list<int32_t>& last_unique_versions);
     182             : 
     183             :     void Uncompress(const std::vector<CBlockHeader>& previous_blocks, std::list<int32_t>& last_unique_versions);
     184             : };
     185             : 
     186             : class CBlock : public CBlockHeader
     187             : {
     188             : public:
     189             :     // network and disk
     190             :     std::vector<CTransactionRef> vtx;
     191             : 
     192             :     // memory only
     193             :     mutable bool fChecked;
     194             : 
     195     2301628 :     CBlock()
     196     1150814 :     {
     197     1150814 :         SetNull();
     198     2301628 :     }
     199             : 
     200      481620 :     CBlock(const CBlockHeader &header)
     201      240810 :     {
     202      240810 :         SetNull();
     203      240810 :         *(static_cast<CBlockHeader*>(this)) = header;
     204      481620 :     }
     205             : 
     206     7919980 :     SERIALIZE_METHODS(CBlock, obj)
     207             :     {
     208     2639998 :         READWRITEAS(CBlockHeader, obj);
     209     2639998 :         READWRITE(obj.vtx);
     210     2639998 :     }
     211             : 
     212     2104031 :     void SetNull()
     213             :     {
     214     2104031 :         CBlockHeader::SetNull();
     215     2104031 :         vtx.clear();
     216     2104031 :         fChecked = false;
     217     2104031 :     }
     218             : 
     219      123775 :     CBlockHeader GetBlockHeader() const
     220             :     {
     221      123775 :         CBlockHeader block;
     222      123775 :         block.nVersion       = nVersion;
     223      123775 :         block.hashPrevBlock  = hashPrevBlock;
     224      123775 :         block.hashMerkleRoot = hashMerkleRoot;
     225      123775 :         block.nTime          = nTime;
     226      123775 :         block.nBits          = nBits;
     227      123775 :         block.nNonce         = nNonce;
     228      123775 :         return block;
     229             :     }
     230             : 
     231             :     std::string ToString() const;
     232             : };
     233             : 
     234             : 
     235             : /** Describes a place in the block chain to another node such that if the
     236             :  * other node doesn't have the same branch, it can find a recent common trunk.
     237             :  * The further back it is, the further before the fork it may be.
     238             :  */
     239             : struct CBlockLocator
     240             : {
     241             :     std::vector<uint256> vHave;
     242             : 
     243       36810 :     CBlockLocator() {}
     244             : 
     245       82178 :     explicit CBlockLocator(const std::vector<uint256>& vHaveIn) : vHave(vHaveIn) {}
     246             : 
     247      168744 :     SERIALIZE_METHODS(CBlockLocator, obj)
     248             :     {
     249       56248 :         int nVersion = s.GetVersion();
     250       56248 :         if (!(s.GetType() & SER_GETHASH))
     251       56248 :             READWRITE(nVersion);
     252       56248 :         READWRITE(obj.vHave);
     253       56248 :     }
     254             : 
     255        3400 :     void SetNull()
     256             :     {
     257        3400 :         vHave.clear();
     258        3400 :     }
     259             : 
     260       22902 :     bool IsNull() const
     261             :     {
     262       22902 :         return vHave.empty();
     263             :     }
     264             : };
     265             : 
     266             : #endif // BITCOIN_PRIMITIVES_BLOCK_H

Generated by: LCOV version 1.16