Skip to content

Commit c29f26b

Browse files
committed
validation: add CChainState::m_disabled and ChainMan::isUsable
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.
1 parent 5ee22cd commit c29f26b

File tree

3 files changed

+39
-17
lines changed

3 files changed

+39
-17
lines changed

doc/design/assumeutxo.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ sequentially.
107107
### Background chainstate hits snapshot base block
108108

109109
Once the tip of the background chainstate hits the base block of the snapshot
110-
chainstate, we stop use of the background chainstate by setting `m_stop_use` (not yet
110+
chainstate, we stop use of the background chainstate by setting `m_disabled` (not yet
111111
committed - see #15606), in `CompleteSnapshotValidation()`, which is checked in
112112
`ActivateBestChain()`). We hash the background chainstate's UTXO set contents and
113113
ensure it matches the compiled value in `CMainParams::m_assumeutxo_data`.
@@ -119,10 +119,10 @@ The background chainstate data lingers on disk until shutdown, when in
119119

120120
| | |
121121
| ---------- | ----------- |
122-
| number of chainstates | 2 (ibd has `m_stop_use=true`) |
122+
| number of chainstates | 2 (ibd has `m_disabled=true`) |
123123
| active chainstate | snapshot |
124124

125-
**Failure consideration:** if bitcoind unexpectedly halts after `m_stop_use` is set on
125+
**Failure consideration:** if bitcoind unexpectedly halts after `m_disabled` is set on
126126
the background chainstate but before `CompleteSnapshotValidation()` can finish, the
127127
need to complete snapshot validation will be detected on subsequent init by
128128
`ChainstateManager::CheckForUncleanShutdown()`.

src/validation.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4859,12 +4859,8 @@ std::vector<Chainstate*> ChainstateManager::GetAll()
48594859
LOCK(::cs_main);
48604860
std::vector<Chainstate*> out;
48614861

4862-
if (!IsSnapshotValidated() && m_ibd_chainstate) {
4863-
out.push_back(m_ibd_chainstate.get());
4864-
}
4865-
4866-
if (m_snapshot_chainstate) {
4867-
out.push_back(m_snapshot_chainstate.get());
4862+
for (Chainstate* cs : {m_ibd_chainstate.get(), m_snapshot_chainstate.get()}) {
4863+
if (this->IsUsable(cs)) out.push_back(cs);
48684864
}
48694865

48704866
return out;
@@ -5263,17 +5259,22 @@ bool ChainstateManager::IsSnapshotActive() const
52635259
void ChainstateManager::MaybeRebalanceCaches()
52645260
{
52655261
AssertLockHeld(::cs_main);
5266-
if (m_ibd_chainstate && !m_snapshot_chainstate) {
5262+
bool ibd_usable = this->IsUsable(m_ibd_chainstate.get());
5263+
bool snapshot_usable = this->IsUsable(m_snapshot_chainstate.get());
5264+
assert(ibd_usable || snapshot_usable);
5265+
5266+
if (ibd_usable && !snapshot_usable) {
52675267
LogPrintf("[snapshot] allocating all cache to the IBD chainstate\n");
52685268
// Allocate everything to the IBD chainstate.
52695269
m_ibd_chainstate->ResizeCoinsCaches(m_total_coinstip_cache, m_total_coinsdb_cache);
52705270
}
5271-
else if (m_snapshot_chainstate && !m_ibd_chainstate) {
5271+
else if (snapshot_usable && !ibd_usable) {
5272+
// If background validation has completed and snapshot is our active chain...
52725273
LogPrintf("[snapshot] allocating all cache to the snapshot chainstate\n");
52735274
// Allocate everything to the snapshot chainstate.
52745275
m_snapshot_chainstate->ResizeCoinsCaches(m_total_coinstip_cache, m_total_coinsdb_cache);
52755276
}
5276-
else if (m_ibd_chainstate && m_snapshot_chainstate) {
5277+
else if (ibd_usable && snapshot_usable) {
52775278
// If both chainstates exist, determine who needs more cache based on IBD status.
52785279
//
52795280
// Note: shrink caches first so that we don't inadvertently overwhelm available memory.

src/validation.h

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,19 @@ class Chainstate
473473
//! Manages the UTXO set, which is a reflection of the contents of `m_chain`.
474474
std::unique_ptr<CoinsViews> m_coins_views;
475475

476+
//! This toggle exists for use when doing background validation for UTXO
477+
//! snapshots.
478+
//!
479+
//! In the expected case, it is set once the background validation chain reaches the
480+
//! same height as the base of the snapshot and its UTXO set is found to hash to
481+
//! the expected assumeutxo value. It signals that we should no longer connect
482+
//! blocks to the background chainstate. When set on the background validation
483+
//! chainstate, it signifies that we have fully validated the snapshot chainstate.
484+
//!
485+
//! In the unlikely case that the snapshot chainstate is found to be invalid, this
486+
//! is set to true on the snapshot chainstate.
487+
bool m_disabled GUARDED_BY(::cs_main) {false};
488+
476489
public:
477490
//! Reference to a BlockManager instance which itself is shared across all
478491
//! Chainstate instances.
@@ -840,10 +853,6 @@ class ChainstateManager
840853
//! that call.
841854
Chainstate* m_active_chainstate GUARDED_BY(::cs_main) {nullptr};
842855

843-
//! If true, the assumed-valid chainstate has been fully validated
844-
//! by the background validation chainstate.
845-
bool m_snapshot_validated GUARDED_BY(::cs_main){false};
846-
847856
CBlockIndex* m_best_invalid GUARDED_BY(::cs_main){nullptr};
848857

849858
//! Internal helper for ActivateSnapshot().
@@ -876,6 +885,15 @@ class ChainstateManager
876885
//! nullopt.
877886
std::optional<int> GetSnapshotBaseHeight() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
878887

888+
//! Return true if a chainstate is considered usable.
889+
//!
890+
//! This is false when a background validation chainstate has completed its
891+
//! validation of an assumed-valid chainstate, or when a snapshot
892+
//! chainstate has been found to be invalid.
893+
bool IsUsable(const Chainstate* const cs) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
894+
return cs && !cs->m_disabled;
895+
}
896+
879897
public:
880898
using Options = kernel::ChainstateManagerOpts;
881899

@@ -987,7 +1005,10 @@ class ChainstateManager
9871005
std::optional<uint256> SnapshotBlockhash() const;
9881006

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

9921013
/**
9931014
* Process an incoming block. This only returns after the best known valid

0 commit comments

Comments
 (0)