|
|
@ -3702,6 +3702,11 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha |
|
|
|
// not process unrequested blocks.
|
|
|
|
// not process unrequested blocks.
|
|
|
|
bool fTooFarAhead = (pindex->nHeight > int(chainActive.Height() + MIN_BLOCKS_TO_KEEP)); |
|
|
|
bool fTooFarAhead = (pindex->nHeight > int(chainActive.Height() + MIN_BLOCKS_TO_KEEP)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Decouple this function from the block download logic by removing fRequested
|
|
|
|
|
|
|
|
// This requires some new chain datastructure 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
|
|
|
|
// TODO: deal better with return value and error conditions for duplicate
|
|
|
|
// and unrequested blocks.
|
|
|
|
// and unrequested blocks.
|
|
|
|
if (fAlreadyHave) return true; |
|
|
|
if (fAlreadyHave) return true; |
|
|
@ -3750,13 +3755,11 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, C |
|
|
|
{ |
|
|
|
{ |
|
|
|
{ |
|
|
|
{ |
|
|
|
LOCK(cs_main); |
|
|
|
LOCK(cs_main); |
|
|
|
bool fRequested = MarkBlockAsReceived(pblock->GetHash()); |
|
|
|
|
|
|
|
fRequested |= fForceProcessing; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Store to disk
|
|
|
|
// Store to disk
|
|
|
|
CBlockIndex *pindex = NULL; |
|
|
|
CBlockIndex *pindex = NULL; |
|
|
|
bool fNewBlock = false; |
|
|
|
bool fNewBlock = false; |
|
|
|
bool ret = AcceptBlock(*pblock, state, chainparams, &pindex, fRequested, dbp, &fNewBlock); |
|
|
|
bool ret = AcceptBlock(*pblock, state, chainparams, &pindex, fForceProcessing, dbp, &fNewBlock); |
|
|
|
if (pindex && pfrom) { |
|
|
|
if (pindex && pfrom) { |
|
|
|
mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId(); |
|
|
|
mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId(); |
|
|
|
if (fNewBlock) pfrom->nLastBlockTime = GetTime(); |
|
|
|
if (fNewBlock) pfrom->nLastBlockTime = GetTime(); |
|
|
@ -5858,12 +5861,16 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, |
|
|
|
std::vector<CInv> invs; |
|
|
|
std::vector<CInv> invs; |
|
|
|
invs.push_back(CInv(MSG_BLOCK | GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus()), resp.blockhash)); |
|
|
|
invs.push_back(CInv(MSG_BLOCK | GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus()), resp.blockhash)); |
|
|
|
pfrom->PushMessage(NetMsgType::GETDATA, invs); |
|
|
|
pfrom->PushMessage(NetMsgType::GETDATA, invs); |
|
|
|
} else |
|
|
|
} else { |
|
|
|
|
|
|
|
MarkBlockAsReceived(resp.blockhash); // it is now an empty pointer
|
|
|
|
fBlockRead = true; |
|
|
|
fBlockRead = true; |
|
|
|
|
|
|
|
} |
|
|
|
} // Don't hold cs_main when we call into ProcessNewBlock
|
|
|
|
} // Don't hold cs_main when we call into ProcessNewBlock
|
|
|
|
if (fBlockRead) { |
|
|
|
if (fBlockRead) { |
|
|
|
CValidationState state; |
|
|
|
CValidationState state; |
|
|
|
ProcessNewBlock(state, chainparams, pfrom, &block, false, NULL); |
|
|
|
// Since we requested this block (it was in mapBlocksInFlight), force it to be processed,
|
|
|
|
|
|
|
|
// even if it would not be a candidate for new tip (missing previous block, chain not long enough, etc)
|
|
|
|
|
|
|
|
ProcessNewBlock(state, chainparams, pfrom, &block, true, NULL); |
|
|
|
int nDoS; |
|
|
|
int nDoS; |
|
|
|
if (state.IsInvalid(nDoS)) { |
|
|
|
if (state.IsInvalid(nDoS)) { |
|
|
|
assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
|
|
|
|
assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
|
|
|
@ -6039,6 +6046,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, |
|
|
|
// Such an unrequested block may still be processed, subject to the
|
|
|
|
// Such an unrequested block may still be processed, subject to the
|
|
|
|
// conditions in AcceptBlock().
|
|
|
|
// conditions in AcceptBlock().
|
|
|
|
bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload(); |
|
|
|
bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload(); |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LOCK(cs_main); |
|
|
|
|
|
|
|
// Also always process if we requested the block explicitly, as we may
|
|
|
|
|
|
|
|
// need it even though it is not a candidate for a new best tip.
|
|
|
|
|
|
|
|
forceProcessing |= MarkBlockAsReceived(block.GetHash()); |
|
|
|
|
|
|
|
} |
|
|
|
ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL); |
|
|
|
ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL); |
|
|
|
int nDoS; |
|
|
|
int nDoS; |
|
|
|
if (state.IsInvalid(nDoS)) { |
|
|
|
if (state.IsInvalid(nDoS)) { |
|
|
|