src/validation.cpp
/** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */
Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk
Store block on disk . If dbp is non - nullptr the file is known to already reside on disk
bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock)
{
    const CBlock& block = *pblock;
    if (fNewBlock) *fNewBlock = false;
    AssertLockHeld(cs_main);
    CBlockIndex *pindexDummy = nullptr;
    CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy;
    if (!AcceptBlockHeader(block, state, chainparams, &pindex))
        return false;
    bool fAlreadyHave = pindex->nStatus & BLOCK_HAVE_DATA;
    bool fHasMoreOrSameWork = (chainActive.Tip() ? pindex->nChainWork >= chainActive.Tip()->nChainWork : true);
    bool fTooFarAhead = (pindex->nHeight > int(chainActive.Height() + MIN_BLOCKS_TO_KEEP));
    if (fAlreadyHave) return true;
    if (!fRequested) {  
        if (pindex->nTx != 0) return true;    
        if (!fHasMoreOrSameWork) return true; 
        if (fTooFarAhead) return true;        
        if (pindex->nChainWork < nMinimumChainWork) return true;
    }
    if (!CheckBlock(block, state, chainparams.GetConsensus()) ||
        !ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindex->pprev)) {
        if (state.IsInvalid() && !state.CorruptionPossible()) {
            pindex->nStatus |= BLOCK_FAILED_VALID;
            setDirtyBlockIndex.insert(pindex);
        }
        return error("%s: %s", __func__, FormatStateMessage(state));
    }
    if (!IsInitialBlockDownload() && chainActive.Tip() == pindex->pprev)
        GetMainSignals().NewPoWValidBlock(pindex, pblock);
    if (fNewBlock) *fNewBlock = true;
    try {
        CDiskBlockPos blockPos = SaveBlockToDisk(block, pindex->nHeight, chainparams, dbp);
        if (blockPos.IsNull()) {
            state.Error(strprintf("%s: Failed to find position to write new block to disk", __func__));
            return false;
        }
        ReceivedBlockTransactions(block, pindex, blockPos, chainparams.GetConsensus());
    } catch (const std::runtime_error& e) {
        return AbortNode(state, std::string("System error: ") + e.what());
    }
    FlushStateToDisk(chainparams, state, FlushStateMode::NONE);
    CheckBlockIndex(chainparams.GetConsensus());
    if (!IsInitialBlockDownload())
        AcceptPendingSyncCheckpoint();
    return true;
}
bool CChainState :: AcceptBlock ( const std :: shared_ptr < const CBlock > & pblock , CValidationState & state , const CChainParams & chainparams , CBlockIndex * * ppindex , bool fRequested , const CDiskBlockPos * dbp , bool * fNewBlock ) { const CBlock & block = * pblock ; if ( fNewBlock ) * fNewBlock = false ; AssertLockHeld ( cs_main ) ; CBlockIndex * pindexDummy = nullptr ; CBlockIndex * & pindex = ppindex ? * ppindex : pindexDummy ; if ( ! AcceptBlockHeader ( block , state , chainparams , & pindex ) ) return false ; bool fAlreadyHave = pindex -> nStatus & BLOCK_HAVE_DATA ; bool fHasMoreOrSameWork = ( chainActive . Tip ( ) ? pindex -> nChainWork >= chainActive . Tip ( ) -> nChainWork : true ) ; bool fTooFarAhead = ( pindex -> nHeight > int ( chainActive . Height ( ) + MIN_BLOCKS_TO_KEEP ) ) ; if ( fAlreadyHave ) return true ; if ( ! fRequested ) { if ( pindex -> nTx != 0 ) return true ; if ( ! fHasMoreOrSameWork ) return true ; if ( fTooFarAhead ) return true ; if ( pindex -> nChainWork < nMinimumChainWork ) return true ; } if ( ! CheckBlock ( block , state , chainparams . GetConsensus ( ) ) || ! ContextualCheckBlock ( block , state , chainparams . GetConsensus ( ) , pindex -> pprev ) ) { if ( state . IsInvalid ( ) && ! state . CorruptionPossible ( ) ) { pindex -> nStatus |= BLOCK_FAILED_VALID ; setDirtyBlockIndex . insert ( pindex ) ; } return error ( " " , __func__ , FormatStateMessage ( state ) ) ; } if ( ! IsInitialBlockDownload ( ) && chainActive . Tip ( ) == pindex -> pprev ) GetMainSignals ( ) . NewPoWValidBlock ( pindex , pblock ) ; if ( fNewBlock ) * fNewBlock = true ; try { CDiskBlockPos blockPos = SaveBlockToDisk ( block , pindex -> nHeight , chainparams , dbp ) ; if ( blockPos . IsNull ( ) ) { state . Error ( strprintf ( " " , __func__ ) ) ; return false ; } ReceivedBlockTransactions ( block , pindex , blockPos , chainparams . GetConsensus ( ) ) ; } catch ( const std :: runtime_error & e ) { return AbortNode ( state , std :: string ( " " ) + e . what ( ) ) ; } FlushStateToDisk ( chainparams , state , FlushStateMode :: NONE ) ; CheckBlockIndex ( chainparams . GetConsensus ( ) ) ; if ( ! IsInitialBlockDownload ( ) ) AcceptPendingSyncCheckpoint ( ) ; return true ; }
Store block on disk.
Store block on disk .
// Try to process all requested blocks that we don't have, but only // process an unrequested block if it's new and has enough work to // advance our tip, and isn't too many blocks ahead. // Blocks that are too out-of-order needlessly limit the effectiveness of // pruning, because pruning will not delete block files that contain any // blocks which are too close in height to the tip.  Apply this test // regardless of whether pruning is enabled; it should generally be safe to // not process unrequested blocks. // TODO: Decouple this function from the block download logic by removing fRequested // This requires some new chain data structure to efficiently look up if a // block is in a chain leading to a candidate for best tip, despite not // being such a candidate itself. // TODO: deal better with return value and error conditions for duplicate // and unrequested blocks. // If we didn't ask for it: // This is a previously-processed block that was pruned // Don't process less-work chains // Block height is too high // Protect against DoS attacks from low-work chains. // If our tip is behind, a peer could try to send us // low-work blocks on a fake chain that we would never // request; don't process these. // Header is valid/has work, merkle tree and segwit merkle tree are good...RELAY NOW // (but if it does not build on our best tip, let the SendMessages loop relay it) // Write block to history file