mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-06-25 00:11:28 +02:00
use ChainstateManager to initialize chainstate
This allows us to easily initialize multiple chainstates on startup in future commits. It retires the g_chainstate global in lieu of g_chainman.
This commit is contained in:
parent
5b690f0aae
commit
4ae29f5f0c
187
src/init.cpp
187
src/init.cpp
@ -233,13 +233,12 @@ void Shutdown(NodeContext& node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing
|
// FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing
|
||||||
//
|
|
||||||
// g_chainstate is referenced here directly (instead of ::ChainstateActive()) because it
|
|
||||||
// may not have been initialized yet.
|
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
if (g_chainstate && g_chainstate->CanFlushToDisk()) {
|
for (CChainState* chainstate : g_chainman.GetAll()) {
|
||||||
g_chainstate->ForceFlushStateToDisk();
|
if (chainstate->CanFlushToDisk()) {
|
||||||
|
chainstate->ForceFlushStateToDisk();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,9 +262,11 @@ void Shutdown(NodeContext& node)
|
|||||||
|
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
if (g_chainstate && g_chainstate->CanFlushToDisk()) {
|
for (CChainState* chainstate : g_chainman.GetAll()) {
|
||||||
g_chainstate->ForceFlushStateToDisk();
|
if (chainstate->CanFlushToDisk()) {
|
||||||
g_chainstate->ResetCoinsViews();
|
chainstate->ForceFlushStateToDisk();
|
||||||
|
chainstate->ResetCoinsViews();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pblocktree.reset();
|
pblocktree.reset();
|
||||||
}
|
}
|
||||||
@ -1502,17 +1503,18 @@ bool AppInitMain(NodeContext& node)
|
|||||||
bool fLoaded = false;
|
bool fLoaded = false;
|
||||||
while (!fLoaded && !ShutdownRequested()) {
|
while (!fLoaded && !ShutdownRequested()) {
|
||||||
bool fReset = fReindex;
|
bool fReset = fReindex;
|
||||||
|
auto is_coinsview_empty = [&](CChainState* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
|
||||||
|
return fReset || fReindexChainState || chainstate->CoinsTip().GetBestBlock().IsNull();
|
||||||
|
};
|
||||||
std::string strLoadError;
|
std::string strLoadError;
|
||||||
|
|
||||||
uiInterface.InitMessage(_("Loading block index...").translated);
|
uiInterface.InitMessage(_("Loading block index...").translated);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
const int64_t load_block_index_start_time = GetTimeMillis();
|
const int64_t load_block_index_start_time = GetTimeMillis();
|
||||||
bool is_coinsview_empty;
|
|
||||||
try {
|
try {
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
// This statement makes ::ChainstateActive() usable.
|
g_chainman.InitializeChainstate();
|
||||||
g_chainstate = MakeUnique<CChainState>();
|
|
||||||
UnloadBlockIndex();
|
UnloadBlockIndex();
|
||||||
|
|
||||||
// new CBlockTreeDB tries to delete the existing file, which
|
// new CBlockTreeDB tries to delete the existing file, which
|
||||||
@ -1565,43 +1567,53 @@ bool AppInitMain(NodeContext& node)
|
|||||||
// At this point we're either in reindex or we've loaded a useful
|
// At this point we're either in reindex or we've loaded a useful
|
||||||
// block tree into BlockIndex()!
|
// block tree into BlockIndex()!
|
||||||
|
|
||||||
::ChainstateActive().InitCoinsDB(
|
bool failed_chainstate_init = false;
|
||||||
/* cache_size_bytes */ nCoinDBCache,
|
|
||||||
/* in_memory */ false,
|
|
||||||
/* should_wipe */ fReset || fReindexChainState);
|
|
||||||
|
|
||||||
::ChainstateActive().CoinsErrorCatcher().AddReadErrCallback([]() {
|
for (CChainState* chainstate : g_chainman.GetAll()) {
|
||||||
uiInterface.ThreadSafeMessageBox(
|
LogPrintf("Initializing chainstate %s\n", chainstate->ToString());
|
||||||
_("Error reading from database, shutting down.").translated,
|
chainstate->InitCoinsDB(
|
||||||
"", CClientUIInterface::MSG_ERROR);
|
/* cache_size_bytes */ nCoinDBCache,
|
||||||
});
|
/* in_memory */ false,
|
||||||
|
/* should_wipe */ fReset || fReindexChainState);
|
||||||
|
|
||||||
// If necessary, upgrade from older database format.
|
chainstate->CoinsErrorCatcher().AddReadErrCallback([]() {
|
||||||
// This is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
|
uiInterface.ThreadSafeMessageBox(
|
||||||
if (!::ChainstateActive().CoinsDB().Upgrade()) {
|
_("Error reading from database, shutting down.").translated,
|
||||||
strLoadError = _("Error upgrading chainstate database").translated;
|
"", CClientUIInterface::MSG_ERROR);
|
||||||
break;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// ReplayBlocks is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
|
// If necessary, upgrade from older database format.
|
||||||
if (!::ChainstateActive().ReplayBlocks(chainparams)) {
|
// This is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
|
||||||
strLoadError = _("Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.").translated;
|
if (!chainstate->CoinsDB().Upgrade()) {
|
||||||
break;
|
strLoadError = _("Error upgrading chainstate database").translated;
|
||||||
}
|
failed_chainstate_init = true;
|
||||||
|
|
||||||
// The on-disk coinsdb is now in a good state, create the cache
|
|
||||||
::ChainstateActive().InitCoinsCache();
|
|
||||||
assert(::ChainstateActive().CanFlushToDisk());
|
|
||||||
|
|
||||||
is_coinsview_empty = fReset || fReindexChainState ||
|
|
||||||
::ChainstateActive().CoinsTip().GetBestBlock().IsNull();
|
|
||||||
if (!is_coinsview_empty) {
|
|
||||||
// LoadChainTip initializes the chain based on CoinsTip()'s best block
|
|
||||||
if (!::ChainstateActive().LoadChainTip(chainparams)) {
|
|
||||||
strLoadError = _("Error initializing block database").translated;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
assert(::ChainActive().Tip() != nullptr);
|
|
||||||
|
// ReplayBlocks is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
|
||||||
|
if (!chainstate->ReplayBlocks(chainparams)) {
|
||||||
|
strLoadError = _("Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.").translated;
|
||||||
|
failed_chainstate_init = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The on-disk coinsdb is now in a good state, create the cache
|
||||||
|
chainstate->InitCoinsCache();
|
||||||
|
assert(chainstate->CanFlushToDisk());
|
||||||
|
|
||||||
|
if (!is_coinsview_empty(chainstate)) {
|
||||||
|
// LoadChainTip initializes the chain based on CoinsTip()'s best block
|
||||||
|
if (!chainstate->LoadChainTip(chainparams)) {
|
||||||
|
strLoadError = _("Error initializing block database").translated;
|
||||||
|
failed_chainstate_init = true;
|
||||||
|
break; // out of the per-chainstate loop
|
||||||
|
}
|
||||||
|
assert(chainstate->m_chain.Tip() != nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failed_chainstate_init) {
|
||||||
|
break; // out of the chainstate activation do-while
|
||||||
}
|
}
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
LogPrintf("%s\n", e.what());
|
LogPrintf("%s\n", e.what());
|
||||||
@ -1609,49 +1621,75 @@ bool AppInitMain(NodeContext& node)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fReset) {
|
bool failed_rewind{false};
|
||||||
// Note that RewindBlockIndex MUST run even if we're about to -reindex-chainstate.
|
|
||||||
// It both disconnects blocks based on ::ChainActive(), and drops block data in
|
for (CChainState* chainstate : g_chainman.GetAll()) {
|
||||||
// BlockIndex() based on lack of available witness data.
|
if (!fReset) {
|
||||||
uiInterface.InitMessage(_("Rewinding blocks...").translated);
|
// Note that RewindBlockIndex MUST run even if we're about to -reindex-chainstate.
|
||||||
if (!::ChainstateActive().RewindBlockIndex(chainparams)) {
|
// It both disconnects blocks based on the chainstate, and drops block data in
|
||||||
strLoadError = _("Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain").translated;
|
// BlockIndex() based on lack of available witness data.
|
||||||
break;
|
uiInterface.InitMessage(_("Rewinding blocks...").translated);
|
||||||
|
if (!chainstate->RewindBlockIndex(chainparams)) {
|
||||||
|
strLoadError = _(
|
||||||
|
"Unable to rewind the database to a pre-fork state. "
|
||||||
|
"You will need to redownload the blockchain").translated;
|
||||||
|
failed_rewind = true;
|
||||||
|
break; // out of the per-chainstate loop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (failed_rewind) {
|
||||||
|
break; // out of the chainstate activation do-while
|
||||||
|
}
|
||||||
|
|
||||||
|
bool failed_verification = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
if (!is_coinsview_empty) {
|
|
||||||
uiInterface.InitMessage(_("Verifying blocks...").translated);
|
|
||||||
if (fHavePruned && gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
|
|
||||||
LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks\n",
|
|
||||||
MIN_BLOCKS_TO_KEEP);
|
|
||||||
}
|
|
||||||
|
|
||||||
CBlockIndex* tip = ::ChainActive().Tip();
|
for (CChainState* chainstate : g_chainman.GetAll()) {
|
||||||
RPCNotifyBlockChange(true, tip);
|
if (!is_coinsview_empty(chainstate)) {
|
||||||
if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) {
|
uiInterface.InitMessage(_("Verifying blocks...").translated);
|
||||||
strLoadError = _("The block database contains a block which appears to be from the future. "
|
if (fHavePruned && gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
|
||||||
"This may be due to your computer's date and time being set incorrectly. "
|
LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks\n",
|
||||||
"Only rebuild the block database if you are sure that your computer's date and time are correct").translated;
|
MIN_BLOCKS_TO_KEEP);
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!CVerifyDB().VerifyDB(chainparams, &::ChainstateActive().CoinsDB(), gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL),
|
const CBlockIndex* tip = chainstate->m_chain.Tip();
|
||||||
gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) {
|
RPCNotifyBlockChange(true, tip);
|
||||||
strLoadError = _("Corrupted block database detected").translated;
|
if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) {
|
||||||
break;
|
strLoadError = _("The block database contains a block which appears to be from the future. "
|
||||||
|
"This may be due to your computer's date and time being set incorrectly. "
|
||||||
|
"Only rebuild the block database if you are sure that your computer's date and time are correct").translated;
|
||||||
|
failed_verification = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only verify the DB of the active chainstate. This is fixed in later
|
||||||
|
// work when we allow VerifyDB to be parameterized by chainstate.
|
||||||
|
if (&::ChainstateActive() == chainstate &&
|
||||||
|
!CVerifyDB().VerifyDB(
|
||||||
|
chainparams, &chainstate->CoinsDB(),
|
||||||
|
gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL),
|
||||||
|
gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) {
|
||||||
|
strLoadError = _("Corrupted block database detected").translated;
|
||||||
|
failed_verification = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
LogPrintf("%s\n", e.what());
|
LogPrintf("%s\n", e.what());
|
||||||
strLoadError = _("Error opening block database").translated;
|
strLoadError = _("Error opening block database").translated;
|
||||||
|
failed_verification = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fLoaded = true;
|
if (!failed_verification) {
|
||||||
LogPrintf(" block index %15dms\n", GetTimeMillis() - load_block_index_start_time);
|
fLoaded = true;
|
||||||
|
LogPrintf(" block index %15dms\n", GetTimeMillis() - load_block_index_start_time);
|
||||||
|
}
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
if (!fLoaded && !ShutdownRequested()) {
|
if (!fLoaded && !ShutdownRequested()) {
|
||||||
@ -1715,8 +1753,11 @@ bool AppInitMain(NodeContext& node)
|
|||||||
LogPrintf("Unsetting NODE_NETWORK on prune mode\n");
|
LogPrintf("Unsetting NODE_NETWORK on prune mode\n");
|
||||||
nLocalServices = ServiceFlags(nLocalServices & ~NODE_NETWORK);
|
nLocalServices = ServiceFlags(nLocalServices & ~NODE_NETWORK);
|
||||||
if (!fReindex) {
|
if (!fReindex) {
|
||||||
uiInterface.InitMessage(_("Pruning blockstore...").translated);
|
LOCK(cs_main);
|
||||||
::ChainstateActive().PruneAndFlush();
|
for (CChainState* chainstate : g_chainman.GetAll()) {
|
||||||
|
uiInterface.InitMessage(_("Pruning blockstore...").translated);
|
||||||
|
chainstate->PruneAndFlush();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1319,7 +1319,7 @@ static UniValue getchaintips(const JSONRPCRequest& request)
|
|||||||
/*
|
/*
|
||||||
* Idea: the set of chain tips is ::ChainActive().tip, plus orphan blocks which do not have another orphan building off of them.
|
* Idea: the set of chain tips is ::ChainActive().tip, plus orphan blocks which do not have another orphan building off of them.
|
||||||
* Algorithm:
|
* Algorithm:
|
||||||
* - Make one pass through g_blockman.m_block_index, picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers.
|
* - Make one pass through BlockIndex(), picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers.
|
||||||
* - Iterate through the orphan blocks. If the block isn't pointed to by another orphan, it is a chain tip.
|
* - Iterate through the orphan blocks. If the block isn't pointed to by another orphan, it is a chain tip.
|
||||||
* - add ::ChainActive().Tip()
|
* - add ::ChainActive().Tip()
|
||||||
*/
|
*/
|
||||||
|
@ -111,7 +111,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
|
|||||||
GetMainSignals().RegisterBackgroundSignalScheduler(*g_rpc_node->scheduler);
|
GetMainSignals().RegisterBackgroundSignalScheduler(*g_rpc_node->scheduler);
|
||||||
|
|
||||||
pblocktree.reset(new CBlockTreeDB(1 << 20, true));
|
pblocktree.reset(new CBlockTreeDB(1 << 20, true));
|
||||||
g_chainstate = MakeUnique<CChainState>();
|
g_chainman.InitializeChainstate();
|
||||||
::ChainstateActive().InitCoinsDB(
|
::ChainstateActive().InitCoinsDB(
|
||||||
/* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
|
/* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
|
||||||
assert(!::ChainstateActive().CanFlushToDisk());
|
assert(!::ChainstateActive().CanFlushToDisk());
|
||||||
@ -153,7 +153,7 @@ TestingSetup::~TestingSetup()
|
|||||||
m_node.mempool = nullptr;
|
m_node.mempool = nullptr;
|
||||||
m_node.scheduler.reset();
|
m_node.scheduler.reset();
|
||||||
UnloadBlockIndex();
|
UnloadBlockIndex();
|
||||||
g_chainstate.reset();
|
g_chainman.Reset();
|
||||||
pblocktree.reset();
|
pblocktree.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,20 +77,17 @@ bool CBlockIndexWorkComparator::operator()(const CBlockIndex *pa, const CBlockIn
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
ChainstateManager g_chainman;
|
||||||
BlockManager g_blockman;
|
|
||||||
} // anon namespace
|
|
||||||
|
|
||||||
std::unique_ptr<CChainState> g_chainstate;
|
CChainState& ChainstateActive()
|
||||||
|
{
|
||||||
CChainState& ChainstateActive() {
|
assert(g_chainman.m_active_chainstate);
|
||||||
assert(g_chainstate);
|
return *g_chainman.m_active_chainstate;
|
||||||
return *g_chainstate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CChain& ChainActive() {
|
CChain& ChainActive()
|
||||||
assert(g_chainstate);
|
{
|
||||||
return g_chainstate->m_chain;
|
return ::ChainstateActive().m_chain;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -152,8 +149,8 @@ namespace {
|
|||||||
CBlockIndex* LookupBlockIndex(const uint256& hash)
|
CBlockIndex* LookupBlockIndex(const uint256& hash)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
BlockMap::const_iterator it = g_blockman.m_block_index.find(hash);
|
BlockMap::const_iterator it = g_chainman.BlockIndex().find(hash);
|
||||||
return it == g_blockman.m_block_index.end() ? nullptr : it->second;
|
return it == g_chainman.BlockIndex().end() ? nullptr : it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator)
|
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator)
|
||||||
@ -1243,13 +1240,10 @@ void CoinsViews::InitCache()
|
|||||||
m_cacheview = MakeUnique<CCoinsViewCache>(&m_catcherview);
|
m_cacheview = MakeUnique<CCoinsViewCache>(&m_catcherview);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: for now m_blockman is set to a global, but this will be changed
|
CChainState::CChainState(BlockManager& blockman, uint256 from_snapshot_blockhash)
|
||||||
// in a future commit.
|
: m_blockman(blockman),
|
||||||
CChainState::CChainState(uint256 from_snapshot_blockhash)
|
|
||||||
: m_blockman(g_blockman),
|
|
||||||
m_from_snapshot_blockhash(from_snapshot_blockhash) {}
|
m_from_snapshot_blockhash(from_snapshot_blockhash) {}
|
||||||
|
|
||||||
|
|
||||||
void CChainState::InitCoinsDB(
|
void CChainState::InitCoinsDB(
|
||||||
size_t cache_size_bytes,
|
size_t cache_size_bytes,
|
||||||
bool in_memory,
|
bool in_memory,
|
||||||
@ -1301,7 +1295,7 @@ static CBlockIndex *pindexBestForkTip = nullptr, *pindexBestForkBase = nullptr;
|
|||||||
|
|
||||||
BlockMap& BlockIndex()
|
BlockMap& BlockIndex()
|
||||||
{
|
{
|
||||||
return g_blockman.m_block_index;
|
return g_chainman.m_blockman.m_block_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AlertNotify(const std::string& strMessage)
|
static void AlertNotify(const std::string& strMessage)
|
||||||
@ -3471,7 +3465,7 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio
|
|||||||
if (fCheckpointsEnabled) {
|
if (fCheckpointsEnabled) {
|
||||||
// Don't accept any forks from the main chain prior to last checkpoint.
|
// Don't accept any forks from the main chain prior to last checkpoint.
|
||||||
// GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our
|
// GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our
|
||||||
// g_blockman.m_block_index.
|
// BlockIndex().
|
||||||
CBlockIndex* pcheckpoint = GetLastCheckpoint(params.Checkpoints());
|
CBlockIndex* pcheckpoint = GetLastCheckpoint(params.Checkpoints());
|
||||||
if (pcheckpoint && nHeight < pcheckpoint->nHeight) {
|
if (pcheckpoint && nHeight < pcheckpoint->nHeight) {
|
||||||
LogPrintf("ERROR: %s: forked chain older than last checkpoint (height %d)\n", __func__, nHeight);
|
LogPrintf("ERROR: %s: forked chain older than last checkpoint (height %d)\n", __func__, nHeight);
|
||||||
@ -3679,7 +3673,8 @@ bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, BlockValid
|
|||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
for (const CBlockHeader& header : headers) {
|
for (const CBlockHeader& header : headers) {
|
||||||
CBlockIndex *pindex = nullptr; // Use a temp pindex instead of ppindex to avoid a const_cast
|
CBlockIndex *pindex = nullptr; // Use a temp pindex instead of ppindex to avoid a const_cast
|
||||||
bool accepted = g_blockman.AcceptBlockHeader(header, state, chainparams, &pindex);
|
bool accepted = g_chainman.m_blockman.AcceptBlockHeader(
|
||||||
|
header, state, chainparams, &pindex);
|
||||||
::ChainstateActive().CheckBlockIndex(chainparams.GetConsensus());
|
::ChainstateActive().CheckBlockIndex(chainparams.GetConsensus());
|
||||||
|
|
||||||
if (!accepted) {
|
if (!accepted) {
|
||||||
@ -3881,7 +3876,7 @@ void PruneOneBlockFile(const int fileNumber)
|
|||||||
{
|
{
|
||||||
LOCK(cs_LastBlockFile);
|
LOCK(cs_LastBlockFile);
|
||||||
|
|
||||||
for (const auto& entry : g_blockman.m_block_index) {
|
for (const auto& entry : g_chainman.BlockIndex()) {
|
||||||
CBlockIndex* pindex = entry.second;
|
CBlockIndex* pindex = entry.second;
|
||||||
if (pindex->nFile == fileNumber) {
|
if (pindex->nFile == fileNumber) {
|
||||||
pindex->nStatus &= ~BLOCK_HAVE_DATA;
|
pindex->nStatus &= ~BLOCK_HAVE_DATA;
|
||||||
@ -3895,12 +3890,12 @@ void PruneOneBlockFile(const int fileNumber)
|
|||||||
// to be downloaded again in order to consider its chain, at which
|
// to be downloaded again in order to consider its chain, at which
|
||||||
// point it would be considered as a candidate for
|
// point it would be considered as a candidate for
|
||||||
// m_blocks_unlinked or setBlockIndexCandidates.
|
// m_blocks_unlinked or setBlockIndexCandidates.
|
||||||
auto range = g_blockman.m_blocks_unlinked.equal_range(pindex->pprev);
|
auto range = g_chainman.m_blockman.m_blocks_unlinked.equal_range(pindex->pprev);
|
||||||
while (range.first != range.second) {
|
while (range.first != range.second) {
|
||||||
std::multimap<CBlockIndex *, CBlockIndex *>::iterator _it = range.first;
|
std::multimap<CBlockIndex *, CBlockIndex *>::iterator _it = range.first;
|
||||||
range.first++;
|
range.first++;
|
||||||
if (_it->second == pindex) {
|
if (_it->second == pindex) {
|
||||||
g_blockman.m_blocks_unlinked.erase(_it);
|
g_chainman.m_blockman.m_blocks_unlinked.erase(_it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4137,9 +4132,11 @@ void BlockManager::Unload() {
|
|||||||
|
|
||||||
bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||||
{
|
{
|
||||||
if (!g_blockman.LoadBlockIndex(
|
if (!g_chainman.m_blockman.LoadBlockIndex(
|
||||||
chainparams.GetConsensus(), *pblocktree, ::ChainstateActive().setBlockIndexCandidates))
|
chainparams.GetConsensus(), *pblocktree,
|
||||||
|
::ChainstateActive().setBlockIndexCandidates)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Load block file info
|
// Load block file info
|
||||||
pblocktree->ReadLastBlockFile(nLastBlockFile);
|
pblocktree->ReadLastBlockFile(nLastBlockFile);
|
||||||
@ -4161,7 +4158,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_RE
|
|||||||
// Check presence of blk files
|
// Check presence of blk files
|
||||||
LogPrintf("Checking all blk files are present...\n");
|
LogPrintf("Checking all blk files are present...\n");
|
||||||
std::set<int> setBlkDataFiles;
|
std::set<int> setBlkDataFiles;
|
||||||
for (const std::pair<const uint256, CBlockIndex*>& item : g_blockman.m_block_index)
|
for (const std::pair<const uint256, CBlockIndex*>& item : g_chainman.BlockIndex())
|
||||||
{
|
{
|
||||||
CBlockIndex* pindex = item.second;
|
CBlockIndex* pindex = item.second;
|
||||||
if (pindex->nStatus & BLOCK_HAVE_DATA) {
|
if (pindex->nStatus & BLOCK_HAVE_DATA) {
|
||||||
@ -4564,8 +4561,7 @@ void CChainState::UnloadBlockIndex() {
|
|||||||
void UnloadBlockIndex()
|
void UnloadBlockIndex()
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
::ChainActive().SetTip(nullptr);
|
g_chainman.Unload();
|
||||||
g_blockman.Unload();
|
|
||||||
pindexBestInvalid = nullptr;
|
pindexBestInvalid = nullptr;
|
||||||
pindexBestHeader = nullptr;
|
pindexBestHeader = nullptr;
|
||||||
mempool.clear();
|
mempool.clear();
|
||||||
@ -4578,8 +4574,6 @@ void UnloadBlockIndex()
|
|||||||
warningcache[b].clear();
|
warningcache[b].clear();
|
||||||
}
|
}
|
||||||
fHavePruned = false;
|
fHavePruned = false;
|
||||||
|
|
||||||
::ChainstateActive().UnloadBlockIndex();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadBlockIndex(const CChainParams& chainparams)
|
bool LoadBlockIndex(const CChainParams& chainparams)
|
||||||
@ -4589,7 +4583,7 @@ bool LoadBlockIndex(const CChainParams& chainparams)
|
|||||||
if (!fReindex) {
|
if (!fReindex) {
|
||||||
bool ret = LoadBlockIndexDB(chainparams);
|
bool ret = LoadBlockIndexDB(chainparams);
|
||||||
if (!ret) return false;
|
if (!ret) return false;
|
||||||
needs_init = g_blockman.m_block_index.empty();
|
needs_init = g_chainman.m_blockman.m_block_index.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needs_init) {
|
if (needs_init) {
|
||||||
@ -5135,10 +5129,10 @@ public:
|
|||||||
CMainCleanup() {}
|
CMainCleanup() {}
|
||||||
~CMainCleanup() {
|
~CMainCleanup() {
|
||||||
// block headers
|
// block headers
|
||||||
BlockMap::iterator it1 = g_blockman.m_block_index.begin();
|
BlockMap::iterator it1 = g_chainman.BlockIndex().begin();
|
||||||
for (; it1 != g_blockman.m_block_index.end(); it1++)
|
for (; it1 != g_chainman.BlockIndex().end(); it1++)
|
||||||
delete (*it1).second;
|
delete (*it1).second;
|
||||||
g_blockman.m_block_index.clear();
|
g_chainman.BlockIndex().clear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static CMainCleanup instance_of_cmaincleanup;
|
static CMainCleanup instance_of_cmaincleanup;
|
||||||
@ -5176,7 +5170,7 @@ CChainState& ChainstateManager::InitializeChainstate(const uint256& snapshot_blo
|
|||||||
throw std::logic_error("should not be overwriting a chainstate");
|
throw std::logic_error("should not be overwriting a chainstate");
|
||||||
}
|
}
|
||||||
|
|
||||||
to_modify.reset(new CChainState(snapshot_blockhash));
|
to_modify.reset(new CChainState(m_blockman, snapshot_blockhash));
|
||||||
|
|
||||||
// Snapshot chainstates and initial IBD chaintates always become active.
|
// Snapshot chainstates and initial IBD chaintates always become active.
|
||||||
if (is_snapshot || (!is_snapshot && !m_active_chainstate)) {
|
if (is_snapshot || (!is_snapshot && !m_active_chainstate)) {
|
||||||
@ -5220,6 +5214,8 @@ void ChainstateManager::Unload()
|
|||||||
chainstate->m_chain.SetTip(nullptr);
|
chainstate->m_chain.SetTip(nullptr);
|
||||||
chainstate->UnloadBlockIndex();
|
chainstate->UnloadBlockIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_blockman.Unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChainstateManager::Reset()
|
void ChainstateManager::Reset()
|
||||||
|
@ -592,8 +592,7 @@ private:
|
|||||||
std::unique_ptr<CoinsViews> m_coins_views;
|
std::unique_ptr<CoinsViews> m_coins_views;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CChainState(BlockManager& blockman) : m_blockman(blockman) {}
|
explicit CChainState(BlockManager& blockman, uint256 from_snapshot_blockhash = uint256());
|
||||||
explicit CChainState(uint256 from_snapshot_blockhash = uint256());
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the CoinsViews UTXO set database management data structures. The in-memory
|
* Initialize the CoinsViews UTXO set database management data structures. The in-memory
|
||||||
@ -839,9 +838,14 @@ private:
|
|||||||
bool m_snapshot_validated{false};
|
bool m_snapshot_validated{false};
|
||||||
|
|
||||||
// For access to m_active_chainstate.
|
// For access to m_active_chainstate.
|
||||||
|
friend CChainState& ChainstateActive();
|
||||||
friend CChain& ChainActive();
|
friend CChain& ChainActive();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
//! A single BlockManager instance is shared across each constructed
|
||||||
|
//! chainstate to avoid duplicating block metadata.
|
||||||
|
BlockManager m_blockman GUARDED_BY(::cs_main);
|
||||||
|
|
||||||
//! Instantiate a new chainstate and assign it based upon whether it is
|
//! Instantiate a new chainstate and assign it based upon whether it is
|
||||||
//! from a snapshot.
|
//! from a snapshot.
|
||||||
//!
|
//!
|
||||||
@ -858,6 +862,11 @@ public:
|
|||||||
int ActiveHeight() const { return ActiveChain().Height(); }
|
int ActiveHeight() const { return ActiveChain().Height(); }
|
||||||
CBlockIndex* ActiveTip() const { return ActiveChain().Tip(); }
|
CBlockIndex* ActiveTip() const { return ActiveChain().Tip(); }
|
||||||
|
|
||||||
|
BlockMap& BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
|
||||||
|
{
|
||||||
|
return m_blockman.m_block_index;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsSnapshotActive() const;
|
bool IsSnapshotActive() const;
|
||||||
|
|
||||||
Optional<uint256> SnapshotBlockhash() const;
|
Optional<uint256> SnapshotBlockhash() const;
|
||||||
@ -885,6 +894,8 @@ public:
|
|||||||
void Reset();
|
void Reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern ChainstateManager g_chainman;
|
||||||
|
|
||||||
/** @returns the most-work valid chainstate. */
|
/** @returns the most-work valid chainstate. */
|
||||||
CChainState& ChainstateActive();
|
CChainState& ChainstateActive();
|
||||||
|
|
||||||
@ -894,11 +905,6 @@ CChain& ChainActive();
|
|||||||
/** @returns the global block index map. */
|
/** @returns the global block index map. */
|
||||||
BlockMap& BlockIndex();
|
BlockMap& BlockIndex();
|
||||||
|
|
||||||
// Most often ::ChainstateActive() should be used instead of this, but some code
|
|
||||||
// may not be able to assume that this has been initialized yet and so must use it
|
|
||||||
// directly, e.g. init.cpp.
|
|
||||||
extern std::unique_ptr<CChainState> g_chainstate;
|
|
||||||
|
|
||||||
/** Global variable that points to the active block tree (protected by cs_main) */
|
/** Global variable that points to the active block tree (protected by cs_main) */
|
||||||
extern std::unique_ptr<CBlockTreeDB> pblocktree;
|
extern std::unique_ptr<CBlockTreeDB> pblocktree;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user