In commit "init: add utxo snapshot detection" (084c8e37494c7423ea53d165cc04354117b4938c)
I think it would clarify things to only call InitializeChainstate one place and eliminate chainstate juggling inside like:
<details><summary>Diff</summary>
<p>
diff --git a/src/validation.cpp b/src/validation.cpp
index f417f82f975..38df4e94d44 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -4848,28 +4848,13 @@ std::vector<CChainState*> ChainstateManager::GetAll()
return out;
}
-CChainState& ChainstateManager::InitializeChainstate(
- CTxMemPool* mempool, const std::optional<uint256>& snapshot_blockhash)
+void ChainstateManager::InitializeChainstate(CTxMemPool* mempool)
{
AssertLockHeld(::cs_main);
- bool is_snapshot = snapshot_blockhash.has_value();
- std::unique_ptr<CChainState>& to_modify =
- is_snapshot ? m_snapshot_chainstate : m_ibd_chainstate;
-
- if (to_modify) {
- throw std::logic_error("should not be overwriting a chainstate");
- }
- to_modify.reset(new CChainState(mempool, m_blockman, *this, snapshot_blockhash));
-
- // Snapshot chainstates and initial IBD chaintates always become active.
- if (is_snapshot || (!is_snapshot && !m_active_chainstate)) {
- LogPrintf("Switching active chainstate to %s\n", to_modify->ToString());
- m_active_chainstate = to_modify.get();
- } else {
- throw std::logic_error("unexpected chainstate activation");
- }
-
- return *to_modify;
+ assert(!m_ibd_chainstate);
+ assert(!m_active_chainstate);
+ m_ibd_chainstate = std::make_unique<CChainState>(mempool, m_blockman, *this);
+ m_active_chainstate = m_ibd_chainstate.get();
}
const AssumeutxoData* ExpectedAssumeutxo(
@@ -5308,6 +5293,7 @@ ChainstateManager::~ChainstateManager()
bool ChainstateManager::DetectSnapshotChainstate(CTxMemPool* mempool)
{
+ assert(!m_snapshot_chainstate);
std::optional<fs::path> path = FindSnapshotChainstateDatadir();
if (!path) {
return false;
@@ -5318,6 +5304,8 @@ bool ChainstateManager::DetectSnapshotChainstate(CTxMemPool* mempool)
if (!base_blockhash) {
return false;
}
- this->InitializeChainstate(mempool, /*snapshot_blockhash=*/ *base_blockhash);
+ m_snapshot_chainstate = std::make_unique<CChainState>(mempool, m_blockman, *this, base_blockhash);
+ LogPrintf("Switching active chainstate to %s\n", m_snapshot_chainstate->ToString());
+ m_active_chainstate = m_snapshot_chainstate.get();
return true;
}
diff --git a/src/validation.h b/src/validation.h
index f8bdda160e5..70fb9c6d324 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -903,17 +903,10 @@ public:
//! coins databases. This will be split somehow across chainstates.
int64_t m_total_coinsdb_cache{0};
- //! Instantiate a new chainstate and assign it based upon whether it is
- //! from a snapshot.
+ //! Instantiate a new chainstate.
//!
- //! [@param](/bitcoin-bitcoin/contributor/param/)[in] mempool The mempool to pass to the chainstate
- // constructor
- //! [@param](/bitcoin-bitcoin/contributor/param/)[in] snapshot_blockhash If given, signify that this chainstate
- //! is based on a snapshot.
- CChainState& InitializeChainstate(
- CTxMemPool* mempool,
- const std::optional<uint256>& snapshot_blockhash = std::nullopt)
- LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
+ //! [@param](/bitcoin-bitcoin/contributor/param/)[in] mempool The mempool to pass to the chainstate constructor
+ void InitializeChainstate(CTxMemPool* mempool) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
//! Get all chainstates currently being used.
std::vector<CChainState*> GetAll();