Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */
| 3697 | |
| 3698 | /** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */ |
| 3699 | bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock) |
| 3700 | { |
| 3701 | const CBlock& block = *pblock; |
| 3702 | |
| 3703 | if (fNewBlock) *fNewBlock = false; |
| 3704 | AssertLockHeld(cs_main); |
| 3705 | |
| 3706 | CBlockIndex *pindexDummy = nullptr; |
| 3707 | CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy; |
| 3708 | |
| 3709 | if (!AcceptBlockHeader(block, state, chainparams, &pindex)) |
| 3710 | return false; |
| 3711 | |
| 3712 | // Try to process all requested blocks that we don't have, but only |
| 3713 | // process an unrequested block if it's new and has enough work to |
| 3714 | // advance our tip, and isn't too many blocks ahead. |
| 3715 | bool fAlreadyHave = pindex->nStatus & BLOCK_HAVE_DATA; |
| 3716 | |
| 3717 | // Compare block header timestamps and received times of the block and the |
| 3718 | // chaintip. If they have the same chain height, use these diffs as a |
| 3719 | // tie-breaker, attempting to pick the more honestly-mined block. |
| 3720 | int64_t newBlockTimeDiff = std::llabs(pindex->GetReceivedTimeDiff()); |
| 3721 | int64_t chainTipTimeDiff = |
| 3722 | chainActive.Tip() ? std::llabs(chainActive.Tip()->GetReceivedTimeDiff()) : 0; |
| 3723 | |
| 3724 | bool isSameHeight = |
| 3725 | chainActive.Tip() && (pindex->nChainWork == chainActive.Tip()->nChainWork); |
| 3726 | if (isSameHeight) { |
| 3727 | LogPrintf("Chain tip timestamp-to-received-time difference: hash=%s, diff=%d\n", |
| 3728 | chainActive.Tip()->GetBlockHash().ToString(), chainTipTimeDiff); |
| 3729 | LogPrintf("New block timestamp-to-received-time difference: hash=%s, diff=%d\n", |
| 3730 | pindex->GetBlockHash().ToString(), newBlockTimeDiff); |
| 3731 | } |
| 3732 | |
| 3733 | bool fHasMoreOrSameWork = (chainActive.Tip() ? pindex->nChainWork >= chainActive.Tip()->nChainWork : true); |
| 3734 | // Blocks that are too out-of-order needlessly limit the effectiveness of |
| 3735 | // pruning, because pruning will not delete block files that contain any |
| 3736 | // blocks which are too close in height to the tip. Apply this test |
| 3737 | // regardless of whether pruning is enabled; it should generally be safe to |
| 3738 | // not process unrequested blocks. |
| 3739 | bool fTooFarAhead = (pindex->nHeight > int(chainActive.Height() + MIN_BLOCKS_TO_KEEP)); |
| 3740 | |
| 3741 | // TODO: Decouple this function from the block download logic by removing fRequested |
| 3742 | // This requires some new chain data structure to efficiently look up if a |
| 3743 | // block is in a chain leading to a candidate for best tip, despite not |
| 3744 | // being such a candidate itself. |
| 3745 | |
| 3746 | // TODO: deal better with return value and error conditions for duplicate |
| 3747 | // and unrequested blocks. |
| 3748 | if (fAlreadyHave) return true; |
| 3749 | if (!fRequested) { // If we didn't ask for it: |
| 3750 | if (pindex->nTx != 0) return true; // This is a previously-processed block that was pruned |
| 3751 | if (!fHasMoreOrSameWork) return true; // Don't process less-work chains |
| 3752 | if (fTooFarAhead) return true; // Block height is too high |
| 3753 | |
| 3754 | // Protect against DoS attacks from low-work chains. |
| 3755 | // If our tip is behind, a peer could try to send us |
| 3756 | // low-work blocks on a fake chain that we would never |
no test coverage detected