mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-20 07:09:15 +01:00
refactor: Add Chainstate m_assumeutxo and m_target_utxohash members
Get rid of m_disabled/IsUsable members. Instead of marking chains disabled for different reasons, store chainstate assumeutxo status explicitly and use that information to determine how chains should be treated.
This commit is contained in:
@@ -1882,6 +1882,7 @@ Chainstate::Chainstate(
|
||||
: m_mempool(mempool),
|
||||
m_blockman(blockman),
|
||||
m_chainman(chainman),
|
||||
m_assumeutxo(from_snapshot_blockhash ? Assumeutxo::UNVALIDATED : Assumeutxo::VALIDATED),
|
||||
m_from_snapshot_blockhash(from_snapshot_blockhash) {}
|
||||
|
||||
const CBlockIndex* Chainstate::SnapshotBase() const
|
||||
@@ -3393,12 +3394,11 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr<
|
||||
// we use m_chainstate_mutex to enforce mutual exclusion so that only one caller may execute this function at a time
|
||||
LOCK(m_chainstate_mutex);
|
||||
|
||||
// Belt-and-suspenders check that we aren't attempting to advance the background
|
||||
// chainstate past the snapshot base block.
|
||||
if (WITH_LOCK(::cs_main, return m_disabled)) {
|
||||
LogError("m_disabled is set - this chainstate should not be in operation. "
|
||||
"Please report this as a bug. %s", CLIENT_BUGREPORT);
|
||||
return false;
|
||||
// Belt-and-suspenders check that we aren't attempting to advance the
|
||||
// chainstate past the target block.
|
||||
if (WITH_LOCK(::cs_main, return m_target_utxohash)) {
|
||||
LogError("%s", STR_INTERNAL_BUG("m_target_utxohash is set - this chainstate should not be in operation."));
|
||||
return Assume(false);
|
||||
}
|
||||
|
||||
CBlockIndex *pindexMostWork = nullptr;
|
||||
@@ -5609,7 +5609,7 @@ std::vector<Chainstate*> ChainstateManager::GetAll()
|
||||
std::vector<Chainstate*> out;
|
||||
|
||||
for (Chainstate* cs : {m_ibd_chainstate.get(), m_snapshot_chainstate.get()}) {
|
||||
if (this->IsUsable(cs)) out.push_back(cs);
|
||||
if (cs && cs->m_assumeutxo != Assumeutxo::INVALID && !cs->m_target_utxohash) out.push_back(cs);
|
||||
}
|
||||
|
||||
return out;
|
||||
@@ -6071,9 +6071,11 @@ SnapshotCompletionResult ChainstateManager::MaybeCompleteSnapshotValidation()
|
||||
// If a snapshot does not need to be validated...
|
||||
if (m_ibd_chainstate.get() == &this->ActiveChainstate() ||
|
||||
// Or if either chainstate is unusable...
|
||||
!this->IsUsable(m_snapshot_chainstate.get()) ||
|
||||
!this->IsUsable(m_ibd_chainstate.get()) ||
|
||||
!m_snapshot_chainstate ||
|
||||
m_snapshot_chainstate->m_assumeutxo != Assumeutxo::UNVALIDATED ||
|
||||
!m_snapshot_chainstate->m_from_snapshot_blockhash ||
|
||||
!m_ibd_chainstate ||
|
||||
m_ibd_chainstate->m_assumeutxo != Assumeutxo::VALIDATED ||
|
||||
!m_ibd_chainstate->m_chain.Tip() ||
|
||||
// Or the validated chainstate is not targeting the snapshot block...
|
||||
!m_ibd_chainstate->m_target_blockhash ||
|
||||
@@ -6112,9 +6114,7 @@ SnapshotCompletionResult ChainstateManager::MaybeCompleteSnapshotValidation()
|
||||
m_ibd_chainstate->SetTargetBlock(nullptr);
|
||||
|
||||
m_active_chainstate = m_ibd_chainstate.get();
|
||||
m_snapshot_chainstate->m_disabled = true;
|
||||
assert(!this->IsUsable(m_snapshot_chainstate.get()));
|
||||
assert(this->IsUsable(m_ibd_chainstate.get()));
|
||||
m_snapshot_chainstate->m_assumeutxo = Assumeutxo::INVALID;
|
||||
|
||||
auto rename_result = m_snapshot_chainstate->InvalidateCoinsDBOnDisk();
|
||||
if (!rename_result) {
|
||||
@@ -6131,7 +6131,6 @@ SnapshotCompletionResult ChainstateManager::MaybeCompleteSnapshotValidation()
|
||||
|
||||
assert(snapshot_base_height == curr_height);
|
||||
assert(snapshot_base_height == index_new.nHeight);
|
||||
assert(this->IsUsable(m_snapshot_chainstate.get()));
|
||||
assert(this->GetAll().size() == 2);
|
||||
|
||||
CCoinsViewDB& ibd_coins_db = m_ibd_chainstate->CoinsDB();
|
||||
@@ -6187,7 +6186,8 @@ SnapshotCompletionResult ChainstateManager::MaybeCompleteSnapshotValidation()
|
||||
LogInfo("[snapshot] snapshot beginning at %s has been fully validated",
|
||||
snapshot_blockhash.ToString());
|
||||
|
||||
m_ibd_chainstate->m_disabled = true;
|
||||
m_snapshot_chainstate->m_assumeutxo = Assumeutxo::VALIDATED;
|
||||
m_ibd_chainstate->m_target_utxohash = AssumeutxoHash{ibd_stats.hashSerialized};
|
||||
this->MaybeRebalanceCaches();
|
||||
|
||||
return SnapshotCompletionResult::SUCCESS;
|
||||
@@ -6209,34 +6209,30 @@ bool ChainstateManager::IsSnapshotActive() const
|
||||
void ChainstateManager::MaybeRebalanceCaches()
|
||||
{
|
||||
AssertLockHeld(::cs_main);
|
||||
bool ibd_usable = this->IsUsable(m_ibd_chainstate.get());
|
||||
bool snapshot_usable = this->IsUsable(m_snapshot_chainstate.get());
|
||||
assert(ibd_usable || snapshot_usable);
|
||||
|
||||
if (ibd_usable && !snapshot_usable) {
|
||||
Chainstate& current_cs{*Assert(m_active_chainstate)};
|
||||
Chainstate* historical_cs{HistoricalChainstate()};
|
||||
if (!historical_cs && !current_cs.m_from_snapshot_blockhash) {
|
||||
// Allocate everything to the IBD chainstate. This will always happen
|
||||
// when we are not using a snapshot.
|
||||
m_ibd_chainstate->ResizeCoinsCaches(m_total_coinstip_cache, m_total_coinsdb_cache);
|
||||
}
|
||||
else if (snapshot_usable && !ibd_usable) {
|
||||
current_cs.ResizeCoinsCaches(m_total_coinstip_cache, m_total_coinsdb_cache);
|
||||
} else if (!historical_cs) {
|
||||
// If background validation has completed and snapshot is our active chain...
|
||||
LogInfo("[snapshot] allocating all cache to the snapshot chainstate");
|
||||
// Allocate everything to the snapshot chainstate.
|
||||
m_snapshot_chainstate->ResizeCoinsCaches(m_total_coinstip_cache, m_total_coinsdb_cache);
|
||||
}
|
||||
else if (ibd_usable && snapshot_usable) {
|
||||
current_cs.ResizeCoinsCaches(m_total_coinstip_cache, m_total_coinsdb_cache);
|
||||
} else {
|
||||
// If both chainstates exist, determine who needs more cache based on IBD status.
|
||||
//
|
||||
// Note: shrink caches first so that we don't inadvertently overwhelm available memory.
|
||||
if (IsInitialBlockDownload()) {
|
||||
m_ibd_chainstate->ResizeCoinsCaches(
|
||||
historical_cs->ResizeCoinsCaches(
|
||||
m_total_coinstip_cache * 0.05, m_total_coinsdb_cache * 0.05);
|
||||
m_snapshot_chainstate->ResizeCoinsCaches(
|
||||
current_cs.ResizeCoinsCaches(
|
||||
m_total_coinstip_cache * 0.95, m_total_coinsdb_cache * 0.95);
|
||||
} else {
|
||||
m_snapshot_chainstate->ResizeCoinsCaches(
|
||||
current_cs.ResizeCoinsCaches(
|
||||
m_total_coinstip_cache * 0.05, m_total_coinsdb_cache * 0.05);
|
||||
m_ibd_chainstate->ResizeCoinsCaches(
|
||||
historical_cs->ResizeCoinsCaches(
|
||||
m_total_coinstip_cache * 0.95, m_total_coinsdb_cache * 0.95);
|
||||
}
|
||||
}
|
||||
@@ -6394,12 +6390,7 @@ bool ChainstateManager::DeleteSnapshotChainstate()
|
||||
|
||||
ChainstateRole Chainstate::GetRole() const
|
||||
{
|
||||
if (m_chainman.GetAll().size() <= 1) {
|
||||
return ChainstateRole::NORMAL;
|
||||
}
|
||||
return (this != &m_chainman.ActiveChainstate()) ?
|
||||
ChainstateRole::BACKGROUND :
|
||||
ChainstateRole::ASSUMEDVALID;
|
||||
return m_target_blockhash ? ChainstateRole::BACKGROUND : m_assumeutxo == Assumeutxo::UNVALIDATED ? ChainstateRole::ASSUMEDVALID : ChainstateRole::NORMAL;
|
||||
}
|
||||
|
||||
const CBlockIndex* ChainstateManager::GetSnapshotBaseBlock() const
|
||||
@@ -6526,10 +6517,11 @@ std::pair<int, int> ChainstateManager::GetPruneRange(const Chainstate& chainstat
|
||||
}
|
||||
int prune_start{0};
|
||||
|
||||
if (this->GetAll().size() > 1 && m_snapshot_chainstate.get() == &chainstate) {
|
||||
// Leave the blocks in the background IBD chain alone if we're pruning
|
||||
// the snapshot chain.
|
||||
prune_start = *Assert(GetSnapshotBaseHeight()) + 1;
|
||||
if (chainstate.m_from_snapshot_blockhash && chainstate.m_assumeutxo != Assumeutxo::VALIDATED) {
|
||||
// Only prune blocks _after_ the snapshot if this is a snapshot chain
|
||||
// that has not been fully validated yet. The earlier blocks need to be
|
||||
// kept to validate the snapshot
|
||||
prune_start = Assert(chainstate.SnapshotBase())->nHeight + 1;
|
||||
}
|
||||
|
||||
int max_prune = std::max<int>(
|
||||
|
||||
Reference in New Issue
Block a user