Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2021 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 <primitives/block.h>
# 13 : : #include <sync.h>
# 14 : : #include <tinyformat.h>
# 15 : : #include <uint256.h>
# 16 : :
# 17 : : #include <vector>
# 18 : :
# 19 : : /**
# 20 : : * Maximum amount of time that a block timestamp is allowed to exceed the
# 21 : : * current network-adjusted time before the block will be accepted.
# 22 : : */
# 23 : : static constexpr int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60;
# 24 : :
# 25 : : /**
# 26 : : * Timestamp window used as a grace period by code that compares external
# 27 : : * timestamps (such as timestamps passed to RPCs, or wallet key creation times)
# 28 : : * to block timestamps. This should be set at least as high as
# 29 : : * MAX_FUTURE_BLOCK_TIME.
# 30 : : */
# 31 : : static constexpr int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME;
# 32 : :
# 33 : : /**
# 34 : : * Maximum gap between node time and block time used
# 35 : : * for the "Catching up..." mode in GUI.
# 36 : : *
# 37 : : * Ref: https://github.com/bitcoin/bitcoin/pull/1026
# 38 : : */
# 39 : : static constexpr int64_t MAX_BLOCK_TIME_GAP = 90 * 60;
# 40 : :
# 41 : : extern RecursiveMutex cs_main;
# 42 : :
# 43 : : class CBlockFileInfo
# 44 : : {
# 45 : : public:
# 46 : : unsigned int nBlocks; //!< number of blocks stored in file
# 47 : : unsigned int nSize; //!< number of used bytes of block file
# 48 : : unsigned int nUndoSize; //!< number of used bytes in the undo file
# 49 : : unsigned int nHeightFirst; //!< lowest height of block in file
# 50 : : unsigned int nHeightLast; //!< highest height of block in file
# 51 : : uint64_t nTimeFirst; //!< earliest time of block in file
# 52 : : uint64_t nTimeLast; //!< latest time of block in file
# 53 : :
# 54 : : SERIALIZE_METHODS(CBlockFileInfo, obj)
# 55 : 1091 : {
# 56 : 1091 : READWRITE(VARINT(obj.nBlocks));
# 57 : 1091 : READWRITE(VARINT(obj.nSize));
# 58 : 1091 : READWRITE(VARINT(obj.nUndoSize));
# 59 : 1091 : READWRITE(VARINT(obj.nHeightFirst));
# 60 : 1091 : READWRITE(VARINT(obj.nHeightLast));
# 61 : 1091 : READWRITE(VARINT(obj.nTimeFirst));
# 62 : 1091 : READWRITE(VARINT(obj.nTimeLast));
# 63 : 1091 : }
# 64 : :
# 65 : : void SetNull()
# 66 : 1920 : {
# 67 : 1920 : nBlocks = 0;
# 68 : 1920 : nSize = 0;
# 69 : 1920 : nUndoSize = 0;
# 70 : 1920 : nHeightFirst = 0;
# 71 : 1920 : nHeightLast = 0;
# 72 : 1920 : nTimeFirst = 0;
# 73 : 1920 : nTimeLast = 0;
# 74 : 1920 : }
# 75 : :
# 76 : : CBlockFileInfo()
# 77 : 1910 : {
# 78 : 1910 : SetNull();
# 79 : 1910 : }
# 80 : :
# 81 : : std::string ToString() const;
# 82 : :
# 83 : : /** update statistics (does not update nSize) */
# 84 : : void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn)
# 85 : 64594 : {
# 86 [ + + ][ + + ]: 64594 : if (nBlocks == 0 || nHeightFirst > nHeightIn)
# 87 : 490 : nHeightFirst = nHeightIn;
# 88 [ + + ][ + + ]: 64594 : if (nBlocks == 0 || nTimeFirst > nTimeIn)
# 89 : 490 : nTimeFirst = nTimeIn;
# 90 : 64594 : nBlocks++;
# 91 [ + + ]: 64594 : if (nHeightIn > nHeightLast)
# 92 : 57527 : nHeightLast = nHeightIn;
# 93 [ + + ]: 64594 : if (nTimeIn > nTimeLast)
# 94 : 24377 : nTimeLast = nTimeIn;
# 95 : 64594 : }
# 96 : : };
# 97 : :
# 98 : : enum BlockStatus : uint32_t {
# 99 : : //! Unused.
# 100 : : BLOCK_VALID_UNKNOWN = 0,
# 101 : :
# 102 : : //! Reserved (was BLOCK_VALID_HEADER).
# 103 : : BLOCK_VALID_RESERVED = 1,
# 104 : :
# 105 : : //! All parent headers found, difficulty matches, timestamp >= median previous, checkpoint. Implies all parents
# 106 : : //! are also at least TREE.
# 107 : : BLOCK_VALID_TREE = 2,
# 108 : :
# 109 : : /**
# 110 : : * Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid, no duplicate txids,
# 111 : : * sigops, size, merkle root. Implies all parents are at least TREE but not necessarily TRANSACTIONS. When all
# 112 : : * parent blocks also have TRANSACTIONS, CBlockIndex::nChainTx will be set.
# 113 : : */
# 114 : : BLOCK_VALID_TRANSACTIONS = 3,
# 115 : :
# 116 : : //! Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends, BIP30.
# 117 : : //! Implies all parents are also at least CHAIN.
# 118 : : BLOCK_VALID_CHAIN = 4,
# 119 : :
# 120 : : //! Scripts & signatures ok. Implies all parents are also at least SCRIPTS.
# 121 : : BLOCK_VALID_SCRIPTS = 5,
# 122 : :
# 123 : : //! All validity bits.
# 124 : : BLOCK_VALID_MASK = BLOCK_VALID_RESERVED | BLOCK_VALID_TREE | BLOCK_VALID_TRANSACTIONS |
# 125 : : BLOCK_VALID_CHAIN | BLOCK_VALID_SCRIPTS,
# 126 : :
# 127 : : BLOCK_HAVE_DATA = 8, //!< full block available in blk*.dat
# 128 : : BLOCK_HAVE_UNDO = 16, //!< undo data available in rev*.dat
# 129 : : BLOCK_HAVE_MASK = BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO,
# 130 : :
# 131 : : BLOCK_FAILED_VALID = 32, //!< stage after last reached validness failed
# 132 : : BLOCK_FAILED_CHILD = 64, //!< descends from failed block
# 133 : : BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,
# 134 : :
# 135 : : BLOCK_OPT_WITNESS = 128, //!< block data in blk*.dat was received with a witness-enforcing client
# 136 : :
# 137 : : /**
# 138 : : * If set, this indicates that the block index entry is assumed-valid.
# 139 : : * Certain diagnostics will be skipped in e.g. CheckBlockIndex().
# 140 : : * It almost certainly means that the block's full validation is pending
# 141 : : * on a background chainstate. See `doc/assumeutxo.md`.
# 142 : : */
# 143 : : BLOCK_ASSUMED_VALID = 256,
# 144 : : };
# 145 : :
# 146 : : /** The block chain is a tree shaped structure starting with the
# 147 : : * genesis block at the root, with each block potentially having multiple
# 148 : : * candidates to be the next block. A blockindex may have multiple pprev pointing
# 149 : : * to it, but at most one of them can be part of the currently active branch.
# 150 : : */
# 151 : : class CBlockIndex
# 152 : : {
# 153 : : public:
# 154 : : //! pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
# 155 : : const uint256* phashBlock{nullptr};
# 156 : :
# 157 : : //! pointer to the index of the predecessor of this block
# 158 : : CBlockIndex* pprev{nullptr};
# 159 : :
# 160 : : //! pointer to the index of some further predecessor of this block
# 161 : : CBlockIndex* pskip{nullptr};
# 162 : :
# 163 : : //! height of the entry in the chain. The genesis block has height 0
# 164 : : int nHeight{0};
# 165 : :
# 166 : : //! Which # file this block is stored in (blk?????.dat)
# 167 : : int nFile GUARDED_BY(::cs_main){0};
# 168 : :
# 169 : : //! Byte offset within blk?????.dat where this block's data is stored
# 170 : : unsigned int nDataPos GUARDED_BY(::cs_main){0};
# 171 : :
# 172 : : //! Byte offset within rev?????.dat where this block's undo data is stored
# 173 : : unsigned int nUndoPos GUARDED_BY(::cs_main){0};
# 174 : :
# 175 : : //! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block
# 176 : : arith_uint256 nChainWork{};
# 177 : :
# 178 : : //! Number of transactions in this block.
# 179 : : //! Note: in a potential headers-first mode, this number cannot be relied upon
# 180 : : //! Note: this value is faked during UTXO snapshot load to ensure that
# 181 : : //! LoadBlockIndex() will load index entries for blocks that we lack data for.
# 182 : : //! @sa ActivateSnapshot
# 183 : : unsigned int nTx{0};
# 184 : :
# 185 : : //! (memory only) Number of transactions in the chain up to and including this block.
# 186 : : //! This value will be non-zero only if and only if transactions for this block and all its parents are available.
# 187 : : //! Change to 64-bit type before 2024 (assuming worst case of 60 byte transactions).
# 188 : : //!
# 189 : : //! Note: this value is faked during use of a UTXO snapshot because we don't
# 190 : : //! have the underlying block data available during snapshot load.
# 191 : : //! @sa AssumeutxoData
# 192 : : //! @sa ActivateSnapshot
# 193 : : unsigned int nChainTx{0};
# 194 : :
# 195 : : //! Verification status of this block. See enum BlockStatus
# 196 : : //!
# 197 : : //! Note: this value is modified to show BLOCK_OPT_WITNESS during UTXO snapshot
# 198 : : //! load to avoid the block index being spuriously rewound.
# 199 : : //! @sa NeedsRedownload
# 200 : : //! @sa ActivateSnapshot
# 201 : : uint32_t nStatus GUARDED_BY(::cs_main){0};
# 202 : :
# 203 : : //! block header
# 204 : : int32_t nVersion{0};
# 205 : : uint256 hashMerkleRoot{};
# 206 : : uint32_t nTime{0};
# 207 : : uint32_t nBits{0};
# 208 : : uint32_t nNonce{0};
# 209 : :
# 210 : : //! (memory only) Sequential id assigned to distinguish order in which blocks are received.
# 211 : : int32_t nSequenceId{0};
# 212 : :
# 213 : : //! (memory only) Maximum nTime in the chain up to and including this block.
# 214 : : unsigned int nTimeMax{0};
# 215 : :
# 216 : : CBlockIndex()
# 217 : 7997272 : {
# 218 : 7997272 : }
# 219 : :
# 220 : : explicit CBlockIndex(const CBlockHeader& block)
# 221 : : : nVersion{block.nVersion},
# 222 : : hashMerkleRoot{block.hashMerkleRoot},
# 223 : : nTime{block.nTime},
# 224 : : nBits{block.nBits},
# 225 : : nNonce{block.nNonce}
# 226 : 95787 : {
# 227 : 95787 : }
# 228 : :
# 229 : : FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
# 230 : 138289 : {
# 231 : 138289 : AssertLockHeld(::cs_main);
# 232 : 138289 : FlatFilePos ret;
# 233 [ + + ]: 138289 : if (nStatus & BLOCK_HAVE_DATA) {
# 234 : 138180 : ret.nFile = nFile;
# 235 : 138180 : ret.nPos = nDataPos;
# 236 : 138180 : }
# 237 : 138289 : return ret;
# 238 : 138289 : }
# 239 : :
# 240 : : FlatFilePos GetUndoPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
# 241 : 82950 : {
# 242 : 82950 : AssertLockHeld(::cs_main);
# 243 : 82950 : FlatFilePos ret;
# 244 [ + + ]: 82950 : if (nStatus & BLOCK_HAVE_UNDO) {
# 245 : 22876 : ret.nFile = nFile;
# 246 : 22876 : ret.nPos = nUndoPos;
# 247 : 22876 : }
# 248 : 82950 : return ret;
# 249 : 82950 : }
# 250 : :
# 251 : : CBlockHeader GetBlockHeader() const
# 252 : 25120 : {
# 253 : 25120 : CBlockHeader block;
# 254 : 25120 : block.nVersion = nVersion;
# 255 [ + - ]: 25120 : if (pprev)
# 256 : 25120 : block.hashPrevBlock = pprev->GetBlockHash();
# 257 : 25120 : block.hashMerkleRoot = hashMerkleRoot;
# 258 : 25120 : block.nTime = nTime;
# 259 : 25120 : block.nBits = nBits;
# 260 : 25120 : block.nNonce = nNonce;
# 261 : 25120 : return block;
# 262 : 25120 : }
# 263 : :
# 264 : : uint256 GetBlockHash() const
# 265 : 3420631 : {
# 266 : 3420631 : return *phashBlock;
# 267 : 3420631 : }
# 268 : :
# 269 : : /**
# 270 : : * Check whether this block's and all previous blocks' transactions have been
# 271 : : * downloaded (and stored to disk) at some point.
# 272 : : *
# 273 : : * Does not imply the transactions are consensus-valid (ConnectTip might fail)
# 274 : : * Does not imply the transactions are still stored on disk. (IsBlockPruned might return true)
# 275 : : */
# 276 : 361150844 : bool HaveTxsDownloaded() const { return nChainTx != 0; }
# 277 : :
# 278 : : int64_t GetBlockTime() const
# 279 : 7642975 : {
# 280 : 7642975 : return (int64_t)nTime;
# 281 : 7642975 : }
# 282 : :
# 283 : : int64_t GetBlockTimeMax() const
# 284 : 358804 : {
# 285 : 358804 : return (int64_t)nTimeMax;
# 286 : 358804 : }
# 287 : :
# 288 : : static constexpr int nMedianTimeSpan = 11;
# 289 : :
# 290 : : int64_t GetMedianTimePast() const
# 291 : 653166 : {
# 292 : 653166 : int64_t pmedian[nMedianTimeSpan];
# 293 : 653166 : int64_t* pbegin = &pmedian[nMedianTimeSpan];
# 294 : 653166 : int64_t* pend = &pmedian[nMedianTimeSpan];
# 295 : :
# 296 : 653166 : const CBlockIndex* pindex = this;
# 297 [ + + ][ + + ]: 7764331 : for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
# 298 : 7111165 : *(--pbegin) = pindex->GetBlockTime();
# 299 : :
# 300 : 653166 : std::sort(pbegin, pend);
# 301 : 653166 : return pbegin[(pend - pbegin) / 2];
# 302 : 653166 : }
# 303 : :
# 304 : : std::string ToString() const
# 305 : 0 : {
# 306 : 0 : return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
# 307 : 0 : pprev, nHeight,
# 308 : 0 : hashMerkleRoot.ToString(),
# 309 : 0 : GetBlockHash().ToString());
# 310 : 0 : }
# 311 : :
# 312 : : //! Check whether this block index entry is valid up to the passed validity level.
# 313 : : bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const
# 314 : : EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
# 315 : 635171 : {
# 316 : 635171 : AssertLockHeld(::cs_main);
# 317 : 635171 : assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
# 318 [ + + ]: 635171 : if (nStatus & BLOCK_FAILED_MASK)
# 319 : 3950 : return false;
# 320 : 631221 : return ((nStatus & BLOCK_VALID_MASK) >= nUpTo);
# 321 : 635171 : }
# 322 : :
# 323 : : //! @returns true if the block is assumed-valid; this means it is queued to be
# 324 : : //! validated by a background chainstate.
# 325 : : bool IsAssumedValid() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
# 326 : 352565437 : {
# 327 : 352565437 : AssertLockHeld(::cs_main);
# 328 : 352565437 : return nStatus & BLOCK_ASSUMED_VALID;
# 329 : 352565437 : }
# 330 : :
# 331 : : //! Raise the validity level of this block index entry.
# 332 : : //! Returns true if the validity was changed.
# 333 : : bool RaiseValidity(enum BlockStatus nUpTo) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
# 334 : 192200 : {
# 335 : 192200 : AssertLockHeld(::cs_main);
# 336 : 192200 : assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
# 337 [ - + ]: 192200 : if (nStatus & BLOCK_FAILED_MASK) return false;
# 338 : :
# 339 [ + - ]: 192200 : if ((nStatus & BLOCK_VALID_MASK) < nUpTo) {
# 340 : : // If this block had been marked assumed-valid and we're raising
# 341 : : // its validity to a certain point, there is no longer an assumption.
# 342 [ - + ][ # # ]: 192200 : if (nStatus & BLOCK_ASSUMED_VALID && nUpTo >= BLOCK_VALID_SCRIPTS) {
# 343 : 0 : nStatus &= ~BLOCK_ASSUMED_VALID;
# 344 : 0 : }
# 345 : :
# 346 : 192200 : nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo;
# 347 : 192200 : return true;
# 348 : 192200 : }
# 349 : 0 : return false;
# 350 : 192200 : }
# 351 : :
# 352 : : //! Build the skiplist pointer for this entry.
# 353 : : void BuildSkip();
# 354 : :
# 355 : : //! Efficiently find an ancestor of this block.
# 356 : : CBlockIndex* GetAncestor(int height);
# 357 : : const CBlockIndex* GetAncestor(int height) const;
# 358 : : };
# 359 : :
# 360 : : arith_uint256 GetBlockProof(const CBlockIndex& block);
# 361 : : /** 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. */
# 362 : : int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params&);
# 363 : : /** Find the forking point between two chain tips. */
# 364 : : const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb);
# 365 : :
# 366 : :
# 367 : : /** Used to marshal pointers into hashes for db storage. */
# 368 : : class CDiskBlockIndex : public CBlockIndex
# 369 : : {
# 370 : : public:
# 371 : : uint256 hashPrev;
# 372 : :
# 373 : : CDiskBlockIndex()
# 374 : 78674 : {
# 375 : 78674 : hashPrev = uint256();
# 376 : 78674 : }
# 377 : :
# 378 : : explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex)
# 379 : 62918 : {
# 380 [ + + ]: 62918 : hashPrev = (pprev ? pprev->GetBlockHash() : uint256());
# 381 : 62918 : }
# 382 : :
# 383 : : SERIALIZE_METHODS(CDiskBlockIndex, obj)
# 384 : 141592 : {
# 385 : 141592 : LOCK(::cs_main);
# 386 : 141592 : int _nVersion = s.GetVersion();
# 387 [ + - ][ + - ]: 141592 : if (!(s.GetType() & SER_GETHASH)) READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED));
# 388 : :
# 389 : 141592 : READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED));
# 390 : 141592 : READWRITE(VARINT(obj.nStatus));
# 391 : 141592 : READWRITE(VARINT(obj.nTx));
# 392 [ + + ][ + + ]: 141592 : if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED));
# 393 [ + + ][ + + ]: 141592 : if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE(VARINT(obj.nDataPos));
# 394 [ + + ][ + + ]: 141592 : if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(obj.nUndoPos));
# 395 : :
# 396 : : // block header
# 397 : 141592 : READWRITE(obj.nVersion);
# 398 : 141592 : READWRITE(obj.hashPrev);
# 399 : 141592 : READWRITE(obj.hashMerkleRoot);
# 400 : 141592 : READWRITE(obj.nTime);
# 401 : 141592 : READWRITE(obj.nBits);
# 402 : 141592 : READWRITE(obj.nNonce);
# 403 : 141592 : }
# 404 : :
# 405 : : uint256 GetBlockHash() const
# 406 : 78674 : {
# 407 : 78674 : CBlockHeader block;
# 408 : 78674 : block.nVersion = nVersion;
# 409 : 78674 : block.hashPrevBlock = hashPrev;
# 410 : 78674 : block.hashMerkleRoot = hashMerkleRoot;
# 411 : 78674 : block.nTime = nTime;
# 412 : 78674 : block.nBits = nBits;
# 413 : 78674 : block.nNonce = nNonce;
# 414 : 78674 : return block.GetHash();
# 415 : 78674 : }
# 416 : :
# 417 : :
# 418 : : std::string ToString() const
# 419 : 0 : {
# 420 : 0 : std::string str = "CDiskBlockIndex(";
# 421 : 0 : str += CBlockIndex::ToString();
# 422 : 0 : str += strprintf("\n hashBlock=%s, hashPrev=%s)",
# 423 : 0 : GetBlockHash().ToString(),
# 424 : 0 : hashPrev.ToString());
# 425 : 0 : return str;
# 426 : 0 : }
# 427 : : };
# 428 : :
# 429 : : /** An in-memory indexed chain of blocks. */
# 430 : : class CChain
# 431 : : {
# 432 : : private:
# 433 : : std::vector<CBlockIndex*> vChain;
# 434 : :
# 435 : : public:
# 436 : 961 : CChain() = default;
# 437 : : CChain(const CChain&) = delete;
# 438 : : CChain& operator=(const CChain&) = delete;
# 439 : :
# 440 : : /** Returns the index entry for the genesis block of this chain, or nullptr if none. */
# 441 : : CBlockIndex* Genesis() const
# 442 : 242848 : {
# 443 [ + + ]: 242848 : return vChain.size() > 0 ? vChain[0] : nullptr;
# 444 : 242848 : }
# 445 : :
# 446 : : /** Returns the index entry for the tip of this chain, or nullptr if none. */
# 447 : : CBlockIndex* Tip() const
# 448 : 129765381 : {
# 449 [ + + ]: 129765381 : return vChain.size() > 0 ? vChain[vChain.size() - 1] : nullptr;
# 450 : 129765381 : }
# 451 : :
# 452 : : /** Returns the index entry at a particular height in this chain, or nullptr if no such height exists. */
# 453 : : CBlockIndex* operator[](int nHeight) const
# 454 : 1259740 : {
# 455 [ - + ][ + + ]: 1259740 : if (nHeight < 0 || nHeight >= (int)vChain.size())
# 456 : 367052 : return nullptr;
# 457 : 892688 : return vChain[nHeight];
# 458 : 1259740 : }
# 459 : :
# 460 : : /** Efficiently check whether a block is present in this chain. */
# 461 : : bool Contains(const CBlockIndex* pindex) const
# 462 : 723460 : {
# 463 : 723460 : return (*this)[pindex->nHeight] == pindex;
# 464 : 723460 : }
# 465 : :
# 466 : : /** Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip. */
# 467 : : CBlockIndex* Next(const CBlockIndex* pindex) const
# 468 : 16622 : {
# 469 [ + - ]: 16622 : if (Contains(pindex))
# 470 : 16622 : return (*this)[pindex->nHeight + 1];
# 471 : 0 : else
# 472 : 0 : return nullptr;
# 473 : 16622 : }
# 474 : :
# 475 : : /** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */
# 476 : : int Height() const
# 477 : 730723 : {
# 478 : 730723 : return int(vChain.size()) - 1;
# 479 : 730723 : }
# 480 : :
# 481 : : /** Set/initialize a chain with a given tip. */
# 482 : : void SetTip(CBlockIndex* pindex);
# 483 : :
# 484 : : /** Return a CBlockLocator that refers to a block in this chain (by default the tip). */
# 485 : : CBlockLocator GetLocator(const CBlockIndex* pindex = nullptr) const;
# 486 : :
# 487 : : /** Find the last common block between this chain and a block index entry. */
# 488 : : const CBlockIndex* FindFork(const CBlockIndex* pindex) const;
# 489 : :
# 490 : : /** Find the earliest block with timestamp equal or greater than the given time and height equal or greater than the given height. */
# 491 : : CBlockIndex* FindEarliestAtLeast(int64_t nTime, int height) const;
# 492 : : };
# 493 : :
# 494 : : #endif // BITCOIN_CHAIN_H
|