src/validation.cpp
bool static DisconnectTip(CValidationState& state, const CChainParams& chainparams)
{
    CBlockIndex *pindexDelete = chainActive.Tip();
    assert(pindexDelete);
    // Read block from disk.
    std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
    CBlock& block = *pblock;
    if (!ReadBlockFromDisk(block, pindexDelete, chainparams.GetConsensus()))
        return AbortNode(state, "Failed to read block");
    // Apply the block atomically to the chain state.
    int64_t nStart = GetTimeMicros();
    {
        CCoinsViewCache view(pcoinsTip);
        assert(view.GetBestBlock() == pindexDelete->GetBlockHash());
        if (DisconnectBlock(block, pindexDelete, view) != DISCONNECT_OK)
            return error("DisconnectTip() : DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString());
        assert(view.Flush());
    }
    LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
    // Write the chain state to disk, if necessary.
    if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED))
        return false;
    // Resurrect mempool transactions from the disconnected block.
    std::vector<uint256> vHashUpdate;
    for (const auto& it : block.vtx) {
        const CTransaction& tx = *it;
        // ignore validation errors in resurrected transactions
        CValidationState stateDummy;
        if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, nullptr, true)) {
            mempool.removeRecursive(tx, MemPoolRemovalReason::REORG);
        } else if (mempool.exists(tx.GetHash())) {
            vHashUpdate.push_back(tx.GetHash());
        }
    }
    // AcceptToMemoryPool/addUnchecked all assume that new mempool entries have
    // no in-mempool children, which is generally not true when adding
    // previously-confirmed transactions back to the mempool.
    // UpdateTransactionsFromBlock finds descendants of any transactions in this
    // block that were added back and cleans up the mempool state.
    mempool.UpdateTransactionsFromBlock(vHashUpdate);
    // Update chainActive and related variables.
    UpdateTip(pindexDelete->pprev, chainparams);
    // Let wallets know transactions went from 1-confirmed to
    // 0-confirmed or conflicted:
    GetMainSignals().BlockDisconnected(pblock);
    return true;
}
/** Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and manually re-limit mempool size after this, with cs_main held. */
Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and manually re-limit mempool size after this, with cs_main held.
Disconnect chainActive ' s tip . You probably want to call mempool . removeForReorg and manually re - limit mempool size after this with cs_main held .
bool static DisconnectTip(CValidationState& state, const CChainParams& chainparams)
{
    CBlockIndex *pindexDelete = chainActive.Tip();
    assert(pindexDelete);
    std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
    CBlock& block = *pblock;
    if (!ReadBlockFromDisk(block, pindexDelete, chainparams.GetConsensus()))
        return AbortNode(state, "Failed to read block");
    int64_t nStart = GetTimeMicros();
    {
        CCoinsViewCache view(pcoinsTip);
        assert(view.GetBestBlock() == pindexDelete->GetBlockHash());
        if (DisconnectBlock(block, pindexDelete, view) != DISCONNECT_OK)
            return error("DisconnectTip() : DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString());
        assert(view.Flush());
    }
    LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
    if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED))
        return false;
    std::vector<uint256> vHashUpdate;
    for (const auto& it : block.vtx) {
        const CTransaction& tx = *it;
        CValidationState stateDummy;
        if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, nullptr, true)) {
            mempool.removeRecursive(tx, MemPoolRemovalReason::REORG);
        } else if (mempool.exists(tx.GetHash())) {
            vHashUpdate.push_back(tx.GetHash());
        }
    }
    mempool.UpdateTransactionsFromBlock(vHashUpdate);
    UpdateTip(pindexDelete->pprev, chainparams);
    GetMainSignals().BlockDisconnected(pblock);
    return true;
}
bool static DisconnectTip ( CValidationState & state , const CChainParams & chainparams ) { CBlockIndex * pindexDelete = chainActive . Tip ( ) ; assert ( pindexDelete ) ; std :: shared_ptr < CBlock > pblock = std :: make_shared < CBlock > ( ) ; CBlock & block = * pblock ; if ( ! ReadBlockFromDisk ( block , pindexDelete , chainparams . GetConsensus ( ) ) ) return AbortNode ( state , " " ) ; int64_t nStart = GetTimeMicros ( ) ; { CCoinsViewCache view ( pcoinsTip ) ; assert ( view . GetBestBlock ( ) == pindexDelete -> GetBlockHash ( ) ) ; if ( DisconnectBlock ( block , pindexDelete , view ) != DISCONNECT_OK ) return error ( " " , pindexDelete -> GetBlockHash ( ) . ToString ( ) ) ; assert ( view . Flush ( ) ) ; } LogPrint ( " " , " \n " , ( GetTimeMicros ( ) - nStart ) * 0.001 ) ; if ( ! FlushStateToDisk ( state , FLUSH_STATE_IF_NEEDED ) ) return false ; std :: vector < uint256 > vHashUpdate ; for ( const auto & it : block . vtx ) { const CTransaction & tx = * it ; CValidationState stateDummy ; if ( tx . IsCoinBase ( ) || ! AcceptToMemoryPool ( mempool , stateDummy , tx , false , nullptr , true ) ) { mempool . removeRecursive ( tx , MemPoolRemovalReason :: REORG ) ; } else if ( mempool . exists ( tx . GetHash ( ) ) ) { vHashUpdate . push_back ( tx . GetHash ( ) ) ; } } mempool . UpdateTransactionsFromBlock ( vHashUpdate ) ; UpdateTip ( pindexDelete -> pprev , chainparams ) ; GetMainSignals ( ) . BlockDisconnected ( pblock ) ; return true ; }
Disconnect chainActive's tip.
Disconnect chainActive ' s tip .
// Read block from disk. // Apply the block atomically to the chain state. // Write the chain state to disk, if necessary. // Resurrect mempool transactions from the disconnected block. // ignore validation errors in resurrected transactions // AcceptToMemoryPool/addUnchecked all assume that new mempool entries have // no in-mempool children, which is generally not true when adding // previously-confirmed transactions back to the mempool. // UpdateTransactionsFromBlock finds descendants of any transactions in this // block that were added back and cleans up the mempool state. // Update chainActive and related variables. // Let wallets know transactions went from 1-confirmed to // 0-confirmed or conflicted: