#35377 wallet: Allow importing of descriptors without private keys when the wallet has the private keys
https://github.com/bitcoin/bitcoin/pull/35377 · · +830/-283 in 18 files, 16 commits · labels: Wallet · draft
Goal
- Allow importing public descriptors into a wallet if it already holds the matching private keys
- Removes the safety hazard and friction of exposing plaintext private keys during import
This PR enables importing public descriptors (including xpubs and individual pubkeys) into wallets that have private keys enabled, provided the wallet already holds the corresponding private keys. During import, the wallet inspects the descriptor for known keys and substitutes master xprvs and individual private keys in place of the public keys before loading.
Problem: Descriptor wallets with private keys currently reject public descriptors unless the private keys are explicitly supplied in the descriptor string. This creates friction and safety hazards for users and external coordinator software, requiring manual private key extraction and plaintext exposure to import derived or multisig descriptors.
Category: Wallet (#9 of 84)
P2 · fund safety
- P2 because it removes the need to handle and expose plaintext private keys to import descriptors
- Resolves a long-standing fund safety issue affecting multisig and coordinator workflows
P2 because it addresses a long-standing key-safety and usability deficiency where users must expose private key material in plaintext to import descriptors into privkey-enabled wallets. Resolves issue #27336 ('Should be able to import an xpub descriptor to a privkey-enabled wallet if the wallet has the privkeys') which has been a recurring pain point for multisig and coordinator workflows.
Membership: Modifies wallet import logic in src/wallet/imports.cpp and src/wallet/wallet.cpp, as well as Descriptor key substitution in src/script/descriptor.cpp
Factors: security/stability 2, bug 0, performance 0, user value 2, leverage 1
Reviewability: Ready
- Review #34861 first
- Ready for review with passing CI and isolated descriptor and wallet changes
The code is clean, CI passes, and the core changes are isolated to descriptor substitution and wallet import logic.
Author status: Active, recently force-pushed updates
Open concerns:
- Sjors suggested an alternative approach exploring whether descriptor parsing could be given direct access to known keys rather than performing substitution after parsing
Agreement: Strong
- Strong support for eliminating manual private key exposure during descriptor imports
- Concept approval because users do not have to deal with private keys manually (rkrux)
- Concept approval pending review of base PR #34861 (polespinasa)
- Concept approval with an alternative key resolution branch explored (Sjors)
Strong concept ACKs from multiple reviewers, with design feedback from Sjors
Reviewers strongly agree with the goal of avoiding manual private key handling during descriptor imports, and multiple contributors expressed intent to use this functionality.
- rkrux gave a Concept ACK noting it 'allows the users to not deal with private keys manually'
- polespinasa gave a Concept ACK pending review after base PR #34861
- Sjors gave a Concept ACK and shared an experimental branch testing an alternative key resolution approach
Review verdicts (DrahtBot): 0
- Concept ACK: rkrux, polespinasa, Sjors
Dependencies
Files
72 lines under test/bench/ci.
- src/script/descriptor.cpp +80/-15
- test/functional/wallet_importdescriptors.py +67/-4
- src/wallet/wallet.cpp +31/-0
- src/wallet/imports.cpp +24/-0
- src/script/descriptor.h +5/-0
- src/wallet/wallet.h +3/-0
- src/wallet/test/walletload_tests.cpp +1/-0
Card
This PR allows descriptor wallets with private keys enabled to import public descriptors when the wallet already holds the matching private keys or master xprvs. Currently, importing such descriptors fails unless private keys are provided in the descriptor, forcing users and coordinator tools to handle and expose raw private key material. The PR implements key substitution during import and closes issue #27336. Concept support is strong across multiple reviewers, with minor discussion regarding whether key resolution should happen inside descriptor parsing or via post-parse substitution.