-
Notifications
You must be signed in to change notification settings - Fork 38.7k
Allow specific private keys to be derived from descriptor #15024
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. ConflictsReviewers, this pull request conflicts with the following ones:
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. |
Sjors
left a comment
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.
Concept ACK. Code changes look simple enough at first glance, will review more once upstream is merged.
I suggest dropping the keys argument for importmulti when a descriptor is used. At least assuming this makes it into the same release as the previous PR.
| Needs rebase |
|
I'll rebase this after #14491 is merged |
|
Needs rebase |
|
I am strongly interested in this for the usability of my offline-signing work, and will give it a look. |
|
Could you rebase now that 14491 is in? It will clean up the diff a lot. Then I'll take a look. |
|
Rebased :) |
|
ACK with some testing. I tested one ranged and one non-ranged descriptor, verified with deriveaddresses and getaddressinfo that I get the correct keypaths and such displayed everywhere, and is_mine is true where expected. I did not test actually spending. I get a slightly weird result from getaddressinfo which I assume is probably not exactly the fault of this PR: I get an "hdseedid" of "0000000000000000000000000000000000000000" for all keys derived this way. It seems like, if we don't have an hdseedid, that key should instead be left out, as it is optional. I suspect before this change we may rarely or never have had derived private keys without an hdseedid available, so it never came up. I am interested in whether a key imported this way would be expected to be used by the wallet, in the case where we are trying to sign for some other descriptor where the key appeared, other than the one imported using importmulti. (In particular, a multisig descriptor where we only have one key and are creating a partial signature using walletprocesspsbt.) |
jnewbery
left a comment
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.
Concept ACK.
I've left a couple of comments on the test. The last two commits should be squashed (currently the penultimate commit fails because the RPC has changed but test hasn't been updated).
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.
Comment above (# Test importing of a ranged descriptor without keys) needs to be updated to something like # Test importing of a ranged descriptor with xpriv
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.
This isn't testing anything (the address loop variable in not being used, and the address tested is left over from the test above)
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.
@jnewbery not sure what you mean, it calls self.test_address(address, ...) with each address to ensure they imported correctly from the xpriv after failing to import in the test before?
EDIT: sorry, I was looking at an older branch, will fix
|
ACK code changes, but I think the tests don't cover much. |
ariard
left a comment
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.
Tested the following descriptors :
- pkh(m/0h/0h/*h), range[1-3]
- pkh(m/0h/0h/0h)
- sh(wpkh(m/0h/0h/*h), range[1-3]
- sh(wpkh(m/0h/0h/0h)
- wpkh(m/0h/0h/0h)
- wpkh(m/0h/0h/*h), range[1-3]
- wsh(multi(2, m/0h/1h/0h, m/0h/1h/0h)))
For each, I took master key from wallet dump, then created a blank wallet and importmulti descriptor then diff expanded private keys from blank wallet dump against master wallet dump ones.
I had to turn require_checksum as false in Parse due to not straighforward way to calculate checksum for descriptors with private keys (and it's not really clear from descriptor.cpp if bip32 encoded xpub or xpriv need to be also in form SCRIPT#CHECKSUM), maybe add checksum boolean in importmulti args ?
Also while testing wsh(multi(2, ..., ...)) I got descriptor parsed as p2sh-segwit address instead of a bech32 one, is this normal (with addresstype=p2sh-segwit) ?
src/wallet/rpcdump.cpp
Outdated
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.
nit: Maybe take opportunity to add importmulti as a supporting RPC in descriptors.md.
You may also add a descriptor import example in importmulti
I don't know what you mean by this. What RPC/function calls did you make, and what did you observe? |
|
I did : Got Result : |
|
That's not surprising, but why are you calling EDIT: Oh, because that's the address you got from the dump? Don't rely on those, it's very hard for the current logic to guess what addresses you actually wanted imported (it inevitably imports other versions of the same policy along with it). |
|
Yes that's it I was relying on address from the dump, it's fine with So tested ACK e00c3dd minor the maybe-add-a-no-checksum option arg in RPC |
|
I'd like to see more tests. I tried a similar example as @ariard, but having some difficulty: I can derive addresses using the public key version with checksum returned above: But I can't import it (in a blank wallet): My guess is that it needs a checksum. See related discussion in #15740. |
|
@meshcollider please update OP as the base PR is already merged. |
|
Fixed the test and amended the comment pointed out by John |
ryanofsky
left a comment
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.
utACK b6dc630019dce4a0852c5c02fd6154c773ca5ebe. Previous reviews asked for more tests: #15024 (comment) and #15024 (comment), but it's unclear what other kinds of tests would be helpful here.
src/script/descriptor.cpp
Outdated
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.
In commit "Add private key derivation functions to descriptors" (ca039db0776b1626ce4d220a0da5ff985d93985d)
This is duplicating code already in GetPubKey above. Since this has to exist separately, it'd be good to change GetPubKey to call this function. It'd simplify GetPubKey and remove a chunk of duplicate code.
|
@ryanofsky done, thanks! |
The added test in this PR checks that importing Suggested additional tests:
|
|
Thanks for the suggestions @jnewbery, I've added the first two tests you suggested, but I'm unsure about the third. The first test already tests the BIP32PubkeyProvider derivation. Did you mean OriginPubkeyProvider? OriginPubkeyProvider just calls the BIP32 derivation though so I don't think it needs a separate test |
achow101
left a comment
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.
Tested ACK 2857bc4
Checked it compiled and passed tests. Also tested an import manually and checked that private keys are actually imported and can be exported with dumpprivkey. I would feel better if you had a test that did dumpprivkey or signmessage on the imported keys to be sure that the private keys exist.
|
@achow101 done |
|
ACK 53b7de6 Squash yo commits |
53b7de6 Add test for dumping the private key imported from descriptor (MeshCollider) 2857bc4 Extend importmulti descriptor tests (MeshCollider) 81a884b Import private keys from descriptor with importmulti if provided (MeshCollider) a4d1bd1 Add private key derivation functions to descriptors (MeshCollider) Pull request description: ~This is based on #14491, review the last 3 commits only.~ Currently, descriptors have an Expand() function which returns public keys and scripts for a specific index of a ranged descriptor. But the private key for a specific index is not given. This allows private keys for specific indices to be derived. This also allows those keys to be imported through the `importmulti` RPC rather than having to provide them separately. ACKs for commit 53b7de: achow101: ACK 53b7de6 Tree-SHA512: c060bc01358a1adc76d3d470fefc2bdd39c837027f452e9bc4bd2e726097e1ece4af9d5627efd942a5f8819271e15ba54f010b169b50a9435a1f0f40fd1cebf3
…escriptor 53b7de6 Add test for dumping the private key imported from descriptor (MeshCollider) 2857bc4 Extend importmulti descriptor tests (MeshCollider) 81a884b Import private keys from descriptor with importmulti if provided (MeshCollider) a4d1bd1 Add private key derivation functions to descriptors (MeshCollider) Pull request description: ~This is based on bitcoin#14491, review the last 3 commits only.~ Currently, descriptors have an Expand() function which returns public keys and scripts for a specific index of a ranged descriptor. But the private key for a specific index is not given. This allows private keys for specific indices to be derived. This also allows those keys to be imported through the `importmulti` RPC rather than having to provide them separately. ACKs for commit 53b7de: achow101: ACK 53b7de6 Tree-SHA512: c060bc01358a1adc76d3d470fefc2bdd39c837027f452e9bc4bd2e726097e1ece4af9d5627efd942a5f8819271e15ba54f010b169b50a9435a1f0f40fd1cebf3
…iptor Summary: 53b7de629d3d9281dc6f8fa10e32c4cdec59c140 Add test for dumping the private key imported from descriptor (MeshCollider) 2857bc4a64cc8dc7914bc984ac878397ac64292d Extend importmulti descriptor tests (MeshCollider) 81a884bbd0dbee108d11776794d9627ca07504aa Import private keys from descriptor with importmulti if provided (MeshCollider) a4d1bd1a29be2dcc5e00c63b6b41916b1c466de0 Add private key derivation functions to descriptors (MeshCollider) Pull request description: ~This is based on #14491, review the last 3 commits only.~ Currently, descriptors have an Expand() function which returns public keys and scripts for a specific index of a ranged descriptor. But the private key for a specific index is not given. This allows private keys for specific indices to be derived. This also allows those keys to be imported through the `importmulti` RPC rather than having to provide them separately. --- Backport of Core [[bitcoin/bitcoin#15024 | PR15024]] Test Plan: ninja all check check-functional ~~afaict, either this functionality is unavailable for legacy addresses or Core didn't add tests aside from sh(wpkh()) descriptors~~ Reviewers: #bitcoin_abc, deadalnix Reviewed By: #bitcoin_abc, deadalnix Subscribers: PiRK, deadalnix Differential Revision: https://reviews.bitcoinabc.org/D7804
This is based on #14491, review the last 3 commits only.Currently, descriptors have an Expand() function which returns public keys and scripts for a specific index of a ranged descriptor. But the private key for a specific index is not given. This allows private keys for specific indices to be derived. This also allows those keys to be imported through the
importmultiRPC rather than having to provide them separately.