#ifndef BITCOIN_INDEX_BASE_H
#define BITCOIN_INDEX_BASE_H
#include <dbwrapper.h>
#include <interfaces/chain.h>
#include <interfaces/types.h>
#include <util/string.h>
#include <util/threadinterrupt.h>
#include <validationinterface.h>
#include <string>
class CBlock;
class CBlockIndex;
class Chainstate;
class ChainstateManager;
namespace interfaces {
class Chain;
}
struct IndexSummary {
std::string name;
bool synced{false};
int best_block_height{0};
uint256 best_block_hash;
};
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);
bool ReadBestBlock(CBlockLocator& locator) 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(ChainstateRole role, const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) override;
void ChainStateFlushed(ChainstateRole role, const CBlockLocator& locator) override;
[[nodiscard]] virtual interfaces::Chain::NotifyOptions CustomOptions() { return {}; }
[[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; }
bool BlockUntilSyncedToCurrentChain() const LOCKS_EXCLUDED(::cs_main);
void Interrupt();
[[nodiscard]] bool Init();
[[nodiscard]] bool StartBackgroundSync();
void Sync();
void Stop();
IndexSummary GetSummary() const;
};
#endif