* Try to make some progress towards making index_most_work the active block. * pblock is either nullptr or a pointer to a CBlock corresponding to index_most_work. * * @returns true unless a system error occurred */
| 3199 | * @returns true unless a system error occurred |
| 3200 | */ |
| 3201 | bool Chainstate::ActivateBestChainStep(BlockValidationState& state, CBlockIndex& index_most_work, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, std::vector<ConnectedBlock>& connected_blocks) |
| 3202 | { |
| 3203 | AssertLockHeld(cs_main); |
| 3204 | if (m_mempool) AssertLockHeld(m_mempool->cs); |
| 3205 | |
| 3206 | const CBlockIndex* pindexOldTip = m_chain.Tip(); |
| 3207 | const CBlockIndex* pindexFork = m_chain.FindFork(index_most_work); |
| 3208 | |
| 3209 | // Disconnect active blocks which are no longer in the best chain. |
| 3210 | bool fBlocksDisconnected = false; |
| 3211 | DisconnectedBlockTransactions disconnectpool{MAX_DISCONNECTED_TX_POOL_BYTES}; |
| 3212 | while (m_chain.Tip() && m_chain.Tip() != pindexFork) { |
| 3213 | if (!DisconnectTip(state, &disconnectpool)) { |
| 3214 | // This is likely a fatal error, but keep the mempool consistent, |
| 3215 | // just in case. Only remove from the mempool in this case. |
| 3216 | MaybeUpdateMempoolForReorg(disconnectpool, false); |
| 3217 | |
| 3218 | // If we're unable to disconnect a block during normal operation, |
| 3219 | // then that is a failure of our local system -- we should abort |
| 3220 | // rather than stay on a less work chain. |
| 3221 | FatalError(m_chainman.GetNotifications(), state, _("Failed to disconnect block.")); |
| 3222 | return false; |
| 3223 | } |
| 3224 | fBlocksDisconnected = true; |
| 3225 | } |
| 3226 | |
| 3227 | // Build list of new blocks to connect (in descending height order). |
| 3228 | std::vector<CBlockIndex*> vpindexToConnect; |
| 3229 | bool fContinue = true; |
| 3230 | int nHeight = pindexFork ? pindexFork->nHeight : -1; |
| 3231 | while (fContinue && nHeight != index_most_work.nHeight) { |
| 3232 | // Don't iterate the entire list of potential improvements toward the best tip, as we likely only need |
| 3233 | // a few blocks along the way. |
| 3234 | int nTargetHeight = std::min(nHeight + 32, index_most_work.nHeight); |
| 3235 | vpindexToConnect.clear(); |
| 3236 | vpindexToConnect.reserve(nTargetHeight - nHeight); |
| 3237 | CBlockIndex* pindexIter = index_most_work.GetAncestor(nTargetHeight); |
| 3238 | while (pindexIter && pindexIter->nHeight != nHeight) { |
| 3239 | vpindexToConnect.push_back(pindexIter); |
| 3240 | pindexIter = pindexIter->pprev; |
| 3241 | } |
| 3242 | nHeight = nTargetHeight; |
| 3243 | |
| 3244 | // Connect new blocks. |
| 3245 | for (CBlockIndex* pindexConnect : vpindexToConnect | std::views::reverse) { |
| 3246 | if (!ConnectTip(state, pindexConnect, pindexConnect == &index_most_work ? pblock : std::shared_ptr<const CBlock>(), connected_blocks, disconnectpool)) { |
| 3247 | if (state.IsInvalid()) { |
| 3248 | // The block violates a consensus rule. |
| 3249 | if (state.GetResult() != BlockValidationResult::BLOCK_MUTATED) { |
| 3250 | InvalidChainFound(vpindexToConnect.front()); |
| 3251 | } |
| 3252 | state = BlockValidationState(); |
| 3253 | fInvalidFound = true; |
| 3254 | fContinue = false; |
| 3255 | break; |
| 3256 | } else { |
| 3257 | // A system error occurred (disk space, database error, ...). |
| 3258 | // Make the mempool consistent with the current tip, just in case |
nothing calls this directly
no test coverage detected