-
Notifications
You must be signed in to change notification settings - Fork 405
Sweeper async change destination source fetching #3734
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
Conversation
👋 Thanks for assigning @tnull as a reviewer! |
} | ||
|
||
Ok(()) | ||
self.persist_state(&*state_lock).map_err(|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.
No more sweeping in this method, all moved to a timer.
if let Some(spending_tx) = spending_tx_opt { | ||
self.broadcaster.broadcast_transactions(&[&spending_tx]); | ||
} | ||
let _ = self.persist_state(&*state_lock).map_err(|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.
No more sweeping in this event handler.
lightning/src/util/sweep.rs
Outdated
if respend_descriptors.is_empty() { | ||
// Nothing to do. | ||
return None; | ||
let change_destination_script = change_destination_script_result?; |
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.
Todo: address risk of getting a tx with a new address every block.
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.
Todo: investigate what BDK does here?
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.
Traced through BDK a bit. It seems that there is only inflation if we actually use the address in a tx. It won't blindly regenerate addresses when called. But will double check this.
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.
It seems that there is only inflation if we actually use the address in a tx. It won't blindly regenerate addresses when called. But will double check this.
This mostly depends on the API used.
c3420ab
to
d6051d9
Compare
90d7104
to
370d677
Compare
lightning/src/util/sweep.rs
Outdated
sweeper: OutputSweeper<B, D, E, F, K, L, O>, | ||
} | ||
|
||
impl<B: Deref, D: Deref, E: Deref, F: Deref, K: Deref, L: Deref, O: 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.
What might be good about this wrapper is that it eliminates the possibility of someone implementing async logic in combination with future poll/ready checking. This wrapper only accepts a sync trait.
a9812ea
to
df47e8d
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3734 +/- ##
==========================================
+ Coverage 89.13% 90.61% +1.47%
==========================================
Files 157 157
Lines 123851 134826 +10975
Branches 123851 134826 +10975
==========================================
+ Hits 110395 122170 +11775
+ Misses 10779 10016 -763
+ Partials 2677 2640 -37 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
f3e911e
to
6cd735c
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. |
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!
Mostly looks good from my side I think, just a few minor comments/nits. Will to another final thorough pass after.
lightning/src/util/sweep.rs
Outdated
|
||
use crate::sync::Arc; |
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.
nit: Let's move this to the other crate
imports
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.
It's cleaner, but also I have to say I never look at these imports. But may be different for others. Moved.
lightning/src/util/sweep.rs
Outdated
@@ -567,16 +623,15 @@ where | |||
} | |||
|
|||
fn spend_outputs( | |||
&self, sweeper_state: &SweeperState, descriptors: Vec<&SpendableOutputDescriptor>, | |||
&self, sweeper_state: &SweeperState, descriptors: &Vec<&SpendableOutputDescriptor>, |
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.
nit: Mhh, &Vec<&..>
looks funny. I guess the signature from spend_spendable_outputs
would be preferable: &[&SpendableOutputDescriptor]
.
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.
Out of curiosity, what is funny about it? Or how is &[&..] less funny? Fixed.
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.
Usually we try to create the least-strict API if there is no reason to. In this case, the prior API would enforce a reference to an allocated Vec
, while, if we just require the slice in the API, we might (easier) be able to drop the allocation if it's not 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.
LGTM, mod one question and a few final nits.
lightning/src/util/sweep.rs
Outdated
}, | ||
Err(e) => { | ||
log_error!(self.logger, "Error spending outputs: {:?}", e); | ||
return Ok(()); |
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.
Why are we ignoring the error here instead of propagating it up? (If we'd want to ignore it for some reason, can we just have spend_outputs
not return a Result
and move this match / logging into it?)
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 think it was pre-existing to not do anything with that error other than log:
rust-lightning/lightning/src/util/sweep.rs
Line 507 in 5316257
Err(e) => { |
I am not sure if the caller can do something more with the error. I do see that there non-happy flow error cases in spend_spendable_outputs
, so might be better to at least give the users the choice. Added map_err.
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.
LGTM, feel free to squash.
One outstanding nit, non-blocking though. If you want, feel free to address while squashing also.
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.
A new comments but they can all happen in followups too.
@@ -677,14 +703,18 @@ use futures_util::{dummy_waker, OptionalSelector, Selector, SelectorOutput}; | |||
/// # persister: Arc<Store>, | |||
/// # logger: Arc<Logger>, | |||
/// # scorer: Arc<Scorer>, | |||
/// # sweeper: Arc<OutputSweeper<Arc<B>, Arc<D>, Arc<FE>, Arc<F>, Arc<K>, Arc<Logger>, Arc<O>>>, |
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.
Here and above at least on the D
line, you have inconsistent spaces/tabs with the existing 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.
Unfortunate that github doesn't show it. Convert all tabs in this block to spaces, so that should have caught them all.
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.
Ironically I can see it in github's diff snippet that they included in the emails about these comments!
}, | ||
}; | ||
|
||
if state_lock.outputs.iter().find(|o| o.descriptor == output_info.descriptor).is_some() |
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.
For move-only/indentation-change changes, please do the move or indentation change and then rustfmt in a separate commit.
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.
This isn't great indeed. Also seems an unfortunate diff by github, because in vscode it detects a lot more whitespace only line changes.
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.
-b
does somewhat better, which I imagine is what vscode is doing. But git show --color-moved
would be much happier if the formatting were a separate commit.
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.
Suppressing rustfmt in a commit for diff optimization. Wasn't prepared for that 😅
let cur_height = sweeper_state.best_block.height; | ||
let cur_hash = sweeper_state.best_block.block_hash; | ||
let filter_fn = |o: &TrackedSpendableOutput| { | ||
/// Regenerates and broadcasts the spending transaction for any outputs that are pending. This method will be a |
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.
Would be nice to explain the return value (specifically that it will return an Err
only due to failures calling user code - failures persisting or failures signing a spending transaction).
lightning/src/util/sweep.rs
Outdated
{ | ||
let mut sweeper_state = self.sweeper_state.lock().unwrap(); | ||
|
||
let change_destination_script = change_destination_script_result?; |
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.
Not sure I buy that we need to do ?
in the state lock :)
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.
Left over from when I didn't have the atomic bool, good catch.
To prepare for asynchronous processing of the sweep, we need to decouple the spending from the chain notifications. These notifications run in a sync context and wouldn't allow calls into an async trait. Instead we now periodically call into the sweeper, to open up the possibility to do so from an async context if desired.
synchronous wrappers for usage in a sync context.
@TheBlueMatt addressed comments. Didn't do fixup commits, the github compare button shows the changes. |
This PR converts
OutputSweeper
to take an asyncChangeDestinationSource
implementation. This allows a (remote) address fetch call to run without blocking chain notifications.Furthermore the changes demonstrates how LDK could be written in a natively async way, and still allow usage from a sync context using wrappers.
Part of #3540