Branch data Line data Source code
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 : : //! Init values for CBlockIndex nSequenceId when loaded from disk
39 : : static constexpr int32_t SEQ_ID_BEST_CHAIN_FROM_DISK = 0;
40 : : static constexpr int32_t SEQ_ID_INIT_FROM_DISK = 1;
41 : :
42 : : enum BlockStatus : uint32_t {
43 : : //! Unused.
44 : : BLOCK_VALID_UNKNOWN = 0,
45 : :
46 : : //! Reserved (was BLOCK_VALID_HEADER).
47 : : BLOCK_VALID_RESERVED = 1,
48 : :
49 : : //! All parent headers found, difficulty matches, timestamp >= median previous. Implies all parents
50 : : //! are also at least TREE.
51 : : BLOCK_VALID_TREE = 2,
52 : :
53 : : /**
54 : : * Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid, no duplicate txids,
55 : : * sigops, size, merkle root. Implies all parents are at least TREE but not necessarily TRANSACTIONS.
56 : : *
57 : : * If a block's validity is at least VALID_TRANSACTIONS, CBlockIndex::nTx will be set. If a block and all previous
58 : : * blocks back to the genesis block or an assumeutxo snapshot block are at least VALID_TRANSACTIONS,
59 : : * CBlockIndex::m_chain_tx_count will be set.
60 : : */
61 : : BLOCK_VALID_TRANSACTIONS = 3,
62 : :
63 : : //! Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends, BIP30.
64 : : //! Implies all previous blocks back to the genesis block or an assumeutxo snapshot block are at least VALID_CHAIN.
65 : : BLOCK_VALID_CHAIN = 4,
66 : :
67 : : //! Scripts & signatures ok. Implies all previous blocks back to the genesis block or an assumeutxo snapshot block
68 : : //! are at least VALID_SCRIPTS.
69 : : BLOCK_VALID_SCRIPTS = 5,
70 : :
71 : : //! All validity bits.
72 : : BLOCK_VALID_MASK = BLOCK_VALID_RESERVED | BLOCK_VALID_TREE | BLOCK_VALID_TRANSACTIONS |
73 : : BLOCK_VALID_CHAIN | BLOCK_VALID_SCRIPTS,
74 : :
75 : : BLOCK_HAVE_DATA = 8, //!< full block available in blk*.dat
76 : : BLOCK_HAVE_UNDO = 16, //!< undo data available in rev*.dat
77 : : BLOCK_HAVE_MASK = BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO,
78 : :
79 : : BLOCK_FAILED_VALID = 32, //!< stage after last reached validness failed
80 : : BLOCK_FAILED_CHILD = 64, //!< descends from failed block
81 : : BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,
82 : :
83 : : BLOCK_OPT_WITNESS = 128, //!< block data in blk*.dat was received with a witness-enforcing client
84 : :
85 : : BLOCK_STATUS_RESERVED = 256, //!< Unused flag that was previously set on assumeutxo snapshot blocks and their
86 : : //!< ancestors before they were validated, and unset when they were validated.
87 : : };
88 : :
89 : : /** The block chain is a tree shaped structure starting with the
90 : : * genesis block at the root, with each block potentially having multiple
91 : : * candidates to be the next block. A blockindex may have multiple pprev pointing
92 : : * to it, but at most one of them can be part of the currently active branch.
93 : : */
94 : : class CBlockIndex
95 : : {
96 : : public:
97 : : //! pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
98 : : const uint256* phashBlock{nullptr};
99 : :
100 : : //! pointer to the index of the predecessor of this block
101 : : CBlockIndex* pprev{nullptr};
102 : :
103 : : //! pointer to the index of some further predecessor of this block
104 : : CBlockIndex* pskip{nullptr};
105 : :
106 : : //! height of the entry in the chain. The genesis block has height 0
107 : : int nHeight{0};
108 : :
109 : : //! Which # file this block is stored in (blk?????.dat)
110 : : int nFile GUARDED_BY(::cs_main){0};
111 : :
112 : : //! Byte offset within blk?????.dat where this block's data is stored
113 : : unsigned int nDataPos GUARDED_BY(::cs_main){0};
114 : :
115 : : //! Byte offset within rev?????.dat where this block's undo data is stored
116 : : unsigned int nUndoPos GUARDED_BY(::cs_main){0};
117 : :
118 : : //! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block
119 : : arith_uint256 nChainWork{};
120 : :
121 : : //! Number of transactions in this block. This will be nonzero if the block
122 : : //! reached the VALID_TRANSACTIONS level, and zero otherwise.
123 : : //! Note: in a potential headers-first mode, this number cannot be relied upon
124 : : unsigned int nTx{0};
125 : :
126 : : //! (memory only) Number of transactions in the chain up to and including this block.
127 : : //! This value will be non-zero if this block and all previous blocks back
128 : : //! to the genesis block or an assumeutxo snapshot block have reached the
129 : : //! VALID_TRANSACTIONS level.
130 : : uint64_t m_chain_tx_count{0};
131 : :
132 : : //! Verification status of this block. See enum BlockStatus
133 : : //!
134 : : //! Note: this value is modified to show BLOCK_OPT_WITNESS during UTXO snapshot
135 : : //! load to avoid a spurious startup failure requiring -reindex.
136 : : //! @sa NeedsRedownload
137 : : //! @sa ActivateSnapshot
138 : : uint32_t nStatus GUARDED_BY(::cs_main){0};
139 : :
140 : : //! block header
141 : : int32_t nVersion{0};
142 : : uint256 hashMerkleRoot{};
143 : : uint32_t nTime{0};
144 : : uint32_t nBits{0};
145 : : uint32_t nNonce{0};
146 : :
147 : : //! (memory only) Sequential id assigned to distinguish order in which blocks are received.
148 : : //! Initialized to SEQ_ID_INIT_FROM_DISK{1} when loading blocks from disk, except for blocks
149 : : //! belonging to the best chain which overwrite it to SEQ_ID_BEST_CHAIN_FROM_DISK{0}.
150 : : int32_t nSequenceId{SEQ_ID_INIT_FROM_DISK};
151 : :
152 : : //! (memory only) Maximum nTime in the chain up to and including this block.
153 : : unsigned int nTimeMax{0};
154 : :
155 : 489322 : explicit CBlockIndex(const CBlockHeader& block)
156 : 489322 : : nVersion{block.nVersion},
157 : 489322 : hashMerkleRoot{block.hashMerkleRoot},
158 : 489322 : nTime{block.nTime},
159 : 489322 : nBits{block.nBits},
160 : 489322 : nNonce{block.nNonce}
161 : : {
162 : 489322 : }
163 : :
164 : 177224 : FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
165 : : {
166 : 177224 : AssertLockHeld(::cs_main);
167 : 177224 : FlatFilePos ret;
168 [ + + ]: 177224 : if (nStatus & BLOCK_HAVE_DATA) {
169 : 177121 : ret.nFile = nFile;
170 : 177121 : ret.nPos = nDataPos;
171 : : }
172 : 177224 : return ret;
173 : : }
174 : :
175 : 194140 : FlatFilePos GetUndoPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
176 : : {
177 : 194140 : AssertLockHeld(::cs_main);
178 : 194140 : FlatFilePos ret;
179 [ + + ]: 194140 : if (nStatus & BLOCK_HAVE_UNDO) {
180 : 66401 : ret.nFile = nFile;
181 : 66401 : ret.nPos = nUndoPos;
182 : : }
183 : 194140 : return ret;
184 : : }
185 : :
186 : 148090 : CBlockHeader GetBlockHeader() const
187 : : {
188 : 148090 : CBlockHeader block;
189 : 148090 : block.nVersion = nVersion;
190 [ + + ]: 148090 : if (pprev)
191 : 148083 : block.hashPrevBlock = pprev->GetBlockHash();
192 : 148090 : block.hashMerkleRoot = hashMerkleRoot;
193 : 148090 : block.nTime = nTime;
194 : 148090 : block.nBits = nBits;
195 : 148090 : block.nNonce = nNonce;
196 : 148090 : return block;
197 : : }
198 : :
199 : 5569762 : uint256 GetBlockHash() const
200 : : {
201 [ - + ]: 5569762 : assert(phashBlock != nullptr);
202 : 5569762 : return *phashBlock;
203 : : }
204 : :
205 : : /**
206 : : * Check whether this block and all previous blocks back to the genesis block or an assumeutxo snapshot block have
207 : : * reached VALID_TRANSACTIONS and had transactions downloaded (and stored to disk) at some point.
208 : : *
209 : : * Does not imply the transactions are consensus-valid (ConnectTip might fail)
210 : : * Does not imply the transactions are still stored on disk. (IsBlockPruned might return true)
211 : : *
212 : : * Note that this will be true for the snapshot base block, if one is loaded, since its m_chain_tx_count value will have
213 : : * been set manually based on the related AssumeutxoData entry.
214 : : */
215 [ + + - + : 536457189 : bool HaveNumChainTxs() const { return m_chain_tx_count != 0; }
+ + + + +
- + - + +
+ - - + ]
[ + - + +
# # # # #
# # # # #
# # # # ]
[ + + ]
216 : :
217 : 202798 : NodeSeconds Time() const
218 : : {
219 [ + + ]: 202798 : return NodeSeconds{std::chrono::seconds{nTime}};
220 : : }
221 : :
222 : 10197236 : int64_t GetBlockTime() const
223 : : {
224 [ + + # # ]: 1000362 : return (int64_t)nTime;
[ + + + +
+ - ][ + +
+ + # # ]
225 : : }
226 : :
227 : 266187 : int64_t GetBlockTimeMax() const
228 : : {
229 [ + + ]: 266187 : return (int64_t)nTimeMax;
[ + - + - ]
230 : : }
231 : :
232 : : static constexpr int nMedianTimeSpan = 11;
233 : :
234 : 839379 : int64_t GetMedianTimePast() const
235 : : {
236 : 839379 : int64_t pmedian[nMedianTimeSpan];
237 : 839379 : int64_t* pbegin = &pmedian[nMedianTimeSpan];
238 : 839379 : int64_t* pend = &pmedian[nMedianTimeSpan];
239 : :
240 : 839379 : const CBlockIndex* pindex = this;
241 [ + + ]: 9992920 : for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
242 : 9153541 : *(--pbegin) = pindex->GetBlockTime();
243 : :
244 : 839379 : std::sort(pbegin, pend);
245 : 839379 : return pbegin[(pend - pbegin) / 2];
246 : : }
247 : :
248 : : std::string ToString() const;
249 : :
250 : : //! Check whether this block index entry is valid up to the passed validity level.
251 : 3115286 : bool IsValid(enum BlockStatus nUpTo) const
252 : : EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
253 : : {
254 : 3115286 : AssertLockHeld(::cs_main);
255 : 3115286 : assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
256 [ + - # # : 3115281 : if (nStatus & BLOCK_FAILED_MASK)
# # # # #
# # # #
# ][ + + +
+ + - + -
+ - + + +
+ + - ][ +
- + - + -
+ + + + +
+ + + ][ #
# # # # #
# # # # #
# ]
257 : : return false;
258 [ + + + - : 3107290 : return ((nStatus & BLOCK_VALID_MASK) >= nUpTo);
+ - + + +
+ + + + -
+ + ][ + -
+ - + + +
+ - + + +
+ - # # ]
[ - + ]
[ + - - - ]
[ # # # #
# # # # #
# # # ]
259 : : }
260 : :
261 : : //! Raise the validity level of this block index entry.
262 : : //! Returns true if the validity was changed.
263 : 408435 : bool RaiseValidity(enum BlockStatus nUpTo) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
264 : : {
265 : 408435 : AssertLockHeld(::cs_main);
266 [ - + ]: 408435 : assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
267 [ + - ]: 408435 : if (nStatus & BLOCK_FAILED_MASK) return false;
268 : :
269 [ + + ]: 408435 : if ((nStatus & BLOCK_VALID_MASK) < nUpTo) {
270 : 408294 : nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo;
271 : 408294 : return true;
272 : : }
273 : : return false;
274 : : }
275 : :
276 : : //! Build the skiplist pointer for this entry.
277 : : void BuildSkip();
278 : :
279 : : //! Efficiently find an ancestor of this block.
280 : : CBlockIndex* GetAncestor(int height);
281 : : const CBlockIndex* GetAncestor(int height) const;
282 : :
283 : 7466900 : CBlockIndex() = default;
284 : : ~CBlockIndex() = default;
285 : :
286 : : protected:
287 : : //! CBlockIndex should not allow public copy construction because equality
288 : : //! comparison via pointer is very common throughout the codebase, making
289 : : //! use of copy a footgun. Also, use of copies do not have the benefit
290 : : //! of simplifying lifetime considerations due to attributes like pprev and
291 : : //! pskip, which are at risk of becoming dangling pointers in a copied
292 : : //! instance.
293 : : //!
294 : : //! We declare these protected instead of simply deleting them so that
295 : : //! CDiskBlockIndex can reuse copy construction.
296 : : CBlockIndex(const CBlockIndex&) = default;
297 : : CBlockIndex& operator=(const CBlockIndex&) = delete;
298 : : CBlockIndex(CBlockIndex&&) = delete;
299 : : CBlockIndex& operator=(CBlockIndex&&) = delete;
300 : : };
301 : :
302 : : arith_uint256 GetBlockProof(const CBlockIndex& block);
303 : : /** 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. */
304 : : int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params&);
305 : : /** Find the forking point between two chain tips. */
306 : : const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb);
307 : :
308 : :
309 : : /** Used to marshal pointers into hashes for db storage. */
310 : : class CDiskBlockIndex : public CBlockIndex
311 : : {
312 : : /** Historically CBlockLocator's version field has been written to disk
313 : : * streams as the client version, but the value has never been used.
314 : : *
315 : : * Hard-code to the highest client version ever written.
316 : : * SerParams can be used if the field requires any meaning in the future.
317 : : **/
318 : : static constexpr int DUMMY_VERSION = 259900;
319 : :
320 : : public:
321 : : uint256 hashPrev;
322 : :
323 : 165781 : CDiskBlockIndex()
324 : 165781 : {
325 : 165781 : hashPrev = uint256();
326 : 165781 : }
327 : :
328 [ + + ]: 159047 : explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex)
329 : : {
330 [ + + ]: 159047 : hashPrev = (pprev ? pprev->GetBlockHash() : uint256());
331 : 159047 : }
332 : :
333 : 649656 : SERIALIZE_METHODS(CDiskBlockIndex, obj)
334 : : {
335 : 324828 : LOCK(::cs_main);
336 [ + - ]: 324828 : int _nVersion = DUMMY_VERSION;
337 [ + - ]: 324828 : READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED));
338 : :
339 [ + - ]: 324828 : READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED));
340 [ + - ]: 324828 : READWRITE(VARINT(obj.nStatus));
341 [ + - ]: 324828 : READWRITE(VARINT(obj.nTx));
342 [ + + + - ]: 324828 : if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED));
343 [ + + + - ]: 324828 : if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE(VARINT(obj.nDataPos));
344 [ + + + - ]: 324828 : if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(obj.nUndoPos));
345 : :
346 : : // block header
347 [ + - ]: 324828 : READWRITE(obj.nVersion);
348 [ + - ]: 324828 : READWRITE(obj.hashPrev);
349 [ + - ]: 324828 : READWRITE(obj.hashMerkleRoot);
350 [ + - ]: 324828 : READWRITE(obj.nTime);
351 [ + - ]: 324828 : READWRITE(obj.nBits);
352 [ + - + - ]: 649656 : READWRITE(obj.nNonce);
353 : 324828 : }
354 : :
355 : 165781 : uint256 ConstructBlockHash() const
356 : : {
357 : 165781 : CBlockHeader block;
358 : 165781 : block.nVersion = nVersion;
359 : 165781 : block.hashPrevBlock = hashPrev;
360 : 165781 : block.hashMerkleRoot = hashMerkleRoot;
361 : 165781 : block.nTime = nTime;
362 : 165781 : block.nBits = nBits;
363 : 165781 : block.nNonce = nNonce;
364 : 165781 : return block.GetHash();
365 : : }
366 : :
367 : : uint256 GetBlockHash() = delete;
368 : : std::string ToString() = delete;
369 : : };
370 : :
371 : : /** An in-memory indexed chain of blocks. */
372 [ + - ]: 380328 : class CChain
373 : : {
374 : : private:
375 : : std::vector<CBlockIndex*> vChain;
376 : :
377 : : public:
378 [ + + ]: 1300 : CChain() = default;
379 : : CChain(const CChain&) = delete;
380 : : CChain& operator=(const CChain&) = delete;
381 : :
382 : : /** Returns the index entry for the genesis block of this chain, or nullptr if none. */
383 : 392429 : CBlockIndex* Genesis() const
384 : : {
385 [ - + + - ]: 392429 : return vChain.size() > 0 ? vChain[0] : nullptr;
[ - + + -
+ - - + -
+ - + ][ -
+ + - - +
+ - ]
386 : : }
387 : :
388 : : /** Returns the index entry for the tip of this chain, or nullptr if none. */
389 : 310219113 : CBlockIndex* Tip() const
390 : : {
391 [ - + + - : 310379403 : return vChain.size() > 0 ? vChain[vChain.size() - 1] : nullptr;
+ + + + +
+ + + # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ][ - + +
- - + +
+ ][ - + +
- - + + -
- + + - -
+ + - - +
+ - # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ]
[ - + + - ]
[ - + + -
- + + - -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + + -
- + + - ]
[ - + + -
- + + - -
+ + - - +
+ - - + +
- - + + -
- + + - #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ][ -
+ + - - +
+ + + + +
+ + + +
+ ][ - + +
- - - - -
- - - - -
- - - - -
- - - - ]
[ - + + -
- + + - -
+ + - + -
- + + - -
+ + - - +
+ + + - -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + + - +
+ - + - +
+ - + + -
- + + - -
+ + + - +
+ - - + +
- - + + -
- + + + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ + - + +
+ - + + -
- + + - +
- + - - +
+ + - + +
+ + - + +
- + + - -
+ + - - +
+ + - + +
- - + - +
+ + - + +
- - + - +
+ - - + +
- - + + +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ - + - -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
+ - + + +
- + + - +
+ ][ - - -
- - + + -
- + + - -
+ + - - -
- - - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + + -
+ - - + +
- - + + -
- + + - -
+ + - - -
- - # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ][ - +
+ - + - ]
[ - + + -
+ - + - -
- - - - +
+ - - + +
- + - - +
+ - - + +
- - + + -
- + + - -
+ + - + -
- + + - -
+ + - - +
+ - - + +
- - - -
- ][ - - -
- - - - -
- + + - -
- - - - -
- - - + +
- - - - -
- - - - -
+ + - - -
- - - - -
- - + + -
- - - - -
- - - - +
+ - - - -
- - - - -
- + + - -
+ + - - +
+ - - + +
- - + + -
- - - - #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ][ -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + +
- ]
392 : : }
393 : :
394 : : /** Returns the index entry at a particular height in this chain, or nullptr if no such height exists. */
395 : 779539833 : CBlockIndex* operator[](int nHeight) const
396 : : {
397 [ - + + + : 779530143 : if (nHeight < 0 || nHeight >= (int)vChain.size())
# # # # #
# # # # #
# # # # #
# ][ - + +
+ - + +
+ ][ + - -
+ + - + -
- + + - +
- - + + -
+ - - + +
- + - +
+ ][ + - +
- + - - +
+ + + - -
+ + + + -
- + + + -
- - - - -
- - ][ + +
+ + + + +
- + + + +
+ + + + -
+ + - # #
# # # # #
# # # ][ +
- - + + +
+ - - + +
+ - - - -
- - - + +
+ + - - -
- - - - -
- ][ - - -
- - - - +
+ + - - -
- - - - -
- - - - -
- + - - +
+ - + - -
+ + - # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ][ -
+ + - - +
+ - - + +
- + - - +
+ - - + +
- + - - +
+ - + - -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + +
- ][ + - -
+ + - + -
- + + - #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ][ +
- - + + +
- + + + ]
398 : : return nullptr;
399 [ + - ]: 777589019 : return vChain[nHeight];
400 : : }
401 : :
402 : : /** Efficiently check whether a block is present in this chain. */
403 : 517387323 : bool Contains(const CBlockIndex* pindex) const
404 : : {
405 [ + - ]: 517387323 : return (*this)[pindex->nHeight] == pindex;
406 : : }
407 : :
408 : : /** Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip. */
409 : 150181 : CBlockIndex* Next(const CBlockIndex* pindex) const
410 : : {
411 [ + + ]: 150181 : if (Contains(pindex))
412 [ + - ]: 150179 : return (*this)[pindex->nHeight + 1];
413 : : else
414 : : return nullptr;
415 : : }
416 : :
417 : : /** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */
418 [ - + ]: 560607 : int Height() const
419 : : {
420 [ + + + + : 1859182 : return int(vChain.size()) - 1;
- + # # ]
[ - + + +
# # # # #
# # # #
# ][ - + +
+ + + - +
+ - - + +
+ ][ - + +
+ - + + +
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ][ -
+ - + - +
+ + - + -
+ - + - +
+ + - + +
+ - + - +
- + - + +
+ - + + +
- + + + -
- - - - +
+ + + + -
+ - + + -
- + + - -
+ - + + -
- + - + +
- - + + -
- + + + -
+ - + -
+ ][ + - -
+ + + - +
+ + - + +
- - + +
+ ][ - + +
- - + + -
- + + - -
+ + - - +
+ - - + +
- - + + +
- + + - -
+ + - -
- ][ - + +
- - + + -
- + + - ]
[ - + # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
421 : : }
422 : :
423 : : /** Set/initialize a chain with a given tip. */
424 : : void SetTip(CBlockIndex& block);
425 : :
426 : : /** Find the last common block between this chain and a block index entry. */
427 : : const CBlockIndex* FindFork(const CBlockIndex* pindex) const;
428 : :
429 : : /** Find the earliest block with timestamp equal or greater than the given time and height equal or greater than the given height. */
430 : : CBlockIndex* FindEarliestAtLeast(int64_t nTime, int height) const;
431 : : };
432 : :
433 : : /** Get a locator for a block index entry. */
434 : : CBlockLocator GetLocator(const CBlockIndex* index);
435 : :
436 : : /** Construct a list of hash entries to put in a locator. */
437 : : std::vector<uint256> LocatorEntries(const CBlockIndex* index);
438 : :
439 : : #endif // BITCOIN_CHAIN_H
|