wallet, rpc: add UTXO set check and incremental rescan to importdescriptors #33392

pull musaHaruna wants to merge 6 commits into bitcoin:master from musaHaruna:feature/scan-utxoset-balance-check changing 11 files +422 −6
  1. musaHaruna commented at 4:17 pm on September 15, 2025: contributor

    Fixes #28898

    When importing descriptors, users may accidentally provide an incorrect birthdate (timestamp). This can cause the wallet to miss relevant historical transactions, leading to incorrect or incomplete balances. Currently, the wallet only relies on rescans starting from the provided timestamp.

    This PR extends the importdescriptors RPC with a new optional argument: scan_utxoset (bool, default=false): If enabled, the wallet will compare its calculated trusted balance against UTXO set balance (by generating the scriptpukeys of the wallet and comparing it with the chains UTXO set scriptpubkeys to get the accurate balance belonging to the wallet and comparing it with the wallet trusted balance).

    If the balances match, import continues as normal. If a discrepancy is detected, the wallet will attempt incremental rescans in chunks of recent blocks until the missing history is found. If the wallet is pruned, incremental rescans will not go earlier than the prune boundary.

    Additional information is returned in the RPC response under an "info" object when scan_utxoset is used, such as: utxo_check: whether the UTXO set matched the wallet balance scanned_chunks: number of incremental rescan chunks attempted scanned_blocks: approximate number of blocks scanned during incremental rescans

    This helps detect and fix balance mismatches caused by wrong descriptor timestamps.

    A big thanks to fjahr for suggesting this approach comment

  2. node: add and implement FindCoinsByScript for UTXO-set scan by script
    Add node::FindCoinsByScript and wire it into the node interface as
    Node::getCoinsByScript(), then implement the DB-backed scan that iterates
    the on-disk UTXO DB with a CCoinsViewCursor.
    ba9f134734
  3. DrahtBot added the label RPC/REST/ZMQ on Sep 15, 2025
  4. DrahtBot commented at 4:17 pm on September 15, 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/33392.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK rkrux

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

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #33135 (wallet: warn against accidental unsafe older() import by Sjors)
    • #32861 (Have createwalletdescriptor auto-detect an unused(KEY) by Sjors)
    • #30343 (wallet, logging: Replace WalletLogPrintf() with LogInfo() by ryanofsky)
    • #29136 (wallet: addhdkey RPC to add just keys to wallets via new unused(KEY) descriptor by achow101)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    LLM Linter (✨ experimental)

    Possible typos and grammar issues:

    • “If true, scans the UTXO set balance and compare with wallet balance and triggers incremental rescan if discrepency is found.” -> “If true, scans the UTXO set balance and compares with wallet balance and triggers incremental rescan if discrepancy is found.” [subject-verb agreement (“compare” -> “compares”) and spelling (“discrepency” -> “discrepancy”)]

    • “# Mine 1000 total 1000 more blocksthen send the second tx” -> “# Mine 1000 more blocks, then send the second tx” [typo/duplication (“total 1000 1000”) and missing space in “blocksthen”; rewritten for clarity]

    drahtbot_id_5_m

  5. musaHaruna force-pushed on Sep 16, 2025
  6. fjahr commented at 2:17 pm on September 16, 2025: contributor
    It seems kind of weird to me to add this as an option to getbalance. The problem is in the importdescriptors call, which is using the wrong birthdate. Have you looked into making this an option of importdescriptors? If the performance isn’t too bad, this could even be on by default. If that is possible that would seem preferred, since you also write “However, users may not realize that their wallet balance is incomplete.”, if they don’t know they likely also won’t call the getbalance with this option. So ideally we could “force” this on users in a way that they don’t feel (much) negative impact from it. If we can’t do that then I am not sure this is of much use since the users could just call rescanblockchain directly if they are aware that there is a problem with their balances.
  7. musaHaruna commented at 4:13 pm on September 16, 2025: contributor

    Have you looked into making this an option of importdescriptors?

    I have not looked into making it an option for importdecriptors, but I will look into it, and get back to you on that.

    Just thinking on a high level and somewhat naively because am a new contributor with little knowledge about the codebase, what if we can atomatically cross check the balance by scanning the utxoset in importdescriptor before triggering the rescan, incase of wrong birthtime, seeing that even if they use the new flags in getbalance, they might/will eventually have to run rescanblockchain.

    Thanks for the suggestion. I really appreciate it.

  8. musaHaruna commented at 7:45 pm on September 16, 2025: contributor

    I have not looked into making it an option for importdecriptors, but I will look into it, and get back to you on that.

    Yes, I have looked into adding the option to importdescriptors by introducing a scan_utxoset flag and it’s possible. The idea is that when enabled, the wallet would scan the UTXO set immediately after import to verify balances against chainstate, and if a discrepancy is detected (for example due to an incorrect birthdate), it could automatically trigger a full rescan from height 0 to restore missing history. This way, users wouldn’t have to manually diagnose incomplete balances — the import flow itself would handle it. What Do you think this approach?.

    I don’t yet know the full impact on performance, but I’m thinking of making the trade-offs very clear in the RPC docs so users can decide whether to enable it.

  9. fjahr commented at 8:53 pm on September 16, 2025: contributor

    Yes, I have looked into adding the option to importdescriptors by introducing a scan_utxoset flag and it’s possible. The idea is that when enabled, the wallet would scan the UTXO set immediately after import to verify balances against chainstate, and if a discrepancy is detected (for example due to an incorrect birthdate), it could automatically trigger a full rescan from height 0 to restore missing history. This way, users wouldn’t have to manually diagnose incomplete balances — the import flow itself would handle it. What Do you think this approach?.

    Cool, this is pretty much what I had in mind, I guess I would slightly prefer that full rescan isn’t started by default and rather the user receives a clear hint that there might be some funds missing and if they want to make sure to get them they should run a full rescan, basically just like what you are doing now in the return from getbalance. But I don’t have a strong preference there, either sound fine, maybe wait for some more conceptual feedback from other reviewers.

    I don’t yet know the full impact on performance, but I’m thinking of making the trade-offs very clear in the RPC docs so users can decide whether to enable it.

    Maybe run some benchmarks on the utxo set scan and full rescan and add them to the PR here. I don’t have a good feeling for what the relation is and this might influence what reviewers think is better concerning running a full rescan automatically or just returning a warning/hint from importdescriptors.

    Another idea concerning performance: It seems likely that if the birth date is wrong the user might be off by just a few days or weeks, rather than they have a wallet with the satoshi coins. So instead of a full rescan from the start of the chain the rescan could move backwards from the originally supplied birth date and scan the chain in 1000 (or so) block increments and it could stop once the balance matches the one from the utxo set scan. A nice side effect of this is that it means the rescan is also pruning compatible (for as many blocks that are available) but I guess this could be also achieved by starting from pruneheight instead of 0 if pruning is enabled. It’s something you need to keep in mind either way. This would also need benchmarks but I can’t imagine moving backwards with somewhat large increments would make the process much slower. And ideally the process would exit early in the most common scenario.

  10. musaHaruna commented at 9:27 am on September 17, 2025: contributor

    Maybe run some benchmarks on the utxo set scan and full rescan and add them to the PR here. I don’t have a good feeling for what the relation is and this might influence what reviewers think is better concerning running a full rescan automatically or just returning a warning/hint from importdescriptors.

    I will run some benchmarks on both utxo set scan and full rescan, update the whole PR to use the new approach you suggested i.e to add the feature on importdescriptors directly, which I honestly think is better.

    Another idea concerning performance: It seems likely that if the birth date is wrong the user might be off by just a few days or weeks, rather than they have a wallet with the satoshi coins. So instead of a full rescan from the start of the chain the rescan could move backwards from the originally supplied birth date and scan the chain in 1000 (or so) block increments and it could stop once the balance matches the one from the utxo set scan. A nice side effect of this is that it means the rescan is also pruning compatible (for as many blocks that are available) but I guess this could be also achieved by starting from pruneheight instead of 0 if pruning is enabled. It’s something you need to keep in mind either way. This would also need benchmarks but I can’t imagine moving backwards with somewhat large increments would make the process much slower. And ideally the process would exit early in the most common scenario.

    Just to make sure we’re on the same page — my understanding is that the idea is to:

    Use chunked backward rescans starting from the supplied birthdate (e.g. 1000-block increments), and stop as soon as the wallet balance matches the UTXO-set scan. This handles the common case where the birthdate is only off by a few days or weeks, so we don’t need to rescan the entire chain.

    At the same time, respect the pruneheight as the lower bound if pruning is enabled. That means we only scan back as far as blocks are available, and if the discrepancy still isn’t resolved at that point, we’d warn the user that a reindex is required.

  11. musaHaruna renamed this:
    rpc: add scan_utxoset option to getbalance(s) to verify wallet balance accuracy
    wallet/rpc: add scan_utxoset option to getbalance(s) to verify wallet balance accuracy
    on Sep 17, 2025
  12. fjahr commented at 12:58 pm on September 18, 2025: contributor

    Just to make sure we’re on the same page — my understanding is that the idea is to:

    Use chunked backward rescans starting from the supplied birthdate (e.g. 1000-block increments), and stop as soon as the wallet balance matches the UTXO-set scan. This handles the common case where the birthdate is only off by a few days or weeks, so we don’t need to rescan the entire chain.

    Right, so for example if the supplied birthdate was blockheight 800,000 but there is a discrepancy, then, instead rescanning from 0 to 800k right away, scan 799k - 800k and check the balance, exit if it’s a match, continue with 798k - 799k and so on. This shouldn’t be too complex to implement since the rescanblockchain RPC already takes a start and an end height.

    At the same time, respect the pruneheight as the lower bound if pruning is enabled. That means we only scan back as far as blocks are available, and if the discrepancy still isn’t resolved at that point, we’d warn the user that a reindex is required.

    Yeah, there would be some kind of safe abort if the approach for walking backwards runs into unavailable blocks, just like rescanblockchain does as well.

  13. in src/wallet/rpc/coins.cpp:234 in 93baccaa35 outdated
    231                 {
    232                     {"dummy", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Remains for backward compatibility. Must be excluded or set to \"*\"."},
    233                     {"minconf", RPCArg::Type::NUM, RPCArg::Default{0}, "Only include transactions confirmed at least this many times."},
    234                     {"include_watchonly", RPCArg::Type::BOOL, RPCArg::Default{false}, "No longer used"},
    235                     {"avoid_reuse", RPCArg::Type::BOOL, RPCArg::Default{true}, "(only available if avoid_reuse wallet flag is set) Do not include balance in dirty outputs; addresses are considered dirty if they have previously been used in a transaction."},
    236+                    {"scan_utxoset", RPCArg::Type::BOOL, RPCArg::Default{false}, "If true, scan the UTXO set and return scanned UTXO balance alongside the trusted balance."},
    


    luke-jr commented at 10:31 pm on September 18, 2025:
    This shouldn’t be a positional parameter, at least.
  14. luke-jr commented at 10:32 pm on September 18, 2025: member

    I agree getbalance* is the wrong place for this kind of check.

    But it also will fail to detect incorrect birthdates if the TXOs are spent, so it can’t be relied on either…

  15. musaHaruna force-pushed on Sep 19, 2025
  16. musaHaruna force-pushed on Sep 19, 2025
  17. musaHaruna force-pushed on Sep 19, 2025
  18. musaHaruna renamed this:
    wallet/rpc: add scan_utxoset option to getbalance(s) to verify wallet balance accuracy
    wallet, rpc: add UTXO set check and incremental rescan to importdescriptors
    on Sep 19, 2025
  19. wallet: add GetWalletUTXOSetBalance to calculate balance from UTXO set
    Introduce a new helper `GetWalletUTXOSetBalance(const CWallet&)` that
    derives the wallet’s balance directly from the UTXO set rather than from
    the wallet’s transaction history.
    
    Usefull for verifying wallet balance correctness against the
    chainstate without requiring a full rescan.
    ac06ddb8b9
  20. wallet/rpc: add scan_utxoset arg & docs for importdescriptors
    Add a new optional boolean RPC argument `scan_utxoset` to
    importdescriptors and document the response fields used when the
    scan_utxoset check is enabled.
    fa3ac7378c
  21. wallet: extend RescanFromTime with optional endTime to limit rescan range
    Add a new overload of CWallet::RescanFromTime that accepts an optional
    endTime parameter. When provided, the method finds the approximate end
    height and calls ScanForWalletTransactions with a bounded [start, end]
    range. This makes incremental or windowed rescans possible while preserving
    existing behavior when no endTime is specified.
    37719609f1
  22. musaHaruna force-pushed on Sep 19, 2025
  23. rpc: extend importdescriptors with UTXO check and incremental rescan
    Extend the importdescriptors RPC with an optional `scan_utxoset` parameter.
    When enabled, the wallet balance is compared against a balance derived from
    the UTXO set. If a discrepancy is found, the wallet attempts incremental,
    non-overlapping rescans in fixed-size block chunks until the balances match,
    allowing for faster recovery in many cases. When a match is detected, the
    RPC returns early with an `info` object describing the UTXO check and rescan
    progress. If no match is found, the code falls back to the existing full
    rescan behavior starting from the earliest descriptor timestamp (or the
    prune boundary if applicable). Responses are updated to include optional
    `info` fields with `utxo_check`, `scanned_chunks`, and `scanned_blocks`
    metadata.
    82a222b00d
  24. musaHaruna force-pushed on Sep 19, 2025
  25. test: add functional test for importdescriptors scan_utxo flag
    Add a functional test that verifies `importdescriptors`
    behavior with and without `scan_utxoset`, ensuring wallets correctly detect
    UTXOs and transactions depending on the timestamp used. The test covers both
    `timestamp="now"` (no history vs. UTXO set scan) and accurate historical timestamps
    (both imports discover full history), and also asserts returned metadata fields
    (`success`, `utxo_check`, `scanned_chunks`, `scanned_blocks`).
    1ed236e3c6
  26. in src/wallet/rpc/backup.cpp:519 in 82a222b00d outdated
    514+        // Compare wallet trusted balance with chainstate-scanned spendable balance.
    515+        const auto bal = GetBalance(wallet);
    516+
    517+        CAmount utxo_scanned_balance = GetWalletUTXOSetBalance(wallet);
    518+
    519+    if (utxo_scanned_balance != bal.m_mine_trusted) {
    


    rkrux commented at 12:54 pm on November 11, 2025:

    In 82a222b00d6497dc22e85205dae577a1adf15989 “rpc: extend importdescriptors with UTXO check and incremental rescan”

    The lack of nesting in the if blocks makes the code harder to read.

      0diff --git a/src/wallet/rpc/backup.cpp b/src/wallet/rpc/backup.cpp
      1index 4146a65876..cf8269b2ef 100644
      2--- a/src/wallet/rpc/backup.cpp
      3+++ b/src/wallet/rpc/backup.cpp
      4@@ -507,7 +507,6 @@ RPCHelpMan importdescriptors()
      5     bool have_prune_boundary = false;
      6     int64_t min_trial_start_time = 0;
      7 
      8-
      9     UniValue utxo_diff_obj;
     10 
     11     if (do_scan_utxoset && rescan) {
     12@@ -516,53 +515,53 @@ RPCHelpMan importdescriptors()
     13 
     14         CAmount utxo_scanned_balance = GetWalletUTXOSetBalance(wallet);
     15 
     16-    if (utxo_scanned_balance != bal.m_mine_trusted) {
     17-        // Incremental-rescan chunking parameters
     18-        const int chunk_blocks = 1000;
     19-        const int64_t avg_block_time = 600; // seconds per block (approx)
     20+        if (utxo_scanned_balance != bal.m_mine_trusted) {
     21+            // Incremental-rescan chunking parameters
     22+            const int chunk_blocks = 1000;
     23+            const int64_t avg_block_time = 600; // seconds per block (approx)
     24 
     25-        // Get tip time and height
     26-        int64_t tip_time = 0;
     27-        int tip_height = 0;
     28-        {
     29-        LOCK(pwallet->cs_wallet);
     30-        CHECK_NONFATAL(pwallet->chain().findBlock(pwallet->GetLastBlockHash(), FoundBlock().time(tip_time).height(tip_height)));
     31-        }
     32+            // Get tip time and height
     33+            int64_t tip_time = 0;
     34+            int tip_height = 0;
     35+            {
     36+                LOCK(pwallet->cs_wallet);
     37+                CHECK_NONFATAL(pwallet->chain().findBlock(pwallet->GetLastBlockHash(), FoundBlock().time(tip_time).height(tip_height)));
     38+            }
     39 
     40-        // If pruned, compute an approximate earliest start time based on prune height
     41-        bool is_pruned = pwallet->chain().havePruned();
     42-        std::optional<int> prune_height_opt = pwallet->chain().getPruneHeight();
     43-        have_prune_boundary = false;
     44-        min_trial_start_time = 0;
     45-        if (is_pruned && prune_height_opt.has_value()) {
     46-            const int prune_height = prune_height_opt.value();
     47-            int64_t blocks_diff = tip_height - prune_height;
     48-            if (blocks_diff < 0) blocks_diff = 0;
     49-            int64_t prune_time_est = tip_time - blocks_diff * avg_block_time;
     50-            if (prune_time_est < 0) prune_time_est = 0;
     51-            min_trial_start_time = prune_time_est;
     52-            have_prune_boundary = true;
     53-        }
     54+            // If pruned, compute an approximate earliest start time based on prune height
     55+            bool is_pruned = pwallet->chain().havePruned();
     56+            std::optional<int> prune_height_opt = pwallet->chain().getPruneHeight();
     57+            have_prune_boundary = false;
     58+            min_trial_start_time = 0;
     59+            if (is_pruned && prune_height_opt.has_value()) {
     60+                const int prune_height = prune_height_opt.value();
     61+                int64_t blocks_diff = tip_height - prune_height;
     62+                if (blocks_diff < 0) blocks_diff = 0;
     63+                int64_t prune_time_est = tip_time - blocks_diff * avg_block_time;
     64+                if (prune_time_est < 0) prune_time_est = 0;
     65+                min_trial_start_time = prune_time_est;
     66+                have_prune_boundary = true;
     67+            }
     68 
     69-        // Attempt incremental rescans using the helper defined above.
     70-        int out_chunks_tried = 0;
     71-        int64_t out_lowest_ts = 0;
     72-        UniValue early = IncrementalRescansNonOverlap(wallet, tip_time, tip_height, chunk_blocks, avg_block_time, have_prune_boundary,
     73-                                                        min_trial_start_time, utxo_scanned_balance, reserver, response, out_chunks_tried, out_lowest_ts);
     74+            // Attempt incremental rescans using the helper defined above.
     75+            int out_chunks_tried = 0;
     76+            int64_t out_lowest_ts = 0;
     77+            UniValue early = IncrementalRescansNonOverlap(wallet, tip_time, tip_height, chunk_blocks, avg_block_time, have_prune_boundary,
     78+                                                            min_trial_start_time, utxo_scanned_balance, reserver, response, out_chunks_tried, out_lowest_ts);
     79 
     80-        if (!early.isNull()) {
     81-            // Matched and response already annotated by helper.
     82-            return early;
     83-        }
     84+            if (!early.isNull()) {
     85+                // Matched and response already annotated by helper.
     86+                return early;
     87+            }
     88 
     89-        if (have_prune_boundary) {
     90-            // Set the fallback rescan start to the prune boundary (instead of 0)
     91-            lowest_timestamp = min_trial_start_time;
     92-        } else {
     93-            // Non-pruned node: incremental attempts scanned back to timestamp 0 (genesis)
     94-            lowest_timestamp = 0;
     95+            if (have_prune_boundary) {
     96+                // Set the fallback rescan start to the prune boundary (instead of 0)
     97+                lowest_timestamp = min_trial_start_time;
     98+            } else {
     99+                // Non-pruned node: incremental attempts scanned back to timestamp 0 (genesis)
    100+                lowest_timestamp = 0;
    101+            }
    102         }
    103-    }
    104 
    105     }
    106 
    
  27. in src/wallet/rpc/backup.cpp:513 in 82a222b00d outdated
    508+    int64_t min_trial_start_time = 0;
    509+
    510+
    511+    UniValue utxo_diff_obj;
    512+
    513+    if (do_scan_utxoset && rescan) {
    


    rkrux commented at 1:08 pm on November 11, 2025:

    In https://github.com/bitcoin/bitcoin/commit/82a222b00d6497dc22e85205dae577a1adf15989 “rpc: extend importdescriptors with UTXO check and incremental rescan”

    Why is the UTXO set balance check (and the corresponding incremental block scan incase of balance mismatch) done before the usual rescan that’s supposed to be done upon a successful descriptor import? Should this not be done after the usual rescan to find any transactions in the older blocks that might have been missed in the rescan because of incorrect timestamp added by the user?

  28. in src/wallet/rpc/backup.cpp:326 in fa3ac7378c outdated
    322@@ -323,6 +323,7 @@ RPCHelpMan importdescriptors()
    323                             },
    324                         },
    325                         RPCArgOptions{.oneline_description="requests"}},
    326+                        {"scan_utxoset", RPCArg::Type::BOOL, RPCArg::Default{false}, "If true, scans the UTXO set balance and compare with wallet balance and triggers incremental rescan if discrepency is found."}
    


    rkrux commented at 1:11 pm on November 11, 2025:

    In fa3ac7378ca016c598d51fa00a9cc02103754569 “wallet/rpc: add scan_utxoset arg & docs for importdescriptors”

    0s/"scan_utxoset"/"verify"
    

    From a user’s POV, this feels to me more like a verification step that the wallet might do if set by the user. Let’s just call it that to keep it simple for the user?


    rkrux commented at 1:43 pm on November 11, 2025:
    0s/discrepency/discrepancy
    
  29. in test/functional/wallet_importdescriptors.py:104 in 1ed236e3c6
     99+        wallet_no_scan = node.get_wallet_rpc('watch_only_no_scan')
    100+        wallet_with_scan = node.get_wallet_rpc('watch_only_with_scan')
    101+
    102+        # Blank wallets don't have a birth time
    103+        assert 'birthtime' not in wallet_no_scan.getwalletinfo()
    104+        assert 'birthtime' not in wallet_with_scan.getwalletinfo()
    


    rkrux commented at 1:11 pm on November 11, 2025:

    In 1ed236e3c686582e35f20ab668cd6d93316fae2c “test: add functional test for importdescriptors scan_utxo flag”

    What’s the reason to assert this at only this stage?

  30. in src/wallet/rpc/backup.cpp:553 in 82a222b00d outdated
    548+        int out_chunks_tried = 0;
    549+        int64_t out_lowest_ts = 0;
    550+        UniValue early = IncrementalRescansNonOverlap(wallet, tip_time, tip_height, chunk_blocks, avg_block_time, have_prune_boundary,
    551+                                                        min_trial_start_time, utxo_scanned_balance, reserver, response, out_chunks_tried, out_lowest_ts);
    552+
    553+        if (!early.isNull()) {
    


    rkrux commented at 1:22 pm on November 11, 2025:

    In https://github.com/bitcoin/bitcoin/commit/82a222b00d6497dc22e85205dae577a1adf15989 “rpc: extend importdescriptors with UTXO check and incremental rescan”

    Shouldn’t the timestamp of the imported descriptors be updated as well in this case to avoid data inconsistency?

  31. in src/wallet/rpc/backup.cpp:344 in fa3ac7378c outdated
    338@@ -338,21 +339,28 @@ RPCHelpMan importdescriptors()
    339                             {
    340                                 {RPCResult::Type::ELISION, "", "JSONRPC error"},
    341                             }},
    342+                            {RPCResult::Type::OBJ, "info", /*optional=*/true, "Optional informational fields. When present, this object will contain details about incremental rescans (examples below).",
    343+                            {
    344+                                {RPCResult::Type::STR, "utxo_check", /*optional=*/true, "Status of the UTXO check. Example values: 'matched' (wallet DB matches UTXO set)."},
    


    rkrux commented at 1:46 pm on November 11, 2025:

    In https://github.com/bitcoin/bitcoin/commit/fa3ac7378ca016c598d51fa00a9cc02103754569 “wallet/rpc: add scan_utxoset arg & docs for importdescriptors”

    This string property seems unnecessary if it is supposed to have only one value all the time.

  32. in src/wallet/rpc/backup.cpp:355 in fa3ac7378c outdated
    360 {
    361     std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(main_request);
    362     if (!pwallet) return UniValue::VNULL;
    363     CWallet& wallet{*pwallet};
    364 
    365-    // Make sure the results are valid at least up to the most recent block
    


    rkrux commented at 1:51 pm on November 11, 2025:

    In https://github.com/bitcoin/bitcoin/commit/fa3ac7378ca016c598d51fa00a9cc02103754569 “wallet/rpc: add scan_utxoset arg & docs for importdescriptors”

    Why is this comment cut midway?

  33. in src/wallet/rpc/backup.cpp:346 in fa3ac7378c outdated
    338@@ -338,21 +339,28 @@ RPCHelpMan importdescriptors()
    339                             {
    340                                 {RPCResult::Type::ELISION, "", "JSONRPC error"},
    341                             }},
    342+                            {RPCResult::Type::OBJ, "info", /*optional=*/true, "Optional informational fields. When present, this object will contain details about incremental rescans (examples below).",
    343+                            {
    344+                                {RPCResult::Type::STR, "utxo_check", /*optional=*/true, "Status of the UTXO check. Example values: 'matched' (wallet DB matches UTXO set)."},
    345+                                {RPCResult::Type::NUM, "scanned_chunks", /*optional=*/true, "If incremental rescans were performed, the number of chunks scanned before a match was found."},
    346+                                {RPCResult::Type::NUM, "scanned_blocks", /*optional=*/true, "If incremental rescans were performed, the approximate number of blocks scanned (scanned_chunks * chunk_size)."},
    


    rkrux commented at 1:58 pm on November 11, 2025:

    In https://github.com/bitcoin/bitcoin/commit/fa3ac7378ca016c598d51fa00a9cc02103754569 “wallet/rpc: add scan_utxoset arg & docs for importdescriptors”

    I think these don’t need to be marked optional when the info object is already marked so. Unless these properties appear optionally inside the info object that I think is not the case.

  34. in src/wallet/receive.cpp:290 in ac06ddb8b9 outdated
    285+        for (const auto& script : spkm->GetScriptPubKeys()) {
    286+            if (has_privkeys) {
    287+                output_scripts_mine.emplace(script);
    288+            } else {
    289+                output_scripts_watchonly.emplace(script);
    290+            }
    


    rkrux commented at 2:03 pm on November 11, 2025:

    In ac06ddb8b9e33b7a594af9e38e00f2a8410947b7 “wallet: add GetWalletUTXOSetBalance to calculate balance from UTXO set”

    I don’t think the bifurcation between output_scripts_mine and output_scripts_watchonly needs to be done anymore because the watch only property in the descriptor wallets is at the wallet level now. Either the whole wallet will be watch-only or all of it will be not. Ref: #32618

  35. in src/wallet/rpc/backup.cpp:510 in 82a222b00d outdated
    505     }
    506 
    507+    bool have_prune_boundary = false;
    508+    int64_t min_trial_start_time = 0;
    509+
    510+
    


    rkrux commented at 2:08 pm on November 11, 2025:

    In https://github.com/bitcoin/bitcoin/commit/82a222b00d6497dc22e85205dae577a1adf15989 “rpc: extend importdescriptors with UTXO check and incremental rescan”

    Can early return from the function here in case rescan is false.

  36. rkrux commented at 2:27 pm on November 11, 2025: contributor

    Concept ACK and cursory review 1ed236e3c686582e35f20ab668cd6d93316fae2c.

    The intent of the PR and the corresponding issue #28898 seems fine to me.


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-11-12 18:13 UTC

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