* Try to make some progress towards making pindexMostWork the active block. * pblock is either nullptr or a pointer to a CBlock corresponding to pindexMostWork. * * @returns true unless a system error occurred */
| 3061 | * @returns true unless a system error occurred |
| 3062 | */ |
| 3063 | bool CChainState::ActivateBestChainStep(BlockValidationState& state, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace, bool& fStall) |
| 3064 | { |
| 3065 | AssertLockHeld(cs_main); |
| 3066 | if (m_mempool) AssertLockHeld(m_mempool->cs); |
| 3067 | |
| 3068 | const CBlockIndex* pindexOldTip = m_chain.Tip(); |
| 3069 | const CBlockIndex* pindexFork = m_chain.FindFork(pindexMostWork); |
| 3070 | |
| 3071 | // Disconnect active blocks which are no longer in the best chain. |
| 3072 | bool fBlocksDisconnected = false; |
| 3073 | DisconnectedBlockTransactions disconnectpool; |
| 3074 | while (m_chain.Tip() && m_chain.Tip() != pindexFork) { |
| 3075 | if (!DisconnectTip(state, &disconnectpool)) { |
| 3076 | // This is likely a fatal error, but keep the mempool consistent, |
| 3077 | // just in case. Only remove from the mempool in this case. |
| 3078 | MaybeUpdateMempoolForReorg(disconnectpool, false); |
| 3079 | |
| 3080 | // If we're unable to disconnect a block during normal operation, |
| 3081 | // then that is a failure of our local system -- we should abort |
| 3082 | // rather than stay on a less work chain. |
| 3083 | AbortNode(state, "Failed to disconnect block; see debug.log for details"); |
| 3084 | return false; |
| 3085 | } |
| 3086 | fBlocksDisconnected = true; |
| 3087 | } |
| 3088 | |
| 3089 | // Build list of new blocks to connect (in descending height order). |
| 3090 | std::vector<CBlockIndex*> vpindexToConnect; |
| 3091 | bool fContinue = true; |
| 3092 | int nHeight = pindexFork ? pindexFork->nHeight : -1; |
| 3093 | while (fContinue && nHeight != pindexMostWork->nHeight) { |
| 3094 | // Don't iterate the entire list of potential improvements toward the best tip, as we likely only need |
| 3095 | // a few blocks along the way. |
| 3096 | int nTargetHeight = std::min(nHeight + 32, pindexMostWork->nHeight); |
| 3097 | vpindexToConnect.clear(); |
| 3098 | vpindexToConnect.reserve(nTargetHeight - nHeight); |
| 3099 | CBlockIndex* pindexIter = pindexMostWork->GetAncestor(nTargetHeight); |
| 3100 | while (pindexIter && pindexIter->nHeight != nHeight) { |
| 3101 | vpindexToConnect.push_back(pindexIter); |
| 3102 | pindexIter = pindexIter->pprev; |
| 3103 | } |
| 3104 | nHeight = nTargetHeight; |
| 3105 | |
| 3106 | // Connect new blocks. |
| 3107 | for (CBlockIndex* pindexConnect : reverse_iterate(vpindexToConnect)) { |
| 3108 | if (!ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : std::shared_ptr<const CBlock>(), connectTrace, disconnectpool, fStall)) { |
| 3109 | if (state.IsInvalid()) { |
| 3110 | // The block violates a consensus rule. |
| 3111 | if (state.GetResult() != BlockValidationResult::BLOCK_MUTATED) { |
| 3112 | InvalidChainFound(vpindexToConnect.front()); |
| 3113 | } |
| 3114 | state = BlockValidationState(); |
| 3115 | fInvalidFound = true; |
| 3116 | fContinue = false; |
| 3117 | break; |
| 3118 | } else { |
| 3119 | // A system error occurred (disk space, database error, ...). |
| 3120 | // Make the mempool consistent with the current tip, just in case |
nothing calls this directly
no test coverage detected