| 3996 | } |
| 3997 | |
| 3998 | bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) |
| 3999 | { |
| 4000 | AssertLockHeld(cs_main); |
| 4001 | |
| 4002 | // Mark the block itself as invalid. |
| 4003 | pindex->nStatus |= BLOCK_FAILED_VALID; |
| 4004 | setDirtyBlockIndex.insert(pindex); |
| 4005 | setBlockIndexCandidates.erase(pindex); |
| 4006 | |
| 4007 | while (chainActive.Contains(pindex)) { |
| 4008 | CBlockIndex* pindexWalk = chainActive.Tip(); |
| 4009 | pindexWalk->nStatus |= BLOCK_FAILED_CHILD; |
| 4010 | setDirtyBlockIndex.insert(pindexWalk); |
| 4011 | setBlockIndexCandidates.erase(pindexWalk); |
| 4012 | // ActivateBestChain considers blocks already in chainActive |
| 4013 | // unconditionally valid already, so force disconnect away from it. |
| 4014 | if (!DisconnectTip(state, chainparams)) { |
| 4015 | return false; |
| 4016 | } |
| 4017 | } |
| 4018 | |
| 4019 | // The resulting new best tip may not be in setBlockIndexCandidates anymore, so |
| 4020 | // add them again. |
| 4021 | BlockMap::iterator it = mapBlockIndex.begin(); |
| 4022 | while (it != mapBlockIndex.end()) { |
| 4023 | if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && !setBlockIndexCandidates.value_comp()(it->second, chainActive.Tip())) { |
| 4024 | setBlockIndexCandidates.insert(it->second); |
| 4025 | } |
| 4026 | it++; |
| 4027 | } |
| 4028 | |
| 4029 | InvalidChainFound(pindex); |
| 4030 | return true; |
| 4031 | } |
| 4032 | |
| 4033 | bool ReconsiderBlock(CValidationState& state, CBlockIndex* pindex) |
| 4034 | { |
no test coverage detected