/root/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 | 0 | { |
60 | 0 | READWRITE(VARINT(obj.nBlocks)); |
61 | 0 | READWRITE(VARINT(obj.nSize)); |
62 | 0 | READWRITE(VARINT(obj.nUndoSize)); |
63 | 0 | READWRITE(VARINT(obj.nHeightFirst)); |
64 | 0 | READWRITE(VARINT(obj.nHeightLast)); |
65 | 0 | READWRITE(VARINT(obj.nTimeFirst)); |
66 | 0 | READWRITE(VARINT(obj.nTimeLast)); |
67 | 0 | } Unexecuted instantiation: _ZN14CBlockFileInfo16SerializationOpsI10DataStreamS_17ActionUnserializeEEvRT0_RT_T1_ Unexecuted instantiation: _ZN14CBlockFileInfo16SerializationOpsI10DataStreamKS_15ActionSerializeEEvRT0_RT_T1_ |
68 | | |
69 | 0 | 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 | 0 | { |
76 | 0 | if (nBlocks == 0 || nHeightFirst > nHeightIn) |
77 | 0 | nHeightFirst = nHeightIn; |
78 | 0 | if (nBlocks == 0 || nTimeFirst > nTimeIn) |
79 | 0 | nTimeFirst = nTimeIn; |
80 | 0 | nBlocks++; |
81 | 0 | if (nHeightIn > nHeightLast) |
82 | 0 | nHeightLast = nHeightIn; |
83 | 0 | if (nTimeIn > nTimeLast) |
84 | 0 | nTimeLast = nTimeIn; |
85 | 0 | } |
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, checkpoint. 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 | 161k | : nVersion{block.nVersion}, |
201 | 161k | hashMerkleRoot{block.hashMerkleRoot}, |
202 | 161k | nTime{block.nTime}, |
203 | 161k | nBits{block.nBits}, |
204 | 161k | nNonce{block.nNonce} |
205 | 161k | { |
206 | 161k | } |
207 | | |
208 | | FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) |
209 | 0 | { |
210 | 0 | AssertLockHeld(::cs_main); |
211 | 0 | FlatFilePos ret; |
212 | 0 | if (nStatus & BLOCK_HAVE_DATA) { |
213 | 0 | ret.nFile = nFile; |
214 | 0 | ret.nPos = nDataPos; |
215 | 0 | } |
216 | 0 | return ret; |
217 | 0 | } |
218 | | |
219 | | FlatFilePos GetUndoPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) |
220 | 0 | { |
221 | 0 | AssertLockHeld(::cs_main); |
222 | 0 | FlatFilePos ret; |
223 | 0 | if (nStatus & BLOCK_HAVE_UNDO) { |
224 | 0 | ret.nFile = nFile; |
225 | 0 | ret.nPos = nUndoPos; |
226 | 0 | } |
227 | 0 | return ret; |
228 | 0 | } |
229 | | |
230 | | CBlockHeader GetBlockHeader() const |
231 | 561 | { |
232 | 561 | CBlockHeader block; |
233 | 561 | block.nVersion = nVersion; |
234 | 561 | if (pprev) |
235 | 0 | block.hashPrevBlock = pprev->GetBlockHash(); |
236 | 561 | block.hashMerkleRoot = hashMerkleRoot; |
237 | 561 | block.nTime = nTime; |
238 | 561 | block.nBits = nBits; |
239 | 561 | block.nNonce = nNonce; |
240 | 561 | return block; |
241 | 561 | } |
242 | | |
243 | | uint256 GetBlockHash() const |
244 | 12.3k | { |
245 | 12.3k | assert(phashBlock != nullptr); |
246 | 12.3k | return *phashBlock; |
247 | 12.3k | } |
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 | 28.7k | bool HaveNumChainTxs() const { return m_chain_tx_count != 0; } |
260 | | |
261 | | NodeSeconds Time() const |
262 | 6.84k | { |
263 | 6.84k | return NodeSeconds{std::chrono::seconds{nTime}}; |
264 | 6.84k | } |
265 | | |
266 | | int64_t GetBlockTime() const |
267 | 8.38k | { |
268 | 8.38k | return (int64_t)nTime; |
269 | 8.38k | } |
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 | 8.38k | { |
280 | 8.38k | int64_t pmedian[nMedianTimeSpan]; |
281 | 8.38k | int64_t* pbegin = &pmedian[nMedianTimeSpan]; |
282 | 8.38k | int64_t* pend = &pmedian[nMedianTimeSpan]; |
283 | | |
284 | 8.38k | const CBlockIndex* pindex = this; |
285 | 16.7k | for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev) |
286 | 8.38k | *(--pbegin) = pindex->GetBlockTime(); |
287 | | |
288 | 8.38k | std::sort(pbegin, pend); |
289 | 8.38k | return pbegin[(pend - pbegin) / 2]; |
290 | 8.38k | } |
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 = BLOCK_VALID_TRANSACTIONS) const |
296 | | EXCLUSIVE_LOCKS_REQUIRED(::cs_main) |
297 | 133 | { |
298 | 133 | AssertLockHeld(::cs_main); |
299 | 133 | assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed. |
300 | 133 | if (nStatus & BLOCK_FAILED_MASK) |
301 | 0 | return false; |
302 | 133 | return ((nStatus & BLOCK_VALID_MASK) >= nUpTo); |
303 | 133 | } |
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 | 0 | { |
309 | 0 | AssertLockHeld(::cs_main); |
310 | 0 | assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed. |
311 | 0 | if (nStatus & BLOCK_FAILED_MASK) return false; |
312 | | |
313 | 0 | if ((nStatus & BLOCK_VALID_MASK) < nUpTo) { |
314 | 0 | nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo; |
315 | 0 | return true; |
316 | 0 | } |
317 | 0 | return false; |
318 | 0 | } |
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 | 0 | 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 | 0 | 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 | 0 | { |
369 | 0 | hashPrev = uint256(); |
370 | 0 | } |
371 | | |
372 | 0 | explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex) |
373 | 0 | { |
374 | 0 | hashPrev = (pprev ? pprev->GetBlockHash() : uint256()); |
375 | 0 | } |
376 | | |
377 | | SERIALIZE_METHODS(CDiskBlockIndex, obj) |
378 | 0 | { |
379 | 0 | LOCK(::cs_main); |
380 | 0 | int _nVersion = DUMMY_VERSION; |
381 | 0 | READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED)); |
382 | |
|
383 | 0 | READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED)); |
384 | 0 | READWRITE(VARINT(obj.nStatus)); |
385 | 0 | READWRITE(VARINT(obj.nTx)); |
386 | 0 | if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED)); |
387 | 0 | if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE(VARINT(obj.nDataPos)); |
388 | 0 | if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(obj.nUndoPos)); |
389 | | |
390 | | // block header |
391 | 0 | READWRITE(obj.nVersion); |
392 | 0 | READWRITE(obj.hashPrev); |
393 | 0 | READWRITE(obj.hashMerkleRoot); |
394 | 0 | READWRITE(obj.nTime); |
395 | 0 | READWRITE(obj.nBits); |
396 | 0 | READWRITE(obj.nNonce); |
397 | 0 | } Unexecuted instantiation: _ZN15CDiskBlockIndex16SerializationOpsI10DataStreamS_17ActionUnserializeEEvRT0_RT_T1_ Unexecuted instantiation: _ZN15CDiskBlockIndex16SerializationOpsI10DataStreamKS_15ActionSerializeEEvRT0_RT_T1_ |
398 | | |
399 | | uint256 ConstructBlockHash() const |
400 | 0 | { |
401 | 0 | CBlockHeader block; |
402 | 0 | block.nVersion = nVersion; |
403 | 0 | block.hashPrevBlock = hashPrev; |
404 | 0 | block.hashMerkleRoot = hashMerkleRoot; |
405 | 0 | block.nTime = nTime; |
406 | 0 | block.nBits = nBits; |
407 | 0 | block.nNonce = nNonce; |
408 | 0 | return block.GetHash(); |
409 | 0 | } |
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 | 9.56k | 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 | 19.1k | { |
429 | 19.1k | return vChain.size() > 0 ? vChain[0] : nullptr; |
430 | 19.1k | } |
431 | | |
432 | | /** Returns the index entry for the tip of this chain, or nullptr if none. */ |
433 | | CBlockIndex* Tip() const |
434 | 72.7k | { |
435 | 72.7k | return vChain.size() > 0 ? vChain[vChain.size() - 1] : nullptr; |
436 | 72.7k | } |
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 | 38.2k | { |
441 | 38.2k | if (nHeight < 0 || nHeight >= (int)vChain.size()) |
442 | 9.56k | return nullptr; |
443 | 28.7k | return vChain[nHeight]; |
444 | 38.2k | } |
445 | | |
446 | | /** Efficiently check whether a block is present in this chain. */ |
447 | | bool Contains(const CBlockIndex* pindex) const |
448 | 19.1k | { |
449 | 19.1k | return (*this)[pindex->nHeight] == pindex; |
450 | 19.1k | } |
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 | 28.7k | { |
464 | 28.7k | return int(vChain.size()) - 1; |
465 | 28.7k | } |
466 | | |
467 | | /** Set/initialize a chain with a given tip. */ |
468 | | void SetTip(CBlockIndex& block); |
469 | | |
470 | | /** Return a CBlockLocator that refers to the tip in of this chain. */ |
471 | | CBlockLocator GetLocator() const; |
472 | | |
473 | | /** Find the last common block between this chain and a block index entry. */ |
474 | | const CBlockIndex* FindFork(const CBlockIndex* pindex) const; |
475 | | |
476 | | /** Find the earliest block with timestamp equal or greater than the given time and height equal or greater than the given height. */ |
477 | | CBlockIndex* FindEarliestAtLeast(int64_t nTime, int height) const; |
478 | | }; |
479 | | |
480 | | /** Get a locator for a block index entry. */ |
481 | | CBlockLocator GetLocator(const CBlockIndex* index); |
482 | | |
483 | | /** Construct a list of hash entries to put in a locator. */ |
484 | | std::vector<uint256> LocatorEntries(const CBlockIndex* index); |
485 | | |
486 | | #endif // BITCOIN_CHAIN_H |