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