diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1691,11 +1691,12 @@ { LOCK(cs_main); CBlockIndex *pblockindex = LookupBlockIndex(hash); + if (!pblockindex) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } - FinalizeBlockAndInvalidate(config, state, pblockindex); + ::ChainstateActive().FinalizeBlock(config, state, pblockindex); } if (state.IsValid()) { diff --git a/src/validation.h b/src/validation.h --- a/src/validation.h +++ b/src/validation.h @@ -833,6 +833,12 @@ // Manual block validity manipulation: bool PreciousBlock(const Config &config, CValidationState &state, CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main); + /** + * Finalize a block. + * A finalized block can not be reorged in any way. + */ + bool FinalizeBlock(const Config &config, CValidationState &state, + CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main); bool UnwindBlock(const Config &config, CValidationState &state, CBlockIndex *pindex, bool invalidate); void ResetBlockFailureFlags(CBlockIndex *pindex) @@ -876,6 +882,10 @@ CBlockIndex *AddToBlockIndex(const CBlockHeader &block) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + bool MarkBlockAsFinal(const Config &config, CValidationState &state, + const CBlockIndex *pindex) + EXCLUSIVE_LOCKS_REQUIRED(cs_main); + /** Create a new block index entry for a given block hash */ CBlockIndex *InsertBlockIndex(const BlockHash &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main); @@ -907,14 +917,6 @@ bool PreciousBlock(const Config &config, CValidationState &state, CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main); -/** - * Mark a block as finalized. - * A finalized block can not be reorged in any way. - */ -bool FinalizeBlockAndInvalidate(const Config &config, CValidationState &state, - CBlockIndex *pindex) - EXCLUSIVE_LOCKS_REQUIRED(cs_main); - /** Mark a block as invalid. */ bool InvalidateBlock(const Config &config, CValidationState &state, CBlockIndex *pindex); diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2232,9 +2232,9 @@ } }; -static bool FinalizeBlockInternal(const Config &config, CValidationState &state, - const CBlockIndex *pindex) - EXCLUSIVE_LOCKS_REQUIRED(cs_main) { +bool CChainState::MarkBlockAsFinal(const Config &config, + CValidationState &state, + const CBlockIndex *pindex) { AssertLockHeld(cs_main); if (pindex->nStatus.isInvalid()) { // We try to finalize an invalid block. @@ -2371,8 +2371,8 @@ const CBlockIndex *pindexToFinalize = FindBlockToFinalize(config, pindexNew); if (pindexToFinalize && - !FinalizeBlockInternal(config, state, pindexToFinalize)) { - return error("ConnectTip(): FinalizeBlock %s failed (%s)", + !MarkBlockAsFinal(config, state, pindexToFinalize)) { + return error("ConnectTip(): MarkBlockAsFinal %s failed (%s)", pindexNew->GetBlockHash().ToString(), FormatStateMessage(state)); } @@ -2907,6 +2907,31 @@ std::move(pblock)); } +bool CChainState::FinalizeBlock(const Config &config, CValidationState &state, + CBlockIndex *pindex) { + AssertLockHeld(cs_main); + if (!MarkBlockAsFinal(config, state, pindex)) { + // state is set by MarkBlockAsFinal. + return false; + } + + // We have a valid candidate, make sure it is not parked. + if (pindex->nStatus.isOnParkedChain()) { + UnparkBlock(pindex); + } + + // If the finalized block is not on the active chain, we may need to rewind. + if (!::ChainActive().Contains(pindex)) { + const CBlockIndex *pindexFork = ::ChainActive().FindFork(pindex); + CBlockIndex *pindexToInvalidate = ::ChainActive().Next(pindexFork); + if (pindexToInvalidate) { + return InvalidateBlock(config, state, pindexToInvalidate); + } + } + + return true; +} + bool CChainState::PreciousBlock(const Config &config, CValidationState &state, CBlockIndex *pindex) { { @@ -3071,31 +3096,6 @@ return true; } -bool FinalizeBlockAndInvalidate(const Config &config, CValidationState &state, - CBlockIndex *pindex) { - AssertLockHeld(cs_main); - if (!FinalizeBlockInternal(config, state, pindex)) { - // state is set by FinalizeBlockInternal. - return false; - } - - // We have a valid candidate, make sure it is not parked. - if (pindex->nStatus.isOnParkedChain()) { - UnparkBlock(pindex); - } - - // If the finalized block is not on the active chain, we may need to rewind. - if (!::ChainActive().Contains(pindex)) { - const CBlockIndex *pindexFork = ::ChainActive().FindFork(pindex); - CBlockIndex *pindexToInvalidate = ::ChainActive().Next(pindexFork); - if (pindexToInvalidate) { - return InvalidateBlock(config, state, pindexToInvalidate); - } - } - - return true; -} - bool InvalidateBlock(const Config &config, CValidationState &state, CBlockIndex *pindex) { return ::ChainstateActive().UnwindBlock(config, state, pindex, true);