LCOV - code coverage report
Current view: top level - src/index - base.h (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 5 9 55.6 %
Date: 2026-06-25 07:23:51 Functions: 6 14 42.9 %

          Line data    Source code
       1             : // Copyright (c) 2017-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_INDEX_BASE_H
       6             : #define BITCOIN_INDEX_BASE_H
       7             : 
       8             : #include <dbwrapper.h>
       9             : #include <tinyformat.h>
      10             : #include <util/threadinterrupt.h>
      11             : #include <validationinterface.h>
      12             : 
      13             : #include <atomic>
      14             : 
      15             : class CBlock;
      16             : class CBlockIndex;
      17             : class CChainState;
      18             : 
      19             : struct IndexSummary {
      20             :     std::string name;
      21             :     bool synced{false};
      22             :     int best_block_height{0};
      23             : };
      24             : 
      25             : /**
      26             :  * Base class for indices of blockchain data. This implements
      27             :  * CValidationInterface and ensures blocks are indexed sequentially according
      28             :  * to their position in the active chain.
      29             :  */
      30          76 : class BaseIndex : public CValidationInterface
      31             : {
      32             : protected:
      33             :     /**
      34             :      * The database stores a block locator of the chain the database is synced to
      35             :      * so that the index can efficiently determine the point it last stopped at.
      36             :      * A locator is used instead of a simple hash of the chain tip because blocks
      37             :      * and block index entries may not be flushed to disk until after this database
      38             :      * is updated.
      39             :     */
      40             :     class DB : public CDBWrapper
      41             :     {
      42             :     public:
      43             :         DB(const fs::path& path, size_t n_cache_size,
      44             :            bool f_memory = false, bool f_wipe = false, bool f_obfuscate = false);
      45             : 
      46             :         /// Read block locator of the chain that the index is in sync with.
      47             :         bool ReadBestBlock(CBlockLocator& locator) const;
      48             : 
      49             :         /// Write block locator of the chain that the index is in sync with.
      50             :         void WriteBestBlock(CDBBatch& batch, const CBlockLocator& locator);
      51             :     };
      52             : 
      53             : private:
      54             :     /// Whether the index is in sync with the main chain. The flag is flipped
      55             :     /// from false to true once, after which point this starts processing
      56             :     /// ValidationInterface notifications to stay in sync.
      57             :     ///
      58             :     /// Note that this will latch to true *immediately* upon startup if
      59             :     /// `m_chainstate->m_chain` is empty, which will be the case upon startup
      60             :     /// with an empty datadir if, e.g., `-txindex=1` is specified.
      61          76 :     std::atomic<bool> m_synced{false};
      62             : 
      63             :     /// The last block in the chain that the index is in sync with.
      64          76 :     std::atomic<const CBlockIndex*> m_best_block_index{nullptr};
      65             : 
      66             :     std::thread m_thread_sync;
      67             :     CThreadInterrupt m_interrupt;
      68             : 
      69             :     /// Sync the index with the block index starting from the current best block.
      70             :     /// Intended to be run in its own thread, m_thread_sync, and can be
      71             :     /// interrupted with m_interrupt. Once the index gets in sync, the m_synced
      72             :     /// flag is set and the BlockConnected ValidationInterface callback takes
      73             :     /// over and the sync thread exits.
      74             :     void ThreadSync();
      75             : 
      76             :     /// Write the current index state (eg. chain block locator and subclass-specific items) to disk.
      77             :     ///
      78             :     /// Recommendations for error handling:
      79             :     /// If called on a successor of the previous committed best block in the index, the index can
      80             :     /// continue processing without risk of corruption, though the index state will need to catch up
      81             :     /// from further behind on reboot. If the new state is not a successor of the previous state (due
      82             :     /// to a chain reorganization), the index must halt until Commit succeeds or else it could end up
      83             :     /// getting corrupted.
      84             :     bool Commit();
      85             : 
      86             :     virtual bool AllowPrune() const = 0;
      87             : 
      88             : protected:
      89          76 :     CChainState* m_chainstate{nullptr};
      90             : 
      91             :     void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) override;
      92             : 
      93             :     void BlockDisconnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) override;
      94             : 
      95             :     void ChainStateFlushed(const CBlockLocator& locator) override;
      96             : 
      97           3 :     const CBlockIndex* CurrentIndex() { return m_best_block_index.load(); };
      98             : 
      99             :     /// Initialize internal state from the database and block index.
     100             :     [[nodiscard]] virtual bool Init();
     101             : 
     102             :     /// Write update index entries for a newly connected block.
     103           0 :     virtual bool WriteBlock(const CBlock& block, const CBlockIndex* pindex) { return true; }
     104             : 
     105             :     /// Virtual method called internally by Commit that can be overridden to atomically
     106             :     /// commit more index state.
     107             :     virtual bool CommitInternal(CDBBatch& batch);
     108             : 
     109             :     /// Rewind index to an earlier chain tip during a chain reorg. The tip must
     110             :     /// be an ancestor of the current best block.
     111             :     virtual bool Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip);
     112             : 
     113             :     virtual DB& GetDB() const = 0;
     114             : 
     115             :     /// Get the name of the index for display in logs.
     116             :     virtual const char* GetName() const = 0;
     117             : 
     118             :     /// Trigger a fatal index error and initiate shutdown.
     119             :     static void FatalErrorImpl(const std::string& message);
     120             : 
     121             :     template <typename... Args>
     122           0 :     void FatalError(const char* fmt, const Args&... args) const
     123             :     {
     124           0 :         FatalErrorImpl(tfm::format(fmt, args...));
     125           0 :     }
     126             : 
     127             :     /// Update the internal best block index as well as the prune lock.
     128             :     void SetBestBlockIndex(const CBlockIndex* block);
     129             : 
     130             : public:
     131             :     /// Destructor interrupts sync thread if running and blocks until it exits.
     132             :     virtual ~BaseIndex();
     133             : 
     134             :     /// Blocks the current thread until the index is caught up to the current
     135             :     /// state of the block chain. This only blocks if the index has gotten in
     136             :     /// sync once and only needs to process blocks in the ValidationInterface
     137             :     /// queue. If the index is catching up from far behind, this method does
     138             :     /// not block and immediately returns false.
     139             :     bool BlockUntilSyncedToCurrentChain() const LOCKS_EXCLUDED(::cs_main);
     140             : 
     141             :     void Interrupt();
     142             : 
     143             :     /// Start initializes the sync state and registers the instance as a
     144             :     /// ValidationInterface so that it stays in sync with blockchain updates.
     145             :     [[nodiscard]] bool Start(CChainState& active_chainstate);
     146             : 
     147             :     /// Stops the instance from staying in sync with blockchain updates.
     148             :     void Stop();
     149             : 
     150             :     /// Get a summary of the index and its state.
     151             :     IndexSummary GetSummary() const;
     152             : };
     153             : 
     154             : #endif // BITCOIN_INDEX_BASE_H

Generated by: LCOV version 1.16