LCOV - code coverage report
Current view: top level - src/primitives - block.h (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 57 116 49.1 %
Date: 2026-06-25 07:23:51 Functions: 71 109 65.1 %

          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       82962 :     CBlockHeader()
      35        1155 :     {
      36       81807 :         SetNull();
      37       82962 :     }
      38             : 
      39     3862648 :     SERIALIZE_METHODS(CBlockHeader, obj) { READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot, obj.nTime, obj.nBits, obj.nNonce); }
      40             : 
      41      207412 :     void SetNull()
      42             :     {
      43      207412 :         nVersion = 0;
      44      207412 :         hashPrevBlock.SetNull();
      45      207412 :         hashMerkleRoot.SetNull();
      46      207412 :         nTime = 0;
      47      207412 :         nBits = 0;
      48      207412 :         nNonce = 0;
      49      207412 :     }
      50             : 
      51         958 :     bool IsNull() const
      52             :     {
      53         958 :         return (nBits == 0);
      54             :     }
      55             : 
      56             :     uint256 GetHash() const;
      57             : 
      58      221416 :     int64_t GetBlockTime() const
      59             :     {
      60      221416 :         return (int64_t)nTime;
      61             :     }
      62             : };
      63             : 
      64           0 : class CompressedHeaderBitField
      65             : {
      66           0 :     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           0 :     inline bool IsCompressed(Flag flag) const
      79             :     {
      80           0 :         return (bit_field & to_byte(flag)) == to_byte(0);
      81             :     }
      82             : 
      83           0 :     inline void MarkAsUncompressed(Flag flag)
      84             :     {
      85           0 :         bit_field |= to_byte(flag);
      86           0 :     }
      87             : 
      88           0 :     inline void MarkAsCompressed(Flag flag)
      89             :     {
      90           0 :         bit_field &= ~to_byte(flag);
      91           0 :     }
      92             : 
      93           0 :     inline bool IsVersionCompressed() const
      94             :     {
      95           0 :         return GetVersionOffset() != 0;
      96             :     }
      97             : 
      98           0 :     inline void SetVersionOffset(uint8_t version)
      99             :     {
     100           0 :         bit_field &= ~VERSION_BIT_MASK;
     101           0 :         bit_field |= to_byte(version) & VERSION_BIT_MASK;
     102           0 :     }
     103             : 
     104           0 :     inline uint8_t GetVersionOffset() const
     105             :     {
     106           0 :         return to_uint8(bit_field & VERSION_BIT_MASK);
     107             :     }
     108             : 
     109             :     template <typename Stream>
     110           0 :     void Serialize(Stream& s) const
     111             :     {
     112           0 :         ::Serialize(s, to_uint8(bit_field));
     113           0 :     }
     114             : 
     115             :     template <typename Stream>
     116           0 :     void Unserialize(Stream& s)
     117             :     {
     118             :         uint8_t new_bit_field_value;
     119           0 :         ::Unserialize(s, new_bit_field_value);
     120           0 :         bit_field = to_byte(new_bit_field_value);
     121           0 :     }
     122             : 
     123             : private:
     124           0 :     static constexpr uint8_t to_uint8(const std::byte value)
     125             :     {
     126           0 :         return std::to_integer<uint8_t>(value);
     127             :     }
     128             : 
     129           0 :     static constexpr std::byte to_byte(const uint8_t value)
     130             :     {
     131           0 :         return std::byte{value};
     132             :     }
     133             : 
     134           0 :     static constexpr std::byte to_byte(const Flag flag)
     135             :     {
     136           0 :         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           0 :     int16_t time_offset{0};
     145             : 
     146           0 :     CompressibleBlockHeader() = default;
     147             : 
     148           0 :     explicit CompressibleBlockHeader(CBlockHeader&& block_header)
     149           0 :     {
     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           0 :         *static_cast<CBlockHeader*>(this) = block_header;
     152             : 
     153             :         // When we create this from a block header, mark everything as uncompressed
     154           0 :         bit_field.SetVersionOffset(0);
     155           0 :         bit_field.MarkAsUncompressed(CompressedHeaderBitField::Flag::PREV_BLOCK_HASH);
     156           0 :         bit_field.MarkAsUncompressed(CompressedHeaderBitField::Flag::TIMESTAMP);
     157           0 :         bit_field.MarkAsUncompressed(CompressedHeaderBitField::Flag::NBITS);
     158           0 :     }
     159             : 
     160           0 :     SERIALIZE_METHODS(CompressibleBlockHeader, obj)
     161             :     {
     162           0 :         READWRITE(obj.bit_field);
     163           0 :         if (!obj.bit_field.IsVersionCompressed()) {
     164           0 :             READWRITE(obj.nVersion);
     165           0 :         }
     166           0 :         if (!obj.bit_field.IsCompressed(CompressedHeaderBitField::Flag::PREV_BLOCK_HASH)) {
     167           0 :             READWRITE(obj.hashPrevBlock);
     168           0 :         }
     169           0 :         READWRITE(obj.hashMerkleRoot);
     170           0 :         if (!obj.bit_field.IsCompressed(CompressedHeaderBitField::Flag::TIMESTAMP)) {
     171           0 :             READWRITE(obj.nTime);
     172           0 :         } else {
     173           0 :             READWRITE(obj.time_offset);
     174             :         }
     175           0 :         if (!obj.bit_field.IsCompressed(CompressedHeaderBitField::Flag::NBITS)) {
     176           0 :             READWRITE(obj.nBits);
     177           0 :         }
     178           0 :         READWRITE(obj.nNonce);
     179           0 :     }
     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      161288 :     CBlock()
     196       80644 :     {
     197       80644 :         SetNull();
     198      161288 :     }
     199             : 
     200          16 :     CBlock(const CBlockHeader &header)
     201           8 :     {
     202           8 :         SetNull();
     203           8 :         *(static_cast<CBlockHeader*>(this)) = header;
     204          16 :     }
     205             : 
     206      801351 :     SERIALIZE_METHODS(CBlock, obj)
     207             :     {
     208      267117 :         READWRITEAS(CBlockHeader, obj);
     209      267117 :         READWRITE(obj.vtx);
     210      267117 :     }
     211             : 
     212      125599 :     void SetNull()
     213             :     {
     214      125599 :         CBlockHeader::SetNull();
     215      125599 :         vtx.clear();
     216      125599 :         fChecked = false;
     217      125599 :     }
     218             : 
     219         837 :     CBlockHeader GetBlockHeader() const
     220             :     {
     221         837 :         CBlockHeader block;
     222         837 :         block.nVersion       = nVersion;
     223         837 :         block.hashPrevBlock  = hashPrevBlock;
     224         837 :         block.hashMerkleRoot = hashMerkleRoot;
     225         837 :         block.nTime          = nTime;
     226         837 :         block.nBits          = nBits;
     227         837 :         block.nNonce         = nNonce;
     228         837 :         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         176 :     CBlockLocator() {}
     244             : 
     245         628 :     explicit CBlockLocator(const std::vector<uint256>& vHaveIn) : vHave(vHaveIn) {}
     246             : 
     247         645 :     SERIALIZE_METHODS(CBlockLocator, obj)
     248             :     {
     249         215 :         int nVersion = s.GetVersion();
     250         215 :         if (!(s.GetType() & SER_GETHASH))
     251         215 :             READWRITE(nVersion);
     252         215 :         READWRITE(obj.vHave);
     253         215 :     }
     254             : 
     255         144 :     void SetNull()
     256             :     {
     257         144 :         vHave.clear();
     258         144 :     }
     259             : 
     260         123 :     bool IsNull() const
     261             :     {
     262         123 :         return vHave.empty();
     263             :     }
     264             : };
     265             : 
     266             : #endif // BITCOIN_PRIMITIVES_BLOCK_H

Generated by: LCOV version 1.16