Skip to content

Expand PaymentClaimable to include all inbound channel IDs for a payment #3655

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

shaavan
Copy link
Member

@shaavan shaavan commented Mar 8, 2025

Resolves #2274

This PR expands PaymentClaimable to include all inbound channel_ids and user_channel_ids associated with a payment.
This update ensures a clearer representation of the channels used, especially for MPP payments.

@ldk-reviews-bot
Copy link

ldk-reviews-bot commented Mar 8, 2025

👋 Thanks for assigning @joostjager as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@shaavan
Copy link
Member Author

shaavan commented Mar 8, 2025

@benthecarman

Would also be nice if the same information is available on the PaymentClaimed event too

In the current version, I haven’t included channel_ids and user_channel_ids for PaymentClaimed, as they can be easily derived from the event itself:

let channel_ids = payment_claimed_event.htlcs.iter().map(|htlc| htlc.channel_id).collect();

That said, let me know if you’d still prefer to include channel_ids in PaymentClaimed, and I'd be happy to make that change. Thanks!

@benthecarman
Copy link
Contributor

Thanks, @shaavan , that is good enough

@ldk-reviews-bot
Copy link

👋 The first review has been submitted!

Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer.

@valentinewallace
Copy link
Contributor

nit: limit commit subject line in 2nd commit to ~50 characters

@shaavan
Copy link
Member Author

shaavan commented Mar 12, 2025

Updated from pr3655.01 to pr3655.02 (diff):
Addressed @valentinewallace comments

  1. Updated the fields to be Vec<ChannelId>, and Vec<u128>
  2. Updated test utilities to check for all the channels id in events list, for improved test completeness.

Comment on lines 1553 to 1557
// legacy field
// (3, via_channel_id, option),
(4, amount_msat, required),
(5, via_user_channel_id, option),
// legacy field
// (5, via_user_channel_id, option),
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should still write these fields for the sake of users who downgrade (can always write the first item in the vec). Also would be nice to comment in what version the fields became legacy.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done! pr3655.03
I’ve updated the writing so that we maintain downgrade support.
Haven’t added a comment yet since I’m not sure what the next version number will be 😅 (would it be 0.1.3?)

@shaavan
Copy link
Member Author

shaavan commented Mar 13, 2025

Updated from pr3655.02 to pr3655.03 (diff):
Addressed @valentinewallace comments

Changes:

  1. Expanded Documentation
  2. Properly write the legacy fields to maintain downgrade support.

@valentinewallace
Copy link
Contributor

Looks good, feel free to squash! Thanks!

@shaavan
Copy link
Member Author

shaavan commented Mar 15, 2025

Updated from pr3655.03 to pr3655.04 (diff):
Addressed @valentinewallace comments

Changes:

  1. Squash commits.

Copy link

codecov bot commented Mar 15, 2025

Codecov Report

Attention: Patch coverage is 96.42857% with 2 lines in your changes missing coverage. Please review.

Project coverage is 91.37%. Comparing base (5bc9ffa) to head (591c5c8).
Report is 180 commits behind head on main.

Files with missing lines Patch % Lines
lightning/src/events/mod.rs 90.47% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3655      +/-   ##
==========================================
+ Coverage   89.21%   91.37%   +2.16%     
==========================================
  Files         155      156       +1     
  Lines      118966   141344   +22378     
  Branches   118966   141344   +22378     
==========================================
+ Hits       106133   129159   +23026     
+ Misses      10253     9799     -454     
+ Partials     2580     2386     -194     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Member Author

@shaavan shaavan left a comment

Choose a reason for hiding this comment

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

Looks good, feel free to squash! Thanks!

Awesome — thanks a lot for the review, Val! 🚀

@shaavan
Copy link
Member Author

shaavan commented Mar 25, 2025

Updated from pr3655.04 to pr3655.05 (diff):
Addressed @valentinewallace comments

Changes:

  • Added comment documenting when, and why via_channel_id_legacy, and via_user_channel_id_legacy were deprecated.

@shaavan
Copy link
Member Author

shaavan commented Apr 4, 2025

Updated from pr3655.05 to pr3655.06 (diff):
Addressed @valentinewallace comments

Changes:

  1. Updated documentation to correctly reflect that the vector will be incomplete for HTLC created using versions prior to LDK 0.1.0 or prior.

@valentinewallace valentinewallace self-requested a review April 4, 2025 17:11
@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @valentinewallace! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

Copy link
Contributor

@valentinewallace valentinewallace left a comment

Choose a reason for hiding this comment

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

Should be good to land after these last tweaks!

These two utilities will be used in following commit to get all the
inbound channel_ids, and user_channel_ids associated with all the
parts of a payment.
@shaavan
Copy link
Member Author

shaavan commented Apr 8, 2025

Updated from pr3655.06 to pr3655.07 (diff):
Addressed @valentinewallace comments

Changes:

  1. Fixed comments to correctly represent for which version and cases the lists would be incomplete.

@jkczyz jkczyz requested a review from joostjager April 10, 2025 17:29
Copy link
Contributor

@joostjager joostjager left a comment

Choose a reason for hiding this comment

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

Code looks good, test coverage could probably be improved a bit.

@shaavan
Copy link
Member Author

shaavan commented Apr 21, 2025

Updated from pr3655.07 to pr3655.08 (diff):
Addressed @joostjager comments

Changes:

  1. Expanded event test-suite, to check that all events are correctly serialised-deserialised.

@shaavan
Copy link
Member Author

shaavan commented Apr 22, 2025

Updated from pr3655.08 to pr3655.09 (diff):
Addressed @joostjager comments

Changes:

  1. Expanded test, to ensure that all the via_channel_id & via_user_channel_ids are present in PaymentClaimable in multi part payment case.

@valentinewallace
Copy link
Contributor

LGTM

@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @joostjager! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 2nd Reminder

Hey @joostjager! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

via_channel_ids: Vec<ChannelId>,
/// The `user_channel_id`(s) corresponding to the channels over which the payment was received.
/// This will be an incomplete vector for MPP payment events created/serialized using LDK version 0.1.0 and prior.
via_user_channel_ids: Vec<u128>,
Copy link
Contributor

Choose a reason for hiding this comment

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

It's a bit late now, but would it be better to keep id and user_id together in a tuple? Not sure if there are interpretation issues when both vecs have different lengths?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for bringing this up, Joost! I did consider that, but I wasn’t sure if it would offer a clear advantage. As far as I understand, both lists will always be of equal length since both fields were introduced together in the same version, so mismatched lengths shouldn’t arise.

Also, keeping them separate makes their distinction more explicit and follows the structure we’ve used in earlier LDK versions, where via_channel_id and via_user_channel_id were also separate fields.

That said, I’m open to discussing it further if you think a tuple-based design would still be better here! Would love to hear your thoughts.

Copy link
Contributor

Choose a reason for hiding this comment

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

I suppose the tuple leaves less room for questions like these. And maybe the original fields should have been a tuple/struct too. In general, I think it is good to keep the data types as strict as they can be.

But here it doesn't seem to be particular critical. Happy to go along with the other reviewer's view on it.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we'd have to have a Vec<(ChannelId, Option<u128>)> since per ClaimablePayment::get_user_channel_ids docs user channel IDs are only always set after 117... Don't have a strong preference here although the option makes the field's API a bit less nice IMO.

Copy link
Contributor

Choose a reason for hiding this comment

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

The option would be consistent with HTLCPreviousHopData for example

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, isn't it the case that pre-117 data just translates to an empty vec<(..,..)> without requiring the option?

// we test all generated events round-trip:
for event in &collected_events {
let ser = event.encode();
if let Some(deser) = events::Event::read(&mut &ser[..]).expect("event should deserialize") {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the None case ok to ignore?

Copy link
Member Author

Choose a reason for hiding this comment

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

AFAIU, yes. Some event enums are designed to map to a None value (for example, 0u8, 4u8, and 17u8), so getting an Ok(None) seems to indicate that the event was read successfully and no further checks are needed in this case.

That said, I'd love to hear @valentinewallace's thoughts to confirm if I’m understanding this correctly!

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, some events are never written so I believe @shaavan is correct here

Copy link
Contributor

Choose a reason for hiding this comment

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

So could also continue when ser is None then, and unwrap the read? Not that it is all that important ofc.

Copy link
Contributor

@valentinewallace valentinewallace Apr 28, 2025

Choose a reason for hiding this comment

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

ser just returns Ok(()) on success, not an option.. But if you want to rearrange this code somehow, no strong preference here.

Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like ser is just Vec<u8>. So if that is empty, we expect None from read? Maybe that can be used to make it slightly stricter and detect the case where read is unexpectedly returning None.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh right, sorry. It looks like for events where we don't write the actual event, we will still write the type for the event: https://github.com/lightningdevkit/rust-lightning/blob/main/lightning/src/events/mod.rs#L1809 so I don't think we can check if it's empty but we could check if only a u8 was written.

Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps a too much internal detail then. Can leave this as is as far as I am concerned.

shaavan added 2 commits April 28, 2025 18:26
Previously, `channel_id` in `PaymentClaimable` only listed a single
inbound channel, which was misleading for MPP payments arriving via
multiple channels.

To better represent MPP scenarios, this update introduces:
- `via_channel_ids`: A list of all inbound channels used in the payment.
- `via_user_channel_ids`: The corresponding user-defined channel IDs for
  each inbound channel.

This change ensures a more accurate representation of multi-path payments
while maintaining backward compatibility.
- Expand testing to ensure proper serialise-deserialise round-trip for
all events.
- Expand a multi-Part payment test to ensure that all the channel ids &
  user channel ids are present in the PaymentClaimable event
@shaavan
Copy link
Member Author

shaavan commented Apr 28, 2025

Updated from pr3655.09 to pr3655.10 (diff):
Addressed @joostjager comments

Changes:

  1. Add check that the via_channel_ids, and via_user_channel_ids only contains one element for the appropriate cases.


/// Returns the inbound `user_channel_id`s for all HTLCs associated with the payment.
///
/// Note: This list will be incomplete for HTLCs created using LDK version 0.0.117 or prior.
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment does seem to suggest that vecs can be different lengths?

Copy link
Contributor

@joostjager joostjager Apr 28, 2025

Choose a reason for hiding this comment

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

@shaavan, @valentinewallace and I chatted about it. Seems something to say for a stronger type, especially because the vecs both map from PrevHopData already. But it's a bit late now also, and not too critical. So leaving up to you to decide.

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.

PaymentClaimable lists inbound channel id
5 participants