src/validation.cpp
/** Disconnect m_chain's tip.
  * After calling, the mempool will be in an inconsistent state, with
  * transactions from disconnected blocks being added to disconnectpool.  You
  * should make the mempool consistent again by calling UpdateMempoolForReorg.
  * with cs_main held.
  *
  * If disconnectpool is nullptr, then no disconnected transactions are added to
  * disconnectpool (note that the caller is responsible for mempool consistency
  * in any case).
  */


If disconnectpool is nullptr, then no disconnected transactions are added to
disconnectpool (note that the caller is responsible for mempool consistency
in any case).
If disconnectpool is nullptr then no disconnected transactions are added to disconnectpool ( note that the caller is responsible for mempool consistency in any case ) .
bool CChainState::DisconnectTip(BlockValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions* disconnectpool)
{
    AssertLockHeld(cs_main);
    AssertLockHeld(m_mempool.cs);
    CBlockIndex *pindexDelete = m_chain.Tip();
    assert(pindexDelete);
    std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
    CBlock& block = *pblock;
    if (!ReadBlockFromDisk(block, pindexDelete, chainparams.GetConsensus()))
        return error("DisconnectTip(): Failed to read block");
    int64_t nStart = GetTimeMicros();
    {
        CCoinsViewCache view(&CoinsTip());
        assert(view.GetBestBlock() == pindexDelete->GetBlockHash());
        if (DisconnectBlock(block, pindexDelete, view, nullptr) != DISCONNECT_OK)
            return error("DisconnectTip(): DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString());
        bool flushed = FlushView(&view, state, true);
        assert(flushed);
    }
    LogPrint(BCLog::BENCH, "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * MILLI);
    if (!FlushStateToDisk(chainparams, state, FlushStateMode::IF_NEEDED))
        return false;
    if (disconnectpool) {
        for (auto it = block.vtx.rbegin(); it != block.vtx.rend(); ++it) {
            disconnectpool->addTransaction(*it);
        }
        while (disconnectpool->DynamicMemoryUsage() > MAX_DISCONNECTED_TX_POOL_SIZE * 1000) {
            auto it = disconnectpool->queuedTx.get<insertion_order>().begin();
            m_mempool.removeRecursive(**it, MemPoolRemovalReason::REORG);
            disconnectpool->removeEntry(it);
        }
    }
    m_chain.SetTip(pindexDelete->pprev);
    UpdateTip(m_mempool, pindexDelete->pprev, chainparams);
    GetMainSignals().BlockDisconnected(pblock, pindexDelete);
    return true;
}
bool CChainState :: DisconnectTip ( BlockValidationState & state , const CChainParams & chainparams , DisconnectedBlockTransactions * disconnectpool ) { AssertLockHeld ( cs_main ) ; AssertLockHeld ( m_mempool . cs ) ; CBlockIndex * pindexDelete = m_chain . Tip ( ) ; assert ( pindexDelete ) ; std :: shared_ptr < CBlock > pblock = std :: make_shared < CBlock > ( ) ; CBlock & block = * pblock ; if ( ! ReadBlockFromDisk ( block , pindexDelete , chainparams . GetConsensus ( ) ) ) return error ( " " ) ; int64_t nStart = GetTimeMicros ( ) ; { CCoinsViewCache view ( & CoinsTip ( ) ) ; assert ( view . GetBestBlock ( ) == pindexDelete -> GetBlockHash ( ) ) ; if ( DisconnectBlock ( block , pindexDelete , view , nullptr ) != DISCONNECT_OK ) return error ( " " , pindexDelete -> GetBlockHash ( ) . ToString ( ) ) ; bool flushed = FlushView ( & view , state , true ) ; assert ( flushed ) ; } LogPrint ( BCLog :: BENCH , " \n " , ( GetTimeMicros ( ) - nStart ) * MILLI ) ; if ( ! FlushStateToDisk ( chainparams , state , FlushStateMode :: IF_NEEDED ) ) return false ; if ( disconnectpool ) { for ( auto it = block . vtx . rbegin ( ) ; it != block . vtx . rend ( ) ; ++ it ) { disconnectpool -> addTransaction ( * it ) ; } while ( disconnectpool -> DynamicMemoryUsage ( ) > MAX_DISCONNECTED_TX_POOL_SIZE * 1000 ) { auto it = disconnectpool -> queuedTx . get < insertion_order > ( ) . begin ( ) ; m_mempool . removeRecursive ( * * it , MemPoolRemovalReason :: REORG ) ; disconnectpool -> removeEntry ( it ) ; } } m_chain . SetTip ( pindexDelete -> pprev ) ; UpdateTip ( m_mempool , pindexDelete -> pprev , chainparams ) ; GetMainSignals ( ) . BlockDisconnected ( pblock , pindexDelete ) ; return true ; }
Disconnect m_chain's tip.
Disconnect m_chain ' s tip .
// Read block from disk. // Apply the block atomically to the chain state. // Write the chain state to disk, if necessary. // Save transactions to re-add to mempool at end of reorg // Drop the earliest entry, and remove its children from the mempool. // Let wallets know transactions went from 1-confirmed to // 0-confirmed or conflicted: