Skip to content

Conversation

a-mpch
Copy link
Contributor

@a-mpch a-mpch commented Sep 19, 2025

This PR is on top of @valentinewallace branch that simplifies how trampoline testing is done. These changes surfaced a bug on how we were building the errors when the receiver is also a Trampoline inside the route. Specifically the first on the route as we aren't routing yet.

The final commit fixes this bug adding trampoline shared secret so we double obfuscate errors in these cases.

@ldk-reviews-bot
Copy link

ldk-reviews-bot commented Sep 19, 2025

👋 I see @tankyleo was un-assigned.
If you'd like another reviewer assignment, please click here.

This simplifies the code and makes it more straightforward to test unblinded
trampoline receives where we need to compute the trampoline session_priv when
manually creating the inner onion. (The trampoline onion needs to be manually
created because LDK does not natively support sending to unblinded trampolines,
just receiving.)
No need to construct unused blinded hop data or hardcode session privs/prng
seeds.
@a-mpch a-mpch force-pushed the 2025-08-trampoline-test-refactor branch 2 times, most recently from b426301 to 1abdff1 Compare September 19, 2025 14:19
&payment_hash,
onion_error
);
let secondary_shared_secret = trampoline_shared_secret.or(*phantom_shared_secret);
Copy link
Contributor

Choose a reason for hiding this comment

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

There appears to be a type mismatch in this line. trampoline_shared_secret is an Option<[u8; 32]> while phantom_shared_secret is a reference &Option<[u8; 32]>.

The .or() method expects both options to be of the same type. Consider using .or_else(|| *phantom_shared_secret) instead to properly handle the different option types.

Suggested change
let secondary_shared_secret = trampoline_shared_secret.or(*phantom_shared_secret);
let secondary_shared_secret = trampoline_shared_secret.or_else(|| *phantom_shared_secret);

Spotted by Diamond

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

@valentinewallace valentinewallace self-requested a review September 19, 2025 14:28
Copy link

codecov bot commented Sep 19, 2025

Codecov Report

❌ Patch coverage is 99.11894% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.65%. Comparing base (0cb7f54) to head (fcc2651).
⚠️ Report is 166 commits behind head on main.

Files with missing lines Patch % Lines
lightning/src/ln/blinded_payment_tests.rs 99.44% 1 Missing ⚠️
lightning/src/ln/channelmanager.rs 92.30% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4095      +/-   ##
==========================================
+ Coverage   88.61%   88.65%   +0.03%     
==========================================
  Files         176      180       +4     
  Lines      132120   135288    +3168     
  Branches   132120   135288    +3168     
==========================================
+ Hits       117083   119934    +2851     
- Misses      12367    12586     +219     
- Partials     2670     2768      +98     
Flag Coverage Δ
fuzzing 21.76% <10.63%> (+0.21%) ⬆️
tests 88.49% <99.11%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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
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.

Thanks @a-mpch!

Comment on lines 288 to 291
}, ..
} =>
(payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat,
cltv_expiry_height, payment_metadata, None, false, keysend_preimage.is_none(), None),
cltv_expiry_height, payment_metadata, None, false, keysend_preimage.is_none(), None, None),
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 also be returning the trampoline ss here? Looks like if we adapted test_trampoline_unblinded_receive to cover both the success and the failure case, it would catch this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, just tested. Added a commit

@a-mpch a-mpch force-pushed the 2025-08-trampoline-test-refactor branch from 1abdff1 to a0f4c41 Compare September 19, 2025 20:04
@a-mpch
Copy link
Contributor Author

a-mpch commented Sep 19, 2025

Thanks @valentinewallace, all comments had been addressed. Re-ordered commits and added one for test_trampoline_unblinded_receive so it catches the one mentioned.

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.

LGTM if CI is happy

&payment_hash,
onion_error
);
let secondary_shared_secret = trampoline_shared_secret.or(*phantom_shared_secret);
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 in the case of trampoline + phantom we may need a third layer of onion wrapping for the error packet... not convinced we need to worry about this though. Are you able to edit the trampoline issue to document this case for follow-up?

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 can't edit the issue

Copy link
Contributor

Choose a reason for hiding this comment

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

If we don't support T+P, it may be better to error rather than prioritize T?

Copy link
Contributor

@valentinewallace valentinewallace Oct 7, 2025

Choose a reason for hiding this comment

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

Error how? We need to fail backwards, I think? Added this to the tracking issue.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, failing to fail isn't quite possible. There could be a log here perhaps if we unexpectedly get T+P?

Copy link
Contributor

@valentinewallace valentinewallace Oct 8, 2025

Choose a reason for hiding this comment

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

A comment or log seems like a good idea to me. Log would be conditional which would add some logic so slightly prefer a 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.

amended changes with a comment!

@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @tankyleo! 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.

@a-mpch
Copy link
Contributor Author

a-mpch commented Sep 22, 2025

@valentinewallace added the removal of the unused to the commit 80c6ad5

Also there are some flaky test that are failing also in other PRs. I think they are not related to this PR if CI is not happy.

tests::test_background_event_handling
 tests::test_payment_path_scoring

@ldk-reviews-bot
Copy link

🔔 2nd Reminder

Hey @tankyleo! 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

🔔 3rd Reminder

Hey @tankyleo! 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

🔔 4th Reminder

Hey @tankyleo! 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

🔔 5th Reminder

Hey @tankyleo! 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.

@tankyleo tankyleo requested review from joostjager and removed request for tankyleo October 3, 2025 17:04
@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.

&payment_hash,
onion_error
);
let secondary_shared_secret = trampoline_shared_secret.or(*phantom_shared_secret);
Copy link
Contributor

Choose a reason for hiding this comment

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

If we don't support T+P, it may be better to error rather than prioritize T?

}

#[test]
fn test_trampoline_forward_payload_encoded_as_receive() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Squashing this commit with the previous, would it make for a nicer diff?

Copy link
Contributor

@valentinewallace valentinewallace Oct 8, 2025

Choose a reason for hiding this comment

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

Hmm, can you check out how it looks like squashed in the GH UI? It kind of looks like it mixes the tests in with each other. Not convinced it's more readable, definitely not gonna block on it though ofc. I agree it's a bit unfortunate how these test diffs aren't the easiest to review...

Copy link
Contributor

Choose a reason for hiding this comment

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

Good point about GH UI. And indeed, it doesn't look good at all.

&payment_hash,
onion_error
);
let secondary_shared_secret = trampoline_shared_secret.or(*phantom_shared_secret);
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, failing to fail isn't quite possible. There could be a log here perhaps if we unexpectedly get T+P?

(5, custom_tlvs, optional_vec),
(7, requires_blinded_error, (default_value, false)),
(9, payment_context, option),
(11, trampoline_shared_secret, option),
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of adding a new field, could it also work by repurposing phantom_shared_secret as secondary_shared_secret and have it contain either the T or P secret?

Copy link
Contributor

Choose a reason for hiding this comment

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

I like a separate field because then we leave the door open to support failing backwards properly (by wrapping the error onion three times) for P+T payments in the future

a-mpch and others added 4 commits October 8, 2025 12:53
When handling HTLC failures in trampoline routing, error packets were not
being properly encrypted with the trampoline shared secret. This caused
error messages to be unreadable by the original sender when failures
occurred within trampoline hops.

The fix prioritizes trampoline_shared_secret over phantom_shared_secret
when both are available, ensuring error packets can be properly decrypted
by trampoline senders.
Previously, this test purported to test for a successful and a failing payment
to a single-hop blinded path containing one trampoline node. However, to induce
the failure the test was manually reconstructing the trampoline onion in a
complicated way that encoded the final onion payload as a receive, when for its
purposes it would be simplier for the recipient to just fail the payment
backwards.

In order to not regress in test coverage, the failure method the test was
previously using is re-added in the next commit as a dedicated test.
This re-adds test coverage for a case that was removed in the previous commit.
Previously this commit, test only check for succesfully claimed case. Now tests
that successfully fail the HTLC and sender can read the error.
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