/root/bitcoin/src/chain.h
Line | Count | Source |
1 | | // Copyright (c) 2009-2010 Satoshi Nakamoto |
2 | | // Copyright (c) 2009-present 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, //!< Unused flag that was previously set when descending from failed block |
81 | | |
82 | | BLOCK_OPT_WITNESS = 128, //!< block data in blk*.dat was received with a witness-enforcing client |
83 | | |
84 | | BLOCK_STATUS_RESERVED = 256, //!< Unused flag that was previously set on assumeutxo snapshot blocks and their |
85 | | //!< ancestors before they were validated, and unset when they were validated. |
86 | | }; |
87 | | |
88 | | /** The block chain is a tree shaped structure starting with the |
89 | | * genesis block at the root, with each block potentially having multiple |
90 | | * candidates to be the next block. A blockindex may have multiple pprev pointing |
91 | | * to it, but at most one of them can be part of the currently active branch. |
92 | | */ |
93 | | class CBlockIndex |
94 | | { |
95 | | public: |
96 | | //! pointer to the hash of the block, if any. Memory is owned by this CBlockIndex |
97 | | const uint256* phashBlock{nullptr}; |
98 | | |
99 | | //! pointer to the index of the predecessor of this block |
100 | | CBlockIndex* pprev{nullptr}; |
101 | | |
102 | | //! pointer to the index of some further predecessor of this block |
103 | | CBlockIndex* pskip{nullptr}; |
104 | | |
105 | | //! height of the entry in the chain. The genesis block has height 0 |
106 | | int nHeight{0}; |
107 | | |
108 | | //! Which # file this block is stored in (blk?????.dat) |
109 | | int nFile GUARDED_BY(::cs_main){0}; |
110 | | |
111 | | //! Byte offset within blk?????.dat where this block's data is stored |
112 | | unsigned int nDataPos GUARDED_BY(::cs_main){0}; |
113 | | |
114 | | //! Byte offset within rev?????.dat where this block's undo data is stored |
115 | | unsigned int nUndoPos GUARDED_BY(::cs_main){0}; |
116 | | |
117 | | //! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block |
118 | | arith_uint256 nChainWork{}; |
119 | | |
120 | | //! Number of transactions in this block. This will be nonzero if the block |
121 | | //! reached the VALID_TRANSACTIONS level, and zero otherwise. |
122 | | //! Note: in a potential headers-first mode, this number cannot be relied upon |
123 | | unsigned int nTx{0}; |
124 | | |
125 | | //! (memory only) Number of transactions in the chain up to and including this block. |
126 | | //! This value will be non-zero if this block and all previous blocks back |
127 | | //! to the genesis block or an assumeutxo snapshot block have reached the |
128 | | //! VALID_TRANSACTIONS level. |
129 | | uint64_t m_chain_tx_count{0}; |
130 | | |
131 | | //! Verification status of this block. See enum BlockStatus |
132 | | //! |
133 | | //! Note: this value is modified to show BLOCK_OPT_WITNESS during UTXO snapshot |
134 | | //! load to avoid a spurious startup failure requiring -reindex. |
135 | | //! @sa NeedsRedownload |
136 | | //! @sa ActivateSnapshot |
137 | | uint32_t nStatus GUARDED_BY(::cs_main){0}; |
138 | | |
139 | | //! block header |
140 | | int32_t nVersion{0}; |
141 | | uint256 hashMerkleRoot{}; |
142 | | uint32_t nTime{0}; |
143 | | uint32_t nBits{0}; |
144 | | uint32_t nNonce{0}; |
145 | | |
146 | | //! (memory only) Sequential id assigned to distinguish order in which blocks are received. |
147 | | //! Initialized to SEQ_ID_INIT_FROM_DISK{1} when loading blocks from disk, except for blocks |
148 | | //! belonging to the best chain which overwrite it to SEQ_ID_BEST_CHAIN_FROM_DISK{0}. |
149 | | int32_t nSequenceId{SEQ_ID_INIT_FROM_DISK}; |
150 | | |
151 | | //! (memory only) Maximum nTime in the chain up to and including this block. |
152 | | unsigned int nTimeMax{0}; |
153 | | |
154 | | explicit CBlockIndex(const CBlockHeader& block) |
155 | 0 | : nVersion{block.nVersion}, |
156 | 0 | hashMerkleRoot{block.hashMerkleRoot}, |
157 | 0 | nTime{block.nTime}, |
158 | 0 | nBits{block.nBits}, |
159 | 0 | nNonce{block.nNonce} |
160 | 0 | { |
161 | 0 | } |
162 | | |
163 | | FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) |
164 | 0 | { |
165 | 0 | AssertLockHeld(::cs_main); Line | Count | Source | 142 | 0 | #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) |
|
166 | 0 | FlatFilePos ret; |
167 | 0 | if (nStatus & BLOCK_HAVE_DATA) { |
168 | 0 | ret.nFile = nFile; |
169 | 0 | ret.nPos = nDataPos; |
170 | 0 | } |
171 | 0 | return ret; |
172 | 0 | } |
173 | | |
174 | | FlatFilePos GetUndoPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) |
175 | 0 | { |
176 | 0 | AssertLockHeld(::cs_main); Line | Count | Source | 142 | 0 | #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) |
|
177 | 0 | FlatFilePos ret; |
178 | 0 | if (nStatus & BLOCK_HAVE_UNDO) { |
179 | 0 | ret.nFile = nFile; |
180 | 0 | ret.nPos = nUndoPos; |
181 | 0 | } |
182 | 0 | return ret; |
183 | 0 | } |
184 | | |
185 | | CBlockHeader GetBlockHeader() const |
186 | 0 | { |
187 | 0 | CBlockHeader block; |
188 | 0 | block.nVersion = nVersion; |
189 | 0 | if (pprev) |
190 | 0 | block.hashPrevBlock = pprev->GetBlockHash(); |
191 | 0 | block.hashMerkleRoot = hashMerkleRoot; |
192 | 0 | block.nTime = nTime; |
193 | 0 | block.nBits = nBits; |
194 | 0 | block.nNonce = nNonce; |
195 | 0 | return block; |
196 | 0 | } |
197 | | |
198 | | uint256 GetBlockHash() const |
199 | 0 | { |
200 | 0 | assert(phashBlock != nullptr); |
201 | 0 | return *phashBlock; |
202 | 0 | } |
203 | | |
204 | | /** |
205 | | * Check whether this block and all previous blocks back to the genesis block or an assumeutxo snapshot block have |
206 | | * reached VALID_TRANSACTIONS and had transactions downloaded (and stored to disk) at some point. |
207 | | * |
208 | | * Does not imply the transactions are consensus-valid (ConnectTip might fail) |
209 | | * Does not imply the transactions are still stored on disk. (IsBlockPruned might return true) |
210 | | * |
211 | | * Note that this will be true for the snapshot base block, if one is loaded, since its m_chain_tx_count value will have |
212 | | * been set manually based on the related AssumeutxoData entry. |
213 | | */ |
214 | 0 | bool HaveNumChainTxs() const { return m_chain_tx_count != 0; } |
215 | | |
216 | | NodeSeconds Time() const |
217 | 0 | { |
218 | 0 | return NodeSeconds{std::chrono::seconds{nTime}}; |
219 | 0 | } |
220 | | |
221 | | int64_t GetBlockTime() const |
222 | 0 | { |
223 | 0 | return (int64_t)nTime; |
224 | 0 | } |
225 | | |
226 | | int64_t GetBlockTimeMax() const |
227 | 0 | { |
228 | 0 | return (int64_t)nTimeMax; |
229 | 0 | } |
230 | | |
231 | | static constexpr int nMedianTimeSpan = 11; |
232 | | |
233 | | int64_t GetMedianTimePast() const |
234 | 0 | { |
235 | 0 | int64_t pmedian[nMedianTimeSpan]; |
236 | 0 | int64_t* pbegin = &pmedian[nMedianTimeSpan]; |
237 | 0 | int64_t* pend = &pmedian[nMedianTimeSpan]; |
238 | |
|
239 | 0 | const CBlockIndex* pindex = this; |
240 | 0 | for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev) |
241 | 0 | *(--pbegin) = pindex->GetBlockTime(); |
242 | |
|
243 | 0 | std::sort(pbegin, pend); |
244 | 0 | return pbegin[(pend - pbegin) / 2]; |
245 | 0 | } |
246 | | |
247 | | std::string ToString() const; |
248 | | |
249 | | //! Check whether this block index entry is valid up to the passed validity level. |
250 | | bool IsValid(enum BlockStatus nUpTo) const |
251 | | EXCLUSIVE_LOCKS_REQUIRED(::cs_main) |
252 | 0 | { |
253 | 0 | AssertLockHeld(::cs_main); Line | Count | Source | 142 | 0 | #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) |
|
254 | 0 | assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed. |
255 | 0 | if (nStatus & BLOCK_FAILED_VALID) |
256 | 0 | return false; |
257 | 0 | return ((nStatus & BLOCK_VALID_MASK) >= nUpTo); |
258 | 0 | } |
259 | | |
260 | | //! Raise the validity level of this block index entry. |
261 | | //! Returns true if the validity was changed. |
262 | | bool RaiseValidity(enum BlockStatus nUpTo) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) |
263 | 0 | { |
264 | 0 | AssertLockHeld(::cs_main); Line | Count | Source | 142 | 0 | #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) |
|
265 | 0 | assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed. |
266 | 0 | if (nStatus & BLOCK_FAILED_VALID) return false; |
267 | | |
268 | 0 | if ((nStatus & BLOCK_VALID_MASK) < nUpTo) { |
269 | 0 | nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo; |
270 | 0 | return true; |
271 | 0 | } |
272 | 0 | return false; |
273 | 0 | } |
274 | | |
275 | | //! Build the skiplist pointer for this entry. |
276 | | void BuildSkip(); |
277 | | |
278 | | //! Efficiently find an ancestor of this block. |
279 | | CBlockIndex* GetAncestor(int height); |
280 | | const CBlockIndex* GetAncestor(int height) const; |
281 | | |
282 | 0 | CBlockIndex() = default; |
283 | | ~CBlockIndex() = default; |
284 | | |
285 | | protected: |
286 | | //! CBlockIndex should not allow public copy construction because equality |
287 | | //! comparison via pointer is very common throughout the codebase, making |
288 | | //! use of copy a footgun. Also, use of copies do not have the benefit |
289 | | //! of simplifying lifetime considerations due to attributes like pprev and |
290 | | //! pskip, which are at risk of becoming dangling pointers in a copied |
291 | | //! instance. |
292 | | //! |
293 | | //! We declare these protected instead of simply deleting them so that |
294 | | //! CDiskBlockIndex can reuse copy construction. |
295 | | CBlockIndex(const CBlockIndex&) = default; |
296 | | CBlockIndex& operator=(const CBlockIndex&) = delete; |
297 | | CBlockIndex(CBlockIndex&&) = delete; |
298 | | CBlockIndex& operator=(CBlockIndex&&) = delete; |
299 | | }; |
300 | | |
301 | | /** Compute how much work an nBits value corresponds to. */ |
302 | | arith_uint256 GetBitsProof(uint32_t bits); |
303 | | |
304 | | /** Compute how much work a block index entry corresponds to. */ |
305 | 0 | inline arith_uint256 GetBlockProof(const CBlockIndex& block) { return GetBitsProof(block.nBits); } |
306 | | |
307 | | /** Compute how much work a block header corresponds to. */ |
308 | 0 | inline arith_uint256 GetBlockProof(const CBlockHeader& header) { return GetBitsProof(header.nBits); } |
309 | | |
310 | | /** 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. */ |
311 | | int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params&); |
312 | | /** Find the forking point between two chain tips. */ |
313 | | const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb); |
314 | | |
315 | | |
316 | | /** Used to marshal pointers into hashes for db storage. */ |
317 | | class CDiskBlockIndex : public CBlockIndex |
318 | | { |
319 | | /** Historically CBlockLocator's version field has been written to disk |
320 | | * streams as the client version, but the value has never been used. |
321 | | * |
322 | | * Hard-code to the highest client version ever written. |
323 | | * SerParams can be used if the field requires any meaning in the future. |
324 | | **/ |
325 | | static constexpr int DUMMY_VERSION = 259900; |
326 | | |
327 | | public: |
328 | | uint256 hashPrev; |
329 | | |
330 | | CDiskBlockIndex() |
331 | 0 | { |
332 | 0 | hashPrev = uint256(); |
333 | 0 | } |
334 | | |
335 | 0 | explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex) |
336 | 0 | { |
337 | 0 | hashPrev = (pprev ? pprev->GetBlockHash() : uint256()); |
338 | 0 | } |
339 | | |
340 | | SERIALIZE_METHODS(CDiskBlockIndex, obj) |
341 | 0 | { |
342 | 0 | LOCK(::cs_main); Line | Count | Source | 266 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 0 | #define PASTE(x, y) x ## y |
|
|
|
| LOCK(::cs_main); Line | Count | Source | 266 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 0 | #define PASTE(x, y) x ## y |
|
|
|
| LOCK(::cs_main); Line | Count | Source | 266 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 0 | #define PASTE(x, y) x ## y |
|
|
|
|
343 | 0 | int _nVersion = DUMMY_VERSION; |
344 | 0 | READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
345 | |
|
346 | 0 | READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(VARINT_MODE(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
347 | 0 | READWRITE(VARINT(obj.nStatus)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(VARINT(obj.nStatus)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(VARINT(obj.nStatus)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
348 | 0 | READWRITE(VARINT(obj.nTx)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(VARINT(obj.nTx)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(VARINT(obj.nTx)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
349 | 0 | if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
350 | 0 | if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE(VARINT(obj.nDataPos)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE(VARINT(obj.nDataPos)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE(VARINT(obj.nDataPos)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
351 | 0 | if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(obj.nUndoPos)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(obj.nUndoPos)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(obj.nUndoPos)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
352 | | |
353 | | // block header |
354 | 0 | READWRITE(obj.nVersion); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.nVersion); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.nVersion); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
355 | 0 | READWRITE(obj.hashPrev); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.hashPrev); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.hashPrev); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
356 | 0 | READWRITE(obj.hashMerkleRoot); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.hashMerkleRoot); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.hashMerkleRoot); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
357 | 0 | READWRITE(obj.nTime); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.nTime); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.nTime); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
358 | 0 | READWRITE(obj.nBits); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.nBits); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.nBits); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
359 | 0 | READWRITE(obj.nNonce); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.nNonce); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.nNonce); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
360 | 0 | } Unexecuted instantiation: void CDiskBlockIndex::SerializationOps<SpanReader, CDiskBlockIndex, ActionUnserialize>(CDiskBlockIndex&, SpanReader&, ActionUnserialize) Unexecuted instantiation: void CDiskBlockIndex::SerializationOps<DataStream, CDiskBlockIndex const, ActionSerialize>(CDiskBlockIndex const&, DataStream&, ActionSerialize) Unexecuted instantiation: void CDiskBlockIndex::SerializationOps<DataStream, CDiskBlockIndex, ActionUnserialize>(CDiskBlockIndex&, DataStream&, ActionUnserialize) |
361 | | |
362 | | uint256 ConstructBlockHash() const |
363 | 0 | { |
364 | 0 | CBlockHeader block; |
365 | 0 | block.nVersion = nVersion; |
366 | 0 | block.hashPrevBlock = hashPrev; |
367 | 0 | block.hashMerkleRoot = hashMerkleRoot; |
368 | 0 | block.nTime = nTime; |
369 | 0 | block.nBits = nBits; |
370 | 0 | block.nNonce = nNonce; |
371 | 0 | return block.GetHash(); |
372 | 0 | } |
373 | | |
374 | | uint256 GetBlockHash() = delete; |
375 | | std::string ToString() = delete; |
376 | | }; |
377 | | |
378 | | /** An in-memory indexed chain of blocks. */ |
379 | | class CChain |
380 | | { |
381 | | private: |
382 | | std::vector<CBlockIndex*> vChain; |
383 | | |
384 | | public: |
385 | 0 | CChain() = default; |
386 | | CChain(const CChain&) = delete; |
387 | | CChain& operator=(const CChain&) = delete; |
388 | | |
389 | | /** Returns the index entry for the genesis block of this chain, or nullptr if none. */ |
390 | | CBlockIndex* Genesis() const |
391 | 0 | { |
392 | 0 | return vChain.size() > 0 ? vChain[0] : nullptr; |
393 | 0 | } |
394 | | |
395 | | /** Returns the index entry for the tip of this chain, or nullptr if none. */ |
396 | | CBlockIndex* Tip() const |
397 | 0 | { |
398 | 0 | return vChain.size() > 0 ? vChain[vChain.size() - 1] : nullptr; |
399 | 0 | } |
400 | | |
401 | | /** Returns the index entry at a particular height in this chain, or nullptr if no such height exists. */ |
402 | | CBlockIndex* operator[](int nHeight) const |
403 | 0 | { |
404 | 0 | if (nHeight < 0 || nHeight >= (int)vChain.size()) |
405 | 0 | return nullptr; |
406 | 0 | return vChain[nHeight]; |
407 | 0 | } |
408 | | |
409 | | /** Efficiently check whether a block is present in this chain. */ |
410 | | bool Contains(const CBlockIndex* pindex) const |
411 | 0 | { |
412 | 0 | return (*this)[pindex->nHeight] == pindex; |
413 | 0 | } |
414 | | |
415 | | /** Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip. */ |
416 | | CBlockIndex* Next(const CBlockIndex* pindex) const |
417 | 0 | { |
418 | 0 | if (Contains(pindex)) |
419 | 0 | return (*this)[pindex->nHeight + 1]; |
420 | 0 | else |
421 | 0 | return nullptr; |
422 | 0 | } |
423 | | |
424 | | /** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */ |
425 | | int Height() const |
426 | 0 | { |
427 | 0 | return int(vChain.size()) - 1; |
428 | 0 | } |
429 | | |
430 | | /** Check whether this chain's tip exists, has enough work, and is recent. */ |
431 | | bool IsTipRecent(const arith_uint256& min_chain_work, std::chrono::seconds max_tip_age) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) |
432 | 0 | { |
433 | 0 | const auto tip{Tip()}; |
434 | 0 | return tip && |
435 | 0 | tip->nChainWork >= min_chain_work && |
436 | 0 | tip->Time() >= Now<NodeSeconds>() - max_tip_age; |
437 | 0 | } |
438 | | |
439 | | /** Set/initialize a chain with a given tip. */ |
440 | | void SetTip(CBlockIndex& block); |
441 | | |
442 | | /** Find the last common block between this chain and a block index entry. */ |
443 | | const CBlockIndex* FindFork(const CBlockIndex* pindex) const; |
444 | | |
445 | | /** Find the earliest block with timestamp equal or greater than the given time and height equal or greater than the given height. */ |
446 | | CBlockIndex* FindEarliestAtLeast(int64_t nTime, int height) const; |
447 | | }; |
448 | | |
449 | | /** Get a locator for a block index entry. */ |
450 | | CBlockLocator GetLocator(const CBlockIndex* index); |
451 | | |
452 | | /** Construct a list of hash entries to put in a locator. */ |
453 | | std::vector<uint256> LocatorEntries(const CBlockIndex* index); |
454 | | |
455 | | #endif // BITCOIN_CHAIN_H |