interfaces, chain, refactor: Remove unused getTipLocator and incaccurate getActiveChainLocator #33169

pull pablomartin4btc wants to merge 2 commits into bitcoin:master from pablomartin4btc:interfaces-chain-refactor-remove-getTipLocator-and-getActiveChainLocator changing 6 files +11 −37
  1. pablomartin4btc commented at 7:15 pm on August 10, 2025: member

    Remove Chain::getTipLocator, Chain::GetLocator(), and Chain::getActiveChainLocator:

    • Chain::getTipLocator is no longer used.
    • Chain::GetLocator, replaced its call by GetLocator(), which uses LocatorEntries, avoiding direct access to the chain itself (change suggested by l0rinc while reviewing this PR to maintain consistency with the overall refactoring).
    • Chain::getActiveChainLocator, whose name was misleading, has functionality redundant with Chain::findBlock.

    This is a follow-up to #29652.

  2. DrahtBot commented at 7:15 pm on August 10, 2025: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/33169.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK bc1cindy, l0rinc
    Stale ACK stickies-v

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

  3. fanquake requested review from ryanofsky on Aug 11, 2025
  4. stickies-v approved
  5. stickies-v commented at 2:07 pm on August 11, 2025: contributor

    ACK 9c0542f26055330b92967a0620fb9ae3f315eb19

    Rationale makes sense, can’t see any behaviour change.

  6. in src/wallet/wallet.cpp:1864 in 9c0542f260 outdated
    1857@@ -1858,7 +1858,8 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
    1858                 result.last_scanned_height = block_height;
    1859 
    1860                 if (save_progress && next_interval) {
    1861-                    CBlockLocator loc = m_chain->getActiveChainLocator(block_hash);
    1862+                    CBlockLocator loc;
    1863+                    chain().findBlock(block_hash, FoundBlock().locator(loc));
    1864 
    1865                     if (!loc.IsNull()) {
    


    stickies-v commented at 2:08 pm on August 11, 2025:

    note: my understanding is that (also prior to this PR), since !block.IsNull() and we’re not doing any traversing to get the locator, loc should never be null. I verified this by adding an Assume and running the debug build test suite. Could potentially add that in here too if you think it makes sense?

     0diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
     1index d17156b2b0..bb56badd81 100644
     2--- a/src/wallet/wallet.cpp
     3+++ b/src/wallet/wallet.cpp
     4@@ -1861,7 +1861,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
     5                     CBlockLocator loc;
     6                     chain().findBlock(block_hash, FoundBlock().locator(loc));
     7 
     8-                    if (!loc.IsNull()) {
     9+                    if (Assume(!loc.IsNull())) {
    10                         WalletLogPrintf("Saving scan progress %d.\n", block_height);
    11                         WalletBatch batch(GetDatabase());
    12                         batch.WriteBestBlock(loc);
    

    furszy commented at 2:23 pm on August 11, 2025:
    Most likely nothing will happen because the locator is built backwards from pprev and not accessing the main-chain but.. the previous function was called getActiveChainLocator, so what if the block is no longer in the active chain at this point? (in-between the first fetch and this second one, the block could have been reorg-ed out).

    ryanofsky commented at 2:37 pm on August 11, 2025:

    but.. the previous function was called getActiveChainLocator, so what if the block is no longer in the active chain at this point?

    Note: If I’m remembering this correctly we don’t actually care whether the block is in active chain or not, we just want the wallet to save the location of the block it is synced to. The only reason a getActiveChainLocator method was used here is that before #25717 there wasn’t an efficient way of getting locators for blocks not on the active chain, and after ed470940cddbeb40425960d51cefeec4948febe4 from #25717 the name getActiveChainLocator was misleading (see #29652 (review))

  7. furszy commented at 5:50 pm on August 11, 2025: member

    I think you could implement the second commit cleaner, and slightly more performant, by unifying the findBlock calls (only performing one at the beginning):

     0diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
     1--- a/src/wallet/wallet.cpp	(revision f6a52c6686b4d14aea2b05ca0413ad664bcf72e6)
     2+++ b/src/wallet/wallet.cpp	(date 1754934464756)
     3@@ -1837,9 +1837,13 @@
     4         chain().findBlock(block_hash, FoundBlock().inActiveChain(block_still_active).nextBlock(FoundBlock().inActiveChain(next_block).hash(next_block_hash)));
     5 
     6         if (fetch_block) {
     7-            // Read block data
     8+            // Read block data and locator if needed (the locator is usually null unless we need to save progress)
     9             CBlock block;
    10-            chain().findBlock(block_hash, FoundBlock().data(block));
    11+            CBlockLocator loc;
    12+            // Find block
    13+            FoundBlock found_block{FoundBlock().data(block)};
    14+            if (save_progress && next_interval) found_block.locator(loc);
    15+            chain().findBlock(block_hash, found_block);
    16 
    17             if (!block.IsNull()) {
    18                 LOCK(cs_wallet);
    19@@ -1857,14 +1861,10 @@
    20                 result.last_scanned_block = block_hash;
    21                 result.last_scanned_height = block_height;
    22 
    23-                if (save_progress && next_interval) {
    24-                    CBlockLocator loc = m_chain->getActiveChainLocator(block_hash);
    25-
    26-                    if (!loc.IsNull()) {
    27-                        WalletLogPrintf("Saving scan progress %d.\n", block_height);
    28-                        WalletBatch batch(GetDatabase());
    29-                        batch.WriteBestBlock(loc);
    30-                    }
    31+                if (!loc.IsNull()) {
    32+                    WalletLogPrintf("Saving scan progress %d.\n", block_height);
    33+                    WalletBatch batch(GetDatabase());
    34+                    batch.WriteBestBlock(loc);
    35                 }
    36             } else {
    37                 // could not scan block, keep scanning but record this block as the most recent failure
    
  8. pablomartin4btc commented at 7:38 pm on August 11, 2025: member

    I think you could implement the second commit cleaner, and slightly more performant, by unifying the findBlock calls (only performing one at the beginning)

    Thanks for the suggestion! I agree with it. I’ll prepare a separate follow-up commit to refactor that, so the current second commit stays minimal and clearly shows the intended change.

    When I first reviewed the code, I considered breaking down CWallet::ScanForWalletTransactions into smaller, more manageable pieces, which might be a worthwhile improvement in a separate PR. Please let me know if you also think that would be valuable.

  9. furszy commented at 8:27 pm on August 11, 2025: member

    Thanks for the suggestion! I agree with it. I’ll prepare a separate follow-up commit to refactor that, so the current second commit stays minimal and clearly shows the intended change.

    I don’t really think adding an another commit just for this makes much sense. Feel free to take the code if you like it. We are talking about a simple refactoring here.

    When I first reviewed the code, I considered breaking down CWallet::ScanForWalletTransactions into smaller, more manageable pieces, which might be a worthwhile improvement in a separate PR. Please let me know if you also think that would be valuable.

    it will depend on how you split it. Not sure if you can do much there; most of the “extra” code is to show and save progress. The rest seems very simple to me.

  10. in src/node/interfaces.cpp:565 in 9a4849f17b outdated
    558@@ -559,11 +559,6 @@ class ChainImpl : public Chain
    559         const CBlockIndex* block{chainman().ActiveChain()[height]};
    560         return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
    561     }
    562-    CBlockLocator getTipLocator() override
    563-    {
    564-        LOCK(::cs_main);
    565-        return chainman().ActiveChain().GetLocator();
    


    l0rinc commented at 1:29 am on August 12, 2025:

    Now that we have one less GetLocator call, the only remaining one can also be inlined to GetLocator(m_chain.Tip()) (we’re already holding cs_main)

     0diff --git a/src/chain.cpp b/src/chain.cpp
     1index 82007a8a1e..4e2d1bf0ac 100644
     2--- a/src/chain.cpp
     3+++ b/src/chain.cpp
     4@@ -52,11 +52,6 @@ CBlockLocator GetLocator(const CBlockIndex* index)
     5     return CBlockLocator{LocatorEntries(index)};
     6 }
     7 
     8-CBlockLocator CChain::GetLocator() const
     9-{
    10-    return ::GetLocator(Tip());
    11-}
    12-
    13 const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
    14     if (pindex == nullptr) {
    15         return nullptr;
    16diff --git a/src/chain.h b/src/chain.h
    17index c6d1640768..03dc801b98 100644
    18--- a/src/chain.h
    19+++ b/src/chain.h
    20@@ -467,9 +467,6 @@ public:
    21     /** Set/initialize a chain with a given tip. */
    22     void SetTip(CBlockIndex& block);
    23 
    24-    /** Return a CBlockLocator that refers to the tip in of this chain. */
    25-    CBlockLocator GetLocator() const;
    26-
    27     /** Find the last common block between this chain and a block index entry. */
    28     const CBlockIndex* FindFork(const CBlockIndex* pindex) const;
    29 
    30diff --git a/src/validation.cpp b/src/validation.cpp
    31index eb8bd2b57c..3dd8450dd4 100644
    32--- a/src/validation.cpp
    33+++ b/src/validation.cpp
    34@@ -2941,7 +2941,7 @@ bool Chainstate::FlushStateToDisk(
    35     }
    36     if (full_flush_completed && m_chainman.m_options.signals) {
    37         // Update best block in wallet (so we can detect restored wallets).
    38-        m_chainman.m_options.signals->ChainStateFlushed(this->GetRole(), m_chain.GetLocator());
    39+        m_chainman.m_options.signals->ChainStateFlushed(this->GetRole(), GetLocator(m_chain.Tip()));
    40     }
    41     } catch (const std::runtime_error& e) {
    42         return FatalError(m_chainman.GetNotifications(), state, strprintf(_("System error while flushing: %s"), e.what()));
    

    l0rinc commented at 5:11 am on August 13, 2025:
    👍, please resolve the comment
  11. bc1cindy commented at 1:36 am on August 12, 2025: none

    Concept ACK

    Tested by building successfully and running wallet functional tests.

    Good cleanup of unused interfaces. I lean towards furszy’s suggestion of unifying the findBlock calls - it’s cleaner and avoids redundant lookups for the same block. Simple enough to include here.

  12. l0rinc changes_requested
  13. l0rinc commented at 1:44 am on August 12, 2025: contributor
    Only had time to review 9a4849f17b1b56a40795c2bc5e953d44959d5e80
  14. interfaces, chain, refactor: Remove unused getTipLocator
    Also removed CChain::GetLocator() and replaced its call
    with GetLocator() which uses LocatorEntries instead.
    
    Co-authored-by: ryanofsky <ryan@ofsky.org>
    Co-authored-by: l0rinc <l0rinc@users.noreply.github.com>
    110a0f405c
  15. interfaces, chain, refactor: Remove inaccurate getActiveChainLocator
    The getActiveChainLocator method name was misleading, and its functionality
    duplicated `Chain::findBlock`. This commit removes the method and replaces
    all its usages with direct `Chain::findBlock` calls.
    
    Additionally, the comment of getActiveChainLocator has been outdated since
    commit ed47094 from #25717.
    
    Finally, in CWallet::ScanForWalletTransactions, the findBlock calls are now
    unified into a single call at the start of the function.
    
    Co-authored-by: Ryan Ofsky <ryan@ofsky.org>
    Co-authored-by: Matias Furszyfer <mfurszy@protonmail.com>
    2b00030af8
  16. pablomartin4btc force-pushed on Aug 13, 2025
  17. pablomartin4btc commented at 3:37 am on August 13, 2025: member

    Updates:

    • Addressed feedback from @furszy, incorporating suggested refactoring.
    • Addressed feedback from @l0rinc, removing Chain::GetLocator() function and replacing its call to be consistent with the overall refactoring done in the PR.
  18. in src/wallet/wallet.cpp:1842 in 2b00030af8
    1836@@ -1837,9 +1837,13 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
    1837         chain().findBlock(block_hash, FoundBlock().inActiveChain(block_still_active).nextBlock(FoundBlock().inActiveChain(next_block).hash(next_block_hash)));
    1838 
    1839         if (fetch_block) {
    1840-            // Read block data
    1841+            // Read block data and locator if needed (the locator is usually null unless we need to save progress)
    1842             CBlock block;
    1843-            chain().findBlock(block_hash, FoundBlock().data(block));
    1844+            CBlockLocator loc;
    


    l0rinc commented at 5:43 am on August 13, 2025:
    could we move this closer to its first usage instead of announcing it early?
  19. in src/wallet/wallet.cpp:1845 in 2b00030af8
    1842             CBlock block;
    1843-            chain().findBlock(block_hash, FoundBlock().data(block));
    1844+            CBlockLocator loc;
    1845+            // Find block
    1846+            FoundBlock found_block{FoundBlock().data(block)};
    1847+            if (save_progress && next_interval) found_block.locator(loc);
    


    l0rinc commented at 5:44 am on August 13, 2025:

    not sure I understand why we’ve moved this out of the condition. Could we split this into two commits, one removing the need for getActiveChainLocator, something like:

     0diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
     1index f45cb8e598..82e626e35d 100644
     2--- a/src/interfaces/chain.h
     3+++ b/src/interfaces/chain.h
     4@@ -143,10 +143,6 @@ public:
     5     //! pruned), and contains transactions.
     6     virtual bool haveBlockOnDisk(int height) = 0;
     7 
     8-    //! Return a locator that refers to a block in the active chain.
     9-    //! If specified block is not in the active chain, return locator for the latest ancestor that is in the chain.
    10-    virtual CBlockLocator getActiveChainLocator(const uint256& block_hash) = 0;
    11-
    12     //! Return height of the highest block on chain in common with the locator,
    13     //! which will either be the original block used to create the locator,
    14     //! or one of its ancestors.
    15diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp
    16index d7ada5ae75..106c961173 100644
    17--- a/src/node/interfaces.cpp
    18+++ b/src/node/interfaces.cpp
    19@@ -559,12 +559,6 @@ public:
    20         const CBlockIndex* block{chainman().ActiveChain()[height]};
    21         return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
    22     }
    23-    CBlockLocator getActiveChainLocator(const uint256& block_hash) override
    24-    {
    25-        LOCK(::cs_main);
    26-        const CBlockIndex* index = chainman().m_blockman.LookupBlockIndex(block_hash);
    27-        return GetLocator(index);
    28-    }
    29     std::optional<int> findLocatorFork(const CBlockLocator& locator) override
    30     {
    31         LOCK(::cs_main);
    32diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
    33index 21de98862b..fe82383ebd 100644
    34--- a/src/wallet/wallet.cpp
    35+++ b/src/wallet/wallet.cpp
    36@@ -1839,7 +1839,8 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
    37         if (fetch_block) {
    38             // Read block data
    39             CBlock block;
    40-            chain().findBlock(block_hash, FoundBlock().data(block));
    41+            auto found_block{FoundBlock().data(block)};
    42+            chain().findBlock(block_hash, found_block);
    43 
    44             if (!block.IsNull()) {
    45                 LOCK(cs_wallet);
    46@@ -1858,7 +1859,8 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
    47                 result.last_scanned_height = block_height;
    48 
    49                 if (save_progress && next_interval) {
    50-                    CBlockLocator loc = m_chain->getActiveChainLocator(block_hash);
    51+                    CBlockLocator loc;
    52+                    found_block.locator(loc);
    53 
    54                     if (!loc.IsNull()) {
    55                         WalletLogPrintf("Saving scan progress %d.\n", block_height);
    

    Which is easy to understand and a second one, moving the locator assignment before the block null check, i.e. something like:

     0diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
     1index fe82383ebd..8f2bbc23c9 100644
     2--- a/src/wallet/wallet.cpp
     3+++ b/src/wallet/wallet.cpp
     4@@ -1837,9 +1837,12 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
     5         chain().findBlock(block_hash, FoundBlock().inActiveChain(block_still_active).nextBlock(FoundBlock().inActiveChain(next_block).hash(next_block_hash)));
     6 
     7         if (fetch_block) {
     8-            // Read block data
     9             CBlock block;
    10             auto found_block{FoundBlock().data(block)};
    11+
    12+            CBlockLocator loc;
    13+            if (save_progress && next_interval) found_block.locator(loc);
    14+
    15             chain().findBlock(block_hash, found_block);
    16 
    17             if (!block.IsNull()) {
    18@@ -1858,15 +1861,10 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
    19                 result.last_scanned_block = block_hash;
    20                 result.last_scanned_height = block_height;
    21 
    22-                if (save_progress && next_interval) {
    23-                    CBlockLocator loc;
    24-                    found_block.locator(loc);
    25-
    26-                    if (!loc.IsNull()) {
    27-                        WalletLogPrintf("Saving scan progress %d.\n", block_height);
    28-                        WalletBatch batch(GetDatabase());
    29-                        batch.WriteBestBlock(loc);
    30-                    }
    31+                if (!loc.IsNull()) {
    32+                    WalletLogPrintf("Saving scan progress %d.\n", block_height);
    33+                    WalletBatch batch(GetDatabase());
    34+                    batch.WriteBestBlock(loc);
    35                 }
    36             } else {
    37                 // could not scan block, keep scanning but record this block as the most recent failure
    

    Which I’m not yet sure I fully understand. The commit message doesn’t help me, but after the split the commit messages could explain the separately with more context, maybe that would help.

  20. l0rinc changes_requested
  21. l0rinc commented at 5:51 am on August 13, 2025: contributor

    Concept ACK

    The last commit is could be split into two, the commit message could explain higher level of what’s happening exactly.


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2025-08-13 06:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me