Support For Arbitrary Number of Keychains#318
Support For Arbitrary Number of Keychains#318thunderbiscuit wants to merge 5 commits intobitcoindevkit:masterfrom
Conversation
7059451 to
0df1a2a
Compare
|
The next few commits:
|
524d4df to
6c50f00
Compare
There was a problem hiding this comment.
Quick review on 6c50f00: given your commit message I thought you were adding the Wallet::new constructor here, but the commit only contains the addition of the KeyRing to the Wallet type. Mind you this might be enough for this commit. Feel free to add a new commit with the constructor, or add it to this commit; whatever you think works best.
Also note that fa984e6 and 6c50f00 don't compile because of
impl AsRef<bdk_chain::tx_graph::TxGraph<ConfirmationBlockTime>> for Wallet {
fn as_ref(&self) -> &bdk_chain::tx_graph::TxGraph<ConfirmationBlockTime> {
self.keychain_tx_graph.graph()
}
}on line 2638 of wallet/mod.rs. You could comment it out with the rest to ensure everything builds.
wallet/src/wallet/changeset.rs
Outdated
| pub keyring: keyring::changeset::ChangeSet<K>, | ||
| /// Changes to the [`LocalChain`](local_chain::LocalChain). | ||
| pub local_chain: local_chain::ChangeSet, | ||
| pub chain: local_chain::ChangeSet, |
There was a problem hiding this comment.
I'm not sure if the renaming of this field is intentional and I don't have an opinion on whether it's a good idea or not yet, but it probably belongs in a different PR.
There was a problem hiding this comment.
I did the rename since the corresponding field in Wallet is so. reverted the rename in 588121b.
7c976e1 to
588121b
Compare
|
I am so sorry 😢 . I completely messed dividing the commits into two. Things should be fixed now! |
|
This one now needs a big ol' rebase @110CodingP. |
dfdcd83 to
4a3486e
Compare
|
Wow! this one was HUGE! For the first few commits I did something like |
|
Adding an example like this fails: // Simple KeyRing, allowing us to build a standard 2-descriptor wallet.
let external_descriptor: &str = "tr(tpubD6NzVbkrYhZ4WyC5VZLuSJQ14uwfUbus7oAFurAFkZA5N3groeQqtW65m8pG1TT1arPpfWu9RbBsc5rSBncrX2d84BAwJJHQfaRjnMCQwuT/86h/1h/0h/0/*)";
let internal_descriptor: &str = "tr(tpubD6NzVbkrYhZ4WyC5VZLuSJQ14uwfUbus7oAFurAFkZA5N3groeQqtW65m8pG1TT1arPpfWu9RbBsc5rSBncrX2d84BAwJJHQfaRjnMCQwuT/86h/1h/0h/1/*)";
let mut keyring: KeyRing<KeychainKind> = KeyRing::new(Network::Regtest, KeychainKind::External, external_descriptor);
keyring.add_descriptor(KeychainKind::Internal, internal_descriptor, false);
let mut wallet = Wallet::new(keyring);With a stacktrace containing: thread 'main' panicked at /Users/user/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/miniscript-12.3.5/src/descriptor/key.rs:687:14:
The key should not contain any wildcards at this pointAfter a bit of poking around I found that this is coming from the descriptor_id() method called inside insert_descriptor(): pub fn insert_descriptor(
&mut self,
keychain: K,
descriptor: Descriptor<DescriptorPublicKey>,
) -> Result<bool, InsertDescriptorError<K>> {
let did = descriptor.descriptor_id();I don't have time to finish the investigation today, but just pointing it out. I'm not sure yet why this worked well in the multi-keychain-wallet crate and not here, nor why the code for the constructor is so different than the other previous constructors like |
|
This almost scared me for a moment 😅 ! Using descriptors with unhardened paths seems to work. |
|
Total facepalm. Sorry @110CodingP! Ok so I simplified the example a little bit just to keep a really neat version of how to build a wallet as close as you can from the 2.0 approach. |
4403cdb to
16d6f8c
Compare
af0e9eb to
4177147
Compare
Completes first 2 of the Todos? |
for e33e007 : Also ig |
|
Also is |
9e9413c to
759dce2
Compare
|
@luisschwab yep good question. This will come into play if we allow dynamically changing the keychains on wallets (it has historically not been possible to do so with BDK wallets, but there might be a case to be made for it? not sure.) It feels like having to deal with the possibility of a user adding or removing a keychain at any point might add more complexity to the codebase than it brings value (since you can always just create a new wallet with the specific keychains you want) but there might be use cases I'm not thinking about. |
|
Makes sense, making dynamic keychain swapping possible would make things a lot more complex. I noticed you have the sync examples commented out for now. When making synching a wallet, are you planning to add all revealed spk's into an "spk pool" and sync everything, or are we going to have to specify which keychain we want to sync? I ask this because with the first option, I can just take the first transaction from the "spk pool" and set the wallet's birthday as the transaction's |
7e8d326 to
25a41f3
Compare
Currently we sync all keychains in one go . But ig having an API to sync a particular keychain would also be great in case of large wallets with multiple keychains?
Yup, I agree this should work if we are not allowing addition of keychains! |
f987f72 to
417f519
Compare
f77ad1f to
a5163af
Compare
|
@110CodingP I worked today on basically applying this loop to all 5 commits: git checkout <commit>
cargo build
cargo testAnd seeing if everything compiled and worked well. I ended up finding a few things. Here is a summary of what I did:
|
a5163af to
c4ff009
Compare
Added #![allow(unused)] to circumvent clippy errors. Removed policy module and related code as policy is anyway being phased out in 3.0.
Added `keyring::ChangeSet`. The `add_descriptor` function returns a `KeyRing::Changeset` since this would eventually be required when we introducing APIs to add descriptors to `Wallet.keyring`. Also implemented `FromSql` and `ToSql` for `KeychainKind`. Also modified `DescriptorError` and added `KeyRingError` since information of whether a keychain/desc is already assigned should be with the wallet and thus belongs to its error types. Co-authored-by: thunderbiscuit <thunderbiscuit@protonmail.com>
6597b07 to
585d3a0
Compare
Modified the `Wallet::ChangeSet` accordingly. Modified AddressInfo, add reveal_next_address Also added default version for address APIs. Added `introduce from_changeset` for Wallet Modified Update to take in a generic Also modified `balance` method to incorporate `CanonicalView` and a more flexible `trust_predicate` which fixes incorrect trusted balance calculation by the `Wallet`. Modified `CreateParams` to incorporate the changes. Modified `persist_test_utils` to incorporate the new `Wallet`. Note: `persist_keychains` and `persist_keychain` are two separate tests keeping in mind that some users may not use > 1 keychain. Among all tests only `persist_keychains` assumes multiple keychains. Co-authored-by: thunderbiscuit <thunderbiscuit@protonmail.com> Co-authored-by: valued mammal <valuedmammal@protonmail.com>
Also fixed original examples. Co-authored-by: codingp110 <codingp110@gmail.com>
585d3a0 to
761f3bf
Compare
Description
This PR allows the
Wallettype to track any number of keychains (descriptors). It is a breaking change.Related Issues: #188, #227
Related PRs: #230, #226
Exploratory Crate: multi-keychain-wallet
Read this one-pager for an overview of user-facing impacts of the proposed feature.
Walletdependent code.KeyRingand related types.Walletto levergage theKeyRing.Todo
Search for the following pattern to find Todos in the codebase:
// TODO PR #318: We should fix this because...KeyRing::newshould throw an errors on certain conditionsSyncRequestandSyncResponseneed to be generic inKWalletAPI docs (Kneeds to beOrdfor example)Wallet::newshould callWallet::create_with_paramsChangeSet.Changelog notice
TODO
Deployment Strategy
As per discussions over different dev calls, this feature is proposed as a breaking change on the
WalletAPI, since the old constructors are removed. It might not be ready in time for the 3.0 release (given the size of the diff and its relative position on the totem pole of priorities). If it does not make the cut for the 3.0 release, it will simply be kept updated and rebased on master until it is ready for merging into a breaking change ready branch for the 4.0 release.Changes On Wallet
Here is a table to help track changes on the
wallet/mod.rsfile. I tried to add everything with a visual of New/Changed/Removed/Identical (⭐/🔄/🚫/✅ respectively), as well as some notes on the changes.Wallet::create_singleWallet::createKeyRingWallet::networkWallet::tx_graphWallet::local_chainWallet::latest_checkpointWallet::spk_indexWallet::keychainsWallet::default_keychainWallet::reveal_next_addressKparameterWallet::reveal_next_default_addressWallet::next_unused_addressKparameterWallet::derivation_indexKparameter