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) 2017-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_INDEX_BASE_H6#define BITCOIN_INDEX_BASE_H8#include <attributes.h>9#include <dbwrapper.h>10#include <interfaces/chain.h>11#include <kernel/cs_main.h>12#include <sync.h>13#include <uint256.h>14#include <util/fs.h>15#include <util/threadinterrupt.h>16#include <validationinterface.h>18#include <atomic>19#include <cstddef>20#include <memory>21#include <optional>22#include <string>23#include <thread>25class CBlock;26class CBlockIndex;27class Chainstate;29struct CBlockLocator;30struct IndexSummary {31std::string name;32bool synced{false};33int best_block_height{0};34uint256 best_block_hash;35};36namespace interfaces {37struct BlockRef;38}39namespace util {40template <unsigned int num_params>41struct ConstevalFormatString;42}44/**45* Base class for indices of blockchain data. This implements46* CValidationInterface and ensures blocks are indexed sequentially according47* to their position in the active chain.48*49* In the presence of multiple chainstates (i.e. if a UTXO snapshot is loaded),50* only the background "IBD" chainstate will be indexed to avoid building the51* index out of order. When the background chainstate completes validation, the52* index will be reinitialized and indexing will continue.53*/54class BaseIndex : public CValidationInterface55{56protected:57/**58* The database stores a block locator of the chain the database is synced to59* so that the index can efficiently determine the point it last stopped at.60* A locator is used instead of a simple hash of the chain tip because blocks61* and block index entries may not be flushed to disk until after this database62* is updated.63*/64class DB : public CDBWrapper65{66public:67DB(const fs::path& path, size_t n_cache_size,68bool f_memory = false, bool f_wipe = false, bool f_obfuscate = false, bool f_bloom = true);69virtual ~DB() = default;71/// Read block locator of the chain that the index is in sync with.72/// Note, the returned locator will be empty if no record exists.73virtual CBlockLocator ReadBestBlock() const;75/// Write block locator of the chain that the index is in sync with.76virtual void WriteBestBlock(CDBBatch& batch, const CBlockLocator& locator);77};79private:80/// Whether the index has been initialized or not.81std::atomic<bool> m_init{false};82/// Whether the index is in sync with the main chain. The flag is flipped83/// from false to true once, after which point this starts processing84/// ValidationInterface notifications to stay in sync.85///86/// Note that this will latch to true *immediately* upon startup if87/// `m_chainstate->m_chain` is empty, which will be the case upon startup88/// with an empty datadir if, e.g., `-txindex=1` is specified.89std::atomic<bool> m_synced{false};91/// The last block in the chain that the index is in sync with.92std::atomic<const CBlockIndex*> m_best_block_index{nullptr};94std::thread m_thread_sync;95CThreadInterrupt m_interrupt;97/// Write the current index state (eg. chain block locator and subclass-specific items) to disk.98/// Will skip the commit if no block has been indexed yet or if the index's best block is99/// ahead of the chainstate's last flushed block. This avoids persisting state an unclean shutdown100/// could not roll back from. A later call commits when the chainstate has flushed far enough.101void Commit();103/// Loop over disconnected blocks and call CustomRemove.104bool Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip);106bool ProcessBlock(const CBlockIndex* pindex, const CBlock* block_data = nullptr);108virtual bool AllowPrune() const = 0;110template <typename... Args>111void FatalErrorf(util::ConstevalFormatString<sizeof...(Args)> fmt, const Args&... args);113protected:114std::unique_ptr<interfaces::Chain> m_chain;115Chainstate* m_chainstate{nullptr};116const std::string m_name;117const std::string m_thread_name;119void BlockConnected(const kernel::ChainstateRole& role, const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) override;121void ChainStateFlushed(const kernel::ChainstateRole& role, const CBlockLocator& locator) override;123/// Initialize internal state from the database and block index.124[[nodiscard]] virtual bool CustomInit(const std::optional<interfaces::BlockRef>& block) { return true; }126/// Write update index entries for a newly connected block.127[[nodiscard]] virtual bool CustomAppend(const interfaces::BlockInfo& block) { return true; }129/// Virtual method called internally by Commit that can be overridden to atomically130/// commit more index state.131virtual bool CustomCommit(CDBBatch& batch) { return true; }133/// Rewind index by one block during a chain reorg.134[[nodiscard]] virtual bool CustomRemove(const interfaces::BlockInfo& block) { return true; }136virtual DB& GetDB() const = 0;138/// Update the internal best block index as well as the prune lock.139void SetBestBlockIndex(const CBlockIndex* block);141public:142BaseIndex(std::unique_ptr<interfaces::Chain> chain, std::string name, std::string thread_name);143/// Destructor interrupts sync thread if running and blocks until it exits.144virtual ~BaseIndex();146/// Get the name of the index for display in logs.147const std::string& GetName() const LIFETIMEBOUND { return m_name; }149/// Return custom notification options for index.150[[nodiscard]] virtual interfaces::Chain::NotifyOptions CustomOptions() { return {}; }152/// Blocks the current thread until the index is caught up to the current153/// state of the block chain. This only blocks if the index has gotten in154/// sync once and only needs to process blocks in the ValidationInterface155/// queue. If the index is catching up from far behind, this method does156/// not block and immediately returns false.157bool BlockUntilSyncedToCurrentChain() const LOCKS_EXCLUDED(::cs_main);159void Interrupt();161/// Initializes the sync state and registers the instance to the162/// validation interface so that it stays in sync with blockchain updates.163[[nodiscard]] bool Init();165/// Starts the initial sync process on a background thread.166[[nodiscard]] bool StartBackgroundSync();168/// \anchor index_sync169/// Sync the index with the block index starting from the current best block.170/// Intended to be run in its own thread, m_thread_sync, and can be171/// interrupted with m_interrupt. Once the index gets in sync, the m_synced172/// flag is set and the BlockConnected ValidationInterface callback takes173/// over and the sync thread exits.174void Sync();176/// Stops the instance from staying in sync with blockchain updates.177void Stop();179/// Get a summary of the index and its state.180IndexSummary GetSummary() const;181};183#endif // BITCOIN_INDEX_BASE_H