/root/bitcoin/src/node/blockstorage.h
Line | Count | Source |
1 | | // Copyright (c) 2011-present The Bitcoin Core developers |
2 | | // Distributed under the MIT software license, see the accompanying |
3 | | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
4 | | |
5 | | #ifndef BITCOIN_NODE_BLOCKSTORAGE_H |
6 | | #define BITCOIN_NODE_BLOCKSTORAGE_H |
7 | | |
8 | | #include <attributes.h> |
9 | | #include <chain.h> |
10 | | #include <dbwrapper.h> |
11 | | #include <flatfile.h> |
12 | | #include <kernel/blockmanager_opts.h> |
13 | | #include <kernel/chainparams.h> |
14 | | #include <kernel/cs_main.h> |
15 | | #include <kernel/messagestartchars.h> |
16 | | #include <primitives/block.h> |
17 | | #include <serialize.h> |
18 | | #include <streams.h> |
19 | | #include <sync.h> |
20 | | #include <uint256.h> |
21 | | #include <util/expected.h> |
22 | | #include <util/fs.h> |
23 | | #include <util/hasher.h> |
24 | | #include <util/obfuscation.h> |
25 | | |
26 | | #include <algorithm> |
27 | | #include <array> |
28 | | #include <atomic> |
29 | | #include <cstddef> |
30 | | #include <cstdint> |
31 | | #include <functional> |
32 | | #include <iosfwd> |
33 | | #include <limits> |
34 | | #include <map> |
35 | | #include <memory> |
36 | | #include <optional> |
37 | | #include <set> |
38 | | #include <span> |
39 | | #include <string> |
40 | | #include <unordered_map> |
41 | | #include <utility> |
42 | | #include <vector> |
43 | | |
44 | | class BlockValidationState; |
45 | | class CBlockUndo; |
46 | | class Chainstate; |
47 | | class ChainstateManager; |
48 | | namespace Consensus { |
49 | | struct Params; |
50 | | } |
51 | | namespace util { |
52 | | class SignalInterrupt; |
53 | | } // namespace util |
54 | | |
55 | | namespace kernel { |
56 | | class CBlockFileInfo |
57 | | { |
58 | | public: |
59 | | uint32_t nBlocks{}; //!< number of blocks stored in file |
60 | | uint32_t nSize{}; //!< number of used bytes of block file |
61 | | uint32_t nUndoSize{}; //!< number of used bytes in the undo file |
62 | | uint32_t nHeightFirst{}; //!< lowest height of block in file |
63 | | uint32_t nHeightLast{}; //!< highest height of block in file |
64 | | uint64_t nTimeFirst{}; //!< earliest time of block in file |
65 | | uint64_t nTimeLast{}; //!< latest time of block in file |
66 | | |
67 | | SERIALIZE_METHODS(CBlockFileInfo, obj) |
68 | 0 | { |
69 | 0 | READWRITE(VARINT(obj.nBlocks)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(VARINT(obj.nBlocks)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
70 | 0 | READWRITE(VARINT(obj.nSize)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(VARINT(obj.nSize)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
71 | 0 | READWRITE(VARINT(obj.nUndoSize)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(VARINT(obj.nUndoSize)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
72 | 0 | READWRITE(VARINT(obj.nHeightFirst)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(VARINT(obj.nHeightFirst)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
73 | 0 | READWRITE(VARINT(obj.nHeightLast)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(VARINT(obj.nHeightLast)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
74 | 0 | READWRITE(VARINT(obj.nTimeFirst)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(VARINT(obj.nTimeFirst)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
75 | 0 | READWRITE(VARINT(obj.nTimeLast)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(VARINT(obj.nTimeLast)); Line | Count | Source | 146 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
76 | 0 | } Unexecuted instantiation: void kernel::CBlockFileInfo::SerializationOps<SpanReader, kernel::CBlockFileInfo, ActionUnserialize>(kernel::CBlockFileInfo&, SpanReader&, ActionUnserialize) Unexecuted instantiation: void kernel::CBlockFileInfo::SerializationOps<DataStream, kernel::CBlockFileInfo const, ActionSerialize>(kernel::CBlockFileInfo const&, DataStream&, ActionSerialize) |
77 | | |
78 | 0 | CBlockFileInfo() = default; |
79 | | |
80 | | std::string ToString() const; |
81 | | |
82 | | /** update statistics (does not update nSize) */ |
83 | | void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) |
84 | 0 | { |
85 | 0 | if (nBlocks == 0 || nHeightFirst > nHeightIn) |
86 | 0 | nHeightFirst = nHeightIn; |
87 | 0 | if (nBlocks == 0 || nTimeFirst > nTimeIn) |
88 | 0 | nTimeFirst = nTimeIn; |
89 | 0 | nBlocks++; |
90 | 0 | if (nHeightIn > nHeightLast) |
91 | 0 | nHeightLast = nHeightIn; |
92 | 0 | if (nTimeIn > nTimeLast) |
93 | 0 | nTimeLast = nTimeIn; |
94 | 0 | } |
95 | | }; |
96 | | |
97 | | /** Access to the block database (blocks/index/) */ |
98 | | class BlockTreeDB : public CDBWrapper |
99 | | { |
100 | | public: |
101 | | using CDBWrapper::CDBWrapper; |
102 | | void WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*>>& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo); |
103 | | bool ReadBlockFileInfo(int nFile, CBlockFileInfo& info); |
104 | | bool ReadLastBlockFile(int& nFile); |
105 | | void WriteReindexing(bool fReindexing); |
106 | | void ReadReindexing(bool& fReindexing); |
107 | | void WriteFlag(const std::string& name, bool fValue); |
108 | | bool ReadFlag(const std::string& name, bool& fValue); |
109 | | bool LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex, const util::SignalInterrupt& interrupt) |
110 | | EXCLUSIVE_LOCKS_REQUIRED(::cs_main); |
111 | | }; |
112 | | } // namespace kernel |
113 | | |
114 | | namespace node { |
115 | | using kernel::CBlockFileInfo; |
116 | | using kernel::BlockTreeDB; |
117 | | |
118 | | /** The pre-allocation chunk size for blk?????.dat files (since 0.8) */ |
119 | | static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB |
120 | | /** The pre-allocation chunk size for rev?????.dat files (since 0.8) */ |
121 | | static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB |
122 | | /** The maximum size of a blk?????.dat file (since 0.8) */ |
123 | | static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB |
124 | | |
125 | | /** Size of header written by WriteBlock before a serialized CBlock (8 bytes) */ |
126 | | static constexpr uint32_t STORAGE_HEADER_BYTES{std::tuple_size_v<MessageStartChars> + sizeof(unsigned int)}; |
127 | | |
128 | | /** Total overhead when writing undo data: header (8 bytes) plus checksum (32 bytes) */ |
129 | | static constexpr uint32_t UNDO_DATA_DISK_OVERHEAD{STORAGE_HEADER_BYTES + uint256::size()}; |
130 | | |
131 | | // Because validation code takes pointers to the map's CBlockIndex objects, if |
132 | | // we ever switch to another associative container, we need to either use a |
133 | | // container that has stable addressing (true of all std associative |
134 | | // containers), or make the key a `std::unique_ptr<CBlockIndex>` |
135 | | using BlockMap = std::unordered_map<uint256, CBlockIndex, BlockHasher>; |
136 | | |
137 | | struct CBlockIndexWorkComparator { |
138 | | bool operator()(const CBlockIndex* pa, const CBlockIndex* pb) const; |
139 | | using is_transparent = void; |
140 | | }; |
141 | | |
142 | | struct CBlockIndexHeightOnlyComparator { |
143 | | /* Only compares the height of two block indices, doesn't try to tie-break */ |
144 | | bool operator()(const CBlockIndex* pa, const CBlockIndex* pb) const; |
145 | | }; |
146 | | |
147 | | struct PruneLockInfo { |
148 | | int height_first{std::numeric_limits<int>::max()}; //! Height of earliest block that should be kept and not pruned |
149 | | }; |
150 | | |
151 | | enum BlockfileType { |
152 | | // Values used as array indexes - do not change carelessly. |
153 | | NORMAL = 0, |
154 | | ASSUMED = 1, |
155 | | NUM_TYPES = 2, |
156 | | }; |
157 | | |
158 | | std::ostream& operator<<(std::ostream& os, const BlockfileType& type); |
159 | | |
160 | | struct BlockfileCursor { |
161 | | // The latest blockfile number. |
162 | | int file_num{0}; |
163 | | |
164 | | // Track the height of the highest block in file_num whose undo |
165 | | // data has been written. Block data is written to block files in download |
166 | | // order, but is written to undo files in validation order, which is |
167 | | // usually in order by height. To avoid wasting disk space, undo files will |
168 | | // be trimmed whenever the corresponding block file is finalized and |
169 | | // the height of the highest block written to the block file equals the |
170 | | // height of the highest block written to the undo file. This is a |
171 | | // heuristic and can sometimes preemptively trim undo files that will write |
172 | | // more data later, and sometimes fail to trim undo files that can't have |
173 | | // more data written later. |
174 | | int undo_height{0}; |
175 | | }; |
176 | | |
177 | | std::ostream& operator<<(std::ostream& os, const BlockfileCursor& cursor); |
178 | | |
179 | | enum class ReadRawError { |
180 | | IO, |
181 | | BadPartRange, |
182 | | }; |
183 | | |
184 | | /** |
185 | | * Maintains a tree of blocks (stored in `m_block_index`) which is consulted |
186 | | * to determine where the most-work tip is. |
187 | | * |
188 | | * This data is used mostly in `Chainstate` - information about, e.g., |
189 | | * candidate tips is not maintained here. |
190 | | */ |
191 | | class BlockManager |
192 | | { |
193 | | friend Chainstate; |
194 | | friend ChainstateManager; |
195 | | |
196 | | private: |
197 | 0 | const CChainParams& GetParams() const { return m_opts.chainparams; } |
198 | 0 | const Consensus::Params& GetConsensus() const { return m_opts.chainparams.GetConsensus(); } |
199 | | /** |
200 | | * Load the blocktree off disk and into memory. Populate certain metadata |
201 | | * per index entry (nStatus, nChainWork, nTimeMax, etc.) as well as peripheral |
202 | | * collections like m_dirty_blockindex. |
203 | | */ |
204 | | bool LoadBlockIndex(const std::optional<uint256>& snapshot_blockhash) |
205 | | EXCLUSIVE_LOCKS_REQUIRED(cs_main); |
206 | | |
207 | | /** Return false if block file or undo file flushing fails. */ |
208 | | [[nodiscard]] bool FlushBlockFile(int blockfile_num, bool fFinalize, bool finalize_undo); |
209 | | |
210 | | /** Return false if undo file flushing fails. */ |
211 | | [[nodiscard]] bool FlushUndoFile(int block_file, bool finalize = false); |
212 | | |
213 | | /** |
214 | | * Helper function performing various preparations before a block can be saved to disk: |
215 | | * Returns the correct position for the block to be saved, which may be in the current or a new |
216 | | * block file depending on nAddSize. May flush the previous blockfile to disk if full, updates |
217 | | * blockfile info, and checks if there is enough disk space to save the block. |
218 | | * |
219 | | * The nAddSize argument passed to this function should include not just the size of the serialized CBlock, but also the size of |
220 | | * separator fields (STORAGE_HEADER_BYTES). |
221 | | */ |
222 | | [[nodiscard]] FlatFilePos FindNextBlockPos(unsigned int nAddSize, unsigned int nHeight, uint64_t nTime); |
223 | | [[nodiscard]] bool FlushChainstateBlockFile(int tip_height); |
224 | | bool FindUndoPos(BlockValidationState& state, int nFile, FlatFilePos& pos, unsigned int nAddSize); |
225 | | |
226 | | AutoFile OpenUndoFile(const FlatFilePos& pos, bool fReadOnly = false) const; |
227 | | |
228 | | /* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */ |
229 | | void FindFilesToPruneManual( |
230 | | std::set<int>& setFilesToPrune, |
231 | | int nManualPruneHeight, |
232 | | const Chainstate& chain); |
233 | | |
234 | | /** |
235 | | * Prune block and undo files (blk???.dat and rev???.dat) so that the disk space used is less than a user-defined target. |
236 | | * The user sets the target (in MB) on the command line or in config file. This will be run on startup and whenever new |
237 | | * space is allocated in a block or undo file, staying below the target. Changing back to unpruned requires a reindex |
238 | | * (which in this case means the blockchain must be re-downloaded.) |
239 | | * |
240 | | * Pruning functions are called from FlushStateToDisk when the m_check_for_pruning flag has been set. |
241 | | * Block and undo files are deleted in lock-step (when blk00003.dat is deleted, so is rev00003.dat.) |
242 | | * Pruning cannot take place until the longest chain is at least a certain length (CChainParams::nPruneAfterHeight). |
243 | | * Pruning will never delete a block within a defined distance (currently 288) from the active chain's tip. |
244 | | * The block index is updated by unsetting HAVE_DATA and HAVE_UNDO for any blocks that were stored in the deleted files. |
245 | | * A db flag records the fact that at least some block files have been pruned. |
246 | | * |
247 | | * @param[out] setFilesToPrune The set of file indices that can be unlinked will be returned |
248 | | * @param last_prune The last height we're able to prune, according to the prune locks |
249 | | */ |
250 | | void FindFilesToPrune( |
251 | | std::set<int>& setFilesToPrune, |
252 | | int last_prune, |
253 | | const Chainstate& chain, |
254 | | ChainstateManager& chainman); |
255 | | |
256 | | RecursiveMutex cs_LastBlockFile; |
257 | | |
258 | | //! Since assumedvalid chainstates may be syncing a range of the chain that is very |
259 | | //! far away from the normal/background validation process, we should segment blockfiles |
260 | | //! for assumed chainstates. Otherwise, we might have wildly different height ranges |
261 | | //! mixed into the same block files, which would impair our ability to prune |
262 | | //! effectively. |
263 | | //! |
264 | | //! This data structure maintains separate blockfile number cursors for each |
265 | | //! BlockfileType. The ASSUMED state is initialized, when necessary, in FindNextBlockPos(). |
266 | | //! |
267 | | //! The first element is the NORMAL cursor, second is ASSUMED. |
268 | | std::array<std::optional<BlockfileCursor>, BlockfileType::NUM_TYPES> |
269 | | m_blockfile_cursors GUARDED_BY(cs_LastBlockFile) = { |
270 | | BlockfileCursor{}, |
271 | | std::nullopt, |
272 | | }; |
273 | | int MaxBlockfileNum() const EXCLUSIVE_LOCKS_REQUIRED(cs_LastBlockFile) |
274 | 0 | { |
275 | 0 | static const BlockfileCursor empty_cursor; |
276 | 0 | const auto& normal = m_blockfile_cursors[BlockfileType::NORMAL].value_or(empty_cursor); |
277 | 0 | const auto& assumed = m_blockfile_cursors[BlockfileType::ASSUMED].value_or(empty_cursor); |
278 | 0 | return std::max(normal.file_num, assumed.file_num); |
279 | 0 | } |
280 | | |
281 | | /** Global flag to indicate we should check to see if there are |
282 | | * block/undo files that should be deleted. Set on startup |
283 | | * or if we allocate more file space when we're in prune mode |
284 | | */ |
285 | | bool m_check_for_pruning = false; |
286 | | |
287 | | const bool m_prune_mode; |
288 | | |
289 | | const Obfuscation m_obfuscation; |
290 | | |
291 | | /** |
292 | | * Map from external index name to oldest block that must not be pruned. |
293 | | * |
294 | | * @note Internally, only blocks at height (height_first - PRUNE_LOCK_BUFFER - 1) and |
295 | | * below will be pruned, but callers should avoid assuming any particular buffer size. |
296 | | */ |
297 | | std::unordered_map<std::string, PruneLockInfo> m_prune_locks GUARDED_BY(::cs_main); |
298 | | |
299 | | BlockfileType BlockfileTypeForHeight(int height); |
300 | | |
301 | | const kernel::BlockManagerOpts m_opts; |
302 | | |
303 | | const FlatFileSeq m_block_file_seq; |
304 | | const FlatFileSeq m_undo_file_seq; |
305 | | |
306 | | protected: |
307 | | std::vector<CBlockFileInfo> m_blockfile_info; |
308 | | |
309 | | /** Dirty block index entries. */ |
310 | | std::set<CBlockIndex*> m_dirty_blockindex; |
311 | | |
312 | | /** Dirty block file entries. */ |
313 | | std::set<int> m_dirty_fileinfo; |
314 | | |
315 | | public: |
316 | | using Options = kernel::BlockManagerOpts; |
317 | | using ReadRawBlockResult = util::Expected<std::vector<std::byte>, ReadRawError>; |
318 | | |
319 | | explicit BlockManager(const util::SignalInterrupt& interrupt, Options opts); |
320 | | |
321 | | const util::SignalInterrupt& m_interrupt; |
322 | | std::atomic<bool> m_importing{false}; |
323 | | |
324 | | /** |
325 | | * Whether all blockfiles have been added to the block tree database. |
326 | | * Normally true, but set to false when a reindex is requested and the |
327 | | * database is wiped. The value is persisted in the database across restarts |
328 | | * and will be false until reindexing completes. |
329 | | */ |
330 | | std::atomic_bool m_blockfiles_indexed{true}; |
331 | | |
332 | | BlockMap m_block_index GUARDED_BY(cs_main); |
333 | | |
334 | | /** |
335 | | * The height of the base block of an assumeutxo snapshot, if one is in use. |
336 | | * |
337 | | * This controls how blockfiles are segmented by chainstate type to avoid |
338 | | * comingling different height regions of the chain when an assumedvalid chainstate |
339 | | * is in use. If heights are drastically different in the same blockfile, pruning |
340 | | * suffers. |
341 | | * |
342 | | * This is set during ActivateSnapshot() or upon LoadBlockIndex() if a snapshot |
343 | | * had been previously loaded. After the snapshot is validated, this is unset to |
344 | | * restore normal LoadBlockIndex behavior. |
345 | | */ |
346 | | std::optional<int> m_snapshot_height; |
347 | | |
348 | | std::vector<CBlockIndex*> GetAllBlockIndices() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); |
349 | | |
350 | | /** |
351 | | * All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions. |
352 | | * Pruned nodes may have entries where B is missing data. |
353 | | */ |
354 | | std::multimap<CBlockIndex*, CBlockIndex*> m_blocks_unlinked; |
355 | | |
356 | | std::unique_ptr<BlockTreeDB> m_block_tree_db GUARDED_BY(::cs_main); |
357 | | |
358 | | void WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); |
359 | | bool LoadBlockIndexDB(const std::optional<uint256>& snapshot_blockhash) |
360 | | EXCLUSIVE_LOCKS_REQUIRED(::cs_main); |
361 | | |
362 | | /** |
363 | | * Remove any pruned block & undo files that are still on disk. |
364 | | * This could happen on some systems if the file was still being read while unlinked, |
365 | | * or if we crash before unlinking. |
366 | | */ |
367 | | void ScanAndUnlinkAlreadyPrunedFiles() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); |
368 | | |
369 | | CBlockIndex* AddToBlockIndex(const CBlockHeader& block, CBlockIndex*& best_header) EXCLUSIVE_LOCKS_REQUIRED(cs_main); |
370 | | /** Create a new block index entry for a given block hash */ |
371 | | CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main); |
372 | | |
373 | | //! Mark one block file as pruned (modify associated database entries) |
374 | | void PruneOneBlockFile(int fileNumber) EXCLUSIVE_LOCKS_REQUIRED(cs_main); |
375 | | |
376 | | CBlockIndex* LookupBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main); |
377 | | const CBlockIndex* LookupBlockIndex(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_main); |
378 | | |
379 | | /** Get block file info entry for one block file */ |
380 | | CBlockFileInfo* GetBlockFileInfo(size_t n); |
381 | | |
382 | | bool WriteBlockUndo(const CBlockUndo& blockundo, BlockValidationState& state, CBlockIndex& block) |
383 | | EXCLUSIVE_LOCKS_REQUIRED(::cs_main); |
384 | | |
385 | | /** Store block on disk and update block file statistics. |
386 | | * |
387 | | * @param[in] block the block to be stored |
388 | | * @param[in] nHeight the height of the block |
389 | | * |
390 | | * @returns in case of success, the position to which the block was written to |
391 | | * in case of an error, an empty FlatFilePos |
392 | | */ |
393 | | FlatFilePos WriteBlock(const CBlock& block, int nHeight); |
394 | | |
395 | | /** Update blockfile info while processing a block during reindex. The block must be available on disk. |
396 | | * |
397 | | * @param[in] block the block being processed |
398 | | * @param[in] nHeight the height of the block |
399 | | * @param[in] pos the position of the serialized CBlock on disk |
400 | | */ |
401 | | void UpdateBlockInfo(const CBlock& block, unsigned int nHeight, const FlatFilePos& pos); |
402 | | |
403 | | /** Whether running in -prune mode. */ |
404 | 0 | [[nodiscard]] bool IsPruneMode() const { return m_prune_mode; } |
405 | | |
406 | | /** Attempt to stay below this number of bytes of block files. */ |
407 | 0 | [[nodiscard]] uint64_t GetPruneTarget() const { return m_opts.prune_target; } |
408 | | static constexpr auto PRUNE_TARGET_MANUAL{std::numeric_limits<uint64_t>::max()}; |
409 | | |
410 | 0 | [[nodiscard]] bool LoadingBlocks() const { return m_importing || !m_blockfiles_indexed; } |
411 | | |
412 | | /** Calculate the amount of disk space the block & undo files currently use */ |
413 | | uint64_t CalculateCurrentUsage(); |
414 | | |
415 | | //! Check if all blocks in the [upper_block, lower_block] range have data available as |
416 | | //! defined by the status mask. |
417 | | //! The caller is responsible for ensuring that lower_block is an ancestor of upper_block |
418 | | //! (part of the same chain). |
419 | | bool CheckBlockDataAvailability(const CBlockIndex& upper_block, const CBlockIndex& lower_block, BlockStatus block_status = BLOCK_HAVE_DATA) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); |
420 | | |
421 | | /** |
422 | | * @brief Returns the earliest block with specified `status_mask` flags set after |
423 | | * the latest block _not_ having those flags. |
424 | | * |
425 | | * This function starts from `upper_block`, which must have all |
426 | | * `status_mask` flags set, and iterates backwards through its ancestors. It |
427 | | * continues as long as each block has all `status_mask` flags set, until |
428 | | * reaching the oldest ancestor or `lower_block`. |
429 | | * |
430 | | * @pre `upper_block` must have all `status_mask` flags set. |
431 | | * @pre `lower_block` must be null or an ancestor of `upper_block` |
432 | | * |
433 | | * @param upper_block The starting block for the search, which must have all |
434 | | * `status_mask` flags set. |
435 | | * @param status_mask Bitmask specifying required status flags. |
436 | | * @param lower_block The earliest possible block to return. If null, the |
437 | | * search can extend to the genesis block. |
438 | | * |
439 | | * @return A reference to the earliest block between `upper_block` |
440 | | * and `lower_block`, inclusive, such that every block between the |
441 | | * returned block and `upper_block` has `status_mask` flags set. |
442 | | */ |
443 | | const CBlockIndex& GetFirstBlock( |
444 | | const CBlockIndex& upper_block LIFETIMEBOUND, |
445 | | uint32_t status_mask, |
446 | | const CBlockIndex* lower_block LIFETIMEBOUND = nullptr |
447 | | ) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main); |
448 | | |
449 | | /** True if any block files have ever been pruned. */ |
450 | | bool m_have_pruned = false; |
451 | | |
452 | | //! Check whether the block associated with this index entry is pruned or not. |
453 | | bool IsBlockPruned(const CBlockIndex& block) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main); |
454 | | |
455 | | //! Create or update a prune lock identified by its name |
456 | | void UpdatePruneLock(const std::string& name, const PruneLockInfo& lock_info) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); |
457 | | |
458 | | /** Open a block file (blk?????.dat) */ |
459 | | AutoFile OpenBlockFile(const FlatFilePos& pos, bool fReadOnly) const; |
460 | | |
461 | | /** Translation to a filesystem path */ |
462 | | fs::path GetBlockPosFilename(const FlatFilePos& pos) const; |
463 | | |
464 | | /** |
465 | | * Actually unlink the specified files |
466 | | */ |
467 | | void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune) const; |
468 | | |
469 | | /** Functions for disk access for blocks */ |
470 | | bool ReadBlock(CBlock& block, const FlatFilePos& pos, const std::optional<uint256>& expected_hash) const; |
471 | | bool ReadBlock(CBlock& block, const CBlockIndex& index) const; |
472 | | ReadRawBlockResult ReadRawBlock(const FlatFilePos& pos, std::optional<std::pair<size_t, size_t>> block_part = std::nullopt) const; |
473 | | |
474 | | bool ReadBlockUndo(CBlockUndo& blockundo, const CBlockIndex& index) const; |
475 | | |
476 | | void CleanupBlockRevFiles() const; |
477 | | }; |
478 | | |
479 | | // Calls ActivateBestChain() even if no blocks are imported. |
480 | | void ImportBlocks(ChainstateManager& chainman, std::span<const fs::path> import_paths); |
481 | | } // namespace node |
482 | | |
483 | | #endif // BITCOIN_NODE_BLOCKSTORAGE_H |