-
Notifications
You must be signed in to change notification settings - Fork 39
Report Pathfinding Outcomes to Scorer in SimNode #291
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
Report Pathfinding Outcomes to Scorer in SimNode #291
Conversation
d151ed3 to
32c4089
Compare
|
Looking really good overall! Let's sort out these pesky MPP issues and make the clock generic then we're gg. |
|
Thanks for the feedback. Will get this sorted asap! |
32c4089 to
c9ef909
Compare
Added Some Key Changes
|
carlaKC
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.
Some questions from a very high level pass.
Reverted SimNode Immutability: I've reverted some changes introduced in 8ded28e to allow SimNode to mutate its internal fields where necessary.
What's the motivation for reverting this change? If possible it's preferable to not require implementations of a trait to be mutable. Would rather add a mutex where we need it than re-introduce trait-required mutability.
simln-lib/src/sim_node.rs
Outdated
| node.1 .0.clone(), | ||
| graph.clone(), | ||
| routing_graph.clone(), | ||
| SystemClock {} |
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.
We should pass this clock in as a parameter to give callers the freedom to choose what impl they want
simln-lib/src/sim_node.rs
Outdated
| } | ||
|
|
||
| /// This trait defines the "interface" for payment propagation logic | ||
| pub trait PaymentPropagator: Send + Sync + 'static { |
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 seems like a lot of boilerplate just for tests (and possibly somewhere we should use async_trait rather than have these boxes + pins?
Doesn't seem like it would be too much test code to just use real propagation and create payments that fail at the points we want?
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.
Yeah, you are right - I actually used async_trait in a fixup of the commit; However I think it's a good idea to use real propagation rather than have all this boilerplate. I'll work on that.
Thanks for this suggestion. Will work on this. |
carlaKC
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.
I think that you can go ahead and squash this then I'll take a last review round.
Just a few generics things that stand out to me.
sim-cli/src/parsing.rs
Outdated
| // to a dyn trait and exclude any nodes that shouldn't be included in random activity | ||
| // generation. | ||
| let nodes = ln_node_from_graph(simulation_graph.clone(), routing_graph).await; | ||
| let nodes = ln_node_from_graph(simulation_graph.clone(), routing_graph, SystemClock {}).await?; |
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.
Should use the clock passed in?
simln-lib/src/clock.rs
Outdated
|
|
||
| /// Provides a wall clock implementation of the Clock trait. | ||
| #[derive(Clone)] | ||
| #[derive(Clone, Copy)] |
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.
Do we need to add Copy?
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.
We actually don't need to - will take that out.
simln-lib/src/sim_node.rs
Outdated
|
|
||
| /// Produces a map of node public key to lightning node implementation to be used for simulations. | ||
| pub async fn ln_node_from_graph( | ||
| pub async fn ln_node_from_graph<C: Clock + std::marker::Copy>( |
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.
Rather than require this to be copy, pass in Arc<C>? This is what we do elsewhere
2eeda7a to
3dfc98a
Compare
|
Running on a mock network, I get the following error: To Reproduce:
|
|
Thanks! Will look into this asap. |
|
Any updates here? |
Apologies for the delay! I'm working on sorting this out and expect to have an update for you by mid next week. |
3dfc98a to
378c3fa
Compare
Fix: Properly track payment hashes for failed route scenariosPreviously, payment hashes were being tracked even when they were not added to the I have tested using the same parameters and can confirm I don't see that error anymore:
Please let me know the outcome on your end. Thanks! |
carlaKC
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.
Getting close, few more comments.
Go ahead and squash, I'll just look at the diff for the remaining changeset.
simln-lib/src/sim_node.rs
Outdated
| assert!(matches!( | ||
| result.unwrap().payment_outcome, | ||
| PaymentOutcome::Unknown | ||
| PaymentOutcome::IndexFailure(_) |
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.
Might as well assert on the value here?
| /// Error that occured when getting clock info. | ||
| #[error("SystemTime conversion error: {0}")] | ||
| SystemTimeConversionError(#[from] SystemTimeError), |
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 used in this commit?
simln-lib/src/sim_node.rs
Outdated
| }; | ||
|
|
||
| // Use the stored scorer when finding a route | ||
| let scorer_guard = self.scorer.lock().await; |
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: do locking inside of find_payment_route?
simln-lib/src/sim_node.rs
Outdated
| if payment_result.payment_outcome == PaymentOutcome::Success { | ||
| self.scorer.lock().await.payment_path_successful(&in_flight.path, duration); | ||
| } else if let PaymentOutcome::IndexFailure(index) = payment_result.payment_outcome { | ||
| self.scorer.lock().await.payment_path_failed(&in_flight.path, index.try_into().unwrap(), duration); |
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.
index.try_into().unwrap() -> as u64?
simln-lib/src/sim_node.rs
Outdated
| // Alter route to make payment fail on first hop (Index 0). | ||
| route.paths[0].hops[0].cltv_expiry_delta = 39; |
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.
Nice test 👌
Let's make this a test for failures at each hop?
- For i = 0; i < hops.len()
- Modify hop at index i
- Send payment
- Assert failure at index i
simln-lib/src/sim_node.rs
Outdated
| match result.payment_outcome { | ||
| PaymentOutcome::IndexFailure(_) => { | ||
| assert_eq!(result.payment_outcome, PaymentOutcome::IndexFailure(0)); | ||
| }, | ||
| _ => panic!( | ||
| "Expected IndexFailure, but got: {:?}", | ||
| result.payment_outcome | ||
| ), | ||
| } |
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.
assert!(matches!(
result.payment_outcome,
PaymentOutcome::IndexFailure(1)
))
simln-lib/src/sim_node.rs
Outdated
| /// The [`lightning::routing::router::build_route_from_hops`] function can be used to build the route to be passed here. | ||
| /// | ||
| /// **Note:** The payment hash passed in here should be used in track_payment to track the payment outcome. | ||
| /// |
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 should be a fixup / squashed.
simln-lib/src/sim_node.rs
Outdated
| None => { | ||
| log::warn!("No path found for payment hash {}, cannot update scorer.", hex::encode(hash.0)); |
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.
Let's check this against the PaymentOutcome and error out if it's anything other than RouteNotFound? I don't think we need the warning for the RouteNotFound, as it's expected.
This commit ensures that the payment apis can only send to a single path. Payment is rejected if the route has multiple paths.
This commit asserts that payment failure on each hop returns the correct hop index where failure occured. On payment failure, this ensures the correct index of hop where failure occured is reported to scorer.
378c3fa to
5b490c0
Compare
carlaKC
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.
LGTM! Just a nit that's not worth blocking merge.
Also in future please try to wrap git messages at 27 chars.
| // We will assert that the failure index returned is the index of the hop that we altered. | ||
| // This is done by setting the CLTV expiry delta to a value that will cause the payment to fail at that hop. | ||
| // The last hop will always succeed, so we only test the first n-1 hops. | ||
| for i in 0..route.paths[0].hops.len() - 1 { |
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.
Nice, thanks for updating this 👌
| assert!(matches!( | ||
| result.payment_outcome, | ||
| PaymentOutcome::IndexFailure(idx) if idx == i | ||
| )); |
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 could just be: assert!(matches!(result.payment_outcome, PaymentOutcome::IndexFailure(i)));
Description
This PR reports pathfinding outcomes to scorer in SimNode. This significantly improves the realism of pathfinding simulations by allowing the scorer to update based on actual payment success or failure.
This is an attempt to complete the work started on this branch.
Changes
SimNode.in_flightusingInFlightPayment.IndexFailurePaymentOutcomevariant, which specifically captures the index of the channel in the payment path that caused the failure.SimNodeusingSimulationClockfor accurate duration reporting.SimNode.scorerusing the newly tracked path and failure index (if applicable).This PR closes #279