diff --git a/src/validation.h b/src/validation.h --- a/src/validation.h +++ b/src/validation.h @@ -636,8 +636,6 @@ bool FinalizeBlockAndInvalidate(const Config &config, CValidationState &state, CBlockIndex *pindex); -const CBlockIndex *GetFinalizedBlock(); - /** Mark a block as invalid. */ bool InvalidateBlock(const Config &config, CValidationState &state, CBlockIndex *pindex); @@ -655,6 +653,16 @@ /** Remove parked status from a block. */ bool UnparkBlock(CBlockIndex *pindex); +/** + * Retrieve the topmost finalized block. + */ +const CBlockIndex *GetFinalizedBlock(); + +/** + * Checks if a block is finalized. + */ +bool IsBlockFinalized(const CBlockIndex *pindex); + /** The currently-connected chain of blocks (protected by cs_main). */ extern CChain chainActive; diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1047,6 +1047,12 @@ pindexBestInvalid = pindexNew; } + // If the invalid chain found is supposed to be finalized, we need to move + // back the finalization point. + if (IsBlockFinalized(pindexNew)) { + pindexFinalized = pindexNew->pprev; + } + LogPrintf( "%s: invalid block=%s height=%d log2_work=%.8g date=%s\n", __func__, pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, @@ -2446,6 +2452,7 @@ pindexNew->GetBlockHash().ToString(), pindexFinalized->nHeight); pindexNew->nStatus = pindexNew->nStatus.withFailed(); + InvalidChainFound(pindexNew); } const CBlockIndex *pindexFork = chainActive.FindFork(pindexNew); @@ -2915,11 +2922,6 @@ return true; } -const CBlockIndex *GetFinalizedBlock() { - AssertLockHeld(cs_main); - return pindexFinalized; -} - bool InvalidateBlock(const Config &config, CValidationState &state, CBlockIndex *pindex) { return UnwindBlock(config, state, pindex, true); @@ -2986,6 +2988,12 @@ pindexBestInvalid = nullptr; } + // In case we are reconsidering something before the finalization point, + // move the finalization point to the last common ancestor. + if (pindexFinalized) { + pindexFinalized = LastCommonAncestor(pindex, pindexFinalized); + } + UpdateFlags(pindex, [](const BlockStatus status) { return status.withClearedFailureFlags(); }); @@ -3023,6 +3031,17 @@ return UnparkBlockImpl(pindex, false); } +const CBlockIndex *GetFinalizedBlock() { + AssertLockHeld(cs_main); + return pindexFinalized; +} + +bool IsBlockFinalized(const CBlockIndex *pindex) { + AssertLockHeld(cs_main); + return pindexFinalized && + pindexFinalized->GetAncestor(pindex->nHeight) == pindex; +} + static CBlockIndex *AddToBlockIndex(const CBlockHeader &block) { // Check for duplicate uint256 hash = block.GetHash(); diff --git a/test/functional/abc-finalize-block.py b/test/functional/abc-finalize-block.py --- a/test/functional/abc-finalize-block.py +++ b/test/functional/abc-finalize-block.py @@ -96,6 +96,11 @@ "Finalize block is alt_node's tip!" assert_equal(node.getfinalizedblockhash(), finalized_block) + self.log.info( + "Make sure reconsidering block move the finalization point...") + node.reconsiderblock(alt_node.getbestblockhash()) + assert_equal(node.getbestblockhash(), alt_node.getbestblockhash()) + if __name__ == '__main__': FinalizeBlockTest().main()