@ -296,7 +296,8 @@ void FinalizeNode(NodeId nodeid) {
}
// Requires cs_main.
void MarkBlockAsReceived ( const uint256 & hash ) {
// Returns a bool indicating whether we requested this block.
bool MarkBlockAsReceived ( const uint256 & hash ) {
map < uint256 , pair < NodeId , list < QueuedBlock > : : iterator > > : : iterator itInFlight = mapBlocksInFlight . find ( hash ) ;
if ( itInFlight ! = mapBlocksInFlight . end ( ) ) {
CNodeState * state = State ( itInFlight - > second . first ) ;
@ -306,7 +307,9 @@ void MarkBlockAsReceived(const uint256& hash) {
state - > nBlocksInFlight - - ;
state - > nStallingSince = 0 ;
mapBlocksInFlight . erase ( itInFlight ) ;
return true ;
}
return false ;
}
// Requires cs_main.
@ -2826,7 +2829,7 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
return true ;
}
bool AcceptBlock ( CBlock & block , CValidationState & state , CBlockIndex * * ppindex , CDiskBlockPos * dbp )
bool AcceptBlock ( CBlock & block , CValidationState & state , CBlockIndex * * ppindex , bool fRequested , CDiskBlockPos * dbp )
{
const CChainParams & chainparams = Params ( ) ;
AssertLockHeld ( cs_main ) ;
@ -2836,13 +2839,18 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
if ( ! AcceptBlockHeader ( block , state , & pindex ) )
return false ;
// If we're pruning, ensure that we don't allow a peer to dump a copy
// of old blocks. But we might need blocks that are not on the main chain
// to handle a reorg, even if we've processed once.
if ( pindex - > nStatus & BLOCK_HAVE_DATA | | chainActive . Contains ( pindex ) ) {
// TODO: deal better with duplicate blocks.
// return state.DoS(20, error("AcceptBlock(): already have block %d %s", pindex->nHeight, pindex->GetBlockHash().ToString()), REJECT_DUPLICATE, "duplicate");
return true ;
// 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.
bool fAlreadyHave = pindex - > nStatus & BLOCK_HAVE_DATA ;
bool fHasMoreWork = ( chainActive . Tip ( ) ? pindex - > nChainWork > chainActive . Tip ( ) - > nChainWork : true ) ;
// TODO: deal better with return value and error conditions for duplicate
// and unrequested blocks.
if ( fAlreadyHave ) return true ;
if ( ! fRequested ) { // If we didn't ask for it:
if ( pindex - > nTx ! = 0 ) return true ; // This is a previously-processed block that was pruned
if ( ! fHasMoreWork ) return true ; // Don't process less-work chains
}
if ( ( ! CheckBlock ( block , state ) ) | | ! ContextualCheckBlock ( block , state , pindex - > pprev ) ) {
@ -2891,21 +2899,22 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned
}
bool ProcessNewBlock ( CValidationState & state , CNode * pfrom , CBlock * pblock , CDiskBlockPos * dbp )
bool ProcessNewBlock ( CValidationState & state , CNode * pfrom , CBlock * pblock , bool fForceProcessing , CDiskBlockPos * dbp )
{
// Preliminary checks
bool checked = CheckBlock ( * pblock , state ) ;
{
LOCK ( cs_main ) ;
MarkBlockAsReceived ( pblock - > GetHash ( ) ) ;
bool fRequested = MarkBlockAsReceived ( pblock - > GetHash ( ) ) ;
fRequested | = fForceProcessing ;
if ( ! checked ) {
return error ( " %s: CheckBlock FAILED " , __func__ ) ;
}
// Store to disk
CBlockIndex * pindex = NULL ;
bool ret = AcceptBlock ( * pblock , state , & pindex , dbp ) ;
bool ret = AcceptBlock ( * pblock , state , & pindex , fRequested , dbp ) ;
if ( pindex & & pfrom ) {
mapBlockSource [ pindex - > GetBlockHash ( ) ] = pfrom - > GetId ( ) ;
}
@ -3453,7 +3462,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
// process in case the block isn't known yet
if ( mapBlockIndex . count ( hash ) = = 0 | | ( mapBlockIndex [ hash ] - > nStatus & BLOCK_HAVE_DATA ) = = 0 ) {
CValidationState state ;
if ( ProcessNewBlock ( state , NULL , & block , dbp ) )
if ( ProcessNewBlock ( state , NULL , & block , true , dbp ) )
nLoaded + + ;
if ( state . IsError ( ) )
break ;
@ -3475,7 +3484,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
LogPrintf ( " %s: Processing out of order child %s of %s \n " , __func__ , block . GetHash ( ) . ToString ( ) ,
head . ToString ( ) ) ;
CValidationState dummy ;
if ( ProcessNewBlock ( dummy , NULL , & block , & it - > second ) )
if ( ProcessNewBlock ( dummy , NULL , & block , true , & it - > second ) )
{
nLoaded + + ;
queue . push_back ( block . GetHash ( ) ) ;
@ -4462,7 +4471,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom - > AddInventoryKnown ( inv ) ;
CValidationState state ;
ProcessNewBlock ( state , pfrom , & block ) ;
// Process all blocks from whitelisted peers, even if not requested.
ProcessNewBlock ( state , pfrom , & block , pfrom - > fWhitelisted , NULL ) ;
int nDoS ;
if ( state . IsInvalid ( nDoS ) ) {
pfrom - > PushMessage ( " reject " , strCommand , state . GetRejectCode ( ) ,