diff --git a/src/main.cpp b/src/main.cpp index 907dc440e..0be08f21c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2419,11 +2419,10 @@ void static UpdateTip(CBlockIndex *pindexNew) { } } -/** Disconnect chainActive's tip. */ +/** Disconnect chainActive's tip. You probably want to call mempool.removeForReorg after this, with cs_main held. */ bool static DisconnectTip(CValidationState &state, bool fBare = false) { CBlockIndex *pindexDelete = chainActive.Tip(); assert(pindexDelete); - mempool.check(pcoinsTip); // Read block from disk. CBlock block; if (!ReadBlockFromDisk(block, pindexDelete)) @@ -2457,8 +2456,6 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { // in which case we don't want to evict from the mempool yet! mempool.removeWithAnchor(anchorBeforeDisconnect); } - mempool.removeForReorg(pcoinsTip, pindexDelete->nHeight); - mempool.check(pcoinsTip); } // Update chainActive and related variables. @@ -2488,7 +2485,6 @@ static int64_t nTimePostConnect = 0; */ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) { assert(pindexNew->pprev == chainActive.Tip()); - mempool.check(pcoinsTip); // Read block from disk. int64_t nTime1 = GetTimeMicros(); CBlock block; @@ -2528,7 +2524,6 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * // Remove conflicting transactions from the mempool. list txConflicted; mempool.removeForBlock(pblock->vtx, pindexNew->nHeight, txConflicted, !IsInitialBlockDownload()); - mempool.check(pcoinsTip); // Update chainActive & related variables. UpdateTip(pindexNew); // Tell wallet about transactions that went from mempool @@ -2632,9 +2627,14 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo const CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork); // Disconnect active blocks which are no longer in the best chain. + bool fBlocksDisconnected = false; while (chainActive.Tip() && chainActive.Tip() != pindexFork) { - if (!DisconnectTip(state)) + if (!DisconnectTip(state)) { + // Probably an AbortNode() error, but try to keep mempool consistent anyway + mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1); return false; + } + fBlocksDisconnected = true; } // Build list of new blocks to connect. @@ -2667,6 +2667,9 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo break; } else { // A system error occurred (disk space, database error, ...). + // Probably gonna shut down ASAP, but try to keep mempool consistent anyway + if (fBlocksDisconnected) + mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1); return false; } } else { @@ -2680,6 +2683,11 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo } } + if (fBlocksDisconnected) { + mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1); + } + mempool.check(pcoinsTip); + // Callbacks/notifications for a new best chain. if (fInvalidFound) CheckForkWarningConditionsOnNewFork(vpindexToConnect.back()); @@ -2764,6 +2772,7 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) { // ActivateBestChain considers blocks already in chainActive // unconditionally valid already, so force disconnect away from it. if (!DisconnectTip(state)) { + mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1); return false; } } @@ -2779,6 +2788,7 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) { } InvalidChainFound(pindex); + mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1); return true; } diff --git a/src/main.h b/src/main.h index 03b0464eb..5b1d1d092 100644 --- a/src/main.h +++ b/src/main.h @@ -514,7 +514,7 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex); /** Remove invalidity status from a block and its descendants. */ bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex); -/** The currently-connected chain of blocks. */ +/** The currently-connected chain of blocks (protected by cs_main). */ extern CChain chainActive; /** Global variable that points to the active CCoinsView (protected by cs_main) */