LCOV - code coverage report
Current view: top level - src/index - base.h (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 0 5 0.0 %
Date: 2023-09-26 12:08:55 Functions: 0 7 0.0 %

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

Generated by: LCOV version 1.14