LCOV - code coverage report
Current view: top level - src/primitives - block.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 6 77 7.8 %
Date: 2026-06-25 07:23:51 Functions: 1 6 16.7 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2019 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             : #include <primitives/block.h>
       7             : 
       8             : #include <hash.h>
       9             : #include <hash_x11.h>
      10             : #include <streams.h>
      11             : #include <tinyformat.h>
      12             : 
      13     1020111 : uint256 CBlockHeader::GetHash() const
      14             : {
      15     1020111 :     std::vector<unsigned char> vch(80);
      16     1020111 :     CVectorWriter ss(SER_GETHASH, PROTOCOL_VERSION, vch, 0);
      17     1020108 :     ss << *this;
      18     1020111 :     return HashX11((const char *)vch.data(), (const char *)vch.data() + vch.size());
      19     1020117 : }
      20             : 
      21           0 : std::string CBlock::ToString() const
      22             : {
      23           0 :     std::stringstream s;
      24           0 :     s << strprintf("CBlock(hash=%s, ver=0x%08x, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
      25           0 :         GetHash().ToString(),
      26           0 :         nVersion,
      27           0 :         hashPrevBlock.ToString(),
      28           0 :         hashMerkleRoot.ToString(),
      29           0 :         nTime, nBits, nNonce,
      30           0 :         vtx.size());
      31           0 :     for (const auto& tx : vtx) {
      32           0 :         s << "  " << tx->ToString() << "\n";
      33             :     }
      34           0 :     return s.str();
      35           0 : }
      36             : 
      37           0 : static void MarkVersionAsMostRecent(std::list<int32_t>& last_unique_versions, std::list<int32_t>::const_iterator version_it)
      38             : {
      39           0 :     if (version_it != last_unique_versions.cbegin()) {
      40             :         // Move the found version to the front of the list
      41           0 :         last_unique_versions.splice(last_unique_versions.begin(), last_unique_versions, version_it, std::next(version_it));
      42           0 :     }
      43           0 : }
      44             : 
      45           0 : static void SaveVersionAsMostRecent(std::list<int32_t>& last_unique_versions, const int32_t version)
      46             : {
      47           0 :     last_unique_versions.push_front(version);
      48             : 
      49             :     // Always keep the last 7 unique versions
      50           0 :     constexpr std::size_t max_backwards_look_ups = 7;
      51           0 :     if (last_unique_versions.size() > max_backwards_look_ups) {
      52             :         // Evict the oldest version
      53           0 :         last_unique_versions.pop_back();
      54           0 :     }
      55           0 : }
      56             : 
      57           0 : void CompressibleBlockHeader::Compress(const std::vector<CompressibleBlockHeader>& previous_blocks, std::list<int32_t>& last_unique_versions)
      58             : {
      59           0 :     if (previous_blocks.empty()) {
      60             :         // Previous block not available, we have to send the block completely uncompressed
      61           0 :         SaveVersionAsMostRecent(last_unique_versions, nVersion);
      62           0 :         return;
      63             :     }
      64             : 
      65             :     // Try to compress version
      66           0 :     const auto version_it = std::find(last_unique_versions.cbegin(), last_unique_versions.cend(), nVersion);
      67           0 :     if (version_it != last_unique_versions.cend()) {
      68             :         // Version is found in the last 7 unique blocks.
      69           0 :         bit_field.SetVersionOffset(static_cast<uint8_t>(std::distance(last_unique_versions.cbegin(), version_it) + 1));
      70             : 
      71             :         // Mark the version as the most recent one
      72           0 :         MarkVersionAsMostRecent(last_unique_versions, version_it);
      73           0 :     } else {
      74             :         // Save the version as the most recent one
      75           0 :         SaveVersionAsMostRecent(last_unique_versions, nVersion);
      76             :     }
      77             : 
      78             :     // Previous block is available
      79           0 :     const auto& last_block = previous_blocks.back();
      80           0 :     bit_field.MarkAsCompressed(CompressedHeaderBitField::Flag::PREV_BLOCK_HASH);
      81             : 
      82             :     // Compute compressed time diff
      83           0 :     const int64_t time_diff = nTime - last_block.nTime;
      84           0 :     if (time_diff <= std::numeric_limits<int16_t>::max() && time_diff >= std::numeric_limits<int16_t>::min()) {
      85           0 :         time_offset = static_cast<int16_t>(time_diff);
      86           0 :         bit_field.MarkAsCompressed(CompressedHeaderBitField::Flag::TIMESTAMP);
      87           0 :     }
      88             : 
      89             :     // If n_bits matches previous block, it can be compressed (not sent at all)
      90           0 :     if (nBits == last_block.nBits) {
      91           0 :         bit_field.MarkAsCompressed(CompressedHeaderBitField::Flag::NBITS);
      92           0 :     }
      93           0 : }
      94             : 
      95           0 : void CompressibleBlockHeader::Uncompress(const std::vector<CBlockHeader>& previous_blocks, std::list<int32_t>& last_unique_versions)
      96             : {
      97           0 :     if (previous_blocks.empty()) {
      98             :         // First block in chain is always uncompressed
      99           0 :         SaveVersionAsMostRecent(last_unique_versions, nVersion);
     100           0 :         return;
     101             :     }
     102             : 
     103             :     // We have the previous block
     104           0 :     const auto& last_block = previous_blocks.back();
     105             : 
     106             :     // Uncompress version
     107           0 :     if (bit_field.IsVersionCompressed()) {
     108           0 :         const auto version_offset = bit_field.GetVersionOffset();
     109           0 :         if (version_offset <= last_unique_versions.size()) {
     110           0 :             auto version_it = last_unique_versions.begin();
     111           0 :             std::advance(version_it, version_offset - 1);
     112           0 :             nVersion = *version_it;
     113           0 :             MarkVersionAsMostRecent(last_unique_versions, version_it);
     114           0 :         }
     115           0 :     } else {
     116             :         // Save the version as the most recent one
     117           0 :         SaveVersionAsMostRecent(last_unique_versions, nVersion);
     118             :     }
     119             : 
     120             :     // Uncompress prev block hash
     121           0 :     if (bit_field.IsCompressed(CompressedHeaderBitField::Flag::PREV_BLOCK_HASH)) {
     122           0 :         hashPrevBlock = last_block.GetHash();
     123           0 :     }
     124             : 
     125             :     // Uncompress timestamp
     126           0 :     if (bit_field.IsCompressed(CompressedHeaderBitField::Flag::TIMESTAMP)) {
     127           0 :         nTime = last_block.nTime + time_offset;
     128           0 :     }
     129             : 
     130             :     // Uncompress n_bits
     131           0 :     if (bit_field.IsCompressed(CompressedHeaderBitField::Flag::NBITS)) {
     132           0 :         nBits = last_block.nBits;
     133           0 :     }
     134           0 : }

Generated by: LCOV version 1.16