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 : }