Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2011-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#ifndef BITCOIN_NODE_BLOCKSTORAGE_H6#define BITCOIN_NODE_BLOCKSTORAGE_H8#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/byte_units.h>22#include <util/expected.h>23#include <util/fs.h>24#include <util/hasher.h>25#include <util/obfuscation.h>27#include <algorithm>28#include <array>29#include <atomic>30#include <cstddef>31#include <cstdint>32#include <functional>33#include <iosfwd>34#include <limits>35#include <map>36#include <memory>37#include <optional>38#include <set>39#include <span>40#include <string>41#include <unordered_map>42#include <utility>43#include <vector>45class BlockValidationState;46class CBlockUndo;47class Chainstate;48class ChainstateManager;49namespace Consensus {50struct Params;51}52namespace util {53class SignalInterrupt;54} // namespace util56namespace kernel {57class CBlockFileInfo58{59public:60uint32_t nBlocks{}; //!< number of blocks stored in file61uint64_t nSize{}; //!< number of used bytes of block file62uint64_t nUndoSize{}; //!< number of used bytes in the undo file63uint32_t nHeightFirst{}; //!< lowest height of block in file64uint32_t nHeightLast{}; //!< highest height of block in file65uint64_t nTimeFirst{}; //!< earliest time of block in file66uint64_t nTimeLast{}; //!< latest time of block in file68SERIALIZE_METHODS(CBlockFileInfo, obj)69{70READWRITE(VARINT(obj.nBlocks));71READWRITE(VARINT(obj.nSize));72READWRITE(VARINT(obj.nUndoSize));73READWRITE(VARINT(obj.nHeightFirst));74READWRITE(VARINT(obj.nHeightLast));75READWRITE(VARINT(obj.nTimeFirst));76READWRITE(VARINT(obj.nTimeLast));77}79CBlockFileInfo() = default;81std::string ToString() const;83/** update statistics (does not update nSize) */84void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn)85{86if (nBlocks == 0 || nHeightFirst > nHeightIn)87nHeightFirst = nHeightIn;88if (nBlocks == 0 || nTimeFirst > nTimeIn)89nTimeFirst = nTimeIn;90nBlocks++;91if (nHeightIn > nHeightLast)92nHeightLast = nHeightIn;93if (nTimeIn > nTimeLast)94nTimeLast = nTimeIn;95}96};98/** Access to the block database (blocks/index/) */99class BlockTreeDB : public CDBWrapper100{101public:102using CDBWrapper::CDBWrapper;103void WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*>>& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo);104bool ReadBlockFileInfo(int nFile, CBlockFileInfo& info);105bool ReadLastBlockFile(int& nFile);106void WriteReindexing(bool fReindexing);107void ReadReindexing(bool& fReindexing);108void WriteFlag(const std::string& name, bool fValue);109bool ReadFlag(const std::string& name, bool& fValue);110bool LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex, const util::SignalInterrupt& interrupt)111EXCLUSIVE_LOCKS_REQUIRED(::cs_main);112};113} // namespace kernel115namespace node {116using kernel::CBlockFileInfo;117using kernel::BlockTreeDB;119/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */120inline constexpr unsigned int BLOCKFILE_CHUNK_SIZE{16_MiB};121/** The pre-allocation chunk size for rev?????.dat files (since 0.8) */122inline constexpr unsigned int UNDOFILE_CHUNK_SIZE{1_MiB};123/** The maximum size of a blk?????.dat file (since 0.8) */124inline constexpr unsigned int MAX_BLOCKFILE_SIZE{128_MiB};126/** Size of header written by WriteBlock before a serialized CBlock (8 bytes) */127inline constexpr uint32_t STORAGE_HEADER_BYTES{std::tuple_size_v<MessageStartChars> + sizeof(unsigned int)};129/** Total overhead when writing undo data: header (8 bytes) plus checksum (32 bytes) */130inline constexpr uint32_t UNDO_DATA_DISK_OVERHEAD{STORAGE_HEADER_BYTES + uint256::size()};132// Because validation code takes pointers to the map's CBlockIndex objects, if133// we ever switch to another associative container, we need to either use a134// container that has stable addressing (true of all std associative135// containers), or make the key a `std::unique_ptr<CBlockIndex>`136using BlockMap = std::unordered_map<uint256, CBlockIndex, BlockHasher>;138struct CBlockIndexWorkComparator {139bool operator()(const CBlockIndex* pa, const CBlockIndex* pb) const;140using is_transparent = void;141};143struct CBlockIndexHeightOnlyComparator {144/* Only compares the height of two block indices, doesn't try to tie-break */145bool operator()(const CBlockIndex* pa, const CBlockIndex* pb) const;146};148struct PruneLockInfo {149/// Height of earliest block that should be kept and not pruned150int height_first{std::numeric_limits<int>::max()};151};153enum BlockfileType {154// Values used as array indexes - do not change carelessly.155NORMAL = 0,156ASSUMED = 1,157NUM_TYPES = 2,158};160std::ostream& operator<<(std::ostream& os, const BlockfileType& type);162struct BlockfileCursor {163// The latest blockfile number.164int file_num{0};166// Track the height of the highest block in file_num whose undo167// data has been written. Block data is written to block files in download168// order, but is written to undo files in validation order, which is169// usually in order by height. To avoid wasting disk space, undo files will170// be trimmed whenever the corresponding block file is finalized and171// the height of the highest block written to the block file equals the172// height of the highest block written to the undo file. This is a173// heuristic and can sometimes preemptively trim undo files that will write174// more data later, and sometimes fail to trim undo files that can't have175// more data written later.176int undo_height{0};177};179std::ostream& operator<<(std::ostream& os, const BlockfileCursor& cursor);181enum class ReadRawError {182IO,183BadPartRange,184};186/**187* Maintains a tree of blocks (stored in `m_block_index`) which is consulted188* to determine where the most-work tip is.189*190* This data is used mostly in `Chainstate` - information about, e.g.,191* candidate tips is not maintained here.192*/193class BlockManager194{195friend Chainstate;196friend ChainstateManager;198private:199const CChainParams& GetParams() const { return m_opts.chainparams; }200const Consensus::Params& GetConsensus() const { return m_opts.chainparams.GetConsensus(); }201/**202* Load the blocktree off disk and into memory. Populate certain metadata203* per index entry (nStatus, nChainWork, nTimeMax, etc.) as well as peripheral204* collections like m_dirty_blockindex.205*/206bool LoadBlockIndex(const std::optional<uint256>& snapshot_blockhash)207EXCLUSIVE_LOCKS_REQUIRED(cs_main);209/** Return false if block file or undo file flushing fails. */210[[nodiscard]] bool FlushBlockFile(int blockfile_num, bool fFinalize, bool finalize_undo) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);212/** Return false if undo file flushing fails. */213[[nodiscard]] bool FlushUndoFile(int block_file, bool finalize = false);215/**216* Helper function performing various preparations before a block can be saved to disk:217* Returns the correct position for the block to be saved, which may be in the current or a new218* block file depending on nAddSize. May flush the previous blockfile to disk if full, updates219* blockfile info, and checks if there is enough disk space to save the block.220*221* The nAddSize argument passed to this function should include not just the size of the serialized CBlock, but also the size of222* separator fields (STORAGE_HEADER_BYTES).223*/224[[nodiscard]] FlatFilePos FindNextBlockPos(unsigned int nAddSize, unsigned int nHeight, uint64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);225[[nodiscard]] bool FlushChainstateBlockFile(int tip_height) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);226[[nodiscard]] bool FindUndoPos(BlockValidationState& state, int nFile, FlatFilePos& pos, unsigned int nAddSize) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);228AutoFile OpenUndoFile(const FlatFilePos& pos, bool fReadOnly = false) const;230/* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */231void FindFilesToPruneManual(232std::set<int>& setFilesToPrune,233int nManualPruneHeight,234const Chainstate& chain);236/**237* Prune block and undo files (blk???.dat and rev???.dat) so that the disk space used is less than a user-defined target.238* The user sets the target (in MB) on the command line or in config file. This will be run on startup and whenever new239* space is allocated in a block or undo file, staying below the target. Changing back to unpruned requires a reindex240* (which in this case means the blockchain must be re-downloaded.)241*242* Pruning functions are called from FlushStateToDisk when the m_check_for_pruning flag has been set.243* Block and undo files are deleted in lock-step (when blk00003.dat is deleted, so is rev00003.dat.)244* Pruning cannot take place until the longest chain is at least a certain length (CChainParams::nPruneAfterHeight).245* Pruning will never delete a block within a defined distance (currently 288) from the active chain's tip.246* The block index is updated by unsetting HAVE_DATA and HAVE_UNDO for any blocks that were stored in the deleted files.247* A db flag records the fact that at least some block files have been pruned.248*249* @param[out] setFilesToPrune The set of file indices that can be unlinked will be returned250* @param last_prune The last height we're able to prune, according to the prune locks