test: Add importdescriptors rpc error coverage #35179

pull polespinasa wants to merge 3 commits into bitcoin:master from polespinasa:2026-04-29-testaddimportdescriptorsrpccoverage changing 2 files +41 −3
  1. polespinasa commented at 11:55 AM on April 29, 2026: member

    The current tests for importdescriptors RPC do not check for cases where RPC errors should be thrown.

    This PR adds coverage for importing a descriptor when the wallet is encrypted , for importing a descriptor while the wallet is rescanning and importing a descriptor while using assumeutxo

    For context, this lack of coverage was found while implementing #34861 when a reviewer found that this was being silently broken in the PR.

    I am not sure if the "rescanning test" approach is the optimal solution, I am open to suggestions.

  2. DrahtBot added the label Tests on Apr 29, 2026
  3. DrahtBot commented at 11:55 AM on April 29, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

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

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Stale ACK ViniciusCestarii

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    No conflicts as of last run.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  4. polespinasa force-pushed on Apr 29, 2026
  5. DrahtBot added the label CI failed on Apr 29, 2026
  6. polespinasa force-pushed on Apr 29, 2026
  7. polespinasa force-pushed on Apr 29, 2026
  8. polespinasa force-pushed on Apr 29, 2026
  9. DrahtBot removed the label CI failed on Apr 29, 2026
  10. in test/functional/wallet_importdescriptors.py:846 in 9b06a8e069 outdated
     841 | +            # which should hold WalletRescanReserver for a few seconds.
     842 | +            with self.nodes[0].assert_debug_log(
     843 | +                expected_msgs=["Rescan started from block 0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206... (slow variant inspecting all blocks)"],
     844 | +                timeout=10,
     845 | +            ):
     846 | +                thread.submit(make_proxy().importdescriptors,
    


    junbyjun1238 commented at 5:17 PM on April 29, 2026:

    Question: Should the submitted import future be checked here?

    The second RPC call is made after the rescan-start log is observed, so this does exercise the "already rescanning" error path. But the background importdescriptors future is not stored or checked, and leaving the ThreadPoolExecutor context waits for it to finish before abortrescan() is called. So the later abortrescan() call likely does not actually abort this rescan.

    Would it be clearer to either assert the background import result, or move the abort/check inside the executor block if the intention is to stop the rescan early?


    polespinasa commented at 5:53 PM on April 29, 2026:

    But the background importdescriptors future is not stored or checked

    It doesn't matter, it is not what this test is doing. There are plenty of tests testing "normal" imports. This test only wants to make sure that if a rescan is going on, trying to import a descriptor to that wallet will fail.

    You are right about the abortrescan(), before it was inside the thread, I guess I moved it by mistake, but given the test is pretty fast, it can just be deleted.

  11. polespinasa force-pushed on Apr 29, 2026
  12. in test/functional/wallet_importdescriptors.py:836 in 9b06a8e069 outdated
     831 | +        wallet_name = "rescan_wallet"
     832 | +        self.nodes[0].createwallet(wallet_name=wallet_name, blank=True)
     833 | +        w_rescan = self.nodes[0].get_wallet_rpc(wallet_name)
     834 | +
     835 | +        def make_proxy():
     836 | +            return AuthServiceProxy(rpc_url(self.nodes[0].datadir_path, self.nodes[0].index, self.nodes[0].chain, self.nodes[0].rpchost) + "/wallet/" + wallet_name)
    


    ViniciusCestarii commented at 5:55 PM on April 29, 2026:

    nit: the testing framework has an util function for this:

            def make_proxy():
                return get_rpc_proxy(f"{self.nodes[0].url}/wallet/{wallet_name}", self.nodes[0].index)
    

    polespinasa commented at 7:12 PM on April 29, 2026:

    I could use get_rpc_proxy but there's no much difference because I cannot use self.nodes[0].url it returns None if --usecli is used.

    If I use get_rpc_proxy the diff would look like:

    <details> <summary>diff</summary>

    $ git diff
    diff --git a/test/functional/wallet_importdescriptors.py b/test/functional/wallet_importdescriptors.py
    index cd18bf4474..ef31bf5eec 100755
    --- a/test/functional/wallet_importdescriptors.py
    +++ b/test/functional/wallet_importdescriptors.py
    @@ -23,10 +23,10 @@ from test_framework.blocktools import COINBASE_MATURITY
     from test_framework.test_framework import BitcoinTestFramework
     from test_framework.descriptors import descsum_create
     from test_framework.script import SEQUENCE_LOCKTIME_TYPE_FLAG
    -from test_framework.authproxy import AuthServiceProxy
     from test_framework.util import (
         assert_equal,
         assert_raises_rpc_error,
    +    get_rpc_proxy,
         rpc_url,
     )
     from test_framework.wallet_util import (
    @@ -833,7 +833,8 @@ class ImportDescriptorsTest(BitcoinTestFramework):
             w_rescan = self.nodes[0].get_wallet_rpc(wallet_name)
     
             def make_proxy():
    -            return AuthServiceProxy(rpc_url(self.nodes[0].datadir_path, self.nodes[0].index, self.nodes[0].chain, self.nodes[0].rpchost) + "/wallet/" + wallet_name)
    +            return get_rpc_proxy(rpc_url(self.nodes[0].datadir_path, self.nodes[0].index, self.nodes[0].chain, self.nodes[0].rpchost) + f"/wallet/{wallet_name}",
    +             self.nodes[0].index)
     
             with concurrent.futures.ThreadPoolExecutor(max_workers=1) as thread:
                 slow_desc = descsum_create("pkh(" + xpriv + "/1h/*h)")
    
    

    </details>

    Which looks even a bit longer so it's less readable. I will let as is unless someone suggest a cleaner way of doing it.


    ViniciusCestarii commented at 7:43 PM on April 29, 2026:

    Cool, didn't know about the --usecli implication. Leaving as-is makes sense

  13. ViniciusCestarii commented at 6:22 PM on April 29, 2026: contributor

    tACK 5e23ea4007b1664c97de4e65c25204f7c6aaa06d

    The rescanning test looks fine. Line 724 has used the same pattern to prevent race condition since dbeca79

  14. polespinasa force-pushed on Apr 29, 2026
  15. DrahtBot added the label CI failed on Apr 29, 2026
  16. polespinasa force-pushed on Apr 29, 2026
  17. polespinasa force-pushed on Apr 29, 2026
  18. polespinasa commented at 8:25 PM on April 29, 2026: member

    Added another test for importdescriptors when using assumeutxo

  19. polespinasa force-pushed on Apr 29, 2026
  20. DrahtBot removed the label CI failed on Apr 29, 2026
  21. test: add coverage for importdescriptor with an encrypted wallet d1106e330b
  22. test: add coverage for importdescriptors while wallet is rescanning db04594f4f
  23. test: add coverage for importdescriptors errors when using assumeutxo
    Co-authored-by: w0xlt <woltx@protonmail.com>
    cb50adad6d
  24. in test/functional/wallet_importdescriptors.py:836 in efeb39996a
     831 | +        wallet_name = "rescan_wallet"
     832 | +        self.nodes[0].createwallet(wallet_name=wallet_name, blank=True)
     833 | +        w_rescan = self.nodes[0].get_wallet_rpc(wallet_name)
     834 | +
     835 | +        def make_proxy():
     836 | +            return AuthServiceProxy(rpc_url(self.nodes[0].datadir_path, self.nodes[0].index, self.nodes[0].chain, self.nodes[0].rpchost) + "/wallet/" + wallet_name)
    


    maflcko commented at 9:14 AM on May 6, 2026:

    you are side-stepping the timeout and the coverage. This may be fine, but I think it is cleaner to have a function here. Maybe faab8e28db0bf205451ff3d30f269167b73f24c0 (if you want to use the rpc), or alternatively, use the cli(), like the other tests that spin up a new thread and need a new rpc socket for that thread.


    polespinasa commented at 9:31 AM on May 6, 2026:

    Done, used cli()

  25. polespinasa force-pushed on May 6, 2026
  26. polespinasa commented at 9:32 AM on May 6, 2026: member

    Force pushed to address comments and rebased on top of master


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: 2026-05-20 06:52 UTC