Skip to content

Commit aee7cec

Browse files
committed
Merge bitcoin/bitcoin#32364: refactor: validation: mark CheckBlockIndex as const
3e6ac5b refactor: validation: mark CheckBlockIndex as const (stickies-v) 61a51ec validation: don't use GetAll() in CheckBlockIndex() (stickies-v) d05481d refactor: validation: mark SnapshotBase as const (stickies-v) Pull request description: While reviewing another PR, I [noticed](bitcoin/bitcoin#31405 (comment)) that `ChainstateManager::CheckBlockIndex()` is not a `const` method. To try and assert that this method was not causing any side-effects, I modified the method to make it `const`. It did not surface any errors, but I think it would be good to merge this change regardless, even if `CheckBlockIndex` is only used in regtest. This PR removes `CheckBlockIndex()`'s calls to non-const `ChainstateManager` methods by marking `SnapshotBase` `const` and ~inlining the `GetAll()` calls (thereby also performing consistency checks on invalid or fully validated `m_disabled==true` chainstates, as slight behaviour change), and finally marks `CheckBlockIndex()` as `const`. ACKs for top commit: achow101: ACK 3e6ac5b mzumsande: Code Review ACK 3e6ac5b TheCharlatan: ACK 3e6ac5b Tree-SHA512: 3d3cd351f5af1fab9a9498218ec62dba6e397fc7b5f4868ae0a77dc2b7c813d12c4f53f253f209101a3f6523695014e20c82dfac27cf0035611d5dd29feb80b5
2 parents ce46000 + 3e6ac5b commit aee7cec

File tree

2 files changed

+27
-26
lines changed

2 files changed

+27
-26
lines changed

src/validation.cpp

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,7 +1972,7 @@ Chainstate::Chainstate(
19721972
m_chainman(chainman),
19731973
m_from_snapshot_blockhash(from_snapshot_blockhash) {}
19741974

1975-
const CBlockIndex* Chainstate::SnapshotBase()
1975+
const CBlockIndex* Chainstate::SnapshotBase() const
19761976
{
19771977
if (!m_from_snapshot_blockhash) return nullptr;
19781978
if (!m_cached_snapshot_base) m_cached_snapshot_base = Assert(m_chainman.m_blockman.LookupBlockIndex(*m_from_snapshot_blockhash));
@@ -5220,7 +5220,7 @@ bool ChainstateManager::ShouldCheckBlockIndex() const
52205220
return true;
52215221
}
52225222

5223-
void ChainstateManager::CheckBlockIndex()
5223+
void ChainstateManager::CheckBlockIndex() const
52245224
{
52255225
if (!ShouldCheckBlockIndex()) {
52265226
return;
@@ -5245,7 +5245,7 @@ void ChainstateManager::CheckBlockIndex()
52455245
assert(m_best_header);
52465246
best_hdr_chain.SetTip(*m_best_header);
52475247

5248-
std::multimap<CBlockIndex*,CBlockIndex*> forward;
5248+
std::multimap<const CBlockIndex*, const CBlockIndex*> forward;
52495249
for (auto& [_, block_index] : m_blockman.m_block_index) {
52505250
// Only save indexes in forward that are not part of the best header chain.
52515251
if (!best_hdr_chain.Contains(&block_index)) {
@@ -5256,27 +5256,27 @@ void ChainstateManager::CheckBlockIndex()
52565256
}
52575257
assert(forward.size() + best_hdr_chain.Height() + 1 == m_blockman.m_block_index.size());
52585258

5259-
CBlockIndex* pindex = best_hdr_chain[0];
5259+
const CBlockIndex* pindex = best_hdr_chain[0];
52605260
assert(pindex);
52615261
// Iterate over the entire block tree, using depth-first search.
52625262
// Along the way, remember whether there are blocks on the path from genesis
52635263
// block being explored which are the first to have certain properties.
52645264
size_t nNodes = 0;
52655265
int nHeight = 0;
5266-
CBlockIndex* pindexFirstInvalid = nullptr; // Oldest ancestor of pindex which is invalid.
5267-
CBlockIndex* pindexFirstMissing = nullptr; // Oldest ancestor of pindex which does not have BLOCK_HAVE_DATA, since assumeutxo snapshot if used.
5268-
CBlockIndex* pindexFirstNeverProcessed = nullptr; // Oldest ancestor of pindex for which nTx == 0, since assumeutxo snapshot if used.
5269-
CBlockIndex* pindexFirstNotTreeValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_TREE (regardless of being valid or not).
5270-
CBlockIndex* pindexFirstNotTransactionsValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_TRANSACTIONS (regardless of being valid or not), since assumeutxo snapshot if used.
5271-
CBlockIndex* pindexFirstNotChainValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_CHAIN (regardless of being valid or not), since assumeutxo snapshot if used.
5272-
CBlockIndex* pindexFirstNotScriptsValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_SCRIPTS (regardless of being valid or not), since assumeutxo snapshot if used.
5266+
const CBlockIndex* pindexFirstInvalid = nullptr; // Oldest ancestor of pindex which is invalid.
5267+
const CBlockIndex* pindexFirstMissing = nullptr; // Oldest ancestor of pindex which does not have BLOCK_HAVE_DATA, since assumeutxo snapshot if used.
5268+
const CBlockIndex* pindexFirstNeverProcessed = nullptr; // Oldest ancestor of pindex for which nTx == 0, since assumeutxo snapshot if used.
5269+
const CBlockIndex* pindexFirstNotTreeValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_TREE (regardless of being valid or not).
5270+
const CBlockIndex* pindexFirstNotTransactionsValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_TRANSACTIONS (regardless of being valid or not), since assumeutxo snapshot if used.
5271+
const CBlockIndex* pindexFirstNotChainValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_CHAIN (regardless of being valid or not), since assumeutxo snapshot if used.
5272+
const CBlockIndex* pindexFirstNotScriptsValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_SCRIPTS (regardless of being valid or not), since assumeutxo snapshot if used.
52735273

52745274
// After checking an assumeutxo snapshot block, reset pindexFirst pointers
52755275
// to earlier blocks that have not been downloaded or validated yet, so
52765276
// checks for later blocks can assume the earlier blocks were validated and
52775277
// be stricter, testing for more requirements.
52785278
const CBlockIndex* snap_base{GetSnapshotBaseBlock()};
5279-
CBlockIndex *snap_first_missing{}, *snap_first_notx{}, *snap_first_notv{}, *snap_first_nocv{}, *snap_first_nosv{};
5279+
const CBlockIndex *snap_first_missing{}, *snap_first_notx{}, *snap_first_notv{}, *snap_first_nocv{}, *snap_first_nosv{};
52805280
auto snap_update_firsts = [&] {
52815281
if (pindex == snap_base) {
52825282
std::swap(snap_first_missing, pindexFirstMissing);
@@ -5317,8 +5317,8 @@ void ChainstateManager::CheckBlockIndex()
53175317
if (pindex->pprev == nullptr) {
53185318
// Genesis block checks.
53195319
assert(pindex->GetBlockHash() == GetConsensus().hashGenesisBlock); // Genesis block's hash must match.
5320-
for (auto c : GetAll()) {
5321-
if (c->m_chain.Genesis() != nullptr) {
5320+
for (const Chainstate* c : {m_ibd_chainstate.get(), m_snapshot_chainstate.get()}) {
5321+
if (c && c->m_chain.Genesis() != nullptr) {
53225322
assert(pindex == c->m_chain.Genesis()); // The chain's genesis block must be this block.
53235323
}
53245324
}
@@ -5371,8 +5371,8 @@ void ChainstateManager::CheckBlockIndex()
53715371
}
53725372

53735373
// Chainstate-specific checks on setBlockIndexCandidates
5374-
for (auto c : GetAll()) {
5375-
if (c->m_chain.Tip() == nullptr) continue;
5374+
for (const Chainstate* c : {m_ibd_chainstate.get(), m_snapshot_chainstate.get()}) {
5375+
if (!c || c->m_chain.Tip() == nullptr) continue;
53765376
// Two main factors determine whether pindex is a candidate in
53775377
// setBlockIndexCandidates:
53785378
//
@@ -5416,19 +5416,19 @@ void ChainstateManager::CheckBlockIndex()
54165416
// pindex only needs to be added if it is an ancestor of
54175417
// the snapshot that is being validated.
54185418
if (c == &ActiveChainstate() || snap_base->GetAncestor(pindex->nHeight) == pindex) {
5419-
assert(c->setBlockIndexCandidates.count(pindex));
5419+
assert(c->setBlockIndexCandidates.contains(const_cast<CBlockIndex*>(pindex)));
54205420
}
54215421
}
54225422
// If some parent is missing, then it could be that this block was in
54235423
// setBlockIndexCandidates but had to be removed because of the missing data.
54245424
// In this case it must be in m_blocks_unlinked -- see test below.
54255425
}
54265426
} else { // If this block sorts worse than the current tip or some ancestor's block has never been seen, it cannot be in setBlockIndexCandidates.
5427-
assert(c->setBlockIndexCandidates.count(pindex) == 0);
5427+
assert(!c->setBlockIndexCandidates.contains(const_cast<CBlockIndex*>(pindex)));
54285428
}
54295429
}
54305430
// Check whether this block is in m_blocks_unlinked.
5431-
std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeUnlinked = m_blockman.m_blocks_unlinked.equal_range(pindex->pprev);
5431+
auto rangeUnlinked{m_blockman.m_blocks_unlinked.equal_range(pindex->pprev)};
54325432
bool foundInUnlinked = false;
54335433
while (rangeUnlinked.first != rangeUnlinked.second) {
54345434
assert(rangeUnlinked.first->first == pindex->pprev);
@@ -5455,9 +5455,10 @@ void ChainstateManager::CheckBlockIndex()
54555455
// tip.
54565456
// So if this block is itself better than any m_chain.Tip() and it wasn't in
54575457
// setBlockIndexCandidates, then it must be in m_blocks_unlinked.
5458-
for (auto c : GetAll()) {
5458+
for (const Chainstate* c : {m_ibd_chainstate.get(), m_snapshot_chainstate.get()}) {
5459+
if (!c) continue;
54595460
const bool is_active = c == &ActiveChainstate();
5460-
if (!CBlockIndexWorkComparator()(pindex, c->m_chain.Tip()) && c->setBlockIndexCandidates.count(pindex) == 0) {
5461+
if (!CBlockIndexWorkComparator()(pindex, c->m_chain.Tip()) && !c->setBlockIndexCandidates.contains(const_cast<CBlockIndex*>(pindex))) {
54615462
if (pindexFirstInvalid == nullptr) {
54625463
if (is_active || snap_base->GetAncestor(pindex->nHeight) == pindex) {
54635464
assert(foundInUnlinked);
@@ -5472,7 +5473,7 @@ void ChainstateManager::CheckBlockIndex()
54725473

54735474
// Try descending into the first subnode. Always process forks first and the best header chain after.
54745475
snap_update_firsts();
5475-
std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> range = forward.equal_range(pindex);
5476+
auto range{forward.equal_range(pindex)};
54765477
if (range.first != range.second) {
54775478
// A subnode not part of the best header chain was found.
54785479
pindex = range.first->second;
@@ -5501,7 +5502,7 @@ void ChainstateManager::CheckBlockIndex()
55015502
// Find our parent.
55025503
CBlockIndex* pindexPar = pindex->pprev;
55035504
// Find which child we just visited.
5504-
std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangePar = forward.equal_range(pindexPar);
5505+
auto rangePar{forward.equal_range(pindexPar)};
55055506
while (rangePar.first->second != pindex) {
55065507
assert(rangePar.first != rangePar.second); // Our parent must have at least the node we're coming from as child.
55075508
rangePar.first++;

src/validation.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ class Chainstate
534534
bool m_disabled GUARDED_BY(::cs_main) {false};
535535

536536
//! Cached result of LookupBlockIndex(*m_from_snapshot_blockhash)
537-
const CBlockIndex* m_cached_snapshot_base GUARDED_BY(::cs_main) {nullptr};
537+
mutable const CBlockIndex* m_cached_snapshot_base GUARDED_BY(::cs_main){nullptr};
538538

539539
public:
540540
//! Reference to a BlockManager instance which itself is shared across all
@@ -598,7 +598,7 @@ class Chainstate
598598
*
599599
* nullptr if this chainstate was not created from a snapshot.
600600
*/
601-
const CBlockIndex* SnapshotBase() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
601+
const CBlockIndex* SnapshotBase() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
602602

603603
/**
604604
* The set of all CBlockIndex entries that have as much work as our current
@@ -984,7 +984,7 @@ class ChainstateManager
984984
*
985985
* By default this only executes fully when using the Regtest chain; see: m_options.check_block_index.
986986
*/
987-
void CheckBlockIndex();
987+
void CheckBlockIndex() const;
988988

989989
/**
990990
* Alias for ::cs_main.

0 commit comments

Comments
 (0)