Skip to content
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

Move InflightHtlcs and Router trait into ChannelManager #1811

Merged

Conversation

valentinewallace
Copy link
Contributor

This prepares us to parameterize ChannelManager with a Router trait, which will then be used to fetch routes on-the-fly for trampoline payments.

Relates to #1157 although trampoline is not blocked by it -- ChannelManager can just not factor in in-flight HTLCs for now.

This helps prepare for moving the Router trait into ChannelManager, which will
help allow ChannelManager to retrieve routes for trampoline
@codecov-commenter
Copy link

codecov-commenter commented Oct 27, 2022

Codecov Report

Base: 90.72% // Head: 91.41% // Increases project coverage by +0.69% 🎉

Coverage data is based on head (7db8052) compared to base (6957fb6).
Patch coverage: 69.23% of modified lines in pull request are covered.

❗ Current head 7db8052 differs from pull request most recent head df593dc. Consider uploading reports for the commit df593dc to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1811      +/-   ##
==========================================
+ Coverage   90.72%   91.41%   +0.69%     
==========================================
  Files          87       87              
  Lines       47361    51151    +3790     
  Branches    47361    51151    +3790     
==========================================
+ Hits        42968    46761    +3793     
+ Misses       4393     4390       -3     
Impacted Files Coverage Δ
lightning-invoice/src/utils.rs 95.17% <ø> (ø)
lightning/src/routing/router.rs 93.18% <ø> (+1.56%) ⬆️
lightning-invoice/src/payment.rs 89.68% <50.00%> (-0.17%) ⬇️
lightning/src/ln/channelmanager.rs 85.19% <85.71%> (+<0.01%) ⬆️
lightning/src/ln/monitor_tests.rs 99.55% <0.00%> (+0.11%) ⬆️
lightning/src/ln/peer_channel_encryptor.rs 93.62% <0.00%> (+0.24%) ⬆️
lightning/src/util/events.rs 38.40% <0.00%> (+0.26%) ⬆️
lightning/src/chain/onchaintx.rs 95.67% <0.00%> (+0.38%) ⬆️
lightning/src/util/test_utils.rs 77.06% <0.00%> (+0.66%) ⬆️
lightning/src/onion_message/functional_tests.rs 96.25% <0.00%> (+0.76%) ⬆️
... and 7 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

&self, payer: &PublicKey, route_params: &RouteParameters, payment_hash: &PaymentHash,
&self, payer: &PublicKey, route_params: &RouteParameters,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we want to do this. It's for implementations wanting to support looking up pre-computed routes from a probe, according to the commit when added.

592bfd7

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wouldn't be ideal to provide users with the payment hash in trampoline payments.

Do either of these options seem reasonable:
(1) make payment_hash into an Option<(PaymentHash, PaymentId)>
(2) make payment_hash into an Option<PaymentId>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wouldn't be ideal to provide users with the payment hash in trampoline payments.

Could you expand on this? Is the hash not available? Or is providing it harmful / misleading in some way?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's leaking the sender's privacy since it's not our payment

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also can't provide a PaymentId for trampoline payments, which we'd like to, I think. We might also want to keep a separate routing trait for the payer? Ugh...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wouldn't be ideal to provide users with the payment hash in trampoline payments.

Do either of these options seem reasonable: (1) make payment_hash into an Option<(PaymentHash, PaymentId)> (2) make payment_hash into an Option<PaymentId>

Where is PaymentId coming from / why is it needed?

I think it's leaking the sender's privacy since it's not our payment

Not really sure I follow this. If our node knows the payment hash, hasn't it already been leaked?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC there's still a difference in privacy between seeing it in an internal update_add_htlc message vs actually providing it to a user in a trait method.

Where is PaymentId coming from / why is it needed?

Same reason a payment_hash is being provided in 592bfd7 I think, to have another option to look up pre-computed probes. As of #1761, PaymentIds will be required upon all payment initiations, so it'd come from there for non-trampoline find_route calls.

Comment on lines 75 to 89
/// A map with liquidity value (in msat) keyed by a short channel id and the direction the HTLC
/// is traveling in. The direction boolean is determined by checking if the HTLC source's public
/// key is less than its destination. See [`InFlightHtlcs::used_liquidity_msat`] for more
/// details.
#[cfg(not(any(test, feature = "_test_utils")))]
pub struct InFlightHtlcs(HashMap<(u64, bool), u64>);
#[cfg(any(test, feature = "_test_utils"))]
pub struct InFlightHtlcs(pub HashMap<(u64, bool), u64>);

impl InFlightHtlcs {
/// Create a new `InFlightHtlcs` via a mapping from:
/// (short_channel_id, source_pubkey < target_pubkey) -> used_liquidity_msat
pub fn new(inflight_map: HashMap<(u64, bool), u64>) -> Self {
InFlightHtlcs(inflight_map)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe could be left to a later refactor (cc: @jurvis), but it seems odd we expose the implementation details about the HashMap. Perhaps we should have a method for adding paths.

Another thought -- when adding this to the Payer interface -- is to have an associated type with a trait bound on some new trait having a used_liquidity_msat. Though that would mean Router and Payer would need to agree on that associated type as it would be need in Router, too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does seem like the best way here could depend on how #1157 shakes out. I agree it's weird but I'm not 100% sure the best approach that wouldn't churn. Open to @jurvis's and your thoughts though if there seems to be a clear way.

when adding this to the Payer interface

Not following, what is being added to Payer?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not following, what is being added to Payer?

A method for accessing InFlightHtlcs. Background: #1643 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I wouldn't be opposed to an associated type. I'm reluctant to be totally blocked on that issue though. Do you think there's something that can be done to make progress in the meantime here?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand why an associated type makes sense - what implementation other than a HashMap would someone want to use for this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was leaning towards the former approach. Anyhow, this is orthogonal to the PR. Figured @jurvis would tackle it when updating the Payer trait.

Comment on lines 116 to 119
/// Lets the router know that payment through a specific path has failed.
fn notify_payment_path_failed(&self, path: &[&RouteHop], short_channel_id: u64);
/// Lets the router know that payment through a specific path was successful.
fn notify_payment_path_successful(&self, path: &[&RouteHop]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will ChannelManager need to care about these methods? Seems like the distinction isn't probing vs non-probing but rather routing vs event handling.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ChannelManager as an async sending LSP has an opportunity to collect a lot of useful payment success/failure data for scoring. That said, I'm ok leaving these methods out for now if it's preferred

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... so essentially ChannelManager wouldn't surface any events for the user to handle but would handle them internally. Wouldn't it also need to retry failures? Seems like something more akin to InvoicePayer would be required rather than just the Router.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline, yes that's accurate but we're not sure what to do yet. W/r/t to the question at hand, would you prefer to remove these methods for now?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline, yes that's accurate but we're not sure what to do yet. W/r/t to the question at hand, would you prefer to remove these methods for now?

Yeah, let's remove them... But that said, should we even bother with the interface churn now -- given this is for experimentation -- if it will likely to be different when accounting for retires? That is, can't the experiment simply call the standalone find_route function directly for now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, i'm definitely gonna remove the payment_path_* methods for now. I was hoping to get your input on:

should we even bother with the interface churn now -- given this is for experimentation -- if it will likely to be different when accounting for retires? That is, can't the experiment simply call the standalone find_route function directly for now?

@TheBlueMatt

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why that changes anything? Yes, we'll want to provide the "previous path attempts" set to the router just like we do for regular payments, but that can come as a parameter (eg via RouteParameters, just like we do for our own payments).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The concern is about essentially re-writing the retry logic of InvoicePayer here. I'm not yet convinced parameterizing ChannelManager with a Router is the right approach. Even if it is, it sorta begs the question as to why we shouldn't move all of InvoicePayer's retry logic inside ChannelManager rather than using InvoicePayer as an EventHandler wrapper, as we currently do. Just think we need to put some more thought into this design.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, sorry, I thought you meant passing previous-try info into the Router. Right, I'd think we'd want to move the retry logic into the ChannelManager, though that seems independent, I dont think the Router trait would look any different once we move retry logic into ChannelManager, so this would still be a good first step.

Indeed, if we didnt want to move retrying into the ChannelManager then we'd probably have this look very different, but the question there seems to me to be "do we want/expect every routing node to support trampoline, or is it really just an LSP-level thing". If we think its an LSP-level thing I think we shouldn't do trampoline at all (it has terrible privacy in that kind of deployment). If we think it should be a part of every routing node, then pushing the trampoline handling out to an event would force users into a good bit of boilerplate that they really have no choice but to implement, which seems wasteful.

Adding retry logic into ChannelManager also seems kinda nice, it simplifies the amount of boilerplate users have to have for handling their own payments, which we've heard is an issue for users, and its no less expressible - you can always pass a RetryCount(0) when sending a payment and handle it yourself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline, gonna move forward with parameterizing ChannelManager with Router but reassess overall API design at each step. There may be an opportunity to break ChannelManager up into multiple subsystems (e.g. payment forwarding) to clean things up along the way.

@jkczyz can speak more to this, but it may be advantageous to create a Node abstraction over InvoicePayer / ChannelManager (which could be renamed).

&self, payer: &PublicKey, route_params: &RouteParameters, payment_hash: &PaymentHash,
&self, payer: &PublicKey, route_params: &RouteParameters,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wouldn't be ideal to provide users with the payment hash in trampoline payments.

Do either of these options seem reasonable: (1) make payment_hash into an Option<(PaymentHash, PaymentId)> (2) make payment_hash into an Option<PaymentId>

Where is PaymentId coming from / why is it needed?

I think it's leaking the sender's privacy since it's not our payment

Not really sure I follow this. If our node knows the payment hash, hasn't it already been leaked?

/// and scoring based on payment success data.
///
/// [`Router`]: lightning::ln::channelmanager::Router
pub trait ScoringRouter: Router {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we define a different find_route function here that does include the PaymentId/PaymentHash and just call out to the underlying find_route by default?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I follow why we want to do this and why it shouldn't be on Router instead. Doesn't look like it's used here?

Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically LGTM.

Copy link
Contributor

@jkczyz jkczyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to squash.

This is part of moving the Router trait into ChannelManager, which will help
allow ChannelManager to fetch routes on-the-fly as part of supporting
trampoline payments.
This helps prepare to parameterize ChannelManager with a Router, to eventually
use in trampoline payments.
@TheBlueMatt TheBlueMatt merged commit e55e0d5 into lightningdevkit:main Nov 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants