LCOV - code coverage report
Current view: top level - src/primitives - block.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 60 77 77.9 %
Date: 2026-06-25 07:23:43 Functions: 5 6 83.3 %

          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     6239753 : uint256 CBlockHeader::GetHash() const
      14             : {
      15     6239753 :     std::vector<unsigned char> vch(80);
      16     6239753 :     CVectorWriter ss(SER_GETHASH, PROTOCOL_VERSION, vch, 0);
      17     6239792 :     ss << *this;
      18     6239807 :     return HashX11((const char *)vch.data(), (const char *)vch.data() + vch.size());
      19     6239867 : }
      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      183551 : static void MarkVersionAsMostRecent(std::list<int32_t>& last_unique_versions, std::list<int32_t>::const_iterator version_it)
      38             : {
      39      183551 :     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      183551 : }
      44             : 
      45      168593 : static void SaveVersionAsMostRecent(std::list<int32_t>& last_unique_versions, const int32_t version)
      46             : {
      47      168593 :     last_unique_versions.push_front(version);
      48             : 
      49             :     // Always keep the last 7 unique versions
      50      168593 :     constexpr std::size_t max_backwards_look_ups = 7;
      51      168593 :     if (last_unique_versions.size() > max_backwards_look_ups) {
      52             :         // Evict the oldest version
      53           0 :         last_unique_versions.pop_back();
      54           0 :     }
      55      168593 : }
      56             : 
      57      172897 : void CompressibleBlockHeader::Compress(const std::vector<CompressibleBlockHeader>& previous_blocks, std::list<int32_t>& last_unique_versions)
      58             : {
      59      172897 :     if (previous_blocks.empty()) {
      60             :         // Previous block not available, we have to send the block completely uncompressed
      61       80434 :         SaveVersionAsMostRecent(last_unique_versions, nVersion);
      62       80434 :         return;
      63             :     }
      64             : 
      65             :     // Try to compress version
      66       92463 :     const auto version_it = std::find(last_unique_versions.cbegin(), last_unique_versions.cend(), nVersion);
      67       92463 :     if (version_it != last_unique_versions.cend()) {
      68             :         // Version is found in the last 7 unique blocks.
      69       91584 :         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       91584 :         MarkVersionAsMostRecent(last_unique_versions, version_it);
      73       91584 :     } else {
      74             :         // Save the version as the most recent one
      75         879 :         SaveVersionAsMostRecent(last_unique_versions, nVersion);
      76             :     }
      77             : 
      78             :     // Previous block is available
      79       92463 :     const auto& last_block = previous_blocks.back();
      80       92463 :     bit_field.MarkAsCompressed(CompressedHeaderBitField::Flag::PREV_BLOCK_HASH);
      81             : 
      82             :     // Compute compressed time diff
      83       92463 :     const int64_t time_diff = nTime - last_block.nTime;
      84       92463 :     if (time_diff <= std::numeric_limits<int16_t>::max() && time_diff >= std::numeric_limits<int16_t>::min()) {
      85       92463 :         time_offset = static_cast<int16_t>(time_diff);
      86       92463 :         bit_field.MarkAsCompressed(CompressedHeaderBitField::Flag::TIMESTAMP);
      87       92463 :     }
      88             : 
      89             :     // If n_bits matches previous block, it can be compressed (not sent at all)
      90       92463 :     if (nBits == last_block.nBits) {
      91       92463 :         bit_field.MarkAsCompressed(CompressedHeaderBitField::Flag::NBITS);
      92       92463 :     }
      93      172897 : }
      94             : 
      95      179247 : void CompressibleBlockHeader::Uncompress(const std::vector<CBlockHeader>& previous_blocks, std::list<int32_t>& last_unique_versions)
      96             : {
      97      179247 :     if (previous_blocks.empty()) {
      98             :         // First block in chain is always uncompressed
      99       86407 :         SaveVersionAsMostRecent(last_unique_versions, nVersion);
     100       86407 :         return;
     101             :     }
     102             : 
     103             :     // We have the previous block
     104       92840 :     const auto& last_block = previous_blocks.back();
     105             : 
     106             :     // Uncompress version
     107       92840 :     if (bit_field.IsVersionCompressed()) {
     108       91967 :         const auto version_offset = bit_field.GetVersionOffset();
     109       91967 :         if (version_offset <= last_unique_versions.size()) {
     110       91967 :             auto version_it = last_unique_versions.begin();
     111       91967 :             std::advance(version_it, version_offset - 1);
     112       91967 :             nVersion = *version_it;
     113       91967 :             MarkVersionAsMostRecent(last_unique_versions, version_it);
     114       91967 :         }
     115       91967 :     } else {
     116             :         // Save the version as the most recent one
     117         873 :         SaveVersionAsMostRecent(last_unique_versions, nVersion);
     118             :     }
     119             : 
     120             :     // Uncompress prev block hash
     121       92840 :     if (bit_field.IsCompressed(CompressedHeaderBitField::Flag::PREV_BLOCK_HASH)) {
     122       92840 :         hashPrevBlock = last_block.GetHash();
     123       92840 :     }
     124             : 
     125             :     // Uncompress timestamp
     126       92840 :     if (bit_field.IsCompressed(CompressedHeaderBitField::Flag::TIMESTAMP)) {
     127       92840 :         nTime = last_block.nTime + time_offset;
     128       92840 :     }
     129             : 
     130             :     // Uncompress n_bits
     131       92840 :     if (bit_field.IsCompressed(CompressedHeaderBitField::Flag::NBITS)) {
     132       92840 :         nBits = last_block.nBits;
     133       92840 :     }
     134      179247 : }

Generated by: LCOV version 1.16