LCOV - code coverage report
Current view: top level - src/node - blockstorage.h (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 8 8 100.0 %
Date: 2026-06-25 07:23:51 Functions: 8 8 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2011-2021 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 <chainparams.h>
      11             : #include <fs.h>
      12             : #include <kernel/blockmanager_opts.h>
      13             : #include <protocol.h>
      14             : #include <sync.h>
      15             : #include <txdb.h>
      16             : 
      17             : #include <cstdint>
      18             : #include <optional>
      19             : #include <unordered_map>
      20             : #include <vector>
      21             : 
      22             : extern RecursiveMutex cs_main; // NOLINT(readability-redundant-declaration)
      23             : 
      24             : class ArgsManager;
      25             : class BlockValidationState;
      26             : class CBlock;
      27             : class CBlockUndo;
      28             : class CChain;
      29             : class CChainParams;
      30             : class CChainState;
      31             : class ChainstateManager;
      32             : struct CCheckpointData;
      33             : struct FlatFilePos;
      34             : namespace Consensus {
      35             : struct Params;
      36             : }
      37             : 
      38             : namespace node {
      39             : static constexpr bool DEFAULT_STOPAFTERBLOCKIMPORT{false};
      40             : 
      41             : /** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
      42             : static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
      43             : /** The pre-allocation chunk size for rev?????.dat files (since 0.8) */
      44             : static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB
      45             : /** The maximum size of a blk?????.dat file (since 0.8) */
      46             : static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
      47             : 
      48             : /** Size of header written by WriteBlockToDisk before a serialized CBlock */
      49             : static constexpr size_t BLOCK_SERIALIZATION_HEADER_SIZE = CMessageHeader::MESSAGE_START_SIZE + sizeof(unsigned int);
      50             : 
      51             : extern std::atomic_bool fImporting;
      52             : extern std::atomic_bool fReindex;
      53             : /** Pruning-related variables and constants */
      54             : /** True if we're running in -prune mode. */
      55             : extern bool fPruneMode;
      56             : /** Number of bytes of block files that we're trying to stay below. */
      57             : extern uint64_t nPruneTarget;
      58             : 
      59             : // Because validation code takes pointers to the map's CBlockIndex objects, if
      60             : // we ever switch to another associative container, we need to either use a
      61             : // container that has stable addressing (true of all std associative
      62             : // containers), or make the key a `std::unique_ptr<CBlockIndex>`
      63             : using BlockMap = std::unordered_map<uint256, CBlockIndex, BlockHasher>;
      64             : using PrevBlockMap = std::unordered_multimap<uint256, CBlockIndex*, BlockHasher>;
      65             : 
      66             : struct CBlockIndexWorkComparator {
      67             :     bool operator()(const CBlockIndex* pa, const CBlockIndex* pb) const;
      68             : };
      69             : 
      70             : struct CBlockIndexHeightOnlyComparator {
      71             :     /* Only compares the height of two block indices, doesn't try to tie-break */
      72             :     bool operator()(const CBlockIndex* pa, const CBlockIndex* pb) const;
      73             : };
      74             : 
      75          26 : struct PruneLockInfo {
      76          26 :     int height_first{std::numeric_limits<int>::max()}; //! Height of earliest block that should be kept and not pruned
      77             : };
      78             : 
      79             : /**
      80             :  * Maintains a tree of blocks (stored in `m_block_index`) which is consulted
      81             :  * to determine where the most-work tip is.
      82             :  *
      83             :  * This data is used mostly in `CChainState` - information about, e.g.,
      84             :  * candidate tips is not maintained here.
      85             :  */
      86             : class BlockManager
      87             : {
      88             :     friend CChainState;
      89             :     friend ChainstateManager;
      90             : 
      91             : private:
      92             :     const kernel::BlockManagerOpts m_opts;
      93             : 
      94       49195 :     const CChainParams& GetParams() const { return m_opts.chainparams; }
      95         180 :     const Consensus::Params& GetConsensus() const { return m_opts.chainparams.GetConsensus(); }
      96             :     /**
      97             :      * Load the blocktree off disk and into memory. Populate certain metadata
      98             :      * per index entry (nStatus, nChainWork, nTimeMax, etc.) as well as peripheral
      99             :      * collections like m_dirty_blockindex.
     100             :      */
     101             :     bool LoadBlockIndex()
     102             :         EXCLUSIVE_LOCKS_REQUIRED(cs_main);
     103             :     void FlushBlockFile(bool fFinalize = false, bool finalize_undo = false);
     104             :     void FlushUndoFile(int block_file, bool finalize = false);
     105             :     bool FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigned int nHeight, CChain& active_chain, uint64_t nTime, bool fKnown);
     106             :     bool FindUndoPos(BlockValidationState& state, int nFile, FlatFilePos& pos, unsigned int nAddSize);
     107             : 
     108             :     /* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */
     109             :     void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight, int chain_tip_height);
     110             : 
     111             :     /**
     112             :      * Prune block and undo files (blk???.dat and rev???.dat) so that the disk space used is less than a user-defined target.
     113             :      * The user sets the target (in MB) on the command line or in config file.  This will be run on startup and whenever new
     114             :      * space is allocated in a block or undo file, staying below the target. Changing back to unpruned requires a reindex
     115             :      * (which in this case means the blockchain must be re-downloaded.)
     116             :      *
     117             :      * Pruning functions are called from FlushStateToDisk when the m_check_for_pruning flag has been set.
     118             :      * Block and undo files are deleted in lock-step (when blk00003.dat is deleted, so is rev00003.dat.)
     119             :      * Pruning cannot take place until the longest chain is at least a certain length (CChainParams::nPruneAfterHeight).
     120             :      * Pruning will never delete a block within a defined distance (currently 288) from the active chain's tip.
     121             :      * The block index is updated by unsetting HAVE_DATA and HAVE_UNDO for any blocks that were stored in the deleted files.
     122             :      * A db flag records the fact that at least some block files have been pruned.
     123             :      *
     124             :      * @param[out]   setFilesToPrune   The set of file indices that can be unlinked will be returned
     125             :      */
     126             :     void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight, int chain_tip_height, int prune_height, bool is_ibd);
     127             : 
     128             :     RecursiveMutex cs_LastBlockFile;
     129             :     std::vector<CBlockFileInfo> m_blockfile_info;
     130         185 :     int m_last_blockfile = 0;
     131             :     /** Global flag to indicate we should check to see if there are
     132             :      *  block/undo files that should be deleted.  Set on startup
     133             :      *  or if we allocate more file space when we're in prune mode
     134             :      */
     135         185 :     bool m_check_for_pruning = false;
     136             : 
     137             :     /** Dirty block index entries. */
     138             :     std::set<CBlockIndex*> m_dirty_blockindex;
     139             : 
     140             :     /** Dirty block file entries. */
     141             :     std::set<int> m_dirty_fileinfo;
     142             : 
     143             :     /**
     144             :      * Map from external index name to oldest block that must not be pruned.
     145             :      *
     146             :      * @note Internally, only blocks at height (height_first - PRUNE_LOCK_BUFFER - 1) and
     147             :      * below will be pruned, but callers should avoid assuming any particular buffer size.
     148             :      */
     149             :     std::unordered_map<std::string, PruneLockInfo> m_prune_locks GUARDED_BY(::cs_main);
     150             : 
     151             : public:
     152             :     using Options = kernel::BlockManagerOpts;
     153             : 
     154         740 :     explicit BlockManager(Options opts) : m_opts{opts} {}
     155             : 
     156             :     BlockMap m_block_index GUARDED_BY(cs_main);
     157             :     PrevBlockMap m_prev_block_index GUARDED_BY(cs_main);
     158             : 
     159             :     std::vector<CBlockIndex*> GetAllBlockIndices() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
     160             : 
     161             :     /**
     162             :      * All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions.
     163             :      * Pruned nodes may have entries where B is missing data.
     164             :      */
     165             :     std::multimap<CBlockIndex*, CBlockIndex*> m_blocks_unlinked;
     166             : 
     167             :     std::unique_ptr<CBlockTreeDB> m_block_tree_db GUARDED_BY(::cs_main);
     168             : 
     169             :     bool WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
     170             :     bool LoadBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
     171             : 
     172             :     CBlockIndex* AddToBlockIndex(const CBlockHeader& block, const uint256& hash, CBlockIndex*& best_header,
     173             :                                  enum BlockStatus nStatus = BLOCK_VALID_TREE)
     174             :         EXCLUSIVE_LOCKS_REQUIRED(cs_main);
     175             :     /** Create a new block index entry for a given block hash */
     176             :     CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
     177             : 
     178             :     //! Mark one block file as pruned (modify associated database entries)
     179             :     void PruneOneBlockFile(const int fileNumber) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
     180             : 
     181             :     CBlockIndex* LookupBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
     182             :     const CBlockIndex* LookupBlockIndex(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
     183             : 
     184             :     /** Get block file info entry for one block file */
     185             :     CBlockFileInfo* GetBlockFileInfo(size_t n);
     186             : 
     187             :     bool WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValidationState& state, CBlockIndex& block)
     188             :         EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
     189             : 
     190             :     /** Store block on disk. If dbp is not nullptr, then it provides the known position of the block within a block file on disk. */
     191             :     FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const FlatFilePos* dbp);
     192             : 
     193             :     /** Calculate the amount of disk space the block & undo files currently use */
     194             :     uint64_t CalculateCurrentUsage();
     195             : 
     196             :     //! Returns last CBlockIndex* that is a checkpoint
     197             :     const CBlockIndex* GetLastCheckpoint(const CCheckpointData& data) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
     198             : 
     199             :     //! Find the first block that is not pruned
     200             :     const CBlockIndex* GetFirstStoredBlock(const CBlockIndex& start_block LIFETIMEBOUND) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
     201             : 
     202             :     /** True if any block files have ever been pruned. */
     203         185 :     bool m_have_pruned = false;
     204             : 
     205             :     //! Check whether the block associated with this index entry is pruned or not.
     206             :     bool IsBlockPruned(const CBlockIndex* pblockindex) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
     207             : 
     208             :     //! Create or update a prune lock identified by its name
     209             :     void UpdatePruneLock(const std::string& name, const PruneLockInfo& lock_info) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
     210             : };
     211             : 
     212             : void CleanupBlockRevFiles();
     213             : 
     214             : /** Open a block file (blk?????.dat) */
     215             : FILE* OpenBlockFile(const FlatFilePos& pos, bool fReadOnly = false);
     216             : /** Translation to a filesystem path */
     217             : fs::path GetBlockPosFilename(const FlatFilePos& pos);
     218             : 
     219             : /**
     220             :  *  Actually unlink the specified files
     221             :  */
     222             : void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune);
     223             : 
     224             : /** Functions for disk access for blocks */
     225             : std::optional<uint256> ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::Params& consensusParams);
     226             : bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams);
     227             : 
     228             : bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex);
     229             : 
     230             : void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFiles, const ArgsManager& args);
     231             : } // namespace node
     232             : 
     233             : #endif // BITCOIN_NODE_BLOCKSTORAGE_H

Generated by: LCOV version 1.16