@@ -296,7 +296,8 @@ void FinalizeNode(NodeId nodeid) {
296
296
}
297
297
298
298
// Requires cs_main.
299
- void MarkBlockAsReceived (const uint256& hash) {
299
+ // Returns a bool indicating whether we requested this block.
300
+ bool MarkBlockAsReceived (const uint256& hash) {
300
301
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> >::iterator itInFlight = mapBlocksInFlight.find (hash);
301
302
if (itInFlight != mapBlocksInFlight.end ()) {
302
303
CNodeState *state = State (itInFlight->second .first );
@@ -306,7 +307,9 @@ void MarkBlockAsReceived(const uint256& hash) {
306
307
state->nBlocksInFlight --;
307
308
state->nStallingSince = 0 ;
308
309
mapBlocksInFlight.erase (itInFlight);
310
+ return true ;
309
311
}
312
+ return false ;
310
313
}
311
314
312
315
// Requires cs_main.
@@ -2826,7 +2829,7 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
2826
2829
return true ;
2827
2830
}
2828
2831
2829
- bool AcceptBlock (CBlock& block, CValidationState& state, CBlockIndex** ppindex, CDiskBlockPos* dbp)
2832
+ bool AcceptBlock (CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool fRequested , CDiskBlockPos* dbp)
2830
2833
{
2831
2834
const CChainParams& chainparams = Params ();
2832
2835
AssertLockHeld (cs_main);
@@ -2836,13 +2839,18 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
2836
2839
if (!AcceptBlockHeader (block, state, &pindex))
2837
2840
return false ;
2838
2841
2839
- // If we're pruning, ensure that we don't allow a peer to dump a copy
2840
- // of old blocks. But we might need blocks that are not on the main chain
2841
- // to handle a reorg, even if we've processed once.
2842
- if (pindex->nStatus & BLOCK_HAVE_DATA || chainActive.Contains (pindex)) {
2843
- // TODO: deal better with duplicate blocks.
2844
- // return state.DoS(20, error("AcceptBlock(): already have block %d %s", pindex->nHeight, pindex->GetBlockHash().ToString()), REJECT_DUPLICATE, "duplicate");
2845
- return true ;
2842
+ // Try to process all requested blocks that we don't have, but only
2843
+ // process an unrequested block if it's new and has enough work to
2844
+ // advance our tip.
2845
+ bool fAlreadyHave = pindex->nStatus & BLOCK_HAVE_DATA;
2846
+ bool fHasMoreWork = (chainActive.Tip () ? pindex->nChainWork > chainActive.Tip ()->nChainWork : true );
2847
+
2848
+ // TODO: deal better with return value and error conditions for duplicate
2849
+ // and unrequested blocks.
2850
+ if (fAlreadyHave ) return true ;
2851
+ if (!fRequested ) { // If we didn't ask for it:
2852
+ if (pindex->nTx != 0 ) return true ; // This is a previously-processed block that was pruned
2853
+ if (!fHasMoreWork ) return true ; // Don't process less-work chains
2846
2854
}
2847
2855
2848
2856
if ((!CheckBlock (block, state)) || !ContextualCheckBlock (block, state, pindex->pprev )) {
@@ -2891,21 +2899,22 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned
2891
2899
}
2892
2900
2893
2901
2894
- bool ProcessNewBlock (CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp)
2902
+ bool ProcessNewBlock (CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing , CDiskBlockPos *dbp)
2895
2903
{
2896
2904
// Preliminary checks
2897
2905
bool checked = CheckBlock (*pblock, state);
2898
2906
2899
2907
{
2900
2908
LOCK (cs_main);
2901
- MarkBlockAsReceived (pblock->GetHash ());
2909
+ bool fRequested = MarkBlockAsReceived (pblock->GetHash ());
2910
+ fRequested |= fForceProcessing ;
2902
2911
if (!checked) {
2903
2912
return error (" %s: CheckBlock FAILED" , __func__);
2904
2913
}
2905
2914
2906
2915
// Store to disk
2907
2916
CBlockIndex *pindex = NULL ;
2908
- bool ret = AcceptBlock (*pblock, state, &pindex, dbp);
2917
+ bool ret = AcceptBlock (*pblock, state, &pindex, fRequested , dbp);
2909
2918
if (pindex && pfrom) {
2910
2919
mapBlockSource[pindex->GetBlockHash ()] = pfrom->GetId ();
2911
2920
}
@@ -3453,7 +3462,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
3453
3462
// process in case the block isn't known yet
3454
3463
if (mapBlockIndex.count (hash) == 0 || (mapBlockIndex[hash]->nStatus & BLOCK_HAVE_DATA) == 0 ) {
3455
3464
CValidationState state;
3456
- if (ProcessNewBlock (state, NULL , &block, dbp))
3465
+ if (ProcessNewBlock (state, NULL , &block, true , dbp))
3457
3466
nLoaded++;
3458
3467
if (state.IsError ())
3459
3468
break ;
@@ -3475,7 +3484,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
3475
3484
LogPrintf (" %s: Processing out of order child %s of %s\n " , __func__, block.GetHash ().ToString (),
3476
3485
head.ToString ());
3477
3486
CValidationState dummy;
3478
- if (ProcessNewBlock (dummy, NULL , &block, &it->second ))
3487
+ if (ProcessNewBlock (dummy, NULL , &block, true , &it->second ))
3479
3488
{
3480
3489
nLoaded++;
3481
3490
queue.push_back (block.GetHash ());
@@ -4462,7 +4471,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
4462
4471
pfrom->AddInventoryKnown (inv);
4463
4472
4464
4473
CValidationState state;
4465
- ProcessNewBlock (state, pfrom, &block);
4474
+ // Process all blocks from whitelisted peers, even if not requested.
4475
+ ProcessNewBlock (state, pfrom, &block, pfrom->fWhitelisted , NULL );
4466
4476
int nDoS;
4467
4477
if (state.IsInvalid (nDoS)) {
4468
4478
pfrom->PushMessage (" reject" , strCommand, state.GetRejectCode (),
0 commit comments