#ifndef BITCOIN_INDEX_BASE_H
#define BITCOIN_INDEX_BASE_H
#include <attributes.h>
#include <dbwrapper.h>
#include <interfaces/chain.h>
#include <kernel/cs_main.h>
#include <sync.h>
#include <uint256.h>
#include <util/fs.h>
#include <util/threadinterrupt.h>
#include <validationinterface.h>
#include <atomic>
#include <cstddef>
#include <memory>
#include <optional>
#include <string>
#include <thread>
class CBlock;
class CBlockIndex;
class Chainstate;
struct CBlockLocator;
struct IndexSummary {
std::string name;
bool synced{false};
int best_block_height{0};
uint256 best_block_hash;
};
namespace interfaces {
struct BlockRef;
}
namespace util {
template <unsigned int num_params>
struct ConstevalFormatString;
}
class BaseIndex : public CValidationInterface
{
protected:
class DB : public CDBWrapper
{
public:
DB(const fs::path& path, size_t n_cache_size,
bool f_memory = false, bool f_wipe = false, bool f_obfuscate = false);
CBlockLocator ReadBestBlock() const;
void WriteBestBlock(CDBBatch& batch, const CBlockLocator& locator);
};
private:
std::atomic<bool> m_init{false};
std::atomic<bool> m_synced{false};
std::atomic<const CBlockIndex*> m_best_block_index{nullptr};
std::thread m_thread_sync;
CThreadInterrupt m_interrupt;
bool Commit();
bool Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip);
bool ProcessBlock(const CBlockIndex* pindex, const CBlock* block_data = nullptr);
virtual bool AllowPrune() const = 0;
template <typename... Args>
void FatalErrorf(util::ConstevalFormatString<sizeof...(Args)> fmt, const Args&... args);
protected:
std::unique_ptr<interfaces::Chain> m_chain;
Chainstate* m_chainstate{nullptr};
const std::string m_name;
void BlockConnected(const kernel::ChainstateRole& role, const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) override;
void ChainStateFlushed(const kernel::ChainstateRole& role, const CBlockLocator& locator) override;
[[nodiscard]] virtual bool CustomInit(const std::optional<interfaces::BlockRef>& block) { return true; }
[[nodiscard]] virtual bool CustomAppend(const interfaces::BlockInfo& block) { return true; }
virtual bool CustomCommit(CDBBatch& batch) { return true; }
[[nodiscard]] virtual bool CustomRemove(const interfaces::BlockInfo& block) { return true; }
virtual DB& GetDB() const = 0;
void SetBestBlockIndex(const CBlockIndex* block);
public:
BaseIndex(std::unique_ptr<interfaces::Chain> chain, std::string name);
virtual ~BaseIndex();
const std::string& GetName() const LIFETIMEBOUND { return m_name; }
[[nodiscard]] virtual interfaces::Chain::NotifyOptions CustomOptions() { return {}; }
bool BlockUntilSyncedToCurrentChain() const LOCKS_EXCLUDED(::cs_main);
void Interrupt();
[[nodiscard]] bool Init();
[[nodiscard]] bool StartBackgroundSync();
void Sync();
void Stop();
IndexSummary GetSummary() const;
};
#endif