Skip to content

Commit

Permalink
merge bitcoin#21866: Farewell, global Chainstate!
Browse files Browse the repository at this point in the history
  • Loading branch information
kwvg committed Jun 26, 2024
1 parent e3687f7 commit 0213fbe
Show file tree
Hide file tree
Showing 43 changed files with 358 additions and 457 deletions.
1 change: 0 additions & 1 deletion src/bench/duplicate_inputs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ static void DuplicateInputs(benchmark::Bench& bench)
CMutableTransaction coinbaseTx{};
CMutableTransaction naughtyTx{};

assert(std::addressof(::ChainActive()) == std::addressof(testing_setup->m_node.chainman->ActiveChain()));
CBlockIndex* pindexPrev = testing_setup->m_node.chainman->ActiveChain().Tip();
assert(pindexPrev != nullptr);
block.nBits = GetNextWorkRequired(pindexPrev, &block, chainparams.GetConsensus());
Expand Down
6 changes: 4 additions & 2 deletions src/dsnotificationinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ CDSNotificationInterface::CDSNotificationInterface(CConnman& connman,
CMasternodeSync& mn_sync,
CGovernanceManager& govman,
PeerManager& peerman,
const ChainstateManager& chainman,
const CActiveMasternodeManager* const mn_activeman,
const std::unique_ptr<CDeterministicMNManager>& dmnman,
const std::unique_ptr<LLMQContext>& llmq_ctx,
Expand All @@ -36,15 +37,16 @@ CDSNotificationInterface::CDSNotificationInterface(CConnman& connman,
m_mn_sync(mn_sync),
m_govman(govman),
m_peerman(peerman),
m_chainman(chainman),
m_mn_activeman(mn_activeman),
m_dmnman(dmnman),
m_llmq_ctx(llmq_ctx),
m_cj_ctx(cj_ctx) {}

void CDSNotificationInterface::InitializeCurrentBlockTip()
{
SynchronousUpdatedBlockTip(::ChainActive().Tip(), nullptr, ::ChainstateActive().IsInitialBlockDownload());
UpdatedBlockTip(::ChainActive().Tip(), nullptr, ::ChainstateActive().IsInitialBlockDownload());
SynchronousUpdatedBlockTip(m_chainman.ActiveChain().Tip(), nullptr, m_chainman.ActiveChainstate().IsInitialBlockDownload());
UpdatedBlockTip(m_chainman.ActiveChain().Tip(), nullptr, m_chainman.ActiveChainstate().IsInitialBlockDownload());
}

void CDSNotificationInterface::AcceptedBlockHeader(const CBlockIndex *pindexNew)
Expand Down
3 changes: 3 additions & 0 deletions src/dsnotificationinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class CActiveMasternodeManager;
class CConnman;
class CDeterministicMNManager;
class CGovernanceManager;
class ChainstateManager;
class CMasternodeSync;
class PeerManager;
struct CJContext;
Expand All @@ -23,6 +24,7 @@ class CDSNotificationInterface : public CValidationInterface
CMasternodeSync& mn_sync,
CGovernanceManager& govman,
PeerManager& peerman,
const ChainstateManager& chainman,
const CActiveMasternodeManager* const mn_activeman,
const std::unique_ptr<CDeterministicMNManager>& dmnman,
const std::unique_ptr<LLMQContext>& llmq_ctx,
Expand Down Expand Up @@ -50,6 +52,7 @@ class CDSNotificationInterface : public CValidationInterface
CMasternodeSync& m_mn_sync;
CGovernanceManager& m_govman;
PeerManager& m_peerman;
const ChainstateManager& m_chainman;
const CActiveMasternodeManager* const m_mn_activeman;
const std::unique_ptr<CDeterministicMNManager>& m_dmnman;
const std::unique_ptr<LLMQContext>& m_llmq_ctx;
Expand Down
3 changes: 1 addition & 2 deletions src/index/base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include <tinyformat.h>
#include <util/thread.h>
#include <util/translation.h>
#include <validation.h> // For g_chainman
#include <validation.h>
#include <warnings.h>

constexpr uint8_t DB_BEST_BLOCK{'B'};
Expand Down Expand Up @@ -349,7 +349,6 @@ void BaseIndex::Interrupt()

bool BaseIndex::Start(CChainState& active_chainstate)
{
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
m_chainstate = &active_chainstate;
// Need to register this ValidationInterface before running Init(), so that
// callbacks are not missed if Init sets m_synced to true.
Expand Down
44 changes: 22 additions & 22 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ void Shutdown(NodeContext& node)
ECC_Stop();
node.mempool.reset();
node.fee_estimator.reset();
node.chainman = nullptr;
node.chainman.reset();
node.scheduler.reset();

try {
Expand Down Expand Up @@ -883,12 +883,12 @@ static void StartupNotify(const ArgsManager& args)
}
#endif

static void PeriodicStats(ArgsManager& args, const CTxMemPool& mempool)
static void PeriodicStats(ArgsManager& args, ChainstateManager& chainman, const CTxMemPool& mempool)
{
assert(args.GetBoolArg("-statsenabled", DEFAULT_STATSD_ENABLE));
CCoinsStats stats{CoinStatsHashType::NONE};
::ChainstateActive().ForceFlushStateToDisk();
if (WITH_LOCK(cs_main, return GetUTXOStats(&::ChainstateActive().CoinsDB(), std::ref(g_chainman.m_blockman), stats, RpcInterruptionPoint, ::ChainActive().Tip()))) {
chainman.ActiveChainstate().ForceFlushStateToDisk();
if (WITH_LOCK(cs_main, return GetUTXOStats(&chainman.ActiveChainstate().CoinsDB(), std::ref(chainman.m_blockman), stats, RpcInterruptionPoint, chainman.ActiveChain().Tip()))) {
statsClient.gauge("utxoset.tx", stats.nTransactions, 1.0f);
statsClient.gauge("utxoset.txOutputs", stats.nTransactionOutputs, 1.0f);
statsClient.gauge("utxoset.dbSizeBytes", stats.nDiskSize, 1.0f);
Expand All @@ -902,7 +902,7 @@ static void PeriodicStats(ArgsManager& args, const CTxMemPool& mempool)
}

// short version of GetNetworkHashPS(120, -1);
CBlockIndex *tip = ::ChainActive().Tip();
CBlockIndex *tip = chainman.ActiveChain().Tip();
CBlockIndex *pindex = tip;
int64_t minTime = pindex->GetBlockTime();
int64_t maxTime = minTime;
Expand All @@ -923,7 +923,7 @@ static void PeriodicStats(ArgsManager& args, const CTxMemPool& mempool)
// No need for cs_main, we never use null tip here
statsClient.gaugeDouble("network.difficulty", (double)GetDifficulty(tip));

statsClient.gauge("transactions.txCacheSize", WITH_LOCK(cs_main, return ::ChainstateActive().CoinsTip().GetCacheSize()), 1.0f);
statsClient.gauge("transactions.txCacheSize", WITH_LOCK(cs_main, return chainman.ActiveChainstate().CoinsTip().GetCacheSize()), 1.0f);
statsClient.gauge("transactions.totalTransactions", tip->nChainTx, 1.0f);

{
Expand Down Expand Up @@ -1716,8 +1716,8 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get(), check_ratio);

assert(!node.chainman);
node.chainman = &g_chainman;
ChainstateManager& chainman = *Assert(node.chainman);
node.chainman = std::make_unique<ChainstateManager>();
ChainstateManager& chainman = *node.chainman;

assert(!node.mn_metaman);
node.mn_metaman = std::make_unique<CMasternodeMetaMan>();
Expand Down Expand Up @@ -1913,7 +1913,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
#endif

pdsNotificationInterface = new CDSNotificationInterface(
*node.connman, *node.mn_sync, *node.govman, *node.peerman, node.mn_activeman.get(), node.dmnman, node.llmq_ctx, node.cj_ctx
*node.connman, *node.mn_sync, *node.govman, *node.peerman, chainman, node.mn_activeman.get(), node.dmnman, node.llmq_ctx, node.cj_ctx
);
RegisterValidationInterface(pdsNotificationInterface);

Expand Down Expand Up @@ -2016,7 +2016,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
node.llmq_ctx = std::make_unique<LLMQContext>(chainman.ActiveChainstate(), *node.connman, *node.dmnman, *node.evodb, *node.mn_metaman, *node.mnhf_manager, *node.sporkman,
*node.mempool, node.mn_activeman.get(), *node.mn_sync, node.peerman, /* unit_tests = */ false, /* wipe = */ fReset || fReindexChainState);
// Enable CMNHFManager::{Process, Undo}Block
node.mnhf_manager->ConnectManagers(node.chainman, node.llmq_ctx->qman.get());
node.mnhf_manager->ConnectManagers(node.chainman.get(), node.llmq_ctx->qman.get());
// Have to start it early to let VerifyDB check ChainLock signatures in coinbase
node.llmq_ctx->Start();

Expand Down Expand Up @@ -2050,12 +2050,12 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
// If the loaded chain has a wrong genesis, bail out immediately
// (we're likely using a testnet datadir, or the other way around).
if (!chainman.BlockIndex().empty() &&
!g_chainman.m_blockman.LookupBlockIndex(chainparams.GetConsensus().hashGenesisBlock)) {
!chainman.m_blockman.LookupBlockIndex(chainparams.GetConsensus().hashGenesisBlock)) {
return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
}

if (!chainparams.GetConsensus().hashDevnetGenesisBlock.IsNull() && !chainman.BlockIndex().empty() &&
!g_chainman.m_blockman.LookupBlockIndex(chainparams.GetConsensus().hashDevnetGenesisBlock)) {
!chainman.m_blockman.LookupBlockIndex(chainparams.GetConsensus().hashDevnetGenesisBlock)) {
return InitError(_("Incorrect or no devnet genesis block found. Wrong datadir for devnet specified?"));
}

Expand Down Expand Up @@ -2088,7 +2088,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
// If we're not mid-reindex (based on disk + args), add a genesis block on disk
// (otherwise we use the one already on disk).
// This is called again in ThreadImport after the reindex completes.
if (!fReindex && !::ChainstateActive().LoadGenesisBlock()) {
if (!fReindex && !chainman.ActiveChainstate().LoadGenesisBlock()) {
strLoadError = _("Error initializing block database");
break;
}
Expand Down Expand Up @@ -2132,7 +2132,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
// TODO: CEvoDB instance should probably be a part of CChainState
// (for multiple chainstates to actually work in parallel)
// and not a global
if (&::ChainstateActive() == chainstate && !node.evodb->CommitRootTransaction()) {
if (&chainman.ActiveChainstate() == chainstate && !node.evodb->CommitRootTransaction()) {
strLoadError = _("Failed to commit EvoDB");
failed_chainstate_init = true;
break;
Expand Down Expand Up @@ -2210,7 +2210,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
// TODO: CEvoDB instance should probably be a part of CChainState
// (for multiple chainstates to actually work in parallel)
// and not a global
if (&::ChainstateActive() == chainstate && !node.evodb->IsEmpty()) {
if (&chainman.ActiveChainstate() == chainstate && !node.evodb->IsEmpty()) {
// EvoDB processed some blocks earlier but we have no blocks anymore, something is wrong
strLoadError = _("Error initializing block database");
failed_verification = true;
Expand Down Expand Up @@ -2271,7 +2271,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc

// ********************************************************* Step 7d: Setup other Dash services

bool fLoadCacheFiles = !(fReindex || fReindexChainState) && (::ChainActive().Tip() != nullptr);
bool fLoadCacheFiles = !(fReindex || fReindexChainState) && (chainman.ActiveChain().Tip() != nullptr);

if (!node.netfulfilledman->LoadCache(fLoadCacheFiles)) {
auto file_path = (GetDataDir() / "netfulfilled.dat").string();
Expand Down Expand Up @@ -2302,21 +2302,21 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
// ********************************************************* Step 8: start indexers
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
g_txindex = std::make_unique<TxIndex>(nTxIndexCache, false, fReindex);
if (!g_txindex->Start(::ChainstateActive())) {
if (!g_txindex->Start(chainman.ActiveChainstate())) {
return false;
}
}

for (const auto& filter_type : g_enabled_filter_types) {
InitBlockFilterIndex(filter_type, filter_index_cache, false, fReindex);
if (!GetBlockFilterIndex(filter_type)->Start(::ChainstateActive())) {
if (!GetBlockFilterIndex(filter_type)->Start(chainman.ActiveChainstate())) {
return false;
}
}

if (args.GetBoolArg("-coinstatsindex", DEFAULT_COINSTATSINDEX)) {
g_coin_stats_index = std::make_unique<CoinStatsIndex>(/* cache size */ 0, false, fReindex);
if (!g_coin_stats_index->Start(::ChainstateActive())) {
if (!g_coin_stats_index->Start(chainman.ActiveChainstate())) {
return false;
}
}
Expand Down Expand Up @@ -2383,7 +2383,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc

if (args.GetBoolArg("-statsenabled", DEFAULT_STATSD_ENABLE)) {
int nStatsPeriod = std::min(std::max((int)args.GetArg("-statsperiod", DEFAULT_STATSD_PERIOD), MIN_STATSD_PERIOD), MAX_STATSD_PERIOD);
node.scheduler->scheduleEvery(std::bind(&PeriodicStats, std::ref(*node.args), std::cref(*node.mempool)), std::chrono::seconds{nStatsPeriod});
node.scheduler->scheduleEvery(std::bind(&PeriodicStats, std::ref(*node.args), std::ref(chainman), std::cref(*node.mempool)), std::chrono::seconds{nStatsPeriod});
}

// ********************************************************* Step 11: import blocks
Expand All @@ -2400,7 +2400,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
// Either install a handler to notify us when genesis activates, or set fHaveGenesis directly.
// No locking, as this happens before any background thread is started.
boost::signals2::connection block_notify_genesis_wait_connection;
if (::ChainActive().Tip() == nullptr) {
if (chainman.ActiveChain().Tip() == nullptr) {
block_notify_genesis_wait_connection = uiInterface.NotifyBlockTip_connect(std::bind(BlockNotifyGenesisWait, std::placeholders::_2));
} else {
fHaveGenesis = true;
Expand Down Expand Up @@ -2476,7 +2476,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
tip_info->header_time = ::pindexBestHeader->GetBlockTime();
}
}
LogPrintf("::ChainActive().Height() = %d\n", chain_active_height);
LogPrintf("nBestHeight = %d\n", chain_active_height);
if (node.peerman) node.peerman->SetBestHeight(chain_active_height);

// Map ports with UPnP or NAT-PMP.
Expand Down
2 changes: 0 additions & 2 deletions src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
pblocktemplate->vTxSigOps.push_back(-1); // updated at end

LOCK2(cs_main, m_mempool.cs);
assert(std::addressof(*::ChainActive().Tip()) == std::addressof(*m_chainstate.m_chain.Tip()));
CBlockIndex* pindexPrev = m_chainstate.m_chain.Tip();
assert(pindexPrev != nullptr);
nHeight = pindexPrev->nHeight + 1;
Expand Down Expand Up @@ -265,7 +264,6 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(*pblock->vtx[0]);

BlockValidationState state;
assert(std::addressof(::ChainstateActive()) == std::addressof(m_chainstate));
if (!TestBlockValidity(state, m_clhandler, m_evoDb, chainparams, m_chainstate, *pblock, pindexPrev, false, false)) {
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, state.ToString()));
}
Expand Down
1 change: 0 additions & 1 deletion src/net_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1899,7 +1899,6 @@ PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& conn
m_mn_activeman(mn_activeman),
m_ignore_incoming_txs(ignore_incoming_txs)
{
assert(std::addressof(g_chainman) == std::addressof(m_chainman));
// Stale tip checking and peer eviction are on two different timers, but we
// don't want them to get out of sync due to drift in the scheduler, so we
// combine them in one function and schedule at the quicker (peer-eviction)
Expand Down
2 changes: 1 addition & 1 deletion src/node/blockstorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ void ThreadImport(ChainstateManager& chainman, CDeterministicMNManager& dmnman,
}

if (mn_activeman != nullptr) {
mn_activeman->Init(::ChainActive().Tip());
mn_activeman->Init(chainman.ActiveTip());
}

g_wallet_init_interface.AutoLockMasternodeCollaterals();
Expand Down
1 change: 0 additions & 1 deletion src/node/coin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ void FindCoins(const NodeContext& node, std::map<COutPoint, Coin>& coins)
assert(node.mempool);
assert(node.chainman);
LOCK2(cs_main, node.mempool->cs);
assert(std::addressof(::ChainstateActive()) == std::addressof(node.chainman->ActiveChainstate()));
CCoinsViewCache& chain_view = node.chainman->ActiveChainstate().CoinsTip();
CCoinsViewMemPool mempool_view(&chain_view, *node.mempool);
for (auto& coin : coins) {
Expand Down
1 change: 0 additions & 1 deletion src/node/coinstats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ static bool GetUTXOStats(CCoinsView* view, BlockManager& blockman, CCoinsStats&

if (!pindex) {
LOCK(cs_main);
assert(std::addressof(g_chainman.m_blockman) == std::addressof(blockman));
pindex = blockman.LookupBlockIndex(view->GetBestBlock());
}
stats.nHeight = Assert(pindex)->nHeight;
Expand Down
1 change: 1 addition & 0 deletions src/node/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <scheduler.h>
#include <spork.h>
#include <txmempool.h>
#include <validation.h>

NodeContext::NodeContext() {}
NodeContext::~NodeContext() {}
2 changes: 1 addition & 1 deletion src/node/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ struct NodeContext {
std::unique_ptr<CTxMemPool> mempool;
std::unique_ptr<CBlockPolicyEstimator> fee_estimator;
std::unique_ptr<PeerManager> peerman;
ChainstateManager* chainman{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
std::unique_ptr<ChainstateManager> chainman;
std::unique_ptr<BanMan> banman;
ArgsManager* args{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
std::unique_ptr<interfaces::Chain> chain;
Expand Down
Loading

0 comments on commit 0213fbe

Please sign in to comment.