mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-21 07:39:08 +01:00
Merge bitcoin/bitcoin#30479: validation: Add eligible ancestors of reconsidered block to setBlockIndexCandidates
8cc3ac6c23validation: Don't use IsValid() to filter for invalid blocks (Martin Zumsande)86d98b94e5test: verify that ancestors of a reconsidered block can become the chain tip (stratospher)3c39a55e64validation: Add ancestors of reconsiderblock to setBlockIndexCandidates (Martin Zumsande) Pull request description: When we call `reconsiderblock` for some block, `Chainstate::ResetBlockFailureFlags` puts the descendants of that block into `setBlockIndexCandidates` (if they meet the criteria, i.e. have more work than the tip etc.), but never put any ancestors into the set even though we do clear their failure flags. I think that this is wrong, because `setBlockIndexCandidates` should always contain all eligible indexes that have at least as much work as the current tip, which can include ancestors of the reconsidered block. This is being checked by `CheckBlockIndex()`, which could fail if it was invoked after `ActivateBestChain` connects a block and releases `cs_main`: ``` diff diff --git a/src/validation.cpp b/src/validation.cpp index 7b04bd9a5b..ff0c3c9f58 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3551,6 +3551,7 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr< } } // When we reach this point, we switched to a new tip (stored in pindexNewTip). + m_chainman.CheckBlockIndex(); if (exited_ibd) { // If a background chainstate is in use, we may need to rebalance our ``` makes `rpc_invalidateblock.py` fail on master. Even though we don't currently have a `CheckBlockIndex()` in that place, after `cs_main` is released other threads could invoke it, which is happening in the rare failures of #16444 where an invalid header received from another peer could trigger a `CheckBlockIndex()` call that would fail. Fix this by adding eligible ancestors to `setBlockIndexCandidates` in `Chainstate::ResetBlockFailureFlags` (also simplifying that function a bit). Fixes #16444 ACKs for top commit: achow101: ACK8cc3ac6c23TheCharlatan: Re-ACK8cc3ac6c23stratospher: reACK8cc3ac6. Tree-SHA512: 53f27591916246be4093d64b86a0494e55094abd8c586026b1247e4a36747bc3d6dbe46dc26ee4a22f47b8eb0d9699d13e577dee0e7198145f3c9b11ab2a30b7
This commit is contained in:
@@ -3851,9 +3851,9 @@ void Chainstate::ResetBlockFailureFlags(CBlockIndex *pindex) {
|
||||
|
||||
int nHeight = pindex->nHeight;
|
||||
|
||||
// Remove the invalidity flag from this block and all its descendants.
|
||||
// Remove the invalidity flag from this block and all its descendants and ancestors.
|
||||
for (auto& [_, block_index] : m_blockman.m_block_index) {
|
||||
if (!block_index.IsValid() && block_index.GetAncestor(nHeight) == pindex) {
|
||||
if ((block_index.nStatus & BLOCK_FAILED_MASK) && (block_index.GetAncestor(nHeight) == pindex || pindex->GetAncestor(block_index.nHeight) == &block_index)) {
|
||||
block_index.nStatus &= ~BLOCK_FAILED_MASK;
|
||||
m_blockman.m_dirty_blockindex.insert(&block_index);
|
||||
if (block_index.IsValid(BLOCK_VALID_TRANSACTIONS) && block_index.HaveNumChainTxs() && setBlockIndexCandidates.value_comp()(m_chain.Tip(), &block_index)) {
|
||||
@@ -3865,15 +3865,6 @@ void Chainstate::ResetBlockFailureFlags(CBlockIndex *pindex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the invalidity flag from all ancestors too.
|
||||
while (pindex != nullptr) {
|
||||
if (pindex->nStatus & BLOCK_FAILED_MASK) {
|
||||
pindex->nStatus &= ~BLOCK_FAILED_MASK;
|
||||
m_blockman.m_dirty_blockindex.insert(pindex);
|
||||
}
|
||||
pindex = pindex->pprev;
|
||||
}
|
||||
}
|
||||
|
||||
void Chainstate::TryAddBlockIndexCandidate(CBlockIndex* pindex)
|
||||
|
||||
Reference in New Issue
Block a user