wallet: Allow importing of descriptors without private keys when the wallet has the private keys #35377

pull achow101 wants to merge 7 commits into bitcoin:master from achow101:importdescriptors-without-priv changing 12 files +648 −277
  1. achow101 commented at 11:55 PM on May 25, 2026: member

    Currently importing a descriptor to a wallet that has private keys requires the descriptor to include the private keys. This is not ideal as it means exposing private key material. This PR makes it so that the wallet will lookup and substitute the private keys for their respective public keys in such descriptors, thus enabling importing of public descriptors into wallets with private keys.

    The underlying mechanism is that the wallet retrieves all of the pubkeys from the descriptor and checks to see if any of them have private keys in any ScriptPubKeyMan. Additionally, if the descriptor has a xpub with key origin info, we will check if any xprvs known to the wallet have a matching fingerprint and derive to the specified xpub. If so, the origin + xpub are replaced with the single xprv with the origin derivation path prepended to the key expression's derivation path.

    Possible future work is to allow the xpub substitution to work when the wallet has some child in the key origin, i.e. the wallet xprv has a key origin that is a prefix of the key origin specified for an xpub in the descriptor. Currently this kind of substitution is not being done, only root master xprvs will be substituted.

    If a wallet does not have the private keys for a public descriptor, the import is still disallowed.

    This PR is based on #34861 to avoid an annoying rebase.

    Closes #27336

  2. DrahtBot added the label Wallet on May 25, 2026
  3. DrahtBot commented at 11:55 PM on May 25, 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/35377.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process. A summary of reviews will appear here.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #bitcoin-core/gui/872 (Menu action to export a watchonly wallet by achow101)
    • #34861 (wallet: Add importdescriptors interface by polespinasa)
    • #34681 (wallet: move rescan logic into ChainScanner and wallet/scan by Eunovo)
    • #34520 (refactor: Add [[nodiscard]] to functions returning bool+mutable ref by maflcko)
    • #33392 (wallet, rpc: add UTXO set check and incremental rescan to importdescriptors by musaHaruna)
    • #32489 (wallet: Add exportwatchonlywallet RPC to export a watchonly version of a wallet by achow101)
    • #31668 (Added rescan option for import descriptors by saikiran57)

    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.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

    LLM Linter (✨ experimental)

    Possible typos and grammar issues:

    • harded -> hardened [misspelling in the comment about derivation]
    • descrptors -> descriptors [misspelling in the comment about ranged descriptors]
    • substition -> substitution [misspelling in the test log message]

    <sup>2026-05-26 18:15:49</sup>

  4. DrahtBot added the label Needs rebase on May 26, 2026
  5. wallet: Add ImportDescriptorRequest and ImportDescriptorResult structs
    Add two new structs used for creating requests and getting response when importing descriptors.
    
    These structs replace the UniValue-based interface of ProcessDescriptorImport()
    in a subsequent commit.
    d77b178245
  6. wallet: refactor importdescriptors RPC
    Rename ProcessDescriptorImport() to ImportDescriptor() and replace its
    UniValue-based arguments and return value with the ImportDescriptorRequest
    and ImportDescriptorResult structs introduced in the previous commit.
    
    Add ProcessDescriptorsImport() to handle wallet locking and rescanning
    over a vector of ImportDescriptorRequest items.
    
    Add ProcessUniValueDescriptor() to translat from the UniValue arguments
    used by the importdescriptors RPC into ImportDescriptorRequest.
    
    This allows a next commit to extract ImportDescriptor() and
    ProcessDescriptorsImport() out of the RPC code so they can be used by
    other future interfaces.
    7f5e87bb82
  7. wallet: Move ImportDescriptor and ProcessDescriptorsImport to imports.cpp
    Extract ImportDescriptor() and ProcessDescriptorsImport() out of backup.cpp and move it into imports.cpp so other future interfaces
    can use them without needing to know about RPC code.
    785a688d7b
  8. wallet: Add an importDescriptors() interface for the wallet 19dd0775ec
  9. descriptor: Implement SubstituteMasterExtPubs
    SubstituteMasterExtPubs replaces Origin + BIP32 inside of a descriptor
    when a master xprv is provided that matches the origin and derives the
    BIP32 xpub.
    3c81eee96c
  10. wallet: Substitute known keys when importing a descriptor
    When an imported descriptor contains pubkeys for which the wallet knows
    the private keys, substitute those pubkeys for the privkeys so that the
    descriptor can be imported. This allows such descriptors without private keys
    to be imported into wallets with private keys enabled.
    5741ac120a
  11. test: Test importdescriptors with descriptors without privkeys
    Test that importdescriptors can import descriptors that don't have
    private keys, but the wallet already has the private key for them.
    2e6d8d0b8b
  12. achow101 force-pushed on May 26, 2026
  13. DrahtBot removed the label Needs rebase on May 26, 2026

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-29 19:51 UTC

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