| 3527 | } |
| 3528 | |
| 3529 | bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp) |
| 3530 | { |
| 3531 | const CChainParams& chainparams = Params(); |
| 3532 | AssertLockHeld(cs_main); |
| 3533 | |
| 3534 | CBlockIndex *pindexDummy = NULL; |
| 3535 | CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy; |
| 3536 | |
| 3537 | if (!AcceptBlockHeader(block, state, &pindex)) |
| 3538 | return false; |
| 3539 | |
| 3540 | // Try to process all requested blocks that we don't have, but only |
| 3541 | // process an unrequested block if it's new and has enough work to |
| 3542 | // advance our tip, and isn't too many blocks ahead. |
| 3543 | bool fAlreadyHave = pindex->nStatus & BLOCK_HAVE_DATA; |
| 3544 | bool fHasMoreWork = (chainActive.Tip() ? pindex->nChainWork > chainActive.Tip()->nChainWork : true); |
| 3545 | // Blocks that are too out-of-order needlessly limit the effectiveness of |
| 3546 | // pruning, because pruning will not delete block files that contain any |
| 3547 | // blocks which are too close in height to the tip. Apply this test |
| 3548 | // regardless of whether pruning is enabled; it should generally be safe to |
| 3549 | // not process unrequested blocks. |
| 3550 | bool fTooFarAhead = (pindex->nHeight > int(chainActive.Height() + MIN_BLOCKS_TO_KEEP)); |
| 3551 | |
| 3552 | // TODO: deal better with return value and error conditions for duplicate |
| 3553 | // and unrequested blocks. |
| 3554 | if (fAlreadyHave) return true; |
| 3555 | if (!fRequested) { // If we didn't ask for it: |
| 3556 | if (pindex->nTx != 0) return true; // This is a previously-processed block that was pruned |
| 3557 | if (!fHasMoreWork) return true; // Don't process less-work chains |
| 3558 | if (fTooFarAhead) return true; // Block height is too high |
| 3559 | } |
| 3560 | |
| 3561 | if ((!CheckBlock(block, state)) || !ContextualCheckBlock(block, state, pindex->pprev)) { |
| 3562 | if (state.IsInvalid() && !state.CorruptionPossible()) { |
| 3563 | pindex->nStatus |= BLOCK_FAILED_VALID; |
| 3564 | setDirtyBlockIndex.insert(pindex); |
| 3565 | } |
| 3566 | return false; |
| 3567 | } |
| 3568 | |
| 3569 | int nHeight = pindex->nHeight; |
| 3570 | |
| 3571 | // Write block to history file |
| 3572 | try { |
| 3573 | unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); |
| 3574 | CDiskBlockPos blockPos; |
| 3575 | if (dbp != NULL) |
| 3576 | blockPos = *dbp; |
| 3577 | if (!FindBlockPos(state, blockPos, nBlockSize+8, nHeight, block.GetBlockTime(), dbp != NULL)) |
| 3578 | return error("AcceptBlock(): FindBlockPos failed"); |
| 3579 | if (dbp == NULL) |
| 3580 | if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) |
| 3581 | AbortNode(state, "Failed to write block"); |
| 3582 | if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) |
| 3583 | return error("AcceptBlock(): ReceivedBlockTransactions failed"); |
| 3584 | } catch (const std::runtime_error& e) { |
| 3585 | return AbortNode(state, std::string("System error: ") + e.what()); |
| 3586 | } |
no test coverage detected