-
Notifications
You must be signed in to change notification settings - Fork 37.8k
wallet, rpc: add an option to list private descriptors #21500
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsNo conflicts as of last run. |
0bb5e35
to
b78fe43
Compare
src/wallet/rpcdump.cpp
Outdated
@@ -1736,7 +1736,9 @@ RPCHelpMan listdescriptors() | |||
return RPCHelpMan{ | |||
"listdescriptors", | |||
"\nList descriptors imported into a descriptor-enabled wallet.", | |||
{}, | |||
{ | |||
{"private", RPCArg::Type::BOOL, /* default */ "false", "Show private descriptors."} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this should be a numbered parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you saying it shouldn't be a parameter at all? Or it should be a "named-only" parameter? I can't see how to make it "named-only"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Named-only parameters are provided in the positional API as an "options" Object.
src/wallet/rpcdump.cpp
Outdated
@@ -1736,7 +1736,9 @@ RPCHelpMan listdescriptors() | |||
return RPCHelpMan{ | |||
"listdescriptors", | |||
"\nList descriptors imported into a descriptor-enabled wallet.", | |||
{}, | |||
{ | |||
{"private", RPCArg::Type::BOOL, /* default */ "false", "Show private descriptors."} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO it would be better to have a separate RPC method for private data.
Concept ACK. The second commit seems unrelated. |
b78fe43
to
d59e43b
Compare
Fixed silent merge conflict and split the 2nd commit into #22334 |
d59e43b
to
a0d9919
Compare
a0d9919
to
2854ddc
Compare
Tried Create Wallet:
List descriptors:
Response (I get the same response for
|
Are you sure you are using this branch? I get the private key with |
ACK 2854ddc Reviewed code and tested manually. |
Yes just noticed the difference. Sorry they looked same and both had 6 results. So, I was confused. |
@prayank23 Thanks for testing! By default descriptor wallet has two descriptors for each type:
One of the two descriptors is for receiving, marked with So in the end you've got 6 of them. Each descriptor is derived from the same extended master private key (you can see it's fingerprint repeating in the descriptors; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tACK 2854ddc
I'm getting a build error trying to test: (edited out). I'm getting these on master as well, so investigating/removing from here as it is not this PR specific. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 2854ddc
Some minor suggestions, happy to re-ACK if you update.
2854ddc
to
cd36796
Compare
cd36796
to
bb822a7
Compare
Added a test case for the error when trying to get private descriptors for watch-only wallet. Plus minor readability and grammar fixes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding the test!
ACK bb822a7 per git diff 2854ddc bb822a7
Verified the test assertions added in this pull fail on master as expected, e.g. they have to be commented-out for the test file to pass
diff --git a/test/functional/wallet_listdescriptors.py b/test/functional/wallet_listdescriptors.py
index 6e7be929cc..61de4621bf 100755
--- a/test/functional/wallet_listdescriptors.py
+++ b/test/functional/wallet_listdescriptors.py
@@ -71,7 +71,7 @@ class ListDescriptorsTest(BitcoinTestFramework):
],
}
assert_equal(expected, wallet.listdescriptors())
- assert_equal(expected, wallet.listdescriptors(False))
+ # assert_equal(expected, wallet.listdescriptors(False))
self.log.info('Test list private descriptors')
expected_private = {
@@ -84,16 +84,16 @@ class ListDescriptorsTest(BitcoinTestFramework):
'next': 0},
],
}
- assert_equal(expected_private, wallet.listdescriptors(True))
+ # assert_equal(expected_private, wallet.listdescriptors(True))
self.log.info("Test listdescriptors with encrypted wallet")
wallet.encryptwallet("pass")
assert_equal(expected, wallet.listdescriptors())
self.log.info('Test list private descriptors with encrypted wallet')
- assert_raises_rpc_error(-13, 'Please enter the wallet passphrase with walletpassphrase first.', wallet.listdescriptors, True)
+ # assert_raises_rpc_error(-13, 'Please enter the wallet passphrase with walletpassphrase first.', wallet.listdescriptors, True)
wallet.walletpassphrase(passphrase="pass", timeout=1000000)
- assert_equal(expected_private, wallet.listdescriptors(True))
+ # assert_equal(expected_private, wallet.listdescriptors(True))
self.log.info('Test list private descriptors with watch-only wallet')
node.createwallet(wallet_name='watch-only', descriptors=True, disable_private_keys=True)
@@ -102,7 +102,7 @@ class ListDescriptorsTest(BitcoinTestFramework):
'desc': descsum_create('wpkh(' + xpub_acc + ')'),
'timestamp': 1296688602,
}])
- assert_raises_rpc_error(-4, 'Can\'t get descriptor string', watch_only_wallet.listdescriptors, True)
+ # assert_raises_rpc_error(-4, 'Can\'t get descriptor string', watch_only_wallet.listdescriptors, True)
self.log.info('Test non-active non-range combo descriptor')
node.createwallet(wallet_name='w4', blank=True, descriptors=True)
'desc': descsum_create('wpkh(' + xpub_acc + ')'), | ||
'timestamp': 1296688602, | ||
}]) | ||
assert_raises_rpc_error(-4, 'Can\'t get descriptor string', watch_only_wallet.listdescriptors, True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(pico-nit, only if you retouch)
assert_raises_rpc_error(-4, 'Can\'t get descriptor string', watch_only_wallet.listdescriptors, True) | |
assert_raises_rpc_error(-4, "Can't get descriptor string", watch_only_wallet.listdescriptors, True) |
@@ -71,11 +71,39 @@ def run_test(self): | |||
], | |||
} | |||
assert_equal(expected, wallet.listdescriptors()) | |||
assert_equal(expected, wallet.listdescriptors(False)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe use named args (as this argument is new and true/false isn't very descriptive), feel free to ignore
assert_equal(expected, wallet.listdescriptors())
- assert_equal(expected, wallet.listdescriptors(False))
+ assert_equal(expected, wallet.listdescriptors(private=False))
self.log.info('Test list private descriptors')
expected_private = {
@@ -84,16 +84,16 @@ class ListDescriptorsTest(BitcoinTestFramework):
'next': 0},
],
}
- assert_equal(expected_private, wallet.listdescriptors(True))
+ assert_equal(expected_private, wallet.listdescriptors(private=True))
self.log.info("Test listdescriptors with encrypted wallet")
wallet.encryptwallet("pass")
assert_equal(expected, wallet.listdescriptors())
self.log.info('Test list private descriptors with encrypted wallet')
- assert_raises_rpc_error(-13, 'Please enter the wallet passphrase with walletpassphrase first.', wallet.listdescriptors, True)
+ assert_raises_rpc_error(-13, 'Please enter the wallet passphrase with walletpassphrase first.', wallet.listdescriptors, private=True)
wallet.walletpassphrase(passphrase="pass", timeout=1000000)
- assert_equal(expected_private, wallet.listdescriptors(True))
+ assert_equal(expected_private, wallet.listdescriptors(private=True))
self.log.info('Test list private descriptors with watch-only wallet')
node.createwallet(wallet_name='watch-only', descriptors=True, disable_private_keys=True)
@@ -102,7 +102,7 @@ class ListDescriptorsTest(BitcoinTestFramework):
'desc': descsum_create('wpkh(' + xpub_acc + ')'),
'timestamp': 1296688602,
}])
- assert_raises_rpc_error(-4, 'Can\'t get descriptor string', watch_only_wallet.listdescriptors, True)
+ assert_raises_rpc_error(-4, 'Can\'t get descriptor string', watch_only_wallet.listdescriptors, private=True)
self.log.info('Test non-active non-range combo descriptor')
node.createwallet(wallet_name='w4', blank=True, descriptors=True)
re-ACK bb822a7 |
@prayank23 @Rspigler do you want to check the latest version? |
Sure. Will try today. I had two questions, maybe @practicalswift can help me:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tACK bb822a7
Tested everything mentioned in PR description and below things:
W1: Descriptor wallet with private keys
W2: Blank Descriptor wallet
W3: Descriptor wallet with private keys disabled
W4: Another Descriptor wallet with private keys
- Export descriptors from wallet W1 and import in same wallet
- Export descriptors from wallet W1 and import in Wallet W2 and W4
- Export descriptors from wallet W1 and import in Wallet W3
Everything looks good with listdescriptors
, maybe we can improve one thing in importdescriptors
:
When exporting-importing in same wallet it does not import duplicates however response is same as 2.
{
"success": true
}
I don't see this warning for watch only wallet. It returns wallet name and blank array for descriptors. |
tACK bb822a7 This would be very helpful for metal or paper backups
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code review ACK bb822a7
…iptors bb822a7 wallet, rpc: add listdescriptors private option (S3RK) Pull request description: Rationale: make it possible to backup your wallet with `listdescriptors` command * The default behaviour is still to show public version * For private version only the root xprv is returned Example use-case: ``` > bitcoin-cli -regtest -named createwallet wallet_name=old descriptors=true > bitcoin-cli -regtest -rpcwallet=old listdescriptors true | jq '.descriptors' > descriptors.txt > bitcoin-cli -regtest -named createwallet wallet_name=new descriptors=true blank=true > bitcoin-cli -regtest -rpcwallet=new importdescriptors "$(cat descriptors.txt)" ``` In case of watch-only wallet without private keys there will be following output: ``` error code: -4 error message: Can't get descriptor string. ``` ACKs for top commit: achow101: re-ACK bb822a7 Rspigler: tACK bb822a7 jonatack: ACK bb822a7 per `git diff 2854ddc bb822a7` prayank23: tACK bitcoin@bb822a7 meshcollider: Code review ACK bb822a7 Tree-SHA512: f6dddc72a74e5667071ccd77f8dce578382e8e29e7ed6a0834ac2e114a6d3918b59c2f194f4079b3259e13d9ba3b4f405619940c3ecb7a1a0344615aed47c43d
Rationale: make it possible to backup your wallet with
listdescriptors
commandExample use-case:
In case of watch-only wallet without private keys there will be following output: