Bitcoin Core  31.0.0
P2P Digital Currency
blockstorage.h
Go to the documentation of this file.
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>
13 #include <kernel/chainparams.h>
14 #include <kernel/cs_main.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 
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 {
57 {
58 public:
59  uint32_t nBlocks{};
60  uint32_t nSize{};
61  uint32_t nUndoSize{};
62  uint32_t nHeightFirst{};
63  uint32_t nHeightLast{};
64  uint64_t nTimeFirst{};
65  uint64_t nTimeLast{};
66 
68  {
69  READWRITE(VARINT(obj.nBlocks));
70  READWRITE(VARINT(obj.nSize));
71  READWRITE(VARINT(obj.nUndoSize));
72  READWRITE(VARINT(obj.nHeightFirst));
73  READWRITE(VARINT(obj.nHeightLast));
74  READWRITE(VARINT(obj.nTimeFirst));
75  READWRITE(VARINT(obj.nTimeLast));
76  }
77 
78  CBlockFileInfo() = default;
79 
80  std::string ToString() const;
81 
83  void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn)
84  {
85  if (nBlocks == 0 || nHeightFirst > nHeightIn)
86  nHeightFirst = nHeightIn;
87  if (nBlocks == 0 || nTimeFirst > nTimeIn)
88  nTimeFirst = nTimeIn;
89  nBlocks++;
90  if (nHeightIn > nHeightLast)
91  nHeightLast = nHeightIn;
92  if (nTimeIn > nTimeLast)
93  nTimeLast = nTimeIn;
94  }
95 };
96 
98 class BlockTreeDB : public CDBWrapper
99 {
100 public:
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)
111 };
112 } // namespace kernel
113 
114 namespace node {
116 using kernel::BlockTreeDB;
117 
119 static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
121 static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB
123 static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
124 
126 static constexpr uint32_t STORAGE_HEADER_BYTES{std::tuple_size_v<MessageStartChars> + sizeof(unsigned int)};
127 
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 
138  bool operator()(const CBlockIndex* pa, const CBlockIndex* pb) const;
139  using is_transparent = void;
140 };
141 
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 
148  int height_first{std::numeric_limits<int>::max()};
149 };
150 
152  // Values used as array indexes - do not change carelessly.
153  NORMAL = 0,
154  ASSUMED = 1,
156 };
157 
158 std::ostream& operator<<(std::ostream& os, const BlockfileType& type);
159 
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 
192 {
193  friend Chainstate;
195 
196 private:
197  const CChainParams& GetParams() const { return m_opts.chainparams; }
204  bool LoadBlockIndex(const std::optional<uint256>& snapshot_blockhash)
206 
208  [[nodiscard]] bool FlushBlockFile(int blockfile_num, bool fFinalize, bool finalize_undo);
209 
211  [[nodiscard]] bool FlushUndoFile(int block_file, bool finalize = false);
212 
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 */
230  std::set<int>& setFilesToPrune,
231  int nManualPruneHeight,
232  const Chainstate& chain);
233 
250  void FindFilesToPrune(
251  std::set<int>& setFilesToPrune,
252  int last_prune,
253  const Chainstate& chain,
254  ChainstateManager& chainman);
255 
257 
268  std::array<std::optional<BlockfileCursor>, BlockfileType::NUM_TYPES>
269  m_blockfile_cursors GUARDED_BY(cs_LastBlockFile) = {
270  BlockfileCursor{},
271  std::nullopt,
272  };
274  {
275  static const BlockfileCursor empty_cursor;
276  const auto& normal = m_blockfile_cursors[BlockfileType::NORMAL].value_or(empty_cursor);
277  const auto& assumed = m_blockfile_cursors[BlockfileType::ASSUMED].value_or(empty_cursor);
278  return std::max(normal.file_num, assumed.file_num);
279  }
280 
285  bool m_check_for_pruning = false;
286 
287  const bool m_prune_mode;
288 
290 
297  std::unordered_map<std::string, PruneLockInfo> m_prune_locks GUARDED_BY(::cs_main);
298 
300 
302 
305 
306 protected:
307  std::vector<CBlockFileInfo> m_blockfile_info;
308 
310  std::set<CBlockIndex*> m_dirty_blockindex;
311 
313  std::set<int> m_dirty_fileinfo;
314 
315 public:
318 
319  explicit BlockManager(const util::SignalInterrupt& interrupt, Options opts);
320 
322  std::atomic<bool> m_importing{false};
323 
330  std::atomic_bool m_blockfiles_indexed{true};
331 
332  BlockMap m_block_index GUARDED_BY(cs_main);
333 
346  std::optional<int> m_snapshot_height;
347 
348  std::vector<CBlockIndex*> GetAllBlockIndices() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
349 
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)
361 
367  void ScanAndUnlinkAlreadyPrunedFiles() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
368 
372 
374  void PruneOneBlockFile(int fileNumber) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
375 
378 
380  CBlockFileInfo* GetBlockFileInfo(size_t n);
381 
382  bool WriteBlockUndo(const CBlockUndo& blockundo, BlockValidationState& state, CBlockIndex& block)
384 
393  FlatFilePos WriteBlock(const CBlock& block, int nHeight);
394 
401  void UpdateBlockInfo(const CBlock& block, unsigned int nHeight, const FlatFilePos& pos);
402 
404  [[nodiscard]] bool IsPruneMode() const { return m_prune_mode; }
405 
407  [[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  [[nodiscard]] bool LoadingBlocks() const { return m_importing || !m_blockfiles_indexed; }
411 
413  uint64_t CalculateCurrentUsage();
414 
419  bool CheckBlockDataAvailability(const CBlockIndex& upper_block, const CBlockIndex& lower_block, BlockStatus block_status = BLOCK_HAVE_DATA) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
420 
443  const CBlockIndex& GetFirstBlock(
444  const CBlockIndex& upper_block LIFETIMEBOUND,
445  uint32_t status_mask,
446  const CBlockIndex* lower_block LIFETIMEBOUND = nullptr
448 
450  bool m_have_pruned = false;
451 
453  bool IsBlockPruned(const CBlockIndex& block) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
454 
456  void UpdatePruneLock(const std::string& name, const PruneLockInfo& lock_info) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
457 
459  AutoFile OpenBlockFile(const FlatFilePos& pos, bool fReadOnly) const;
460 
462  fs::path GetBlockPosFilename(const FlatFilePos& pos) const;
463 
467  void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune) const;
468 
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
uint32_t nSize
number of used bytes of block file
Definition: blockstorage.h:60
#define VARINT(obj)
Definition: serialize.h:491
std::optional< int > m_snapshot_height
The height of the base block of an assumeutxo snapshot, if one is in use.
Definition: blockstorage.h:346
std::set< int > m_dirty_fileinfo
Dirty block file entries.
Definition: blockstorage.h:313
const util::SignalInterrupt & m_interrupt
Definition: blockstorage.h:321
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:285
void UpdateBlockInfo(const CBlock &block, unsigned int nHeight, const FlatFilePos &pos)
Update blockfile info while processing a block during reindex.
bool WriteBlockUndo(const CBlockUndo &blockundo, BlockValidationState &state, CBlockIndex &block) EXCLUSIVE_LOCKS_REQUIRED(FlatFilePos WriteBlock(const CBlock &block, int nHeight)
Store block on disk and update block file statistics.
Definition: blockstorage.h:393
bool IsPruneMode() const
Whether running in -prune mode.
Definition: blockstorage.h:404
uint32_t nUndoSize
number of used bytes in the undo file
Definition: blockstorage.h:61
void CleanupBlockRevFiles() const
static constexpr auto PRUNE_TARGET_MANUAL
Definition: blockstorage.h:408
uint64_t CalculateCurrentUsage()
Calculate the amount of disk space the block & undo files currently use.
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &info)
Definition: block.h:73
RecursiveMutex cs_LastBlockFile
Definition: blockstorage.h:256
Interface for managing multiple Chainstate objects, where each chainstate is associated with chainsta...
Definition: validation.h:939
uint32_t nBlocks
number of blocks stored in file
Definition: blockstorage.h:59
Access to the block database (blocks/index/)
Definition: blockstorage.h:98
static constexpr unsigned int size()
Definition: uint256.h:106
const Consensus::Params & GetConsensus() const
Definition: blockstorage.h:198
std::unordered_map< uint256, CBlockIndex, BlockHasher > BlockMap
Definition: blockstorage.h:135
AutoFile OpenUndoFile(const FlatFilePos &pos, bool fReadOnly=false) const
Open an undo file (rev?????.dat)
bool FlushBlockFile(int blockfile_num, bool fFinalize, bool finalize_undo)
Return false if block file or undo file flushing fails.
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...
bool CheckBlockDataAvailability(const CBlockIndex &upper_block, const CBlockIndex &lower_block, BlockStatus block_status=BLOCK_HAVE_DATA) EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex &GetFirstBlock(const CBlockIndex &upper_block LIFETIMEBOUND, uint32_t status_mask, const CBlockIndex *lower_block LIFETIMEBOUND=nullptr) const EXCLUSIVE_LOCKS_REQUIRED(boo m_have_pruned)
Check if all blocks in the [upper_block, lower_block] range have data available as defined by the sta...
Definition: blockstorage.h:450
Definition: common.h:29
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
Definition: chainparams.h:76
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) const
Check whether the block associated with this index entry is pruned or not.
Definition: blockstorage.h:459
const Obfuscation m_obfuscation
Definition: blockstorage.h:289
BlockManager(const util::SignalInterrupt &interrupt, Options opts)
bool ReadFlag(const std::string &name, bool &fValue)
void ImportBlocks(ChainstateManager &chainman, std::span< const fs::path > import_paths)
SERIALIZE_METHODS(CBlockFileInfo, obj)
Definition: blockstorage.h:67
void UnlinkPrunedFiles(const std::set< int > &setFilesToPrune) const
Actually unlink the specified files.
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:372
void WriteBatchSync(const std::vector< std::pair< int, const CBlockFileInfo *>> &fileInfo, int nLastFile, const std::vector< const CBlockIndex *> &blockinfo)
uint32_t nHeightFirst
lowest height of block in file
Definition: blockstorage.h:62
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:348
bool ReadLastBlockFile(int &nFile)
Transaction validation functions.
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...
const bool m_prune_mode
Definition: blockstorage.h:287
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...
int MaxBlockfileNum() const EXCLUSIVE_LOCKS_REQUIRED(cs_LastBlockFile)
Definition: blockstorage.h:273
static const unsigned int BLOCKFILE_CHUNK_SIZE
The pre-allocation chunk size for blk?????.dat files (since 0.8)
Definition: blockstorage.h:119
void 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:369
An options struct for BlockManager, more ergonomically referred to as BlockManager::Options due to th...
void PruneOneBlockFile(int fileNumber) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Mark one block file as pruned (modify associated database entries)
#define LIFETIMEBOUND
Definition: attributes.h:16
Chainstate stores and provides an API to update our local knowledge of the current best chain...
Definition: validation.h:550
ReadRawError
Definition: blockstorage.h:179
bool FindUndoPos(BlockValidationState &state, int nFile, FlatFilePos &pos, unsigned int nAddSize)
CDBWrapper(const DBParams &params)
Definition: dbwrapper.cpp:217
static constexpr uint32_t UNDO_DATA_DISK_OVERHEAD
Total overhead when writing undo data: header (8 bytes) plus checksum (32 bytes)
Definition: blockstorage.h:129
const char * name
Definition: rest.cpp:48
static constexpr uint32_t STORAGE_HEADER_BYTES
Size of header written by WriteBlock before a serialized CBlock (8 bytes)
Definition: blockstorage.h:126
const kernel::BlockManagerOpts m_opts
Definition: blockstorage.h:301
const FlatFileSeq m_block_file_seq
Definition: blockstorage.h:303
bool LoadingBlocks() const
Definition: blockstorage.h:410
BlockfileType BlockfileTypeForHeight(int height)
uint32_t nHeightLast
highest height of block in file
Definition: blockstorage.h:63
ReadRawBlockResult ReadRawBlock(const FlatFilePos &pos, std::optional< std::pair< size_t, size_t >> block_part=std::nullopt) const
Maintains a tree of blocks (stored in m_block_index) which is consulted to determine where the most-w...
Definition: blockstorage.h:191
const CChainParams & chainparams
std::atomic_bool m_blockfiles_indexed
Whether all blockfiles have been added to the block tree database.
Definition: blockstorage.h:330
bool LoadBlockIndex(const std::optional< uint256 > &snapshot_blockhash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Load the blocktree off disk and into memory.
Parameters that influence chain consensus.
Definition: params.h:84
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
BlockfileType
Definition: blockstorage.h:151
bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const
unsigned int nHeight
std::string ToString() const
const FlatFileSeq m_undo_file_seq
Definition: blockstorage.h:304
uint64_t nTimeFirst
earliest time of block in file
Definition: blockstorage.h:64
const CChainParams & GetParams() const
Definition: blockstorage.h:197
Definition: messages.h:21
Helper class that manages an interrupt flag, and allows a thread or signal to interrupt another threa...
void WriteReindexing(bool fReindexing)
256-bit opaque blob.
Definition: uint256.h:195
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:51
The util::Expected class provides a standard way for low-level functions to return either error value...
Definition: expected.h:44
fs::path GetBlockPosFilename(const FlatFilePos &pos) const
Translation to a filesystem path.
void FindFilesToPruneManual(std::set< int > &setFilesToPrune, int nManualPruneHeight, const Chainstate &chain)
bool FlushUndoFile(int block_file, bool finalize=false)
Return false if undo file flushing fails.
std::set< CBlockIndex * > m_dirty_blockindex
Dirty block index entries.
Definition: blockstorage.h:310
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:93
const CChainParams & Params()
Return the currently selected parameters.
Undo information for a CBlock.
Definition: undo.h:62
static const unsigned int MAX_BLOCKFILE_SIZE
The maximum size of a blk?????.dat file (since 0.8)
Definition: blockstorage.h:123
void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn)
update statistics (does not update nSize)
Definition: blockstorage.h:83
bool ReadBlock(CBlock &block, const FlatFilePos &pos, const std::optional< uint256 > &expected_hash) const
Functions for disk access for blocks.
CBlockIndex * InsertBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Create a new block index entry for a given block hash.
bool FlushChainstateBlockFile(int tip_height)
BlockStatus
Definition: chain.h:42
static const unsigned int UNDOFILE_CHUNK_SIZE
The pre-allocation chunk size for rev?????.dat files (since 0.8)
Definition: blockstorage.h:121
void ReadReindexing(bool &fReindexing)
uint64_t nTimeLast
latest time of block in file
Definition: blockstorage.h:65
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:89
void CheckBlockDataAvailability(BlockManager &blockman, const CBlockIndex &blockindex, bool check_for_undo)
Definition: blockchain.cpp:671
full block available in blk*.dat
Definition: chain.h:75
CBlockFileInfo * GetBlockFileInfo(size_t n)
Get block file info entry for one block file.
#define READWRITE(...)
Definition: serialize.h:145
FlatFileSeq represents a sequence of numbered files storing raw data.
Definition: flatfile.h:41
std::atomic< bool > m_importing
Definition: blockstorage.h:322
uint64_t GetPruneTarget() const
Attempt to stay below this number of bytes of block files.
Definition: blockstorage.h:407
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
Definition: cs_main.cpp:8
std::ostream & operator<<(std::ostream &os, const BlockfileType &type)
Nodes collect new transactions into a block, hash them into a hash tree, and scan through nonce value...
Definition: block.h:26
bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const
void WriteFlag(const std::string &name, bool fValue)
bool ReadBlockUndo(CBlockUndo &blockundo, const CBlockIndex &index) const
std::vector< CBlockFileInfo > m_blockfile_info
Definition: blockstorage.h:307