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