Bitcoin Core  27.99.0
P2P Digital Currency
blockstorage.h
Go to the documentation of this file.
1 // Copyright (c) 2011-2022 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>
13 #include <kernel/chainparams.h>
14 #include <kernel/cs_main.h>
16 #include <primitives/block.h>
17 #include <streams.h>
18 #include <sync.h>
19 #include <uint256.h>
20 #include <util/fs.h>
21 #include <util/hasher.h>
22 
23 #include <array>
24 #include <atomic>
25 #include <cstdint>
26 #include <functional>
27 #include <limits>
28 #include <map>
29 #include <memory>
30 #include <optional>
31 #include <set>
32 #include <string>
33 #include <unordered_map>
34 #include <utility>
35 #include <vector>
36 
38 class CBlockUndo;
39 class Chainstate;
40 class ChainstateManager;
41 namespace Consensus {
42 struct Params;
43 }
44 namespace util {
45 class SignalInterrupt;
46 } // namespace util
47 
48 namespace kernel {
50 class BlockTreeDB : public CDBWrapper
51 {
52 public:
54  bool WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*>>& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo);
55  bool ReadBlockFileInfo(int nFile, CBlockFileInfo& info);
56  bool ReadLastBlockFile(int& nFile);
57  bool WriteReindexing(bool fReindexing);
58  void ReadReindexing(bool& fReindexing);
59  bool WriteFlag(const std::string& name, bool fValue);
60  bool ReadFlag(const std::string& name, bool& fValue);
61  bool LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex, const util::SignalInterrupt& interrupt)
63 };
64 } // namespace kernel
65 
66 namespace node {
68 
70 static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
72 static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB
74 static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
75 
77 static constexpr size_t BLOCK_SERIALIZATION_HEADER_SIZE = std::tuple_size_v<MessageStartChars> + sizeof(unsigned int);
78 
79 // Because validation code takes pointers to the map's CBlockIndex objects, if
80 // we ever switch to another associative container, we need to either use a
81 // container that has stable addressing (true of all std associative
82 // containers), or make the key a `std::unique_ptr<CBlockIndex>`
83 using BlockMap = std::unordered_map<uint256, CBlockIndex, BlockHasher>;
84 
86  bool operator()(const CBlockIndex* pa, const CBlockIndex* pb) const;
87 };
88 
90  /* Only compares the height of two block indices, doesn't try to tie-break */
91  bool operator()(const CBlockIndex* pa, const CBlockIndex* pb) const;
92 };
93 
94 struct PruneLockInfo {
95  int height_first{std::numeric_limits<int>::max()};
96 };
97 
99  // Values used as array indexes - do not change carelessly.
100  NORMAL = 0,
101  ASSUMED = 1,
103 };
104 
105 std::ostream& operator<<(std::ostream& os, const BlockfileType& type);
106 
108  // The latest blockfile number.
109  int file_num{0};
110 
111  // Track the height of the highest block in file_num whose undo
112  // data has been written. Block data is written to block files in download
113  // order, but is written to undo files in validation order, which is
114  // usually in order by height. To avoid wasting disk space, undo files will
115  // be trimmed whenever the corresponding block file is finalized and
116  // the height of the highest block written to the block file equals the
117  // height of the highest block written to the undo file. This is a
118  // heuristic and can sometimes preemptively trim undo files that will write
119  // more data later, and sometimes fail to trim undo files that can't have
120  // more data written later.
121  int undo_height{0};
122 };
123 
124 std::ostream& operator<<(std::ostream& os, const BlockfileCursor& cursor);
125 
126 
135 {
136  friend Chainstate;
138 
139 private:
140  const CChainParams& GetParams() const { return m_opts.chainparams; }
147  bool LoadBlockIndex(const std::optional<uint256>& snapshot_blockhash)
149 
151  [[nodiscard]] bool FlushBlockFile(int blockfile_num, bool fFinalize, bool finalize_undo);
152 
154  [[nodiscard]] bool FlushUndoFile(int block_file, bool finalize = false);
155 
165  [[nodiscard]] FlatFilePos FindNextBlockPos(unsigned int nAddSize, unsigned int nHeight, uint64_t nTime);
166  [[nodiscard]] bool FlushChainstateBlockFile(int tip_height);
167  bool FindUndoPos(BlockValidationState& state, int nFile, FlatFilePos& pos, unsigned int nAddSize);
168 
169  AutoFile OpenUndoFile(const FlatFilePos& pos, bool fReadOnly = false) const;
170 
177  bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos) const;
178  bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const uint256& hashBlock) const;
179 
180  /* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */
182  std::set<int>& setFilesToPrune,
183  int nManualPruneHeight,
184  const Chainstate& chain,
185  ChainstateManager& chainman);
186 
203  void FindFilesToPrune(
204  std::set<int>& setFilesToPrune,
205  int last_prune,
206  const Chainstate& chain,
207  ChainstateManager& chainman);
208 
210  std::vector<CBlockFileInfo> m_blockfile_info;
211 
222  std::array<std::optional<BlockfileCursor>, BlockfileType::NUM_TYPES>
223  m_blockfile_cursors GUARDED_BY(cs_LastBlockFile) = {
224  BlockfileCursor{},
225  std::nullopt,
226  };
228  {
229  static const BlockfileCursor empty_cursor;
230  const auto& normal = m_blockfile_cursors[BlockfileType::NORMAL].value_or(empty_cursor);
231  const auto& assumed = m_blockfile_cursors[BlockfileType::ASSUMED].value_or(empty_cursor);
232  return std::max(normal.file_num, assumed.file_num);
233  }
234 
239  bool m_check_for_pruning = false;
240 
241  const bool m_prune_mode;
242 
244  std::set<CBlockIndex*> m_dirty_blockindex;
245 
247  std::set<int> m_dirty_fileinfo;
248 
255  std::unordered_map<std::string, PruneLockInfo> m_prune_locks GUARDED_BY(::cs_main);
256 
258 
260 
263 
264 public:
266 
267  explicit BlockManager(const util::SignalInterrupt& interrupt, Options opts)
268  : m_prune_mode{opts.prune_target > 0},
269  m_opts{std::move(opts)},
270  m_block_file_seq{FlatFileSeq{m_opts.blocks_dir, "blk", m_opts.fast_prune ? 0x4000 /* 16kB */ : BLOCKFILE_CHUNK_SIZE}},
272  m_interrupt{interrupt} {}
273 
275  std::atomic<bool> m_importing{false};
276 
283  std::atomic_bool m_blockfiles_indexed{true};
284 
285  BlockMap m_block_index GUARDED_BY(cs_main);
286 
299  std::optional<int> m_snapshot_height;
300 
301  std::vector<CBlockIndex*> GetAllBlockIndices() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
302 
308 
309  std::unique_ptr<BlockTreeDB> m_block_tree_db GUARDED_BY(::cs_main);
310 
311  bool WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
312  bool LoadBlockIndexDB(const std::optional<uint256>& snapshot_blockhash)
314 
320  void ScanAndUnlinkAlreadyPrunedFiles() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
321 
325 
327  void PruneOneBlockFile(const int fileNumber) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
328 
331 
333  CBlockFileInfo* GetBlockFileInfo(size_t n);
334 
335  bool WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValidationState& state, CBlockIndex& block)
337 
347 
355  void UpdateBlockInfo(const CBlock& block, unsigned int nHeight, const FlatFilePos& pos);
356 
358  [[nodiscard]] bool IsPruneMode() const { return m_prune_mode; }
359 
361  [[nodiscard]] uint64_t GetPruneTarget() const { return m_opts.prune_target; }
362  static constexpr auto PRUNE_TARGET_MANUAL{std::numeric_limits<uint64_t>::max()};
363 
364  [[nodiscard]] bool LoadingBlocks() const { return m_importing || !m_blockfiles_indexed; }
365 
367  uint64_t CalculateCurrentUsage();
368 
371 
375  bool CheckBlockDataAvailability(const CBlockIndex& upper_block LIFETIMEBOUND, const CBlockIndex& lower_block LIFETIMEBOUND) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
376 
399  const CBlockIndex* GetFirstBlock(
400  const CBlockIndex& upper_block LIFETIMEBOUND,
401  uint32_t status_mask,
402  const CBlockIndex* lower_block = nullptr
404 
406  bool m_have_pruned = false;
407 
409  bool IsBlockPruned(const CBlockIndex& block) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
410 
412  void UpdatePruneLock(const std::string& name, const PruneLockInfo& lock_info) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
413 
415  AutoFile OpenBlockFile(const FlatFilePos& pos, bool fReadOnly = false) const;
416 
418  fs::path GetBlockPosFilename(const FlatFilePos& pos) const;
419 
423  void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune) const;
424 
426  bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos) const;
427  bool ReadBlockFromDisk(CBlock& block, const CBlockIndex& index) const;
428  bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos) const;
429 
430  bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex& index) const;
431 
432  void CleanupBlockRevFiles() const;
433 };
434 
435 void ImportBlocks(ChainstateManager& chainman, std::vector<fs::path> vImportFiles);
436 } // namespace node
437 
438 #endif // BITCOIN_NODE_BLOCKSTORAGE_H
#define LIFETIMEBOUND
Definition: attributes.h:16
const CChainParams & Params()
Return the currently selected parameters.
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:389
Nodes collect new transactions into a block, hash them into a hash tree, and scan through nonce value...
Definition: block.h:22
Definition: block.h:69
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:141
Undo information for a CBlock.
Definition: undo.h:63
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Definition: chainparams.h:81
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:93
CDBWrapper(const DBParams &params)
Definition: dbwrapper.cpp:221
Chainstate stores and provides an API to update our local knowledge of the current best chain.
Definition: validation.h:513
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Definition: validation.h:871
FlatFileSeq represents a sequence of numbered files storing raw data.
Definition: flatfile.h:46
Access to the block database (blocks/index/)
Definition: blockstorage.h:51
bool ReadLastBlockFile(int &nFile)
bool ReadFlag(const std::string &name, bool &fValue)
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &info)
bool WriteBatchSync(const std::vector< std::pair< int, const CBlockFileInfo * >> &fileInfo, int nLastFile, const std::vector< const CBlockIndex * > &blockinfo)
void ReadReindexing(bool &fReindexing)
bool WriteFlag(const std::string &name, bool fValue)
bool WriteReindexing(bool fReindexing)
Maintains a tree of blocks (stored in m_block_index) which is consulted to determine where the most-w...
Definition: blockstorage.h:135
const kernel::BlockManagerOpts m_opts
Definition: blockstorage.h:259
std::set< int > m_dirty_fileinfo
Dirty block file entries.
Definition: blockstorage.h:247
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos) const
Functions for disk access for blocks.
const FlatFileSeq m_undo_file_seq
Definition: blockstorage.h:262
RecursiveMutex cs_LastBlockFile
Definition: blockstorage.h:209
const Consensus::Params & GetConsensus() const
Definition: blockstorage.h:141
bool FlushChainstateBlockFile(int tip_height)
void FindFilesToPrune(std::set< int > &setFilesToPrune, int last_prune, const Chainstate &chain, ChainstateManager &chainman)
Prune block and undo files (blk???.dat and rev???.dat) so that the disk space used is less than a use...
void UpdateBlockInfo(const CBlock &block, unsigned int nHeight, const FlatFilePos &pos)
Update blockfile info while processing a block during reindex.
static constexpr auto PRUNE_TARGET_MANUAL
Definition: blockstorage.h:362
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
std::array< std::optional< BlockfileCursor >, BlockfileType::NUM_TYPES > m_blockfile_cursors GUARDED_BY(cs_LastBlockFile)
Since assumedvalid chainstates may be syncing a range of the chain that is very far away from the nor...
std::unordered_map< std::string, PruneLockInfo > m_prune_locks GUARDED_BY(::cs_main)
Map from external index name to oldest block that must not be pruned.
void PruneOneBlockFile(const int fileNumber) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Mark one block file as pruned (modify associated database entries)
BlockfileType BlockfileTypeForHeight(int height)
std::atomic_bool m_blockfiles_indexed
Whether all blockfiles have been added to the block tree database.
Definition: blockstorage.h:283
std::vector< CBlockIndex * > GetAllBlockIndices() EXCLUSIVE_LOCKS_REQUIRED(std::multimap< CBlockIndex *, CBlockIndex * > m_blocks_unlinked
All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions.
Definition: blockstorage.h:301
BlockManager(const util::SignalInterrupt &interrupt, Options opts)
Definition: blockstorage.h:267
bool ReadRawBlockFromDisk(std::vector< uint8_t > &block, const FlatFilePos &pos) const
std::set< CBlockIndex * > m_dirty_blockindex
Dirty block index entries.
Definition: blockstorage.h:244
bool LoadingBlocks() const
Definition: blockstorage.h:364
bool UndoReadFromDisk(CBlockUndo &blockundo, const CBlockIndex &index) const
fs::path GetBlockPosFilename(const FlatFilePos &pos) const
Translation to a filesystem path.
bool FlushBlockFile(int blockfile_num, bool fFinalize, bool finalize_undo)
Return false if block file or undo file flushing fails.
uint64_t GetPruneTarget() const
Attempt to stay below this number of bytes of block files.
Definition: blockstorage.h:361
bool WriteBlockToDisk(const CBlock &block, FlatFilePos &pos) const
Write a block to disk.
int MaxBlockfileNum() const EXCLUSIVE_LOCKS_REQUIRED(cs_LastBlockFile)
Definition: blockstorage.h:227
void UnlinkPrunedFiles(const std::set< int > &setFilesToPrune) const
Actually unlink the specified files.
bool WriteUndoDataForBlock(const CBlockUndo &blockundo, BlockValidationState &state, CBlockIndex &block) EXCLUSIVE_LOCKS_REQUIRED(FlatFilePos SaveBlockToDisk(const CBlock &block, int nHeight)
Store block on disk and update block file statistics.
Definition: blockstorage.h:346
bool WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(bool LoadBlockIndexDB(const std::optional< uint256 > &snapshot_blockhash) EXCLUSIVE_LOCKS_REQUIRED(void ScanAndUnlinkAlreadyPrunedFiles() EXCLUSIVE_LOCKS_REQUIRED(CBlockIndex * AddToBlockIndex(const CBlockHeader &block, CBlockIndex *&best_header) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Remove any pruned block & undo files that are still on disk.
Definition: blockstorage.h:322
FlatFilePos FindNextBlockPos(unsigned int nAddSize, unsigned int nHeight, uint64_t nTime)
Helper function performing various preparations before a block can be saved to disk: Returns the corr...
const bool m_prune_mode
Definition: blockstorage.h:241
bool CheckBlockDataAvailability(const CBlockIndex &upper_block LIFETIMEBOUND, const CBlockIndex &lower_block LIFETIMEBOUND) EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetFirstBlock(const CBlockIndex &upper_block LIFETIMEBOUND, uint32_t status_mask, const CBlockIndex *lower_block=nullptr) const EXCLUSIVE_LOCKS_REQUIRED(boo m_have_pruned)
Check if all blocks in the [upper_block, lower_block] range have data available.
Definition: blockstorage.h:406
bool FlushUndoFile(int block_file, bool finalize=false)
Return false if undo file flushing fails.
uint64_t CalculateCurrentUsage()
Calculate the amount of disk space the block & undo files currently use.
const util::SignalInterrupt & m_interrupt
Definition: blockstorage.h:274
const CBlockIndex * GetLastCheckpoint(const CCheckpointData &data) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Returns last CBlockIndex* that is a checkpoint.
const FlatFileSeq m_block_file_seq
Definition: blockstorage.h:261
CBlockIndex * InsertBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Create a new block index entry for a given block hash.
bool m_check_for_pruning
Global flag to indicate we should check to see if there are block/undo files that should be deleted.
Definition: blockstorage.h:239
const CChainParams & GetParams() const
Definition: blockstorage.h:140
bool FindUndoPos(BlockValidationState &state, int nFile, FlatFilePos &pos, unsigned int nAddSize)
bool IsBlockPruned(const CBlockIndex &block) const EXCLUSIVE_LOCKS_REQUIRED(void UpdatePruneLock(const std::string &name, const PruneLockInfo &lock_info) EXCLUSIVE_LOCKS_REQUIRED(AutoFile OpenBlockFile(const FlatFilePos &pos, bool fReadOnly=false) const
Check whether the block associated with this index entry is pruned or not.
Definition: blockstorage.h:415
bool IsPruneMode() const
Whether running in -prune mode.
Definition: blockstorage.h:358
void CleanupBlockRevFiles() const
void FindFilesToPruneManual(std::set< int > &setFilesToPrune, int nManualPruneHeight, const Chainstate &chain, ChainstateManager &chainman)
std::atomic< bool > m_importing
Definition: blockstorage.h:275
std::vector< CBlockFileInfo > m_blockfile_info
Definition: blockstorage.h:210
bool UndoWriteToDisk(const CBlockUndo &blockundo, FlatFilePos &pos, const uint256 &hashBlock) const
CBlockFileInfo * GetBlockFileInfo(size_t n)
Get block file info entry for one block file.
bool LoadBlockIndex(const std::optional< uint256 > &snapshot_blockhash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Load the blocktree off disk and into memory.
AutoFile OpenUndoFile(const FlatFilePos &pos, bool fReadOnly=false) const
Open an undo file (rev?????.dat)
std::optional< int > m_snapshot_height
The height of the base block of an assumeutxo snapshot, if one is in use.
Definition: blockstorage.h:299
BlockMap m_block_index GUARDED_BY(cs_main)
256-bit opaque blob.
Definition: uint256.h:127
Helper class that manages an interrupt flag, and allows a thread or signal to interrupt another threa...
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: cs_main.cpp:8
unsigned int nHeight
Transaction validation functions.
Filesystem operations and types.
Definition: messages.h:20
static const unsigned int UNDOFILE_CHUNK_SIZE
The pre-allocation chunk size for rev?????.dat files (since 0.8)
Definition: blockstorage.h:72
BlockfileType
Definition: blockstorage.h:98
@ NUM_TYPES
Definition: blockstorage.h:102
@ NORMAL
Definition: blockstorage.h:100
@ ASSUMED
Definition: blockstorage.h:101
void ImportBlocks(ChainstateManager &chainman, std::vector< fs::path > vImportFiles)
static const unsigned int BLOCKFILE_CHUNK_SIZE
The pre-allocation chunk size for blk?????.dat files (since 0.8)
Definition: blockstorage.h:70
std::ostream & operator<<(std::ostream &os, const BlockfileType &type)
std::unordered_map< uint256, CBlockIndex, BlockHasher > BlockMap
Definition: blockstorage.h:83
static constexpr size_t BLOCK_SERIALIZATION_HEADER_SIZE
Size of header written by WriteBlockToDisk before a serialized CBlock.
Definition: blockstorage.h:77
static const unsigned int MAX_BLOCKFILE_SIZE
The maximum size of a blk?????.dat file (since 0.8)
Definition: blockstorage.h:74
const char * name
Definition: rest.cpp:49
Parameters that influence chain consensus.
Definition: params.h:74
An options struct for BlockManager, more ergonomically referred to as BlockManager::Options due to th...
const CChainParams & chainparams
bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const
bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49