Skip to content

Commit

Permalink
validation: add CChainState::m_disabled and ChainMan::isUsable
Browse files Browse the repository at this point in the history
Summary:
and remove m_snapshot_validated. This state can now be inferred by the
number of isUsable chainstates.

m_disabled is used to signal that a chainstate should no longer be used
by validation logic; it is used as a sentinel when background validation
completes or if the snapshot chainstate is found to be invalid.

isUsable is a convenience method that incorporates m_disabled.

This is a partial backport of [[bitcoin/bitcoin#25740 | core#25740]]
bitcoin/bitcoin@c29f26b

Depends on D14673

Test Plan: `ninja all check-all`

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Subscribers: Fabien

Differential Revision: https://reviews.bitcoinabc.org/D14685
  • Loading branch information
jamesob authored and PiRK committed Oct 26, 2023
1 parent f6f26b3 commit b9af6d5
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 14 deletions.
23 changes: 14 additions & 9 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5770,12 +5770,11 @@ std::vector<Chainstate *> ChainstateManager::GetAll() {
LOCK(::cs_main);
std::vector<Chainstate *> out;

if (!IsSnapshotValidated() && m_ibd_chainstate) {
out.push_back(m_ibd_chainstate.get());
}

if (m_snapshot_chainstate) {
out.push_back(m_snapshot_chainstate.get());
for (Chainstate *pchainstate :
{m_ibd_chainstate.get(), m_snapshot_chainstate.get()}) {
if (this->IsUsable(pchainstate)) {
out.push_back(pchainstate);
}
}

return out;
Expand Down Expand Up @@ -6194,18 +6193,24 @@ bool ChainstateManager::IsSnapshotActive() const {
}
void ChainstateManager::MaybeRebalanceCaches() {
AssertLockHeld(::cs_main);
if (m_ibd_chainstate && !m_snapshot_chainstate) {
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) {
LogPrintf("[snapshot] allocating all cache to the IBD chainstate\n");
// Allocate everything to the IBD chainstate.
m_ibd_chainstate->ResizeCoinsCaches(m_total_coinstip_cache,
m_total_coinsdb_cache);
} else if (m_snapshot_chainstate && !m_ibd_chainstate) {
} else if (snapshot_usable && !ibd_usable) {
// If background validation has completed and snapshot is our active
// chain...
LogPrintf(
"[snapshot] allocating all cache to the snapshot chainstate\n");
// Allocate everything to the snapshot chainstate.
m_snapshot_chainstate->ResizeCoinsCaches(m_total_coinstip_cache,
m_total_coinsdb_cache);
} else if (m_ibd_chainstate && m_snapshot_chainstate) {
} else if (ibd_usable && snapshot_usable) {
// If both chainstates exist, determine who needs more cache based on
// IBD status.
//
Expand Down
31 changes: 26 additions & 5 deletions src/validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,20 @@ class Chainstate {
//! `m_chain`.
std::unique_ptr<CoinsViews> m_coins_views;

//! This toggle exists for use when doing background validation for UTXO
//! snapshots.
//!
//! In the expected case, it is set once the background validation chain
//! reaches the same height as the base of the snapshot and its UTXO set is
//! found to hash to the expected assumeutxo value. It signals that we
//! should no longer connect blocks to the background chainstate. When set
//! on the background validation chainstate, it signifies that we have fully
//! validated the snapshot chainstate.
//!
//! In the unlikely case that the snapshot chainstate is found to be
//! invalid, this is set to true on the snapshot chainstate.
bool m_disabled GUARDED_BY(::cs_main){false};

mutable Mutex cs_avalancheFinalizedBlockIndex;

/**
Expand Down Expand Up @@ -1104,10 +1118,6 @@ class ChainstateManager {
//! that call.
Chainstate *m_active_chainstate GUARDED_BY(::cs_main){nullptr};

//! If true, the assumed-valid chainstate has been fully validated
//! by the background validation chainstate.
bool m_snapshot_validated GUARDED_BY(::cs_main){false};

CBlockIndex *m_best_invalid GUARDED_BY(::cs_main){nullptr};
CBlockIndex *m_best_parked GUARDED_BY(::cs_main){nullptr};

Expand All @@ -1128,6 +1138,16 @@ class ChainstateManager {
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
friend Chainstate;

//! Return true if a chainstate is considered usable.
//!
//! This is false when a background validation chainstate has completed its
//! validation of an assumed-valid chainstate, or when a snapshot
//! chainstate has been found to be invalid.
bool IsUsable(const Chainstate *const pchainstate) const
EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
return pchainstate && !pchainstate->m_disabled;
}

public:
explicit ChainstateManager(const Config &config) : m_config{config} {}

Expand Down Expand Up @@ -1243,7 +1263,8 @@ class ChainstateManager {

//! Is there a snapshot in use and has it been fully validated?
bool IsSnapshotValidated() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
return m_snapshot_validated;
return m_snapshot_chainstate && m_ibd_chainstate &&
m_ibd_chainstate->m_disabled;
}

/**
Expand Down

0 comments on commit b9af6d5

Please sign in to comment.