-
Notifications
You must be signed in to change notification settings - Fork 116
Use BDK events in update_payment_store
#658
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: main
Are you sure you want to change the base?
Use BDK events in update_payment_store
#658
Conversation
|
👋 Thanks for assigning @tnull as a reviewer! |
75ff700 to
d3f7855
Compare
|
🔔 1st Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 2nd Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 3rd Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 4th Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 5th Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 6th Reminder Hey @tnull! This PR has been waiting for your review. |
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.
Excuse the delay here!
Unfortunately I don't think we can make the move until we get corresponding functionality for all chain sources, i.e., also for bitcoind/apply_block. Will raise that with the BDK folks to make some progress.
I now opened bitcoindevkit/bdk_wallet#336 to add the missing APIs we need. In the meantime we can see to get this as close to being mergeable as possible.
src/wallet/mod.rs
Outdated
| })?; | ||
|
|
||
| self.update_payment_store(&mut *locked_wallet).map_err(|e| { | ||
| let events_vec: Vec<WalletEvent> = events.into_iter().collect(); |
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.
I don't think this re-allocation is necessary?
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.
Thanks! I have removed the re-allocation
src/wallet/mod.rs
Outdated
| ); | ||
| } | ||
|
|
||
| match locked_wallet.apply_block(block, height) { |
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.
Ugh, seems there is no corresponding apply_block_events method. I think we need that before actually moving forward here. Will raise it with the BDK folks.
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.
Alright
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.
I saw that the PR on BDK wallet has been merged and added to the next release milestone. This will be updated as soon as there is a new release on BDK wallet
src/wallet/mod.rs
Outdated
| } | ||
|
|
||
| self.payment_store | ||
| .list_filter(|p| { |
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.
Hmm, ugh, that's already slow right now, but will be prohibitively slow when we don't keep our entire payment store in-memory. I think we can't get around adding another persisted lookup table that tracks RBF-Txid to original-Txid.
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.
Yes, this is true, if we have another table, the lookup will be faster and the original Txid can be updated when the RBF-Txid for example, has a confirmed event from BDK
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.
@tnull, I created a new persisted ReplacedTransactionStore that maintains lookups from any txid in an RBF chain to its associated payment. Store entries are automatically cleaned up when any transaction in the chain confirms. This keeps lookups fast even with large payment histories.
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.
@tnull, I created a new persisted
ReplacedTransactionStorethat maintains lookups from any txid in anRBFchain to its associated payment. Store entries are automatically cleaned up when any transaction in the chain confirms. This keeps lookups fast even with large payment histories.
Huh, why do we need a whole other module/store for this? Let's just use a HashMap<Txid, Txid> and be done with it? Or do we need all that additionally tracked data somehow?
I guess we could use a DataStore implementation for this, but I don't quite see why we need to track ConfirmationStatus and latest_update_timestamp?
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.
Huh, why do we need a whole other module/store for this? Let's just use a
HashMap<Txid, Txid>and be done with it? Or do we need all that additionally tracked data somehow?
Yes, we need to track this data for faster lookup of replaced transaction IDs instead of a full iteration
I guess we could use a
DataStoreimplementation for this, but I don't quite see why we need to trackConfirmationStatusandlatest_update_timestamp?
You are right about the ConfirmationStatus and latest_update_timestamp, they were part of my original design, and as I proceeded with my implementation, I decided to clean the store instead upon confirmation of any of the transactions. I will go ahead and remove them. I also used a DataStore implementation for this.
d3f7855 to
a2c8a55
Compare
ecaae51 to
8609d97
Compare
|
🔔 1st Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 2nd Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 3rd Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 4th Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 5th Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 6th Reminder Hey @tnull! This PR has been waiting for your review. |
b442739 to
e13e503
Compare
Thanks, I've completed all the requested changes, including restructuring the commits to separate concerns. |
|
🔔 1st Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 2nd Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 3rd Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 4th Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 5th Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 6th Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 7th Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 8th Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 9th Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 10th Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 11th Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 12th Reminder Hey @tnull! This PR has been waiting for your review. |
tnull
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.
Please excuse the considerable delay here!
Revisiting the WalletEvent::ChainTipChanged logic makes me wonder if rather than just tracking 'replaced transactions' in a separate store, it would make more sense to track pending payments (including fields for replaced/conflicting txids) in a separate store.
For one this would avoid us having to scan all entries in the payment store, and it would also allow us to clean up pending payment entries (including associated replaced txids) after ANTI_REORG_DELAY. And even if looking up replaced Txids wouldn't be O(1) anymore, the number of pending payments at any given point of time would be so small that we could still easily iterate over all entries.
Sorry for raising this only now. - Do you have any thoughts on this?
| WalletEvent::ChainTipChanged { new_tip, .. } => { | ||
| // Get all payments that are Pending with Confirmed status | ||
| let pending_payments: Vec<PaymentDetails> = | ||
| self.payment_store.list_filter(|p| { |
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.
Hmm, this is unfortunate as it is basically back to scanning all transactions, though this time scanning even all entries in our payment store which might be worse. This makes me wonder if we should, rather than just track conflicting/replaced transactions, track 'pending payments' (with a field for conflicting/replaced txids) to also make this lookup reasonably fast. This might become especially crucial since we're looking to eventually only keep a cache of the payment store in memory, so scanning all entries might at that point mean a lot of slow, costly IO lookups from the KVStore.
src/wallet/mod.rs
Outdated
|
|
||
| let kind = crate::payment::PaymentKind::Onchain { txid, status: confirmation_status }; | ||
| let existing_payment = self.payment_store.get(&payment_id); | ||
| let final_conflicting_txids = if let Some(provided_conflicts) = conflicting_txids { |
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.
Hmm, tbh, this gets a bit confusing: why are we providing conflicts, and then also looking up conflicts from an existing payment here? Wouldn't it make sense to just have create_payment_from_tx a list of conflicts and populate that at the callsite?
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.
I've removed the conflicting_txids parameter from create_payment_from_tx and moved the logic to the callsite. In WalletEvent::TxReplaced we already have the conflicts from the event, so we just assign them after creating the payment.
src/io/utils.rs
Outdated
| } | ||
|
|
||
| /// Read previously persisted replaced transaction information from the store. | ||
| pub(crate) fn read_replaced_txs<L: Deref>( |
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.
Similar to what we did with the other read_ methods this (or rather the pending payments counterpart) should be async now.
| } | ||
|
|
||
| if events.len() > 1 { | ||
| events.sort_by_key(|e| match e { |
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.
Mind adding the explanation you gave w.r.t. why we sort the event as a comment here in the code?
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.
Thanks for the suggestion, I'll add that explanation as a comment
…sactions Replace the full transaction list scan in `update_payment_store` with handling of BDK's `WalletEvent` stream during sync. This leverages the new events in BDK 2.2, reduces redundant work, and prepares the foundation for reliable RBF/CPFP tracking via `WalletEvent::TxReplaced`
Thanks for the suggestion. You're right. I initially thought |
Introduce a new lookup `ReplacedTransactionStore` that maps old/replaced transaction IDs to their current replacement transaction IDs, enabling reliable tracking of replaced transactions throughout the replacement chain. Key changes: - Add persisted storage for RBF replacement relationships - Link transactions in replacement trees using payment IDs - Remove entire replacement chains from persistence when any transaction in the tree is confirmed
e13e503 to
e5e120c
Compare
|
🔔 1st Reminder Hey @tnull! This PR has been waiting for your review. |
This PR updates
update_payment_storeto use BDK 2.2’sWalletEventstream during sync instead of iterating over the full list of wallet transactions every time. The new event-based approach reduces redundant work and ensures the payment store stays in sync with only the changes that actually occurred.It also sets up the foundation for RBF support in #628 with
WalletEvent::TxReplaced. Since #628 depends on this event handling, this PR should be merged first.This PR will also address #452