MCPcopy Create free account
hub / github.com/bitcoin/bitcoin / InvalidateBlock

Method InvalidateBlock

src/validation.cpp:3531–3707  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

3529}
3530
3531bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* const pindex)
3532{
3533 AssertLockNotHeld(m_chainstate_mutex);
3534 AssertLockNotHeld(::cs_main);
3535
3536 // Genesis block can't be invalidated
3537 assert(pindex);
3538 if (pindex->nHeight == 0) return false;
3539
3540 // We do not allow ActivateBestChain() to run while InvalidateBlock() is
3541 // running, as that could cause the tip to change while we disconnect
3542 // blocks.
3543 LOCK(m_chainstate_mutex);
3544
3545 // We'll be acquiring and releasing cs_main below, to allow the validation
3546 // callbacks to run. However, we should keep the block index in a
3547 // consistent state as we disconnect blocks -- in particular we need to
3548 // add equal-work blocks to setBlockIndexCandidates as we disconnect.
3549 // To avoid walking the block index repeatedly in search of candidates,
3550 // build a map once so that we can look up candidate blocks by chain
3551 // work as we go.
3552 std::multimap<const arith_uint256, CBlockIndex*> highpow_outofchain_headers;
3553
3554 {
3555 LOCK(cs_main);
3556 for (auto& entry : m_blockman.m_block_index) {
3557 CBlockIndex& candidate = entry.second;
3558 // We don't need to put anything in our active chain into the
3559 // multimap, because those candidates will be found and considered
3560 // as we disconnect.
3561 // Instead, consider only non-active-chain blocks that score
3562 // at least as good with CBlockIndexWorkComparator as the new tip.
3563 if (!m_chain.Contains(candidate) &&
3564 !CBlockIndexWorkComparator()(&candidate, pindex->pprev) &&
3565 !(candidate.nStatus & BLOCK_FAILED_VALID)) {
3566 highpow_outofchain_headers.insert({candidate.nChainWork, &candidate});
3567 }
3568 }
3569 }
3570
3571 CBlockIndex* to_mark_failed = pindex;
3572 bool pindex_was_in_chain = false;
3573 int disconnected = 0;
3574
3575 // Disconnect (descendants of) pindex, and mark them invalid.
3576 while (true) {
3577 if (m_chainman.m_interrupt) break;
3578
3579 // Make sure the queue of validation callbacks doesn't grow unboundedly.
3580 if (m_chainman.m_options.signals) LimitValidationInterfaceQueue(*m_chainman.m_options.signals);
3581
3582 LOCK(cs_main);
3583 // Lock for as long as disconnectpool is in scope to make sure MaybeUpdateMempoolForReorg is
3584 // called after DisconnectTip without unlocking in between
3585 LOCK(MempoolMutex());
3586 if (!m_chain.Contains(*pindex)) break;
3587 pindex_was_in_chain = true;
3588 CBlockIndex* const disconnected_tip{m_chain.Tip()};

Callers 4

BOOST_FIXTURE_TEST_CASEFunction · 0.80
BOOST_FIXTURE_TEST_CASEFunction · 0.80
BOOST_FIXTURE_TEST_CASEFunction · 0.80
InvalidateBlockFunction · 0.80

Calls 15

GetSynchronizationStateFunction · 0.85
lower_boundMethod · 0.80
HaveNumChainTxsMethod · 0.80
CheckBlockIndexMethod · 0.80
ContainsMethod · 0.45
insertMethod · 0.45
TipMethod · 0.45
eraseMethod · 0.45
GetAncestorMethod · 0.45

Tested by 3

BOOST_FIXTURE_TEST_CASEFunction · 0.64
BOOST_FIXTURE_TEST_CASEFunction · 0.64
BOOST_FIXTURE_TEST_CASEFunction · 0.64