-
Notifications
You must be signed in to change notification settings - Fork 27
wip: Support N keychains #230
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
base: master
Are you sure you want to change the base?
Conversation
If you bring in the idea of the KeyRing into 3.0, then two things we could offer on it to enable ease-of-migration between major versions would be something like |
1f974bc
to
115b920
Compare
Pull Request Test Coverage Report for Build 15786383238Details
💛 - Coveralls |
Wow this is taking shape! Quick comments/questions as I'm looking at the diff (sorry if it's jumping the gun and you're actually in the middle of adding new stuff as I review).
Some APIs I could see being useful on the
|
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.
Some thoughts I don't want to miss about this:
-
We could enforce some expected format for descriptors to be accepted in a
KeyRing
. Mainly to avoid ambiguity and the aggregated complexity of many border cases. I would suggest to only consider descriptors that have wildcards. For cases like multipath, I would split the descriptor first into multiple descriptors. -
I would prefer a flat structure rather than nested. For the case of Internal descriptors, and thinking in terms of a table, I would add a field to link through the descriptor Id the one used for change. That field would be optional, if the descriptor isn't expected to create change, can be elided. Also, multiple keychains could refer to the same change keychain.
-
Continuing with the idea of a flat structure, the external/internal consideration could be reduced to a boolean. If a keychain is linked to another keychain to use as change by the descriptor id, the second keychain should have the boolean field "external" enabled.
-
I think the behavior desired by the use of group ids could also be achieved just by looking at the properties of the descriptor. Getting balance from all the descriptors of the same type should be easily achieved by filtering by their variant. In the case of multipath descriptors the balance can be obtained by filtering by the descriptor fingerprint. In more complex query cases that don't necessarily share any of the common traits a descriptor can have, I would leave the implementation for higher layers.
Thanks for working on this! Consider these comments as mere suggestions.
Last time I talked to thunderbiscuit we agreed on possibly doing away with the extra "grouping" logic, and for simplicity go back to using |
I've also been playing around with the "group" idea in my head and I can't see a super strong case for it yet. I think those kinds of grouping would be built at the application layer in a structure that would map descriptor ids to groups. I suggest we build without, and bring them back if more review brings to light more information. |
One more thing that needs some hashing out on is the idea of keychain "pairs", which would provide you with a way to link two keychains together, one being the external and one being the internal. The more I think about this one, the less hot I am on it. Here's a breakdown of my thoughts. Pros + Use CasesAfter thinking about this one for a while, I honestly can't write a good paragraph on it. Why would people need the pairs? Note that the idea that you might want to use the same script type for change as you do for the recipient (for privacy reasons) is valid, but is not actually enabled by the pairs idea! In fact, what's needed for this to work is for the TxBuilder to recognize what script type it is paying to when building a transaction, and then be able to choose from a pool of keychains one that will match the script type (i.e., if you are paying to a P2SH address, pick a P2SH keychain for producing the change outputs). The pairs don't have anything to do with this, and I myself was confusing the 2 ideas at first. Reasons why I'm not so sure about keychain pairs
Final thoughtsAll this being said, I'm looking forward to hearing from users if I have maybe overlooked a use case for them at the |
I'm convinced by thunderbiscuit arguments, let's move this logic up to the application layer, and keep the interface simpler. I still hold the following argument:
|
Here are my high-level goals for N keychain support (originally called multi-descriptor support in #188).
|
- Add rusqlite support for `Wallet<DescriptorId>`.
115b920
to
974f31f
Compare
Updated the PR description after pushing a new change adding the |
Description
This PR introduces initial support for multi-keychain wallets in
bdk_wallet
, allowing a single wallet instance to manage and track potentially many descriptors ("keychains"). This allows more complex/flexible wallet constructions in contrast to the current 2-keychain design.Summary of changes
multi_keychain
module:KeyRing
for managing multiple descriptors.Wallet
that can index tx data for multiple keychains.ChangeSet
type for managing persistence.K
is generic throughout themulti_keychain
module, allowing the user to define the keychain type at wallet creation time, provided thatK
implements core::cmp::Ord.rusqlite
. This is currently only supported forWallet<DescriptorId>
, i.e. wallets where the keychain has the concrete typeDescriptorId
.multi_keychain
module in crate root (lib.rs
).For example usage see
wallet/examples/keyring.rs
for a demo of how to set up and persist a multi-keychain wallet.Note: This is a work in progress and feedback is welcome on the design and API.