From 64817da0e349a0a80e7612c351d12376e3852f3f Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sat, 21 Dec 2024 02:00:50 +0700 Subject: [PATCH] feat: add optional argument to ignore ChainLocks for reconsiderblocks RPC Co-Authored-By: UdjinM6 --- src/rpc/blockchain.cpp | 4 +++- src/rpc/client.cpp | 1 + src/validation.cpp | 22 ++++++++++++++++------ src/validation.h | 2 +- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 2eb41cee62..fff5676e19 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -2125,6 +2125,7 @@ static RPCHelpMan reconsiderblock() "This can be used to undo the effects of invalidateblock.\n", { {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to reconsider"}, + {"ignore_chainlocks", RPCArg::Type::BOOL, RPCArg::Default{false}, "if true, existing chainlocks will be ignored"}, }, RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ @@ -2137,6 +2138,7 @@ static RPCHelpMan reconsiderblock() CChainState& active_chainstate = chainman.ActiveChainstate(); uint256 hash(ParseHashV(request.params[0], "blockhash")); + const bool ignore_chainlocks{request.params[1].isNull() ? false : request.params[1].get_bool()}; { LOCK(cs_main); @@ -2145,7 +2147,7 @@ static RPCHelpMan reconsiderblock() throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } - active_chainstate.ResetBlockFailureFlags(pblockindex); + active_chainstate.ResetBlockFailureFlags(pblockindex, ignore_chainlocks); } BlockValidationState state; diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index e66797cd88..957046f90b 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -75,6 +75,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "waitforblockheight", 0, "height" }, { "waitforblockheight", 1, "timeout" }, { "waitforblock", 1, "timeout" }, + { "reconsiderblock", 1, "ignore_chainlocks" }, { "waitfornewblock", 0, "timeout" }, { "listtransactions", 1, "count" }, { "listtransactions", 2, "skip" }, diff --git a/src/validation.cpp b/src/validation.cpp index 3cd5345de0..8e34f43bbf 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3410,7 +3410,7 @@ bool CChainState::MarkConflictingBlock(BlockValidationState& state, CBlockIndex return true; } -void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) { +void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex, bool ignore_chainlocks) { AssertLockHeld(cs_main); if (!pindex) { @@ -3429,9 +3429,14 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) { for (auto& [_, block_index] : m_blockman.m_block_index) { if (!block_index.IsValid() && block_index.GetAncestor(nHeight) == pindex) { block_index.nStatus &= ~BLOCK_FAILED_MASK; + if (ignore_chainlocks) { + block_index.nStatus &= ~BLOCK_CONFLICT_CHAINLOCK; + } m_blockman.m_dirty_blockindex.insert(&block_index); - if (block_index.IsValid(BLOCK_VALID_TRANSACTIONS) && !(block_index.nStatus & BLOCK_CONFLICT_CHAINLOCK) && block_index.HaveTxsDownloaded() && setBlockIndexCandidates.value_comp()(m_chain.Tip(), &block_index)) { - setBlockIndexCandidates.insert(&block_index); + if (block_index.IsValid(BLOCK_VALID_TRANSACTIONS) && block_index.HaveTxsDownloaded() && setBlockIndexCandidates.value_comp()(m_chain.Tip(), &block_index)) { + if (ignore_chainlocks || !(block_index.nStatus & BLOCK_CONFLICT_CHAINLOCK)) { + setBlockIndexCandidates.insert(&block_index); + } } if (&block_index == m_chainman.m_best_invalid) { // Reset invalid block marker if it was pointing to one of those. @@ -3443,11 +3448,16 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) { // Remove the invalidity flag from all ancestors too. while (pindex != nullptr) { - if (pindex->nStatus & BLOCK_FAILED_MASK) { + if (pindex->nStatus & (BLOCK_FAILED_MASK | BLOCK_CONFLICT_CHAINLOCK)) { pindex->nStatus &= ~BLOCK_FAILED_MASK; + if (ignore_chainlocks) { + pindex->nStatus &= ~BLOCK_CONFLICT_CHAINLOCK; + } m_blockman.m_dirty_blockindex.insert(pindex); - if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && !(pindex->nStatus & BLOCK_CONFLICT_CHAINLOCK) && pindex->HaveTxsDownloaded() && setBlockIndexCandidates.value_comp()(m_chain.Tip(), pindex)) { - setBlockIndexCandidates.insert(pindex); + if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && pindex->HaveTxsDownloaded() && setBlockIndexCandidates.value_comp()(m_chain.Tip(), pindex)) { + if (ignore_chainlocks || !(pindex->nStatus & BLOCK_CONFLICT_CHAINLOCK)) { + setBlockIndexCandidates.insert(pindex); + } } if (pindex == m_chainman.m_best_invalid) { // Reset invalid block marker if it was pointing to one of those. diff --git a/src/validation.h b/src/validation.h index ab12d9378d..8ebc41d9ce 100644 --- a/src/validation.h +++ b/src/validation.h @@ -713,7 +713,7 @@ public: LOCKS_EXCLUDED(::cs_main); /** Remove invalidity status from a block and its descendants. */ - void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + void ResetBlockFailureFlags(CBlockIndex* pindex, bool ignore_chainlocks = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main); /** Replay blocks that aren't fully applied to the database. */ bool ReplayBlocks();