cs_main
while leaving the block index in a state
that would fail CheckBlockIndex()
, because setBlockIndexCandidates
was not being
fully populated before releasing cs_main
.
cs_main
while leaving the block index in a state
that would fail CheckBlockIndex()
, because setBlockIndexCandidates
was not being
fully populated before releasing cs_main
.
2800+ // multimap, because those candidates will be found and considered
2801+ // as we disconnect.
2802+ // Instead, consider only non-active-chain blocks that have at
2803+ // least as much work as where we expect the new tip to end up.
2804+ if (!m_chain.Contains(candidate) &&
2805+ !CBlockIndexWorkComparator()(candidate, pindex->pprev) &&
candidate
s with equal work as pindex->pprev
(depending on nSequenceId/pointer address)?
CheckBlockIndex()
: https://github.com/bitcoin/bitcoin/blob/1985c4efda56b48f6f9c04f39d69268ee8f0b40a/src/validation.cpp#L4604
Previously, we could release cs_main while leaving the block index in a state
that would fail CheckBlockIndex, because setBlockIndexCandidates was not being
fully populated before releasing cs_main.
The only remaining case I’ve thought of that is unaddressed is if a new block were to arrive while InvalidateBlock() is running that (a) builds off a chain tip that is not being invalidated and (b) has less work than the current tip at the time the block is received, then we might still end up in a state that is temporarily inconsistent. I left in the old code that cleans up before returning as a belt-and-suspenders to ensure that this case is handled the same as before.
As this is an essentially unobservable bug (outside of travis) to begin with, I’m not sure it would be worth fixing this any further beyond documenting the situation.
ACK 2a4e60b. Tested on top of #16899. Also tested invalidateblock
with -checkblockindex=1
.
The changed code is only called by the invalidateblock
RPC.
Nit: maybe mention InvalidateBlock()
as well in validation.h comment for CCriticalSection m_cs_chainstate
.
invalidateblock
.