diff --git a/src/chain.cpp b/src/chain.cpp index 958872e5ff6..b066f0f7c68 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -47,10 +47,9 @@ CBlockLocator GetLocator(const CBlockIndex* index) return CBlockLocator{LocatorEntries(index)}; } -const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const { - if (pindex == nullptr) { - return nullptr; - } +const CBlockIndex* CChain::FindFork(const CBlockIndex& index) const +{ + const auto* pindex{&index}; if (pindex->nHeight > Height()) pindex = pindex->GetAncestor(Height()); while (pindex && !Contains(*pindex)) diff --git a/src/chain.h b/src/chain.h index a2295b0883c..7701e9262a4 100644 --- a/src/chain.h +++ b/src/chain.h @@ -440,7 +440,7 @@ public: void SetTip(CBlockIndex& block); /** Find the last common block between this chain and a block index entry. */ - const CBlockIndex* FindFork(const CBlockIndex* pindex) const; + const CBlockIndex* FindFork(const CBlockIndex& index) const; /** Find the earliest block with timestamp equal or greater than the given time and height equal or greater than the given height. */ CBlockIndex* FindEarliestAtLeast(int64_t nTime, int height) const; diff --git a/src/index/base.cpp b/src/index/base.cpp index 416137dd57a..bb41cc2a632 100644 --- a/src/index/base.cpp +++ b/src/index/base.cpp @@ -166,7 +166,7 @@ static const CBlockIndex* NextSyncBlock(const CBlockIndex* const pindex_prev, CC // Since block is not in the chain, return the next block in the chain AFTER the last common ancestor. // Caller will be responsible for rewinding back to the common ancestor. - const auto* fork{chain.FindFork(pindex_prev)}; + const auto* fork{chain.FindFork(*pindex_prev)}; // Common ancestor must exist (genesis). return chain.Next(*Assert(fork)); } diff --git a/src/init.cpp b/src/init.cpp index 6642c87f41d..aa153a27f60 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -2374,7 +2374,7 @@ bool StartIndexBackgroundSync(NodeContext& node) LogWarning("Failed to find block manager entry for best block %s from %s, falling back to genesis for index sync", summary.best_block_hash.ToString(), summary.name); } else if (!index_chain.Contains(*pindex)) { - pindex = index_chain.FindFork(pindex); + pindex = index_chain.FindFork(*pindex); } } if (!pindex) { diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 956f7066ae0..d65b672f475 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1649,11 +1649,12 @@ static RPCMethod getchaintips() /* Construct the output array. */ UniValue res(UniValue::VARR); for (const CBlockIndex* block : setTips) { + CHECK_NONFATAL(block); UniValue obj(UniValue::VOBJ); obj.pushKV("height", block->nHeight); obj.pushKV("hash", block->phashBlock->GetHex()); - const int branchLen = block->nHeight - active_chain.FindFork(block)->nHeight; + const int branchLen = block->nHeight - active_chain.FindFork(*block)->nHeight; obj.pushKV("branchlen", branchLen); std::string status; diff --git a/src/test/chain_tests.cpp b/src/test/chain_tests.cpp index cf620958cba..966802b65ad 100644 --- a/src/test/chain_tests.cpp +++ b/src/test/chain_tests.cpp @@ -96,13 +96,13 @@ BOOST_AUTO_TEST_CASE(findfork_tests) const auto check_same{[](const CChain& chain, const auto& blocks) { for (const auto& block : blocks) { - BOOST_CHECK_EQUAL(chain.FindFork(&block), &block); + BOOST_CHECK_EQUAL(chain.FindFork(block), &block); } }}; const auto check_fork_point{[](const CChain& chain, const auto& blocks, const CBlockIndex& fork_point) { for (const auto& block : blocks) { - BOOST_CHECK_EQUAL(chain.FindFork(&block), &fork_point); + BOOST_CHECK_EQUAL(chain.FindFork(block), &fork_point); } }}; @@ -139,7 +139,7 @@ BOOST_AUTO_TEST_CASE(findfork_tests) // Invalid test case. Mixing chains is not supported CBlockIndex block_on_unrelated_chain; - BOOST_CHECK_EQUAL(chain_long.FindFork(&block_on_unrelated_chain), nullptr); + BOOST_CHECK_EQUAL(chain_long.FindFork(block_on_unrelated_chain), nullptr); } BOOST_AUTO_TEST_CASE(chain_test) diff --git a/src/test/fuzz/block_index_tree.cpp b/src/test/fuzz/block_index_tree.cpp index 0e333cd6288..2eac6d6bd26 100644 --- a/src/test/fuzz/block_index_tree.cpp +++ b/src/test/fuzz/block_index_tree.cpp @@ -102,7 +102,7 @@ FUZZ_TARGET(block_index_tree, .init = initialize_block_index_tree) assert(best_tip); // Should at least return current tip if (best_tip == chain.Tip()) break; // Nothing to do // Rewind chain to forking point - const CBlockIndex* fork = chain.FindFork(best_tip); + const CBlockIndex* fork = chain.FindFork(*best_tip); // If we can't go back to the fork point due to pruned data, abort this run. In reality, a pruned node would also currently just crash in this scenario. // This is very unlikely to happen due to the minimum pruning threshold of 550MiB. CBlockIndex* it = chain.Tip(); diff --git a/src/validation.cpp b/src/validation.cpp index b8903e816ee..d57997ced5e 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3183,7 +3183,7 @@ bool Chainstate::ActivateBestChainStep(BlockValidationState& state, CBlockIndex* if (m_mempool) AssertLockHeld(m_mempool->cs); const CBlockIndex* pindexOldTip = m_chain.Tip(); - const CBlockIndex* pindexFork = m_chain.FindFork(pindexMostWork); + const CBlockIndex* pindexFork = pindexMostWork ? m_chain.FindFork(*pindexMostWork) : nullptr; // Disconnect active blocks which are no longer in the best chain. bool fBlocksDisconnected = false; @@ -3397,7 +3397,7 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr< } while (!m_chain.Tip() || (starting_tip && CBlockIndexWorkComparator()(m_chain.Tip(), starting_tip))); if (!blocks_connected) return true; - const CBlockIndex* pindexFork = m_chain.FindFork(starting_tip); + const CBlockIndex* pindexFork = starting_tip ? m_chain.FindFork(*starting_tip) : nullptr; bool still_in_ibd = m_chainman.IsInitialBlockDownload(); if (was_in_ibd && !still_in_ibd) {