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