Skip to content

Commit 13abf3f

Browse files
mzumsandestratospher
authored andcommitted
validation: remove m_failed_blocks
We now mark all blocks that descend from an invalid block immediately as the invalid block is encountered (by iterating over the entire block index). As a result, m_failed_blocks, which was a heuristic to only mark descendants of failed blocks as failed when necessary, (i.e., when we have do decide whether to add another descendant or not) is no longer required.
1 parent 14250f4 commit 13abf3f

File tree

3 files changed

+1
-64
lines changed

3 files changed

+1
-64
lines changed

src/test/fuzz/block_index_tree.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ FUZZ_TARGET(block_index_tree, .init = initialize_block_index_tree)
195195
chainman.nBlockSequenceId = 1;
196196
chainman.ActiveChain().SetTip(*genesis);
197197
chainman.ActiveChainstate().setBlockIndexCandidates.clear();
198-
chainman.m_failed_blocks.clear();
198+
// chainman.m_failed_blocks.clear();
199199
blockman.m_blocks_unlinked.clear();
200200
blockman.m_have_pruned = false;
201201
blockman.CleanupForFuzzing();

src/validation.cpp

-42
Original file line numberDiff line numberDiff line change
@@ -2091,7 +2091,6 @@ void Chainstate::InvalidBlockFound(CBlockIndex* pindex, const BlockValidationSta
20912091
AssertLockHeld(cs_main);
20922092
if (state.GetResult() != BlockValidationResult::BLOCK_MUTATED) {
20932093
pindex->nStatus |= BLOCK_FAILED_VALID;
2094-
m_chainman.m_failed_blocks.insert(pindex);
20952094
m_blockman.m_dirty_blockindex.insert(pindex);
20962095
setBlockIndexCandidates.erase(pindex);
20972096
InvalidChainFound(pindex);
@@ -3821,7 +3820,6 @@ bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* pinde
38213820
auto not_inserted_yet = m_blockman.m_dirty_blockindex.insert(to_mark_failed);
38223821
assert(!not_inserted_yet.second);
38233822
setBlockIndexCandidates.erase(to_mark_failed);
3824-
m_chainman.m_failed_blocks.insert(to_mark_failed);
38253823

38263824
// If any new blocks somehow arrived while we were disconnecting
38273825
// (above), then the pre-calculation of what should go into
@@ -3888,7 +3886,6 @@ void Chainstate::ResetBlockFailureFlags(CBlockIndex *pindex) {
38883886
// Reset invalid block marker if it was pointing to one of those.
38893887
m_chainman.m_best_invalid = nullptr;
38903888
}
3891-
m_chainman.m_failed_blocks.erase(&block_index);
38923889
}
38933890
}
38943891
}
@@ -4391,45 +4388,6 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
43914388
LogDebug(BCLog::VALIDATION, "%s: Consensus::ContextualCheckBlockHeader: %s, %s\n", __func__, hash.ToString(), state.ToString());
43924389
return false;
43934390
}
4394-
4395-
/* Determine if this block descends from any block which has been found
4396-
* invalid (m_failed_blocks), then mark pindexPrev and any blocks between
4397-
* them as failed. For example:
4398-
*
4399-
* D3
4400-
* /
4401-
* B2 - C2
4402-
* / \
4403-
* A D2 - E2 - F2
4404-
* \
4405-
* B1 - C1 - D1 - E1
4406-
*
4407-
* In the case that we attempted to reorg from E1 to F2, only to find
4408-
* C2 to be invalid, we would mark D2, E2, and F2 as BLOCK_FAILED_CHILD
4409-
* but NOT D3 (it was not in any of our candidate sets at the time).
4410-
*
4411-
* In any case D3 will also be marked as BLOCK_FAILED_CHILD at restart
4412-
* in LoadBlockIndex.
4413-
*/
4414-
if (!pindexPrev->IsValid(BLOCK_VALID_SCRIPTS)) {
4415-
// The above does not mean "invalid": it checks if the previous block
4416-
// hasn't been validated up to BLOCK_VALID_SCRIPTS. This is a performance
4417-
// optimization, in the common case of adding a new block to the tip,
4418-
// we don't need to iterate over the failed blocks list.
4419-
for (const CBlockIndex* failedit : m_failed_blocks) {
4420-
if (pindexPrev->GetAncestor(failedit->nHeight) == failedit) {
4421-
assert(failedit->nStatus & BLOCK_FAILED_VALID);
4422-
CBlockIndex* invalid_walk = pindexPrev;
4423-
while (invalid_walk != failedit) {
4424-
invalid_walk->nStatus |= BLOCK_FAILED_CHILD;
4425-
m_blockman.m_dirty_blockindex.insert(invalid_walk);
4426-
invalid_walk = invalid_walk->pprev;
4427-
}
4428-
LogDebug(BCLog::VALIDATION, "header %s has prev block invalid: %s\n", hash.ToString(), block.hashPrevBlock.ToString());
4429-
return state.Invalid(BlockValidationResult::BLOCK_INVALID_PREV, "bad-prevblk");
4430-
}
4431-
}
4432-
}
44334391
}
44344392
if (!min_pow_checked) {
44354393
LogDebug(BCLog::VALIDATION, "%s: not adding new block header %s, missing anti-dos proof-of-work validation\n", __func__, hash.ToString());

src/validation.h

-21
Original file line numberDiff line numberDiff line change
@@ -1037,27 +1037,6 @@ class ChainstateManager
10371037
}
10381038

10391039

1040-
/**
1041-
* In order to efficiently track invalidity of headers, we keep the set of
1042-
* blocks which we tried to connect and found to be invalid here (ie which
1043-
* were set to BLOCK_FAILED_VALID since the last restart). We can then
1044-
* walk this set and check if a new header is a descendant of something in
1045-
* this set, preventing us from having to walk m_block_index when we try
1046-
* to connect a bad block and fail.
1047-
*
1048-
* While this is more complicated than marking everything which descends
1049-
* from an invalid block as invalid at the time we discover it to be
1050-
* invalid, doing so would require walking all of m_block_index to find all
1051-
* descendants. Since this case should be very rare, keeping track of all
1052-
* BLOCK_FAILED_VALID blocks in a set should be just fine and work just as
1053-
* well.
1054-
*
1055-
* Because we already walk m_block_index in height-order at startup, we go
1056-
* ahead and mark descendants of invalid blocks as FAILED_CHILD at that time,
1057-
* instead of putting things in this set.
1058-
*/
1059-
std::set<CBlockIndex*> m_failed_blocks;
1060-
10611040
/** Best header we've seen so far (used for getheaders queries' starting points). */
10621041
CBlockIndex* m_best_header GUARDED_BY(::cs_main){nullptr};
10631042
CBlockIndex* m_best_invalid GUARDED_BY(::cs_main){nullptr};

0 commit comments

Comments
 (0)