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 <uint256.h>
# 15 : : #include <util/time.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 : 1499 : {
# 56 : 1499 : READWRITE(VARINT(obj.nBlocks));
# 57 : 1499 : READWRITE(VARINT(obj.nSize));
# 58 : 1499 : READWRITE(VARINT(obj.nUndoSize));
# 59 : 1499 : READWRITE(VARINT(obj.nHeightFirst));
# 60 : 1499 : READWRITE(VARINT(obj.nHeightLast));
# 61 : 1499 : READWRITE(VARINT(obj.nTimeFirst));
# 62 : 1499 : READWRITE(VARINT(obj.nTimeLast));
# 63 : 1499 : }
# 64 : :
# 65 : : void SetNull()
# 66 : 1928 : {
# 67 : 1928 : nBlocks = 0;
# 68 : 1928 : nSize = 0;
# 69 : 1928 : nUndoSize = 0;
# 70 : 1928 : nHeightFirst = 0;
# 71 : 1928 : nHeightLast = 0;
# 72 : 1928 : nTimeFirst = 0;
# 73 : 1928 : nTimeLast = 0;
# 74 : 1928 : }
# 75 : :
# 76 : : CBlockFileInfo()
# 77 : 1925 : {
# 78 : 1925 : SetNull();
# 79 : 1925 : }
# 80 : :
# 81 : : std::string ToString() const;
# 82 : :
# 83 : : /** update statistics (does not update nSize) */
# 84 : : void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn)
# 85 : 83200 : {
# 86 [ + + ][ + + ]: 83200 : if (nBlocks == 0 || nHeightFirst > nHeightIn)
# 87 : 497 : nHeightFirst = nHeightIn;
# 88 [ + + ][ + + ]: 83200 : if (nBlocks == 0 || nTimeFirst > nTimeIn)
# 89 : 497 : nTimeFirst = nTimeIn;
# 90 : 83200 : nBlocks++;
# 91 [ + + ]: 83200 : if (nHeightIn > nHeightLast)
# 92 : 71690 : nHeightLast = nHeightIn;
# 93 [ + + ]: 83200 : if (nTimeIn > nTimeLast)
# 94 : 25869 : nTimeLast = nTimeIn;
# 95 : 83200 : }
# 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/design/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 : 7984293 : {
# 218 : 7984293 : }
# 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 : 824528 : {
# 227 : 824528 : }
# 228 : :
# 229 : : FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
# 230 : 168984 : {
# 231 : 168984 : AssertLockHeld(::cs_main);
# 232 : 168984 : FlatFilePos ret;
# 233 [ + + ]: 168984 : if (nStatus & BLOCK_HAVE_DATA) {
# 234 : 168875 : ret.nFile = nFile;
# 235 : 168875 : ret.nPos = nDataPos;
# 236 : 168875 : }
# 237 : 168984 : return ret;
# 238 : 168984 : }
# 239 : :
# 240 : : FlatFilePos GetUndoPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
# 241 : 105918 : {
# 242 : 105918 : AssertLockHeld(::cs_main);
# 243 : 105918 : FlatFilePos ret;
# 244 [ + + ]: 105918 : if (nStatus & BLOCK_HAVE_UNDO) {
# 245 : 25906 : ret.nFile = nFile;
# 246 : 25906 : ret.nPos = nUndoPos;
# 247 : 25906 : }
# 248 : 105918 : return ret;
# 249 : 105918 : }
# 250 : :
# 251 : : CBlockHeader GetBlockHeader() const
# 252 : 516427 : {
# 253 : 516427 : CBlockHeader block;
# 254 : 516427 : block.nVersion = nVersion;
# 255 [ + + ]: 516427 : if (pprev)
# 256 : 516414 : block.hashPrevBlock = pprev->GetBlockHash();
# 257 : 516427 : block.hashMerkleRoot = hashMerkleRoot;
# 258 : 516427 : block.nTime = nTime;
# 259 : 516427 : block.nBits = nBits;
# 260 : 516427 : block.nNonce = nNonce;
# 261 : 516427 : return block;
# 262 : 516427 : }
# 263 : :
# 264 : : uint256 GetBlockHash() const
# 265 : 5008623 : {
# 266 : 5008623 : assert(phashBlock != nullptr);
# 267 : 0 : return *phashBlock;
# 268 : 5008623 : }
# 269 : :
# 270 : : /**
# 271 : : * Check whether this block's and all previous blocks' transactions have been
# 272 : : * downloaded (and stored to disk) at some point.
# 273 : : *
# 274 : : * Does not imply the transactions are consensus-valid (ConnectTip might fail)
# 275 : : * Does not imply the transactions are still stored on disk. (IsBlockPruned might return true)
# 276 : : */
# 277 : 285023105 : bool HaveTxsDownloaded() const { return nChainTx != 0; }
# 278 : :
# 279 : : NodeSeconds Time() const
# 280 : 37352 : {
# 281 : 37352 : return NodeSeconds{std::chrono::seconds{nTime}};
# 282 : 37352 : }
# 283 : :
# 284 : : int64_t GetBlockTime() const
# 285 : 8540944 : {
# 286 : 8540944 : return (int64_t)nTime;
# 287 : 8540944 : }
# 288 : :
# 289 : : int64_t GetBlockTimeMax() const
# 290 : 354666 : {
# 291 : 354666 : return (int64_t)nTimeMax;
# 292 : 354666 : }
# 293 : :
# 294 : : static constexpr int nMedianTimeSpan = 11;
# 295 : :
# 296 : : int64_t GetMedianTimePast() const
# 297 : 728363 : {
# 298 : 728363 : int64_t pmedian[nMedianTimeSpan];
# 299 : 728363 : int64_t* pbegin = &pmedian[nMedianTimeSpan];
# 300 : 728363 : int64_t* pend = &pmedian[nMedianTimeSpan];
# 301 : :
# 302 : 728363 : const CBlockIndex* pindex = this;
# 303 [ + + ][ + + ]: 8664705 : for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
# 304 : 7936342 : *(--pbegin) = pindex->GetBlockTime();
# 305 : :
# 306 : 728363 : std::sort(pbegin, pend);
# 307 : 728363 : return pbegin[(pend - pbegin) / 2];
# 308 : 728363 : }
# 309 : :
# 310 : : std::string ToString() const;
# 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 : 911856 : {
# 316 : 911856 : AssertLockHeld(::cs_main);
# 317 : 911856 : assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
# 318 [ + + ]: 911856 : if (nStatus & BLOCK_FAILED_MASK)
# 319 : 2446 : return false;
# 320 : 909410 : return ((nStatus & BLOCK_VALID_MASK) >= nUpTo);
# 321 : 911856 : }
# 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 : 285045100 : {
# 327 : 285045100 : AssertLockHeld(::cs_main);
# 328 : 285045100 : return nStatus & BLOCK_ASSUMED_VALID;
# 329 : 285045100 : }
# 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 : 255912 : {
# 335 : 255912 : AssertLockHeld(::cs_main);
# 336 : 255912 : assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
# 337 [ - + ]: 255912 : if (nStatus & BLOCK_FAILED_MASK) return false;
# 338 : :
# 339 [ + - ]: 255912 : 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 [ - + ][ # # ]: 255912 : if (nStatus & BLOCK_ASSUMED_VALID && nUpTo >= BLOCK_VALID_SCRIPTS) {
# 343 : 0 : nStatus &= ~BLOCK_ASSUMED_VALID;
# 344 : 0 : }
# 345 : :
# 346 : 255912 : nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo;
# 347 : 255912 : return true;
# 348 : 255912 : }
# 349 : 0 : return false;
# 350 : 255912 : }
# 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 : 74316 : {
# 375 : 74316 : hashPrev = uint256();
# 376 : 74316 : }
# 377 : :
# 378 : : explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex)
# 379 : 86709 : {
# 380 [ + + ]: 86709 : hashPrev = (pprev ? pprev->GetBlockHash() : uint256());
# 381 : 86709 : }
# 382 : :
# 383 : : SERIALIZE_METHODS(CDiskBlockIndex, obj)
# 384 : 161025 : {
# 385 : 161025 : LOCK(::cs_main);
# 386 : 161025 : int _nVersion = s.GetVersion();
# 387 [ + - ][ + - ]: 161025 : if (!(s.GetType() & SER_GETHASH)) READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED));
# 388 : :
# 389 : 161025 : READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED));
# 390 : 161025 : READWRITE(VARINT(obj.nStatus));
# 391 : 161025 : READWRITE(VARINT(obj.nTx));
# 392 [ + + ][ + + ]: 161025 : if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED));
# 393 [ + + ][ + + ]: 161025 : if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE(VARINT(obj.nDataPos));
# 394 [ + + ][ + + ]: 161025 : if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(obj.nUndoPos));
# 395 : :
# 396 : : // block header
# 397 : 161025 : READWRITE(obj.nVersion);
# 398 : 161025 : READWRITE(obj.hashPrev);
# 399 : 161025 : READWRITE(obj.hashMerkleRoot);
# 400 : 161025 : READWRITE(obj.nTime);
# 401 : 161025 : READWRITE(obj.nBits);
# 402 : 161025 : READWRITE(obj.nNonce);
# 403 : 161025 : }
# 404 : :
# 405 : : uint256 ConstructBlockHash() const
# 406 : 74316 : {
# 407 : 74316 : CBlockHeader block;
# 408 : 74316 : block.nVersion = nVersion;
# 409 : 74316 : block.hashPrevBlock = hashPrev;
# 410 : 74316 : block.hashMerkleRoot = hashMerkleRoot;
# 411 : 74316 : block.nTime = nTime;
# 412 : 74316 : block.nBits = nBits;
# 413 : 74316 : block.nNonce = nNonce;
# 414 : 74316 : return block.GetHash();
# 415 : 74316 : }
# 416 : :
# 417 : : uint256 GetBlockHash() = delete;
# 418 : : std::string ToString() = delete;
# 419 : : };
# 420 : :
# 421 : : /** An in-memory indexed chain of blocks. */
# 422 : : class CChain
# 423 : : {
# 424 : : private:
# 425 : : std::vector<CBlockIndex*> vChain;
# 426 : :
# 427 : : public:
# 428 : 983 : CChain() = default;
# 429 : : CChain(const CChain&) = delete;
# 430 : : CChain& operator=(const CChain&) = delete;
# 431 : :
# 432 : : /** Returns the index entry for the genesis block of this chain, or nullptr if none. */
# 433 : : CBlockIndex* Genesis() const
# 434 : 215866 : {
# 435 [ + + ]: 215866 : return vChain.size() > 0 ? vChain[0] : nullptr;
# 436 : 215866 : }
# 437 : :
# 438 : : /** Returns the index entry for the tip of this chain, or nullptr if none. */
# 439 : : CBlockIndex* Tip() const
# 440 : 99000347 : {
# 441 [ + + ]: 99000347 : return vChain.size() > 0 ? vChain[vChain.size() - 1] : nullptr;
# 442 : 99000347 : }
# 443 : :
# 444 : : /** Returns the index entry at a particular height in this chain, or nullptr if no such height exists. */
# 445 : : CBlockIndex* operator[](int nHeight) const
# 446 : 2531895 : {
# 447 [ - + ][ + + ]: 2531895 : if (nHeight < 0 || nHeight >= (int)vChain.size())
# 448 : 538433 : return nullptr;
# 449 : 1993462 : return vChain[nHeight];
# 450 : 2531895 : }
# 451 : :
# 452 : : /** Efficiently check whether a block is present in this chain. */
# 453 : : bool Contains(const CBlockIndex* pindex) const
# 454 : 1499967 : {
# 455 : 1499967 : return (*this)[pindex->nHeight] == pindex;
# 456 : 1499967 : }
# 457 : :
# 458 : : /** Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip. */
# 459 : : CBlockIndex* Next(const CBlockIndex* pindex) const
# 460 : 509384 : {
# 461 [ + - ]: 509384 : if (Contains(pindex))
# 462 : 509384 : return (*this)[pindex->nHeight + 1];
# 463 : 0 : else
# 464 : 0 : return nullptr;
# 465 : 509384 : }
# 466 : :
# 467 : : /** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */
# 468 : : int Height() const
# 469 : 756642 : {
# 470 : 756642 : return int(vChain.size()) - 1;
# 471 : 756642 : }
# 472 : :
# 473 : : /** Set/initialize a chain with a given tip. */
# 474 : : void SetTip(CBlockIndex& block);
# 475 : :
# 476 : : /** Return a CBlockLocator that refers to the tip in of this chain. */
# 477 : : CBlockLocator GetLocator() const;
# 478 : :
# 479 : : /** Find the last common block between this chain and a block index entry. */
# 480 : : const CBlockIndex* FindFork(const CBlockIndex* pindex) const;
# 481 : :
# 482 : : /** Find the earliest block with timestamp equal or greater than the given time and height equal or greater than the given height. */
# 483 : : CBlockIndex* FindEarliestAtLeast(int64_t nTime, int height) const;
# 484 : : };
# 485 : :
# 486 : : /** Get a locator for a block index entry. */
# 487 : : CBlockLocator GetLocator(const CBlockIndex* index);
# 488 : :
# 489 : : /** Construct a list of hash entries to put in a locator. */
# 490 : : std::vector<uint256> LocatorEntries(const CBlockIndex* index);
# 491 : :
# 492 : : #endif // BITCOIN_CHAIN_H
|