| 3595 | } |
| 3596 | |
| 3597 | bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex) |
| 3598 | { |
| 3599 | AssertLockHeld(cs_main); |
| 3600 | // Check for duplicate |
| 3601 | uint256 hash = block.GetHash(); |
| 3602 | BlockMap::iterator miSelf = mapBlockIndex.find(hash); |
| 3603 | CBlockIndex *pindex = nullptr; |
| 3604 | if (hash != chainparams.GetConsensus().hashGenesisBlock) { |
| 3605 | if (miSelf != mapBlockIndex.end()) { |
| 3606 | // Block header is already known. |
| 3607 | pindex = miSelf->second; |
| 3608 | if (ppindex) |
| 3609 | *ppindex = pindex; |
| 3610 | if (pindex->nStatus & BLOCK_FAILED_MASK) |
| 3611 | return state.Invalid(error("%s: block %s is marked invalid", __func__, hash.ToString()), 0, "duplicate"); |
| 3612 | return true; |
| 3613 | } |
| 3614 | |
| 3615 | if (!CheckBlockHeader(block, state, chainparams.GetConsensus())) |
| 3616 | return error("%s: Consensus::CheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state)); |
| 3617 | |
| 3618 | // Get prev block index |
| 3619 | CBlockIndex* pindexPrev = nullptr; |
| 3620 | BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock); |
| 3621 | if (mi == mapBlockIndex.end()) |
| 3622 | return state.DoS(10, error("%s: prev block not found", __func__), 0, "prev-blk-not-found"); |
| 3623 | pindexPrev = (*mi).second; |
| 3624 | if (pindexPrev->nStatus & BLOCK_FAILED_MASK) |
| 3625 | return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk"); |
| 3626 | if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev, GetAdjustedTime())) |
| 3627 | return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state)); |
| 3628 | |
| 3629 | // If the previous block index isn't valid, determine if it descends from any block which |
| 3630 | // has been found invalid (m_failed_blocks), then mark pindexPrev and any blocks |
| 3631 | // between them as failed. |
| 3632 | if (!pindexPrev->IsValid(BLOCK_VALID_SCRIPTS)) { |
| 3633 | for (const CBlockIndex* failedit : m_failed_blocks) { |
| 3634 | if (pindexPrev->GetAncestor(failedit->nHeight) == failedit) { |
| 3635 | assert(failedit->nStatus & BLOCK_FAILED_VALID); |
| 3636 | CBlockIndex* invalid_walk = pindexPrev; |
| 3637 | while (invalid_walk != failedit) { |
| 3638 | invalid_walk->nStatus |= BLOCK_FAILED_CHILD; |
| 3639 | setDirtyBlockIndex.insert(invalid_walk); |
| 3640 | invalid_walk = invalid_walk->pprev; |
| 3641 | } |
| 3642 | return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk"); |
| 3643 | } |
| 3644 | } |
| 3645 | } |
| 3646 | } |
| 3647 | if (pindex == nullptr) |
| 3648 | pindex = AddToBlockIndex(block); |
| 3649 | |
| 3650 | if (ppindex) |
| 3651 | *ppindex = pindex; |
| 3652 | |
| 3653 | CheckBlockIndex(chainparams.GetConsensus()); |
| 3654 |
no test coverage detected