-
Notifications
You must be signed in to change notification settings - Fork 385
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
Track in-flight HTLCs across payments when routing #1643
Track in-flight HTLCs across payments when routing #1643
Conversation
fa440fa
to
d03d6a8
Compare
@TheBlueMatt Would good to have some early feedback on this PR. Upcoming commits will use in-flight HTLC tracking during routing. Follow-up PR will deal with persistence. |
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.
As for the followup to do the tracking, I don't think we need a new interface in the router at all, I think we can do it entirely by wrapping the scorer and changing the amounts we pass through to the user-provided scorer.
Going to be using this for review club session 5. Nice to dig into payment logic a bit. :) |
hm, I think we do need to pass in the inflight htlcs map into |
Yea, if we want to exactly match the behavior, but I'm not sure that is neccessary - it'll result in a few suboptimal decisions, but we can do it only in the scorer and we'll still get most of the way there, without more complexity in the router itself. |
There may be another case when computing rust-lightning/lightning/src/routing/router.rs Lines 1002 to 1004 in d024251
|
Yea, that's generally what I was referring to - we'll not make the same decisions we'd like to around how much we'd maximally want to send over a channel. I do kinda now wonder if we shouldn't have made that a method on the scorer, but either way, I'm not sure its totally critical that we get it exactly right here - at worse we'll end up refusing to re-use channels that we already have pending payments over where we may have been willing to re-use some small part of their capacity. |
which method? rust-lightning/lightning/src/routing/scoring.rs Lines 807 to 808 in d024251
|
@TheBlueMatt Did you mean should have not shouldn't have? |
Err, yes lol. |
Another thing to keep in mind is that we'd eventually like to move the |
f827add
to
b184bee
Compare
e8e05fd
to
e657138
Compare
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 other than a few nits.
033028b
to
9911955
Compare
1abd3df
to
a434146
Compare
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.
Ok, I'm happy with this other than one test change to make it more realistic.
a434146
to
08130b7
Compare
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. @TheBlueMatt could you take another look?
Introduces a new `PaymentInfo` struct that contains both the previous `attempts` count that was tracked as well as the paths that are also currently inflight.
08130b7
to
51b90ab
Compare
let final_value_msat = invoice.amount_milli_satoshis().unwrap(); | ||
let route = TestRouter::route_for_value(final_value_msat); | ||
let router = TestRouter {}; | ||
let scorer = RefCell::new(TestScorer::new()); |
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.
Are these RefCells really needed? Wouldn't just creating TestScorers work generally?
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 believe this is because InvoicePayer
expects the scorer to implement LockableScore
.
TestScorer
here is really just a mocked version of a scorer that we'd expect users to implement on their own
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, a scorer needs to be locked to (a) use its mutable interface in InvoicePayer
's event handling and (b) use its immutable interface when routing such that its state doesn't change between calls. Additionally, another reference to it may be needed for serialization.
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 see, thanks! MinCostFlowRouter pull request is at a point where it needs to be tested together with InvoicePayer and tracking in-flight HTLCs, but in a conversion with @TheBlueMatt, he said that as MinCostFlowRouter needs to access liquidity tracking, but not a custom scorer provided by LDK users, LiquidityTracker should be a separate trait implemented by the scorers. Another option in my opinion would be keeping liquidity tracking from scoring totally separate, and DefaultRouter should request the estimated liquidity information and provide it to the immutable Scorer (that can be customized by LDK user, while liquidity tracking implementation probably shouldn't be surfaced in the API).
What do you guys think?
Here's a link to the comments:
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, I think we want at least two follow-ups to this PR:
(1) Move the LockableScore
type parameter to DefaultRouter
since some routers (e.g., remote server routing) don't need a scorer.
(2) Move liquidity tracking to either the Payer
trait or a dedicated one, having InvoicePayer
query it and pass the liquidity information to Router
akin to how it currently passes a scorer.
The latter comes from an observation that I made in review club. ChannelManager
actually knows all the liquidity information given it is the one producing PaymentPathFailed
and PaymentPathSuccessful
events. It also would make liquidity tracking persist across restarts.
See also #1157 for exposing pending payments more generally, which should be considered when making this change.
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 see, thanks, that makes a lot of sense.
51b90ab
to
c43843e
Compare
c43843e
to
e1fddf1
Compare
Added two methods, `process_path_inflight_htlcs` and `remove_path_inflight_htlcs`, that updates that `payment_cache` map with path information that may have failed, succeeded, or have been given up on. Introduced `AccountForInflightHtlcs`, which will wrap our user-provided scorer. We move the `S:Score` type parameterization from the `Router` to `find_route`, so we can use our newly introduced `AccountForInflightHtlcs`. `AccountForInflightHtlcs` keeps track of a map of inflight HTLCs by their short channel id, direction, and give us the value that is being used up. This map will in turn be populated prior to calling `find_route`, where we’ll use `create_inflight_map`, to generate a current map of all inflight HTLCs based on what was stored in `payment_cache`.
Made sure that every hop has a unique receipient. When we simulate calling `channel_penalty_msat` in `TestRouter`’s find route, use actual previous node ids instead of just using the payer’s.
e1fddf1
to
80daf94
Compare
Addresses #1267.
Purpose
As a sender, we want to keep track of all the HTLCs that are currently in flight. We currently do that between pathfinding attempts in
find_route
. However, that information is not currently shared across payments, leading to some inaccuracies.Proposed Implementation
Accounting for the HTLCs will consist of two efforts: keeping track of them, and using them.
Keep Track
In
pay_internal
, we want to respond to specific results ofsend_payment
which will tell us when we'll need to store the path information for use later.Path information is then stored in
payment_cache
of our payer.Using
Before
find_route
is called, we retrieve all the paths we stored, and loop through them to construct a HashMap (HashMap<(u64, bool), u64>
) mapping a channel's short channel id and direction with the amount being sent.This map is wrapped with our user-supplied score in a
AccountForInFlightHtlcs
struct, which will serve to delegateScore
functions to its underlying scorer. It will also use our new liquidity map to construct aChannelUsage
accounting for the inflight HTLCs to be passed tochannel_penalty_msat
.Last Edited: 2022-08-15T05:27:11.602Z
Other Notes
Future opportunities: