validation: call InvalidBlockFound also from AcceptBlock

When a block it found invalid during acceptance (but before connection)
we now mark its descendants with BLOCK_FAILED_CHILD and update
m_best_header when these things weren't done reliably before.

This does not fix a serious bug because the flags and m_best_header were being set on a best-effort basis before
and not used for anything critical.
Setting these reliably has a slight performance cost (iterating over the
entire block index) but leads to more consistency in validation and allows removing m_failed_blocks in a later commit.
This can only be triggered by providing a block with sufficient PoW
that is otherwise invalid, so it is not a DoS vector.
This commit is contained in:
Martin Zumsande
2024-11-30 23:46:10 -05:00
parent 458720e5e9
commit 15fa5b5a90

View File

@@ -4537,9 +4537,8 @@ bool ChainstateManager::AcceptBlock(const std::shared_ptr<const CBlock>& pblock,
if (!CheckBlock(block, state, params.GetConsensus()) ||
!ContextualCheckBlock(block, state, *this, pindex->pprev)) {
if (state.IsInvalid() && state.GetResult() != BlockValidationResult::BLOCK_MUTATED) {
pindex->nStatus |= BLOCK_FAILED_VALID;
m_blockman.m_dirty_blockindex.insert(pindex);
if (Assume(state.IsInvalid())) {
ActiveChainstate().InvalidBlockFound(pindex, state);
}
LogError("%s: %s\n", __func__, state.ToString());
return false;