validation: refactor: encapsulate Chainstate::m_target_blockhash

m_target_blockhash is paired with a mutable m_cached_target_block that
must be kept in sync whenever the hash changes.
This commit is contained in:
stickies-v
2026-09-04 02:21:57 +02:00
parent 4519933391
commit 852f201e09
2 changed files with 21 additions and 12 deletions

View File

@@ -5993,8 +5993,8 @@ SnapshotCompletionResult ChainstateManager::MaybeValidateSnapshot(Chainstate& va
validated_cs.m_assumeutxo != Assumeutxo::VALIDATED ||
!validated_cs.m_chain.Tip() ||
// Or the validated chainstate is not targeting the snapshot block...
!validated_cs.m_target_blockhash ||
*validated_cs.m_target_blockhash != *unvalidated_cs.m_from_snapshot_blockhash ||
!validated_cs.TargetBlockHash() ||
*validated_cs.TargetBlockHash() != *unvalidated_cs.m_from_snapshot_blockhash ||
// Or the validated chainstate has not reached the snapshot block yet...
!validated_cs.ReachedTarget()) {
// Then the snapshot cannot be validated and there is nothing to do.
@@ -6190,7 +6190,7 @@ Chainstate& ChainstateManager::AddChainstate(std::unique_ptr<Chainstate> chainst
Chainstate& prev_chainstate{CurrentChainstate()};
assert(prev_chainstate.m_assumeutxo == Assumeutxo::VALIDATED);
// Set target block for historical chainstate to snapshot block.
assert(!prev_chainstate.m_target_blockhash);
assert(!prev_chainstate.TargetBlockHash());
prev_chainstate.SetTargetBlockHash(*Assert(chainstate->m_from_snapshot_blockhash));
m_chainstates.push_back(std::move(chainstate));
Chainstate& curr_chainstate{CurrentChainstate()};

View File

@@ -566,6 +566,12 @@ protected:
//! Cached result of LookupBlockIndex(*m_from_snapshot_blockhash)
mutable const CBlockIndex* m_cached_snapshot_base GUARDED_BY(::cs_main){nullptr};
//! Target block for this chainstate. If this is not set, chainstate will
//! target the most-work, valid block. If this is set, ChainstateManager
//! considers this a "historical" chainstate since it will only contain old
//! blocks up to the target block, not newer blocks.
std::optional<uint256> m_target_blockhash GUARDED_BY(::cs_main);
//! Cached result of LookupBlockIndex(*m_target_blockhash)
mutable const CBlockIndex* m_cached_target_block GUARDED_BY(::cs_main){nullptr};
@@ -635,12 +641,6 @@ public:
*/
const std::optional<uint256> m_from_snapshot_blockhash;
//! Target block for this chainstate. If this is not set, chainstate will
//! target the most-work, valid block. If this is set, ChainstateManager
//! considers this a "historical" chainstate since it will only contain old
//! blocks up to the target block, not newer blocks.
std::optional<uint256> m_target_blockhash GUARDED_BY(::cs_main);
//! Hash of the UTXO set at the target block, computed when the chainstate
//! reaches the target block, and null before then.
std::optional<AssumeutxoHash> m_target_utxohash GUARDED_BY(::cs_main);
@@ -654,8 +654,17 @@ public:
//! Return target block which chainstate tip is expected to reach, if this
//! is a historic chainstate being used to validate a snapshot, or null if
//! chainstate targets the most-work block.
//! chainstate targets the most-work block. Requires the block index to be
//! loaded, so prefer TargetBlockHash() when the block itself is not needed.
const CBlockIndex* TargetBlock() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
//! Return hash of the target block, or nullopt if chainstate targets the
//! most-work block. Unlike TargetBlock(), does not require the block index
//! to be loaded.
std::optional<uint256> TargetBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
{
AssertLockHeld(::cs_main);
return m_target_blockhash;
}
//! Set target block for this chainstate. If null, chainstate will target
//! the most-work valid block. If non-null chainstate will be a historic
//! chainstate and target the specified block.
@@ -1123,7 +1132,7 @@ public:
Chainstate& CurrentChainstate() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
{
for (auto& cs : m_chainstates) {
if (cs && cs->m_assumeutxo != Assumeutxo::INVALID && !cs->m_target_blockhash) return *cs;
if (cs && cs->m_assumeutxo != Assumeutxo::INVALID && !cs->TargetBlockHash()) return *cs;
}
abort();
}
@@ -1132,7 +1141,7 @@ public:
Chainstate* HistoricalChainstate() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
{
for (auto& cs : m_chainstates) {
if (cs && cs->m_assumeutxo != Assumeutxo::INVALID && cs->m_target_blockhash && !cs->m_target_utxohash) return cs.get();
if (cs && cs->m_assumeutxo != Assumeutxo::INVALID && cs->TargetBlockHash() && !cs->m_target_utxohash) return cs.get();
}
return nullptr;
}