feat(wallet): add Wallet::sign_psbt<K> wrapping bitcoin::Psbt::sign#438
feat(wallet): add Wallet::sign_psbt<K> wrapping bitcoin::Psbt::sign#438EliteCoder18 wants to merge 3 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #438 +/- ##
==========================================
+ Coverage 80.96% 81.01% +0.04%
==========================================
Files 24 24
Lines 5489 5503 +14
Branches 247 247
==========================================
+ Hits 4444 4458 +14
Misses 968 968
Partials 77 77
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Concept ACK. I've not had an extensive look at the implementation.
|
6694fbb to
ce3d189
Compare
|
@ValuedMammal Thanks for the feedback! I've updated the tests to use a base64 PSBT with pre-populated Would appreciate a review when you get a chance. |
| /// [`bitcoin::Psbt::sign`] uses the `bip32_derivation` fields in each PSBT input to | ||
| /// locate the correct child keys. PSBTs received from external coordinator tools or |
There was a problem hiding this comment.
the
bip32_derivationfields in each PSBT input to locate the correct child keys.
Or tap_key_origins in the case of taproot.
There was a problem hiding this comment.
Updated the doc comment to mention both bip32_derivation (legacy/segwit) and tap_key_origins (taproot). Thanks for catching that!
ce3d189 to
0884a8d
Compare
There was a problem hiding this comment.
cACK 0884a8d
Thanks for adding this. It will be useful after this is merged: rust-bitcoin/rust-miniscript#872
| /// Sign a PSBT using an external key provider via [`bitcoin::Psbt::sign`]. | ||
| /// | ||
| /// This is a thin wrapper around [`bitcoin::Psbt::sign`] that supplies the wallet's | ||
| /// internal [`secp256k1`] context. It lets callers sign with any type that implements | ||
| /// [`psbt::GetKey`], such as [`bitcoin::bip32::Xpriv`], without having to manage their | ||
| /// own secp256k1 context. | ||
| /// | ||
| /// # BIP32 derivation metadata | ||
| /// | ||
| /// [`bitcoin::Psbt::sign`] uses the `bip32_derivation` fields (for legacy and segwit inputs) | ||
| /// or the `tap_key_origins` fields (for taproot inputs) in each PSBT input to locate | ||
| /// the correct child keys. PSBTs received from external coordinator tools or | ||
| /// hardware wallet flows typically carry this metadata already. | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// On success, a [`psbt::SigningKeysMap`] mapping each signed input index to the keys | ||
| /// that were used. On failure, a tuple of the partial success map and a | ||
| /// [`psbt::SigningErrors`] map of per-input errors. | ||
| /// | ||
| /// [`secp256k1`]: bitcoin::secp256k1 |
There was a problem hiding this comment.
nit: What do you think of those docs changes? I added that it's used for software signing and pointed to the correct approach for external signing.
| /// Sign a PSBT using an external key provider via [`bitcoin::Psbt::sign`]. | |
| /// | |
| /// This is a thin wrapper around [`bitcoin::Psbt::sign`] that supplies the wallet's | |
| /// internal [`secp256k1`] context. It lets callers sign with any type that implements | |
| /// [`psbt::GetKey`], such as [`bitcoin::bip32::Xpriv`], without having to manage their | |
| /// own secp256k1 context. | |
| /// | |
| /// # BIP32 derivation metadata | |
| /// | |
| /// [`bitcoin::Psbt::sign`] uses the `bip32_derivation` fields (for legacy and segwit inputs) | |
| /// or the `tap_key_origins` fields (for taproot inputs) in each PSBT input to locate | |
| /// the correct child keys. PSBTs received from external coordinator tools or | |
| /// hardware wallet flows typically carry this metadata already. | |
| /// | |
| /// # Returns | |
| /// | |
| /// On success, a [`psbt::SigningKeysMap`] mapping each signed input index to the keys | |
| /// that were used. On failure, a tuple of the partial success map and a | |
| /// [`psbt::SigningErrors`] map of per-input errors. | |
| /// | |
| /// [`secp256k1`]: bitcoin::secp256k1 | |
| /// Sign a PSBT using an external key provider via [`bitcoin::Psbt::sign`]. | |
| /// | |
| /// This is a thin wrapper around [`bitcoin::Psbt::sign`] that supplies the wallet's | |
| /// internal [`secp256k1`] context. It lets callers sign with any type that implements | |
| /// [`psbt::GetKey`], such as [`bitcoin::bip32::Xpriv`], without having to manage their | |
| /// own secp256k1 context. Use it for software signing. | |
| /// | |
| /// # BIP32 derivation metadata | |
| /// | |
| /// [`bitcoin::Psbt::sign`] uses the `bip32_derivation` fields (for legacy and segwit inputs) | |
| /// or the `tap_key_origins` fields (for taproot inputs) in each PSBT input to locate | |
| /// the correct child keys. PSBTs constructed from within the wallet, or PSBTs received from | |
| /// external coordinator tools or hardware wallet flows, typically carry this metadata already. | |
| /// | |
| /// # Returns | |
| /// | |
| /// On success, a [`psbt::SigningKeysMap`] mapping each signed input index to the keys | |
| /// that were used. On failure, a tuple of the partial success map and a | |
| /// [`psbt::SigningErrors`] map of per-input errors. | |
| /// | |
| /// [`secp256k1`]: bitcoin::secp256k1 | |
| /// [`TransactionSigner`]: crate::signer::TransactionSigner |
There was a problem hiding this comment.
I'm not sure if we should refer to TransactionSigner, as it'll be later removed with signers module.
The hardware signers should handle the PSBT and signing keys on their own, considering that we had archived https://github.com/bitcoindevkit/rust-hwi and it's considered unmaintained.
There was a problem hiding this comment.
I'm not sure if we should refer to
TransactionSigner, as it'll be later removed with signers module.
Anyway, we can add it now and remove it when removing the module.
There was a problem hiding this comment.
Yep thanks, was thinking about it too.
From my understanding we added sign_with_signers as a transition step to keep supporting the bdk signer for some more time while moving to psbt.sign.
Which means yeah agree we shouldn't refer to it.
oleonardolima
left a comment
There was a problem hiding this comment.
cACK 0884a8d
I suggest squashing the doc commit into the first one, and also updating the PR description to reflect the current state.
|
nit: I think it's a good idea to also add the helper method As you add the helper method here, you can add an example of how to use in the documentation of NOTE: that you'd need to use the |
|
Happy to add
|
0884a8d to
0b62d13
Compare
This PR is aimed to |
|
Thanks for the suggestion. I've added I left out a
|
Add a thin wrapper method `sign_psbt` that delegates to `bitcoin::Psbt::sign`, passing the wallet's internal secp256k1 context. This allows users to sign PSBTs with their own `GetKey` implementor (e.g., `Xpriv` or hardware wallet adapters) without managing a separate secp256k1 context. docs(wallet): document Wallet::sign_psbt usage and requirement
Add tests covering signing with a matching and non-matching `Xpriv`. - `test_sign_psbt_with_xpriv`: verifies that a matching key signs at least one input - `test_sign_psbt_with_wrong_key_signs_nothing`: verifies that an unrelated key returns Ok but produces no signatures
bed270d to
40a8cac
Compare
| "expected no partial signatures when signing with an unrelated key" | ||
| ); | ||
| } | ||
| } |
There was a problem hiding this comment.
nit: you could also add a test that uses the get_keymap and sign with Wallet keys here.
|
cc'in @thunderbiscuit as you're interested in the new signing flow. |
40a8cac to
43702e7
Compare
|
Why do we want |
This is a good point. If this is something we can do without and will have to later remove then we shouldn't do it at all. Based on the docs in bitcoindevkit/book-of-bdk#155 it looks like we don't need this helper. |
Yes, it'll be removed in the next breaking change when removing the signers, though it's a good helper (not a MUST) method for current users to use the |
Won't the |
Description
Related to #331
Incorporates get_keymap() from #334
Adds
Wallet::sign_psbt<K>, a thin wrapper aroundbitcoin::Psbt::signthat passes the wallet's internal secp256k1 context to the caller'sGetKeyimplementor (e.g.Xpriv, a hardware wallet adapter).Without this, callers driving signing themselves via the bitcoin crate must construct their own
Secp256k1<All>— setup the wallet already owns.Notes to the reviewers
Wallet::signuses BDK's internal signer infrastructure (InputSigner/TransactionSigner).sign_psbtdelegates entirely tobitcoin::Psbt::sign; callers supply their ownGetKey. Both methods coexist without conflict.Changelog notice
Wallet::sign_psbt<K>wrapper aroundbitcoin::Psbt::signusing the wallet's internal secp256k1 context.Wallet::get_keymap()to retrieve a combined KeyMap from all wallet signers for use withKeyMapWrapperandWallet::sign_psbt.Checklists
All Submissions: