/Users/eugenesiegel/btc/bitcoin/src/chain.h
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | // Copyright (c) 2009-2010 Satoshi Nakamoto | 
| 2 |  | // Copyright (c) 2009-2022 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_CHAIN_H | 
| 7 |  | #define BITCOIN_CHAIN_H | 
| 8 |  |  | 
| 9 |  | #include <arith_uint256.h> | 
| 10 |  | #include <consensus/params.h> | 
| 11 |  | #include <flatfile.h> | 
| 12 |  | #include <kernel/cs_main.h> | 
| 13 |  | #include <primitives/block.h> | 
| 14 |  | #include <serialize.h> | 
| 15 |  | #include <sync.h> | 
| 16 |  | #include <uint256.h> | 
| 17 |  | #include <util/time.h> | 
| 18 |  |  | 
| 19 |  | #include <algorithm> | 
| 20 |  | #include <cassert> | 
| 21 |  | #include <cstdint> | 
| 22 |  | #include <string> | 
| 23 |  | #include <vector> | 
| 24 |  |  | 
| 25 |  | /** | 
| 26 |  |  * Maximum amount of time that a block timestamp is allowed to exceed the | 
| 27 |  |  * current time before the block will be accepted. | 
| 28 |  |  */ | 
| 29 |  | static constexpr int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60; | 
| 30 |  |  | 
| 31 |  | /** | 
| 32 |  |  * Timestamp window used as a grace period by code that compares external | 
| 33 |  |  * timestamps (such as timestamps passed to RPCs, or wallet key creation times) | 
| 34 |  |  * to block timestamps. This should be set at least as high as | 
| 35 |  |  * MAX_FUTURE_BLOCK_TIME. | 
| 36 |  |  */ | 
| 37 |  | static constexpr int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME; | 
| 38 |  |  | 
| 39 |  | /** | 
| 40 |  |  * Maximum gap between node time and block time used | 
| 41 |  |  * for the "Catching up..." mode in GUI. | 
| 42 |  |  * | 
| 43 |  |  * Ref: https://github.com/bitcoin/bitcoin/pull/1026 | 
| 44 |  |  */ | 
| 45 |  | static constexpr int64_t MAX_BLOCK_TIME_GAP = 90 * 60; | 
| 46 |  |  | 
| 47 |  | class CBlockFileInfo | 
| 48 |  | { | 
| 49 |  | public: | 
| 50 |  |     unsigned int nBlocks{};      //!< number of blocks stored in file | 
| 51 |  |     unsigned int nSize{};        //!< number of used bytes of block file | 
| 52 |  |     unsigned int nUndoSize{};    //!< number of used bytes in the undo file | 
| 53 |  |     unsigned int nHeightFirst{}; //!< lowest height of block in file | 
| 54 |  |     unsigned int nHeightLast{};  //!< highest height of block in file | 
| 55 |  |     uint64_t nTimeFirst{};       //!< earliest time of block in file | 
| 56 |  |     uint64_t nTimeLast{};        //!< latest time of block in file | 
| 57 |  |  | 
| 58 |  |     SERIALIZE_METHODS(CBlockFileInfo, obj) | 
| 59 | 53.1k |     { | 
| 60 | 53.1k |         READWRITE(VARINT(obj.nBlocks)); | Line | Count | Source |  | 145 | 51.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(VARINT(obj.nBlocks)); | Line | Count | Source |  | 145 | 1.89k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 61 | 53.1k |         READWRITE(VARINT(obj.nSize)); | Line | Count | Source |  | 145 | 51.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(VARINT(obj.nSize)); | Line | Count | Source |  | 145 | 1.89k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 62 | 53.1k |         READWRITE(VARINT(obj.nUndoSize)); | Line | Count | Source |  | 145 | 51.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(VARINT(obj.nUndoSize)); | Line | Count | Source |  | 145 | 1.89k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 63 | 53.1k |         READWRITE(VARINT(obj.nHeightFirst)); | Line | Count | Source |  | 145 | 51.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(VARINT(obj.nHeightFirst)); | Line | Count | Source |  | 145 | 1.89k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 64 | 53.1k |         READWRITE(VARINT(obj.nHeightLast)); | Line | Count | Source |  | 145 | 51.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(VARINT(obj.nHeightLast)); | Line | Count | Source |  | 145 | 1.89k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 65 | 53.1k |         READWRITE(VARINT(obj.nTimeFirst)); | Line | Count | Source |  | 145 | 51.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(VARINT(obj.nTimeFirst)); | Line | Count | Source |  | 145 | 1.89k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 66 | 53.1k |         READWRITE(VARINT(obj.nTimeLast)); | Line | Count | Source |  | 145 | 51.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(VARINT(obj.nTimeLast)); | Line | Count | Source |  | 145 | 1.89k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 67 | 53.1k |     } _ZN14CBlockFileInfo16SerializationOpsI10DataStreamS_17ActionUnserializeEEvRT0_RT_T1_| Line | Count | Source |  | 59 | 51.2k |     { |  | 60 | 51.2k |         READWRITE(VARINT(obj.nBlocks)); | Line | Count | Source |  | 145 | 51.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 61 | 51.2k |         READWRITE(VARINT(obj.nSize)); | Line | Count | Source |  | 145 | 51.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 62 | 51.2k |         READWRITE(VARINT(obj.nUndoSize)); | Line | Count | Source |  | 145 | 51.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 63 | 51.2k |         READWRITE(VARINT(obj.nHeightFirst)); | Line | Count | Source |  | 145 | 51.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 64 | 51.2k |         READWRITE(VARINT(obj.nHeightLast)); | Line | Count | Source |  | 145 | 51.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 65 | 51.2k |         READWRITE(VARINT(obj.nTimeFirst)); | Line | Count | Source |  | 145 | 51.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 66 | 51.2k |         READWRITE(VARINT(obj.nTimeLast)); | Line | Count | Source |  | 145 | 51.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 67 | 51.2k |     } | 
_ZN14CBlockFileInfo16SerializationOpsI10DataStreamKS_15ActionSerializeEEvRT0_RT_T1_| Line | Count | Source |  | 59 | 1.89k |     { |  | 60 | 1.89k |         READWRITE(VARINT(obj.nBlocks)); | Line | Count | Source |  | 145 | 1.89k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 61 | 1.89k |         READWRITE(VARINT(obj.nSize)); | Line | Count | Source |  | 145 | 1.89k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 62 | 1.89k |         READWRITE(VARINT(obj.nUndoSize)); | Line | Count | Source |  | 145 | 1.89k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 63 | 1.89k |         READWRITE(VARINT(obj.nHeightFirst)); | Line | Count | Source |  | 145 | 1.89k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 64 | 1.89k |         READWRITE(VARINT(obj.nHeightLast)); | Line | Count | Source |  | 145 | 1.89k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 65 | 1.89k |         READWRITE(VARINT(obj.nTimeFirst)); | Line | Count | Source |  | 145 | 1.89k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 66 | 1.89k |         READWRITE(VARINT(obj.nTimeLast)); | Line | Count | Source |  | 145 | 1.89k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 67 | 1.89k |     } | 
 | 
| 68 |  |  | 
| 69 | 102k |     CBlockFileInfo() = default; | 
| 70 |  |  | 
| 71 |  |     std::string ToString() const; | 
| 72 |  |  | 
| 73 |  |     /** update statistics (does not update nSize) */ | 
| 74 |  |     void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) | 
| 75 | 28.2k |     { | 
| 76 | 28.2k |         if (nBlocks == 0 || nHeightFirst > nHeightIn) | 
| 77 | 0 |             nHeightFirst = nHeightIn; | 
| 78 | 28.2k |         if (nBlocks == 0 || nTimeFirst > nTimeIn) | 
| 79 | 0 |             nTimeFirst = nTimeIn; | 
| 80 | 28.2k |         nBlocks++; | 
| 81 | 28.2k |         if (nHeightIn > nHeightLast) | 
| 82 | 24.6k |             nHeightLast = nHeightIn; | 
| 83 | 28.2k |         if (nTimeIn > nTimeLast) | 
| 84 | 0 |             nTimeLast = nTimeIn; | 
| 85 | 28.2k |     } | 
| 86 |  | }; | 
| 87 |  |  | 
| 88 |  | enum BlockStatus : uint32_t { | 
| 89 |  |     //! Unused. | 
| 90 |  |     BLOCK_VALID_UNKNOWN      =    0, | 
| 91 |  |  | 
| 92 |  |     //! Reserved (was BLOCK_VALID_HEADER). | 
| 93 |  |     BLOCK_VALID_RESERVED     =    1, | 
| 94 |  |  | 
| 95 |  |     //! All parent headers found, difficulty matches, timestamp >= median previous. Implies all parents | 
| 96 |  |     //! are also at least TREE. | 
| 97 |  |     BLOCK_VALID_TREE         =    2, | 
| 98 |  |  | 
| 99 |  |     /** | 
| 100 |  |      * Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid, no duplicate txids, | 
| 101 |  |      * sigops, size, merkle root. Implies all parents are at least TREE but not necessarily TRANSACTIONS. | 
| 102 |  |      * | 
| 103 |  |      * If a block's validity is at least VALID_TRANSACTIONS, CBlockIndex::nTx will be set. If a block and all previous | 
| 104 |  |      * blocks back to the genesis block or an assumeutxo snapshot block are at least VALID_TRANSACTIONS, | 
| 105 |  |      * CBlockIndex::m_chain_tx_count will be set. | 
| 106 |  |      */ | 
| 107 |  |     BLOCK_VALID_TRANSACTIONS =    3, | 
| 108 |  |  | 
| 109 |  |     //! Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends, BIP30. | 
| 110 |  |     //! Implies all previous blocks back to the genesis block or an assumeutxo snapshot block are at least VALID_CHAIN. | 
| 111 |  |     BLOCK_VALID_CHAIN        =    4, | 
| 112 |  |  | 
| 113 |  |     //! Scripts & signatures ok. Implies all previous blocks back to the genesis block or an assumeutxo snapshot block | 
| 114 |  |     //! are at least VALID_SCRIPTS. | 
| 115 |  |     BLOCK_VALID_SCRIPTS      =    5, | 
| 116 |  |  | 
| 117 |  |     //! All validity bits. | 
| 118 |  |     BLOCK_VALID_MASK         =   BLOCK_VALID_RESERVED | BLOCK_VALID_TREE | BLOCK_VALID_TRANSACTIONS | | 
| 119 |  |                                  BLOCK_VALID_CHAIN | BLOCK_VALID_SCRIPTS, | 
| 120 |  |  | 
| 121 |  |     BLOCK_HAVE_DATA          =    8, //!< full block available in blk*.dat | 
| 122 |  |     BLOCK_HAVE_UNDO          =   16, //!< undo data available in rev*.dat | 
| 123 |  |     BLOCK_HAVE_MASK          =   BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO, | 
| 124 |  |  | 
| 125 |  |     BLOCK_FAILED_VALID       =   32, //!< stage after last reached validness failed | 
| 126 |  |     BLOCK_FAILED_CHILD       =   64, //!< descends from failed block | 
| 127 |  |     BLOCK_FAILED_MASK        =   BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD, | 
| 128 |  |  | 
| 129 |  |     BLOCK_OPT_WITNESS        =   128, //!< block data in blk*.dat was received with a witness-enforcing client | 
| 130 |  |  | 
| 131 |  |     BLOCK_STATUS_RESERVED    =   256, //!< Unused flag that was previously set on assumeutxo snapshot blocks and their | 
| 132 |  |                                       //!< ancestors before they were validated, and unset when they were validated. | 
| 133 |  | }; | 
| 134 |  |  | 
| 135 |  | /** The block chain is a tree shaped structure starting with the | 
| 136 |  |  * genesis block at the root, with each block potentially having multiple | 
| 137 |  |  * candidates to be the next block. A blockindex may have multiple pprev pointing | 
| 138 |  |  * to it, but at most one of them can be part of the currently active branch. | 
| 139 |  |  */ | 
| 140 |  | class CBlockIndex | 
| 141 |  | { | 
| 142 |  | public: | 
| 143 |  |     //! pointer to the hash of the block, if any. Memory is owned by this CBlockIndex | 
| 144 |  |     const uint256* phashBlock{nullptr}; | 
| 145 |  |  | 
| 146 |  |     //! pointer to the index of the predecessor of this block | 
| 147 |  |     CBlockIndex* pprev{nullptr}; | 
| 148 |  |  | 
| 149 |  |     //! pointer to the index of some further predecessor of this block | 
| 150 |  |     CBlockIndex* pskip{nullptr}; | 
| 151 |  |  | 
| 152 |  |     //! height of the entry in the chain. The genesis block has height 0 | 
| 153 |  |     int nHeight{0}; | 
| 154 |  |  | 
| 155 |  |     //! Which # file this block is stored in (blk?????.dat) | 
| 156 |  |     int nFile GUARDED_BY(::cs_main){0}; | 
| 157 |  |  | 
| 158 |  |     //! Byte offset within blk?????.dat where this block's data is stored | 
| 159 |  |     unsigned int nDataPos GUARDED_BY(::cs_main){0}; | 
| 160 |  |  | 
| 161 |  |     //! Byte offset within rev?????.dat where this block's undo data is stored | 
| 162 |  |     unsigned int nUndoPos GUARDED_BY(::cs_main){0}; | 
| 163 |  |  | 
| 164 |  |     //! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block | 
| 165 |  |     arith_uint256 nChainWork{}; | 
| 166 |  |  | 
| 167 |  |     //! Number of transactions in this block. This will be nonzero if the block | 
| 168 |  |     //! reached the VALID_TRANSACTIONS level, and zero otherwise. | 
| 169 |  |     //! Note: in a potential headers-first mode, this number cannot be relied upon | 
| 170 |  |     unsigned int nTx{0}; | 
| 171 |  |  | 
| 172 |  |     //! (memory only) Number of transactions in the chain up to and including this block. | 
| 173 |  |     //! This value will be non-zero if this block and all previous blocks back | 
| 174 |  |     //! to the genesis block or an assumeutxo snapshot block have reached the | 
| 175 |  |     //! VALID_TRANSACTIONS level. | 
| 176 |  |     uint64_t m_chain_tx_count{0}; | 
| 177 |  |  | 
| 178 |  |     //! Verification status of this block. See enum BlockStatus | 
| 179 |  |     //! | 
| 180 |  |     //! Note: this value is modified to show BLOCK_OPT_WITNESS during UTXO snapshot | 
| 181 |  |     //! load to avoid a spurious startup failure requiring -reindex. | 
| 182 |  |     //! @sa NeedsRedownload | 
| 183 |  |     //! @sa ActivateSnapshot | 
| 184 |  |     uint32_t nStatus GUARDED_BY(::cs_main){0}; | 
| 185 |  |  | 
| 186 |  |     //! block header | 
| 187 |  |     int32_t nVersion{0}; | 
| 188 |  |     uint256 hashMerkleRoot{}; | 
| 189 |  |     uint32_t nTime{0}; | 
| 190 |  |     uint32_t nBits{0}; | 
| 191 |  |     uint32_t nNonce{0}; | 
| 192 |  |  | 
| 193 |  |     //! (memory only) Sequential id assigned to distinguish order in which blocks are received. | 
| 194 |  |     int32_t nSequenceId{0}; | 
| 195 |  |  | 
| 196 |  |     //! (memory only) Maximum nTime in the chain up to and including this block. | 
| 197 |  |     unsigned int nTimeMax{0}; | 
| 198 |  |  | 
| 199 |  |     explicit CBlockIndex(const CBlockHeader& block) | 
| 200 | 1.91M |         : nVersion{block.nVersion}, | 
| 201 | 1.91M |           hashMerkleRoot{block.hashMerkleRoot}, | 
| 202 | 1.91M |           nTime{block.nTime}, | 
| 203 | 1.91M |           nBits{block.nBits}, | 
| 204 | 1.91M |           nNonce{block.nNonce} | 
| 205 | 1.91M |     { | 
| 206 | 1.91M |     } | 
| 207 |  |  | 
| 208 |  |     FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) | 
| 209 | 308k |     { | 
| 210 | 308k |         AssertLockHeld(::cs_main); | Line | Count | Source |  | 137 | 308k | #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) | 
 | 
| 211 | 308k |         FlatFilePos ret; | 
| 212 | 308k |         if (nStatus & BLOCK_HAVE_DATA) { | 
| 213 | 308k |             ret.nFile = nFile; | 
| 214 | 308k |             ret.nPos = nDataPos; | 
| 215 | 308k |         } | 
| 216 | 308k |         return ret; | 
| 217 | 308k |     } | 
| 218 |  |  | 
| 219 |  |     FlatFilePos GetUndoPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) | 
| 220 | 944k |     { | 
| 221 | 944k |         AssertLockHeld(::cs_main); | Line | Count | Source |  | 137 | 944k | #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) | 
 | 
| 222 | 944k |         FlatFilePos ret; | 
| 223 | 944k |         if (nStatus & BLOCK_HAVE_UNDO) { | 
| 224 | 923k |             ret.nFile = nFile; | 
| 225 | 923k |             ret.nPos = nUndoPos; | 
| 226 | 923k |         } | 
| 227 | 944k |         return ret; | 
| 228 | 944k |     } | 
| 229 |  |  | 
| 230 |  |     CBlockHeader GetBlockHeader() const | 
| 231 | 1.40k |     { | 
| 232 | 1.40k |         CBlockHeader block; | 
| 233 | 1.40k |         block.nVersion = nVersion; | 
| 234 | 1.40k |         if (pprev) | 
| 235 | 1.40k |             block.hashPrevBlock = pprev->GetBlockHash(); | 
| 236 | 1.40k |         block.hashMerkleRoot = hashMerkleRoot; | 
| 237 | 1.40k |         block.nTime = nTime; | 
| 238 | 1.40k |         block.nBits = nBits; | 
| 239 | 1.40k |         block.nNonce = nNonce; | 
| 240 | 1.40k |         return block; | 
| 241 | 1.40k |     } | 
| 242 |  |  | 
| 243 |  |     uint256 GetBlockHash() const | 
| 244 | 31.8M |     { | 
| 245 | 31.8M |         assert(phashBlock != nullptr); | 
| 246 | 31.8M |         return *phashBlock; | 
| 247 | 31.8M |     } | 
| 248 |  |  | 
| 249 |  |     /** | 
| 250 |  |      * Check whether this block and all previous blocks back to the genesis block or an assumeutxo snapshot block have | 
| 251 |  |      * reached VALID_TRANSACTIONS and had transactions downloaded (and stored to disk) at some point. | 
| 252 |  |      * | 
| 253 |  |      * Does not imply the transactions are consensus-valid (ConnectTip might fail) | 
| 254 |  |      * Does not imply the transactions are still stored on disk. (IsBlockPruned might return true) | 
| 255 |  |      * | 
| 256 |  |      * Note that this will be true for the snapshot base block, if one is loaded, since its m_chain_tx_count value will have | 
| 257 |  |      * been set manually based on the related AssumeutxoData entry. | 
| 258 |  |      */ | 
| 259 | 1.26G |     bool HaveNumChainTxs() const { return m_chain_tx_count != 0; } | 
| 260 |  |  | 
| 261 |  |     NodeSeconds Time() const | 
| 262 | 2.32M |     { | 
| 263 | 2.32M |         return NodeSeconds{std::chrono::seconds{nTime}}; | 
| 264 | 2.32M |     } | 
| 265 |  |  | 
| 266 |  |     int64_t GetBlockTime() const | 
| 267 | 52.7M |     { | 
| 268 | 52.7M |         return (int64_t)nTime; | 
| 269 | 52.7M |     } | 
| 270 |  |  | 
| 271 |  |     int64_t GetBlockTimeMax() const | 
| 272 | 0 |     { | 
| 273 | 0 |         return (int64_t)nTimeMax; | 
| 274 | 0 |     } | 
| 275 |  |  | 
| 276 |  |     static constexpr int nMedianTimeSpan = 11; | 
| 277 |  |  | 
| 278 |  |     int64_t GetMedianTimePast() const | 
| 279 | 4.68M |     { | 
| 280 | 4.68M |         int64_t pmedian[nMedianTimeSpan]; | 
| 281 | 4.68M |         int64_t* pbegin = &pmedian[nMedianTimeSpan]; | 
| 282 | 4.68M |         int64_t* pend = &pmedian[nMedianTimeSpan]; | 
| 283 |  |  | 
| 284 | 4.68M |         const CBlockIndex* pindex = this; | 
| 285 | 56.1M |         for (int i = 0; i < nMedianTimeSpan && pindex51.5M; i++, pindex = pindex->pprev51.5M) | 
| 286 | 51.5M |             *(--pbegin) = pindex->GetBlockTime(); | 
| 287 |  |  | 
| 288 | 4.68M |         std::sort(pbegin, pend); | 
| 289 | 4.68M |         return pbegin[(pend - pbegin) / 2]; | 
| 290 | 4.68M |     } | 
| 291 |  |  | 
| 292 |  |     std::string ToString() const; | 
| 293 |  |  | 
| 294 |  |     //! Check whether this block index entry is valid up to the passed validity level. | 
| 295 |  |     bool IsValid(enum BlockStatus nUpTo) const | 
| 296 |  |         EXCLUSIVE_LOCKS_REQUIRED(::cs_main) | 
| 297 | 25.0M |     { | 
| 298 | 25.0M |         AssertLockHeld(::cs_main); | Line | Count | Source |  | 137 | 25.0M | #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) | 
 | 
| 299 | 25.0M |         assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed. | 
| 300 | 25.0M |         if (nStatus & BLOCK_FAILED_MASK) | 
| 301 | 91.7k |             return false; | 
| 302 | 24.9M |         return ((nStatus & BLOCK_VALID_MASK) >= nUpTo); | 
| 303 | 25.0M |     } | 
| 304 |  |  | 
| 305 |  |     //! Raise the validity level of this block index entry. | 
| 306 |  |     //! Returns true if the validity was changed. | 
| 307 |  |     bool RaiseValidity(enum BlockStatus nUpTo) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) | 
| 308 | 158k |     { | 
| 309 | 158k |         AssertLockHeld(::cs_main); | Line | Count | Source |  | 137 | 158k | #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) | 
 | 
| 310 | 158k |         assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed. | 
| 311 | 158k |         if (nStatus & BLOCK_FAILED_MASK) return false0; | 
| 312 |  |  | 
| 313 | 158k |         if ((nStatus & BLOCK_VALID_MASK) < nUpTo) { | 
| 314 | 158k |             nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo; | 
| 315 | 158k |             return true; | 
| 316 | 158k |         } | 
| 317 | 0 |         return false; | 
| 318 | 158k |     } | 
| 319 |  |  | 
| 320 |  |     //! Build the skiplist pointer for this entry. | 
| 321 |  |     void BuildSkip(); | 
| 322 |  |  | 
| 323 |  |     //! Efficiently find an ancestor of this block. | 
| 324 |  |     CBlockIndex* GetAncestor(int height); | 
| 325 |  |     const CBlockIndex* GetAncestor(int height) const; | 
| 326 |  |  | 
| 327 | 21.9M |     CBlockIndex() = default; | 
| 328 |  |     ~CBlockIndex() = default; | 
| 329 |  |  | 
| 330 |  | protected: | 
| 331 |  |     //! CBlockIndex should not allow public copy construction because equality | 
| 332 |  |     //! comparison via pointer is very common throughout the codebase, making | 
| 333 |  |     //! use of copy a footgun. Also, use of copies do not have the benefit | 
| 334 |  |     //! of simplifying lifetime considerations due to attributes like pprev and | 
| 335 |  |     //! pskip, which are at risk of becoming dangling pointers in a copied | 
| 336 |  |     //! instance. | 
| 337 |  |     //! | 
| 338 |  |     //! We declare these protected instead of simply deleting them so that | 
| 339 |  |     //! CDiskBlockIndex can reuse copy construction. | 
| 340 |  |     CBlockIndex(const CBlockIndex&) = default; | 
| 341 |  |     CBlockIndex& operator=(const CBlockIndex&) = delete; | 
| 342 |  |     CBlockIndex(CBlockIndex&&) = delete; | 
| 343 |  |     CBlockIndex& operator=(CBlockIndex&&) = delete; | 
| 344 |  | }; | 
| 345 |  |  | 
| 346 |  | arith_uint256 GetBlockProof(const CBlockIndex& block); | 
| 347 |  | /** Return the time it would take to redo the work difference between from and to, assuming the current hashrate corresponds to the difficulty at tip, in seconds. */ | 
| 348 |  | int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params&); | 
| 349 |  | /** Find the forking point between two chain tips. */ | 
| 350 |  | const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb); | 
| 351 |  |  | 
| 352 |  |  | 
| 353 |  | /** Used to marshal pointers into hashes for db storage. */ | 
| 354 |  | class CDiskBlockIndex : public CBlockIndex | 
| 355 |  | { | 
| 356 |  |     /** Historically CBlockLocator's version field has been written to disk | 
| 357 |  |      * streams as the client version, but the value has never been used. | 
| 358 |  |      * | 
| 359 |  |      * Hard-code to the highest client version ever written. | 
| 360 |  |      * SerParams can be used if the field requires any meaning in the future. | 
| 361 |  |      **/ | 
| 362 |  |     static constexpr int DUMMY_VERSION = 259900; | 
| 363 |  |  | 
| 364 |  | public: | 
| 365 |  |     uint256 hashPrev; | 
| 366 |  |  | 
| 367 |  |     CDiskBlockIndex() | 
| 368 | 10.3M |     { | 
| 369 | 10.3M |         hashPrev = uint256(); | 
| 370 | 10.3M |     } | 
| 371 |  |  | 
| 372 | 10.4k |     explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex) | 
| 373 | 10.4k |     { | 
| 374 | 10.4k |         hashPrev = (pprev ? pprev->GetBlockHash() : uint256()0); | 
| 375 | 10.4k |     } | 
| 376 |  |  | 
| 377 |  |     SERIALIZE_METHODS(CDiskBlockIndex, obj) | 
| 378 | 10.3M |     { | 
| 379 | 10.3M |         LOCK(::cs_main); | Line | Count | Source |  | 259 | 10.3M | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) | Line | Count | Source |  | 11 | 10.3M | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) | Line | Count | Source |  | 9 | 10.3M | #define PASTE2(x, y) PASTE(x, y) | Line | Count | Source |  | 8 | 10.3M | #define PASTE(x, y) x ## y | 
 | 
 | 
 | 
 |         LOCK(::cs_main); | Line | Count | Source |  | 259 | 10.4k | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) | Line | Count | Source |  | 11 | 10.4k | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) | Line | Count | Source |  | 9 | 10.4k | #define PASTE2(x, y) PASTE(x, y) | Line | Count | Source |  | 8 | 10.4k | #define PASTE(x, y) x ## y | 
 | 
 | 
 | 
 | 
| 380 | 10.3M |         int _nVersion = DUMMY_VERSION; | 
| 381 | 10.3M |         READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED)); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED)); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 382 |  |  | 
| 383 | 10.3M |         READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED)); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED)); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 384 | 10.3M |         READWRITE(VARINT(obj.nStatus)); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(VARINT(obj.nStatus)); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 385 | 10.3M |         READWRITE(VARINT(obj.nTx)); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(VARINT(obj.nTx)); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 386 | 10.3M |         if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE10.3M(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED)); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE10.3M(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED)); | Line | Count | Source |  | 145 | 3.00k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 387 | 10.3M |         if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE10.3M(VARINT(obj.nDataPos)); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE10.3M(VARINT(obj.nDataPos)); | Line | Count | Source |  | 145 | 3.00k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 388 | 10.3M |         if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE10.2M(VARINT(obj.nUndoPos)); | Line | Count | Source |  | 145 | 10.2M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE10.2M(VARINT(obj.nUndoPos)); | Line | Count | Source |  | 145 | 2.82k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 389 |  |  | 
| 390 |  |         // block header | 
| 391 | 10.3M |         READWRITE(obj.nVersion); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(obj.nVersion); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 392 | 10.3M |         READWRITE(obj.hashPrev); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(obj.hashPrev); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 393 | 10.3M |         READWRITE(obj.hashMerkleRoot); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(obj.hashMerkleRoot); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 394 | 10.3M |         READWRITE(obj.nTime); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(obj.nTime); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 395 | 10.3M |         READWRITE(obj.nBits); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(obj.nBits); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 396 | 10.3M |         READWRITE(obj.nNonce); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |         READWRITE(obj.nNonce); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
| 397 | 10.3M |     } _ZN15CDiskBlockIndex16SerializationOpsI10DataStreamS_17ActionUnserializeEEvRT0_RT_T1_| Line | Count | Source |  | 378 | 10.3M |     { |  | 379 | 10.3M |         LOCK(::cs_main); | Line | Count | Source |  | 259 | 10.3M | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) | Line | Count | Source |  | 11 | 10.3M | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) | Line | Count | Source |  | 9 | 10.3M | #define PASTE2(x, y) PASTE(x, y) | Line | Count | Source |  | 8 | 10.3M | #define PASTE(x, y) x ## y | 
 | 
 | 
 | 
 |  | 380 | 10.3M |         int _nVersion = DUMMY_VERSION; |  | 381 | 10.3M |         READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED)); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 382 |  |  |  | 383 | 10.3M |         READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED)); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 384 | 10.3M |         READWRITE(VARINT(obj.nStatus)); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 385 | 10.3M |         READWRITE(VARINT(obj.nTx)); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 386 | 10.3M |         if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED)); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 387 | 10.3M |         if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE(VARINT(obj.nDataPos)); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 388 | 10.3M |         if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE10.2M(VARINT(obj.nUndoPos)); | Line | Count | Source |  | 145 | 10.2M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 389 |  |  |  | 390 |  |         // block header |  | 391 | 10.3M |         READWRITE(obj.nVersion); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 392 | 10.3M |         READWRITE(obj.hashPrev); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 393 | 10.3M |         READWRITE(obj.hashMerkleRoot); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 394 | 10.3M |         READWRITE(obj.nTime); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 395 | 10.3M |         READWRITE(obj.nBits); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 396 | 10.3M |         READWRITE(obj.nNonce); | Line | Count | Source |  | 145 | 10.3M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 397 | 10.3M |     } | 
_ZN15CDiskBlockIndex16SerializationOpsI10DataStreamKS_15ActionSerializeEEvRT0_RT_T1_| Line | Count | Source |  | 378 | 10.4k |     { |  | 379 | 10.4k |         LOCK(::cs_main); | Line | Count | Source |  | 259 | 10.4k | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) | Line | Count | Source |  | 11 | 10.4k | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) | Line | Count | Source |  | 9 | 10.4k | #define PASTE2(x, y) PASTE(x, y) | Line | Count | Source |  | 8 | 10.4k | #define PASTE(x, y) x ## y | 
 | 
 | 
 | 
 |  | 380 | 10.4k |         int _nVersion = DUMMY_VERSION; |  | 381 | 10.4k |         READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED)); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 382 |  |  |  | 383 | 10.4k |         READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED)); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 384 | 10.4k |         READWRITE(VARINT(obj.nStatus)); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 385 | 10.4k |         READWRITE(VARINT(obj.nTx)); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 386 | 10.4k |         if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE3.00k(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED)); | Line | Count | Source |  | 145 | 3.00k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 387 | 10.4k |         if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE3.00k(VARINT(obj.nDataPos)); | Line | Count | Source |  | 145 | 3.00k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 388 | 10.4k |         if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE2.82k(VARINT(obj.nUndoPos)); | Line | Count | Source |  | 145 | 2.82k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 389 |  |  |  | 390 |  |         // block header |  | 391 | 10.4k |         READWRITE(obj.nVersion); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 392 | 10.4k |         READWRITE(obj.hashPrev); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 393 | 10.4k |         READWRITE(obj.hashMerkleRoot); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 394 | 10.4k |         READWRITE(obj.nTime); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 395 | 10.4k |         READWRITE(obj.nBits); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 396 | 10.4k |         READWRITE(obj.nNonce); | Line | Count | Source |  | 145 | 10.4k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |  | 397 | 10.4k |     } | 
 | 
| 398 |  |  | 
| 399 |  |     uint256 ConstructBlockHash() const | 
| 400 | 10.3M |     { | 
| 401 | 10.3M |         CBlockHeader block; | 
| 402 | 10.3M |         block.nVersion = nVersion; | 
| 403 | 10.3M |         block.hashPrevBlock = hashPrev; | 
| 404 | 10.3M |         block.hashMerkleRoot = hashMerkleRoot; | 
| 405 | 10.3M |         block.nTime = nTime; | 
| 406 | 10.3M |         block.nBits = nBits; | 
| 407 | 10.3M |         block.nNonce = nNonce; | 
| 408 | 10.3M |         return block.GetHash(); | 
| 409 | 10.3M |     } | 
| 410 |  |  | 
| 411 |  |     uint256 GetBlockHash() = delete; | 
| 412 |  |     std::string ToString() = delete; | 
| 413 |  | }; | 
| 414 |  |  | 
| 415 |  | /** An in-memory indexed chain of blocks. */ | 
| 416 |  | class CChain | 
| 417 |  | { | 
| 418 |  | private: | 
| 419 |  |     std::vector<CBlockIndex*> vChain; | 
| 420 |  |  | 
| 421 |  | public: | 
| 422 | 2.11M |     CChain() = default; | 
| 423 |  |     CChain(const CChain&) = delete; | 
| 424 |  |     CChain& operator=(const CChain&) = delete; | 
| 425 |  |  | 
| 426 |  |     /** Returns the index entry for the genesis block of this chain, or nullptr if none. */ | 
| 427 |  |     CBlockIndex* Genesis() const | 
| 428 | 4.12M |     { | 
| 429 | 4.12M |         return vChain.size() > 0 ? vChain[0] : nullptr0; | 
| 430 | 4.12M |     } | 
| 431 |  |  | 
| 432 |  |     /** Returns the index entry for the tip of this chain, or nullptr if none. */ | 
| 433 |  |     CBlockIndex* Tip() const | 
| 434 | 883M |     { | 
| 435 | 883M |         return vChain.size() > 0 ? vChain[vChain.size() - 1]873M: nullptr10.4M; | 
| 436 | 883M |     } | 
| 437 |  |  | 
| 438 |  |     /** Returns the index entry at a particular height in this chain, or nullptr if no such height exists. */ | 
| 439 |  |     CBlockIndex* operator[](int nHeight) const | 
| 440 | 1.26G |     { | 
| 441 | 1.26G |         if (nHeight < 0 || nHeight >= (int)vChain.size()) | 
| 442 | 5.03M |             return nullptr; | 
| 443 | 1.25G |         return vChain[nHeight]; | 
| 444 | 1.26G |     } | 
| 445 |  |  | 
| 446 |  |     /** Efficiently check whether a block is present in this chain. */ | 
| 447 |  |     bool Contains(const CBlockIndex* pindex) const | 
| 448 | 843M |     { | 
| 449 | 843M |         return (*this)[pindex->nHeight] == pindex; | 
| 450 | 843M |     } | 
| 451 |  |  | 
| 452 |  |     /** Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip. */ | 
| 453 |  |     CBlockIndex* Next(const CBlockIndex* pindex) const | 
| 454 | 0 |     { | 
| 455 | 0 |         if (Contains(pindex)) | 
| 456 | 0 |             return (*this)[pindex->nHeight + 1]; | 
| 457 | 0 |         else | 
| 458 | 0 |             return nullptr; | 
| 459 | 0 |     } | 
| 460 |  |  | 
| 461 |  |     /** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */ | 
| 462 |  |     int Height() const | 
| 463 | 12.0M |     { | 
| 464 | 12.0M |         return int(vChain.size()) - 1; | 
| 465 | 12.0M |     } | 
| 466 |  |  | 
| 467 |  |     /** Set/initialize a chain with a given tip. */ | 
| 468 |  |     void SetTip(CBlockIndex& block); | 
| 469 |  |  | 
| 470 |  |     /** Find the last common block between this chain and a block index entry. */ | 
| 471 |  |     const CBlockIndex* FindFork(const CBlockIndex* pindex) const; | 
| 472 |  |  | 
| 473 |  |     /** Find the earliest block with timestamp equal or greater than the given time and height equal or greater than the given height. */ | 
| 474 |  |     CBlockIndex* FindEarliestAtLeast(int64_t nTime, int height) const; | 
| 475 |  | }; | 
| 476 |  |  | 
| 477 |  | /** Get a locator for a block index entry. */ | 
| 478 |  | CBlockLocator GetLocator(const CBlockIndex* index); | 
| 479 |  |  | 
| 480 |  | /** Construct a list of hash entries to put in a locator.  */ | 
| 481 |  | std::vector<uint256> LocatorEntries(const CBlockIndex* index); | 
| 482 |  |  | 
| 483 |  | #endif // BITCOIN_CHAIN_H |