Feature/multi keychain take 3 - #524
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## pre-multi-keychain #524 +/- ##
======================================================
+ Coverage 81.79% 82.20% +0.40%
======================================================
Files 25 27 +2
Lines 6362 6371 +9
Branches 289 281 -8
======================================================
+ Hits 5204 5237 +33
+ Misses 1058 1038 -20
+ Partials 100 96 -4
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:
|
|
A few ideas for interesting helper features to add to the
|
b2f34b5 to
dd4d5d0
Compare
dd4d5d0 to
9e43360
Compare
|
TODO: Figure out how to deal with change in the My current naive idea to deal with this would be to add a field on the wallet @ValuedMammal happy to hear your thoughts on this. One thought on this comment: by default the wallet would currently use UTXOs from all keychains to build transactions (maybe that needs work too; kind of like locking UTXOs, you might want to lock keychains or at least prevent the wallet mixing up all your keychains for privacy reasons), but in any case the base workflow would use all keychains. If each of those had defined a sister change keychain, then the wallet is back at square 1, not really knowing which one to use for change. Here again, explicitly setting the keychain to use for change is preferable IMO. |
c9f4922 to
09c9c5d
Compare
thunderbiscuit
left a comment
There was a problem hiding this comment.
Leaving here for review for tomorrow.
| /// | ||
| /// Two keychains sharing a descriptor cannot be told apart when attributing discovered | ||
| /// outputs, so the indexer rejects it. | ||
| DescriptorAlreadyAssigned(Box<Descriptor<DescriptorPublicKey>>), |
There was a problem hiding this comment.
Need to confirm where exactly this check will succeed/fail given corner cases, because I know we've discussed this in the past and I need a refresh on it. Posting here for self-review.
There was a problem hiding this comment.
Won't we encounter this, if we try to add a descriptor to the keyring but it already exists under a different keychain?
There was a problem hiding this comment.
Won't we encounter this, if we try to add a descriptor to the keyring but it already exists under a different keychain?
Yes and no. The equality check is not perfect if I remember correctly, and we ended up deciding that a hash of the first script derived by the descriptor was a more robust (if not perfect) way to check that two descriptors were basically "the same".
The wallet creation does that check using the descriptor_id() method (what I'm referring to above), so I'll use that instead of the equality used previously.
09c9c5d to
eaa0946
Compare
| let tx = &psbt.unsigned_tx; | ||
| if psbt.inputs.len() < tx.input.len() { | ||
| return Err(IndexOutOfBoundsError::new( | ||
| psbt.inputs.len(), |
| let index = &mut self.tx_graph.index; | ||
| let stage = &mut self.stage; | ||
|
|
||
| let ((index, spk), index_changeset) = index | ||
| .reveal_next_spk(keychain) | ||
| .reveal_next_spk(keychain.clone()) | ||
| .expect("keychain must exist"); |
There was a problem hiding this comment.
We should return an error instead?
| let psbt_input = &psbt | ||
| .inputs | ||
| .get(n) | ||
| .ok_or(IndexOutOfBoundsError::new(n, psbt.inputs.len()))?; |
There was a problem hiding this comment.
We have already ensured this won't happen?
|
|
||
| fee_amount += fee_rate * tx.weight(); | ||
| /// The derivation index of this wallet. It will return `None` if it has not derived any |
There was a problem hiding this comment.
We need to handle the case when keychain doesn't exist here too.
If convenience is the only reason for this change can we avoid persisting this? Can we have |
|
Run cargo audit locally to see the full details of the 4 securities issues. |
|
I'll follow up on the comments here in this thread! @ValuedMammal
You're correct I got this backwards there for a second.
Yeah I see your point there. It conflicts with @110CodingP's idea above ("If convenience is the only reason for this change can we avoid persisting this?"), but if we really value this idea of "set it and forget it" then I think adding it to persistence could be worth the trouble. On having multiple change keychainsI don't personally like the idea of defining more than 1 change keychain wallet-wide at the I think a reasonable feature would be to be able to define a single global change keychain, which would come into play when going down the order of preference for change keychain selection in the psbt creation process as you defined in the linked post. This would also facilitate and keep simple the "basic case" of 2-keychain wallets as we have them now in Order of preference for change
Thanks for laying this out. I would do exactly this, but remove step 2. Or maybe I can be convinced, or it could come as a new feature at some point? On choosing the change based on payment scriptsFor me, this lives better at the application layer than the bdk_wallet layer. The basic privacy workflow is this:
Attempting to do this on the bdk_wallet side is probably not impossible, but feels messy to me and very hard to do well, because the wallet would need to know so much about the user/app layer, i.e. carry a lot of metadata on all keychains and when to use which, which is exactly what the Even for the base case, the wallet would need to be able to parse the script type being paid to (what if it's a few different ones?), then see if it has keychains that are marked as |
|
This was a long post but here is what I suggest I focus on for the next round of this:
|
|
Do we want to allow the |
| /// change descriptor should be defined at wallet creation time and respected for the life of the | ||
| /// wallet, meaning that if a change descriptor is originally defined, it must also be present in | ||
| /// the aggregate change set. | ||
| /// A keychain may be introduced by a later change set — a wallet can start tracking a new one at |
There was a problem hiding this comment.
Are we planning to allow addition of descriptors in bdk_wallet 4.0 itself?
| pub change_descriptor: Option<Descriptor<DescriptorPublicKey>>, | ||
| #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] | ||
| pub struct ChangeSet<K: Ord> { | ||
| /// The descriptor tracked by each keychain. |
There was a problem hiding this comment.
Mammal brought this up on #318 : Since we need to follow the ChangeSet's field-deprecation policy we would need to keep the change_descriptor and descriptor fields around for v4.
|
Also ig we could just let the user specify the |
Take 3 on the multi-keychain PR feature. I'm opening this as a new PR in order to not lose all the work done in #318, since it's a fairly new/reimagined way to work it (2 PRs together, etc.). See #523 for part 1 of this.
Note that this is made against the pre-multi-keychain branch.
Quite experimental at this point, but I wanted to share where I'm at so others can build upon it.
TODO
KeyRing.Wallet::balancemethod not being able to tell what's a change keychain and what's not, and so the concept of "trusted" is a bit lost in the current API (all defaults to untrusted until the UTXO is mined). But this is I believe fixed by refactor(wallet): derive balance trust from output ancestry #431 and would land hopefully before this, and so I choose to let this one sit as is for now.Changelog notice
TODO
Before submitting