Add support for custom HTLC TLVs - #2308

Merged
TheBlueMatt merged 7 commits into
lightningdevkit:mainfrom
alecchendev:2023-05-custom-htlc-tlvs
Aug 10, 2023
Merged

Add support for custom HTLC TLVs#2308
TheBlueMatt merged 7 commits into
lightningdevkit:mainfrom
alecchendev:2023-05-custom-htlc-tlvs

Conversation

@alecchendev

@alecchendevalecchendev commented May 19, 2023

Copy link
Copy Markdown
Contributor

Closes#1298. This PR adds support for sending and receiving custom HTLC TLVs.

Custom TLVs allow users to send extra application-specific data with a payment. These have the additional flexibility compared to payment_metadata that they don't have to reflect recipient generated data provided in an invoice, in which payment_metadata could (probably) be reused.

On the send side, a user can provide their serialized TLVs as a Vec<(u64, Vec<u8>)> to RecipientOnionFields::with_custom_tlvs which checks whether the type numbers are unique, increasing, and in the range reserved for custom values. They'll then pass this into whichever send payment function they use, it'll be serialized in the onion payload, and sent with the payment.

On the receive side, when deserializing the onion payload, we just add the bytes back into this type, then pipe it from the onion through to Event::PaymentClaimable, dropping non-matching TLVs between payment parts.

@alecchendevalecchendev left a comment

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

A couple questions for reviewers:

Comment threadlightning/src/offers/merkle.rs Outdated
Comment threadlightning/src/offers/merkle.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 2 times, most recently from 87ec6b0 to 4cb0a4bCompareMay 20, 2023 21:49
Comment threadlightning/src/ln/msgs.rs
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 4cb0a4b to 07a9910CompareMay 20, 2023 22:22
@codecov-commenter

codecov-commenter commented May 20, 2023

Copy link
Copy Markdown

Codecov Report

Patch coverage: 95.32% and project coverage change: +0.34% 🎉

Comparison is base (e13ff10) 90.24% compared to head (93a8fb6) 90.58%.
Report is 21 commits behind head on main.

❗ Current head 93a8fb6 differs from pull request most recent head 1db481f. Consider uploading reports for the commit 1db481f to get more accurate results

❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

Additional details and impacted files
@@ Coverage Diff @@## main #2308 +/- ##
==========================================
+ Coverage 90.24% 90.58% +0.34% 
==========================================
Files 106 106 Lines 55817 59617 +3800 Branches 55817 59617 +3800 ==========================================
+ Hits 50370 54007 +3637 - Misses 5447 5610 +163 
Files ChangedCoverage Δ
lightning/src/events/mod.rs41.98% <ø> (+0.37%)⬆️
lightning/src/util/ser_macros.rs67.75% <0.00%> (-2.81%)⬇️
lightning/src/ln/onion_route_tests.rs98.51% <85.71%> (+0.01%)⬆️
lightning/src/ln/payment_tests.rs97.38% <95.04%> (-0.28%)⬇️
lightning/src/ln/msgs.rs85.10% <96.55%> (+0.36%)⬆️
lightning/src/ln/channelmanager.rs86.73% <97.91%> (+1.28%)⬆️
lightning-invoice/src/payment.rs88.59% <100.00%> (-0.08%)⬇️
lightning/src/ln/functional_test_utils.rs88.93% <100.00%> (+0.01%)⬆️
lightning/src/ln/onion_utils.rs90.90% <100.00%> (-0.16%)⬇️
lightning/src/ln/outbound_payment.rs92.77% <100.00%> (+3.57%)⬆️

... and 4 files with indirect coverage changes

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

@wpaulino
wpaulino self-requested a review May 21, 2023 02:11
@dunxen
dunxen self-requested a review May 26, 2023 07:05

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sorry for the delay here, just getting caught up post-travels.

Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/offers/merkle.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 07a9910 to 3d848a6CompareJune 2, 2023 04:00
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/outbound_payment.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 4 times, most recently from 3483289 to 59f3fb6CompareJune 8, 2023 18:53
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/msgs.rs
@alecchendev
alecchendev marked this pull request as ready for review June 8, 2023 18:59
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 2 times, most recently from a7a2162 to ad4376eCompareJune 10, 2023 23:02
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Rebased due to conflicts.

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This basically looks good, I think, needs another reviewer.

Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 3 times, most recently from 751c245 to a0d10a3CompareJune 14, 2023 05:44

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good! Since a user can now include arbitrary data, do we know if the router can handle restricting the number of hops based on the existing recipient payload?

Comment threadlightning/src/util/ser_macros.rs Outdated
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

do we know if the router can handle restricting the number of hops based on the existing recipient payload?

It currently cannot, though this is an issue that was really introduced in payment metadata, this just makes it worse. Tracked at #2201.

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Feel free to squash fixups when you next push, I think.

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from a0d10a3 to fdbcbffCompareJune 20, 2023 23:35
@wpaulinowpaulino added this to the 0.0.117 milestone Jul 5, 2023
@TheBlueMattTheBlueMatt added the blocked on next release Should Wait Until Next Release To Land label Jul 8, 2023
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

While we're still debating nits on the docs, can you go ahead and squash so we're set up to land? @wpaulino or @dunxen might want to take a look thereafter.

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 93a8fb6 to e8eedd3CompareJuly 31, 2023 02:03

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from e8eedd3 to 9a77843CompareAugust 1, 2023 02:26
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Fixed and squashed immediately since they were just small nits

@ariard

Copy link
Copy Markdown

this is why blinded paths have no error returned at all.

yes, though i’m not sure no returning error is workable on the long-term due to onion bandwidth cost and payment reliability (at least end-to-end), though here more conversation at the spec-level.

answered on the two comments:

  • i still wish we do our best to mask user agent and version from deanonymization attacks like done for browser / tor services
  • i still think “authentication” should be a strong suggestion, seen example of multiple payer not compatible with current payment_secret

though overall i won’t insist and if / when we have users privacy screwed up on those vectors, i’ll just pointed it back to you guys :)

@ariard

Copy link
Copy Markdown

i still wish we do our best to mask user agent and version from deanonymization attacks like done for browser / tor services

here the code is good in fact after looking (though doc confusing), just good if we don’t change it in the future to match BOLT4 bad suggestion imho

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 9a77843 to 1db481fCompareAugust 3, 2023 17:33
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Squashed immediately for minor doc change:

diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index 968b0765..daa0b34f 100644
--- a/lightning/src/ln/channelmanager.rs+++ b/lightning/src/ln/channelmanager.rs@@ -371,7 +371,7 @@ pub enum FailureCode {
/// We failed to process the payload after the onion was decrypted. You may wish to
/// use this when receiving custom HTLC TLVs with even type numbers that you don't recognize.
///
- /// If available, the tuple data should include the type number and byte offset in the+ /// If available, the tuple data may include the type number and byte offset in the
/// decrypted byte stream where the failure occurred.
InvalidOnionPayload(Option<(u64, u16)>),
}

@ariard

Copy link
Copy Markdown

Happy after following diff applied, payment_secret does not work for N-payer / N-payee flows, though it sounds reasonable for one payer / one payer flow, as far as I know about things like cancellable payments

diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index daa0b34f..db1108b4 100644
--- a/lightning/src/ln/channelmanager.rs
+++ b/lightning/src/ln/channelmanager.rs
@@ -4769,6 +4769,8 @@ where
/// You MUST check you've understood all even TLVs before using this to
/// claim, otherwise you may unintentionally agree to some protocol you do not understand.
///
+ /// You MAY authenticate the even TLVs additionally of `payment_secret` if the protocol
+ /// flow is more sophisticated than one payer / one payee.
/// [`claim_funds`]: Self::claim_funds
pub fn claim_funds_with_known_custom_tlvs(&self, payment_preimage: PaymentPreimage) {
self.claim_payment_internal(payment_preimage, true);

wpaulino
wpaulino previously approved these changes Aug 4, 2023

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review ACK 1db481f

Nevermind the above comment effectively multi-payer scheme would need additional code changes in our MPP validation and as such wider custom HTLC support (though they’re the ones more exposed in term of potential deanonymization attacks)

FailureCode::InvalidOnionPayload(data) => {
let fail_data = match data {
Some((typ, offset)) => [BigSize(typ).encode(), offset.encode()].concat(),
None => Vec::new(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: I think the debug_assert(data.is_none()) could be added due to its only usage in claim_payment_internal with a None value given to InvalidOnionPayload.

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Grrr, needs rebase, sorry about that.

Custom TLVs allow users to send extra application-specific data with
a payment. These have the additional flexibility compared to
`payment_metadata` that they don't have to reflect recipient generated
data provided in an invoice, in which `payment_metadata` could be
reused.
We ensure provided type numbers are unique, increasing, and within the
experimental range with the `RecipientOnionFields::with_custom_tlvs`
method.
This begins sender-side support for custom TLVs.
When serialized, the TLVs in `OutboundOnionPayload`, unlike a normal
TLV stream, are prefixed with the length of the stream. To allow a user
to add arbitrary custom TLVs, we aren't able to communicate to our
serialization macros exactly which fields to expect, so this commit
adds new macro variants to allow appending an extra set of bytes (and
modifying the prefixed length accordingly).
Because the keysend preimage TLV has a type number in the custom type
range, and a user's TLVs may have type numbers above and/or below
keysend's type number, and because TLV streams must be serialized in
increasing order by type number, this commit also ensures the keysend
TLV is properly sorted/serialized amongst the custom TLVs.
This completes basic receiver-side support for custom TLVs and adds
functional testing for sending and receiving.
Upon receiving multiple payment parts with custom TLVs, we fail payments
if they have any non-matching or missing even TLVs, and otherwise just
drop non-matching TLVs if they're odd.
When a user decodes custom TLVs, if they fail to recognize even type
numbers they should fail back with the correct failure code and fail
data. This new variant adds the proper failure variant for the user to
pass into `ChannelManager::fail_htlc_backwards_with_reason`.
Note that the enum discriminants were removed because when adding a
struct variant we can no longer make use of the discriminant through
casting like we previously did, and instead have to manually define the
associated failure code anyway.
Because we don't know which custom TLV type numbers the user is
expecting (and it would be cumbersome for them to tell us), instead of
failing unknown even custom TLVs on deserialization, we accept all
custom TLVs, and pass them to the user to check whether they recognize
them and choose to fail back if they don't. However, a user may not
check for custom TLVs, in which case we should reject any even custom
TLVs as unknown.
This commit makes sure a user must explicitly accept a payment with
even custom TLVs, by (1) making the default
`ChannelManager::claim_funds` fail if the payment had even custom TLVs
and (2) adding a new function
`ChannelManager::claim_funds_with_known_custom_tlvs` that accepts them.
This commit also refactors our custom TLVs test and updates various
documentation to account for this.
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Rebased

}

#[cfg(debug_assertions)] {
let mut last_seen: Option<u64> = None;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

it'd be nice to have this in one macro body with the above non-custom TLVs so that we can debug_assert!() that the ordering including custom TLVs is correct.

let tlvs = &mut self.custom_tlvs;
let further_tlvs = &mut further_htlc_fields.custom_tlvs;

let even_tlvs: Vec<&(u64, Vec<u8>)> = tlvs.iter().filter(|(typ, _)| *typ % 2 == 0).collect();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You should be able to do the comparison here without collecting into a Vec.

let preimage = if let Some(ref preimage) = keysend_preimage {
Some((5482373484, preimage.encode()))
} else { None };
let mut custom_tlvs: Vec<&(u64, Vec<u8>)> = custom_tlvs.iter().chain(preimage.iter()).collect();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We are trying to build an interator, we shouldn't have to collect here (though the macro may want it twice, so we may have to do the iter().chain() in the macro argument rather than here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Though AFAIK it wouldn't be possible to sort the tlvs as an iterator?

match &purpose {
PaymentPurpose::InvoicePayment { payment_secret, .. } => {
assert_eq!(our_payment_secret, *payment_secret);
assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: just for your reference, if we're copying test util bits into a test, we can usually skip a bunch of the assertions - the test utility methods tend to be a bit verbose and check everything, which is great in the general code, but in an individual test we don't need to test too much more than we care about for the purpose of the specific test.

@TheBlueMatt
TheBlueMatt merged commit 9e4a35a into lightningdevkit:mainAug 10, 2023
if let Some(expected_tlvs) = expected_receive_tlvs {
// Claim and match expected
let events = nodes[3].node.get_and_clear_pending_events();
println!("events: {:?}", events);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oops, I missed this before hitting merge, let's do a followup and remove this (and maybe hit a few other nits, though no real pressure on those).

@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Thanks for all the review everybody, will get a follow up up soon :)

Sign up for freeto 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.

Custom HTLC TLVs

6 participants

@alecchendev@codecov-commenter@TheBlueMatt@ariard@dunxen@wpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Add support for custom HTLC TLVs - #2308

Merged
TheBlueMatt merged 7 commits into
lightningdevkit:mainfrom
alecchendev:2023-05-custom-htlc-tlvs
Aug 10, 2023
Merged

Add support for custom HTLC TLVs#2308
TheBlueMatt merged 7 commits into
lightningdevkit:mainfrom
alecchendev:2023-05-custom-htlc-tlvs

Conversation

@alecchendev

@alecchendevalecchendev commented May 19, 2023

Copy link
Copy Markdown
Contributor

Closes#1298. This PR adds support for sending and receiving custom HTLC TLVs.

Custom TLVs allow users to send extra application-specific data with a payment. These have the additional flexibility compared to payment_metadata that they don't have to reflect recipient generated data provided in an invoice, in which payment_metadata could (probably) be reused.

On the send side, a user can provide their serialized TLVs as a Vec<(u64, Vec<u8>)> to RecipientOnionFields::with_custom_tlvs which checks whether the type numbers are unique, increasing, and in the range reserved for custom values. They'll then pass this into whichever send payment function they use, it'll be serialized in the onion payload, and sent with the payment.

On the receive side, when deserializing the onion payload, we just add the bytes back into this type, then pipe it from the onion through to Event::PaymentClaimable, dropping non-matching TLVs between payment parts.

@alecchendevalecchendev left a comment

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

A couple questions for reviewers:

Comment threadlightning/src/offers/merkle.rs Outdated
Comment threadlightning/src/offers/merkle.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 2 times, most recently from 87ec6b0 to 4cb0a4bCompareMay 20, 2023 21:49
Comment threadlightning/src/ln/msgs.rs
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 4cb0a4b to 07a9910CompareMay 20, 2023 22:22
@codecov-commenter

codecov-commenter commented May 20, 2023

Copy link
Copy Markdown

Codecov Report

Patch coverage: 95.32% and project coverage change: +0.34% 🎉

Comparison is base (e13ff10) 90.24% compared to head (93a8fb6) 90.58%.
Report is 21 commits behind head on main.

❗ Current head 93a8fb6 differs from pull request most recent head 1db481f. Consider uploading reports for the commit 1db481f to get more accurate results

❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

Additional details and impacted files
@@ Coverage Diff @@## main #2308 +/- ##
==========================================
+ Coverage 90.24% 90.58% +0.34% 
==========================================
Files 106 106 Lines 55817 59617 +3800 Branches 55817 59617 +3800 ==========================================
+ Hits 50370 54007 +3637 - Misses 5447 5610 +163 
Files ChangedCoverage Δ
lightning/src/events/mod.rs41.98% <ø> (+0.37%)⬆️
lightning/src/util/ser_macros.rs67.75% <0.00%> (-2.81%)⬇️
lightning/src/ln/onion_route_tests.rs98.51% <85.71%> (+0.01%)⬆️
lightning/src/ln/payment_tests.rs97.38% <95.04%> (-0.28%)⬇️
lightning/src/ln/msgs.rs85.10% <96.55%> (+0.36%)⬆️
lightning/src/ln/channelmanager.rs86.73% <97.91%> (+1.28%)⬆️
lightning-invoice/src/payment.rs88.59% <100.00%> (-0.08%)⬇️
lightning/src/ln/functional_test_utils.rs88.93% <100.00%> (+0.01%)⬆️
lightning/src/ln/onion_utils.rs90.90% <100.00%> (-0.16%)⬇️
lightning/src/ln/outbound_payment.rs92.77% <100.00%> (+3.57%)⬆️

... and 4 files with indirect coverage changes

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

@wpaulino
wpaulino self-requested a review May 21, 2023 02:11
@dunxen
dunxen self-requested a review May 26, 2023 07:05

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sorry for the delay here, just getting caught up post-travels.

Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/offers/merkle.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 07a9910 to 3d848a6CompareJune 2, 2023 04:00
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/outbound_payment.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 4 times, most recently from 3483289 to 59f3fb6CompareJune 8, 2023 18:53
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/msgs.rs
@alecchendev
alecchendev marked this pull request as ready for review June 8, 2023 18:59
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 2 times, most recently from a7a2162 to ad4376eCompareJune 10, 2023 23:02
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Rebased due to conflicts.

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This basically looks good, I think, needs another reviewer.

Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 3 times, most recently from 751c245 to a0d10a3CompareJune 14, 2023 05:44

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good! Since a user can now include arbitrary data, do we know if the router can handle restricting the number of hops based on the existing recipient payload?

Comment threadlightning/src/util/ser_macros.rs Outdated
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

do we know if the router can handle restricting the number of hops based on the existing recipient payload?

It currently cannot, though this is an issue that was really introduced in payment metadata, this just makes it worse. Tracked at #2201.

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Feel free to squash fixups when you next push, I think.

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from a0d10a3 to fdbcbffCompareJune 20, 2023 23:35
@wpaulinowpaulino added this to the 0.0.117 milestone Jul 5, 2023
@TheBlueMattTheBlueMatt added the blocked on next release Should Wait Until Next Release To Land label Jul 8, 2023
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

While we're still debating nits on the docs, can you go ahead and squash so we're set up to land? @wpaulino or @dunxen might want to take a look thereafter.

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 93a8fb6 to e8eedd3CompareJuly 31, 2023 02:03

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from e8eedd3 to 9a77843CompareAugust 1, 2023 02:26
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Fixed and squashed immediately since they were just small nits

@ariard

Copy link
Copy Markdown

this is why blinded paths have no error returned at all.

yes, though i’m not sure no returning error is workable on the long-term due to onion bandwidth cost and payment reliability (at least end-to-end), though here more conversation at the spec-level.

answered on the two comments:

  • i still wish we do our best to mask user agent and version from deanonymization attacks like done for browser / tor services
  • i still think “authentication” should be a strong suggestion, seen example of multiple payer not compatible with current payment_secret

though overall i won’t insist and if / when we have users privacy screwed up on those vectors, i’ll just pointed it back to you guys :)

@ariard

Copy link
Copy Markdown

i still wish we do our best to mask user agent and version from deanonymization attacks like done for browser / tor services

here the code is good in fact after looking (though doc confusing), just good if we don’t change it in the future to match BOLT4 bad suggestion imho

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 9a77843 to 1db481fCompareAugust 3, 2023 17:33
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Squashed immediately for minor doc change:

diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index 968b0765..daa0b34f 100644
--- a/lightning/src/ln/channelmanager.rs+++ b/lightning/src/ln/channelmanager.rs@@ -371,7 +371,7 @@ pub enum FailureCode {
/// We failed to process the payload after the onion was decrypted. You may wish to
/// use this when receiving custom HTLC TLVs with even type numbers that you don't recognize.
///
- /// If available, the tuple data should include the type number and byte offset in the+ /// If available, the tuple data may include the type number and byte offset in the
/// decrypted byte stream where the failure occurred.
InvalidOnionPayload(Option<(u64, u16)>),
}

@ariard

Copy link
Copy Markdown

Happy after following diff applied, payment_secret does not work for N-payer / N-payee flows, though it sounds reasonable for one payer / one payer flow, as far as I know about things like cancellable payments

diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index daa0b34f..db1108b4 100644
--- a/lightning/src/ln/channelmanager.rs
+++ b/lightning/src/ln/channelmanager.rs
@@ -4769,6 +4769,8 @@ where
/// You MUST check you've understood all even TLVs before using this to
/// claim, otherwise you may unintentionally agree to some protocol you do not understand.
///
+ /// You MAY authenticate the even TLVs additionally of `payment_secret` if the protocol
+ /// flow is more sophisticated than one payer / one payee.
/// [`claim_funds`]: Self::claim_funds
pub fn claim_funds_with_known_custom_tlvs(&self, payment_preimage: PaymentPreimage) {
self.claim_payment_internal(payment_preimage, true);

wpaulino
wpaulino previously approved these changes Aug 4, 2023

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review ACK 1db481f

Nevermind the above comment effectively multi-payer scheme would need additional code changes in our MPP validation and as such wider custom HTLC support (though they’re the ones more exposed in term of potential deanonymization attacks)

FailureCode::InvalidOnionPayload(data) => {
let fail_data = match data {
Some((typ, offset)) => [BigSize(typ).encode(), offset.encode()].concat(),
None => Vec::new(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: I think the debug_assert(data.is_none()) could be added due to its only usage in claim_payment_internal with a None value given to InvalidOnionPayload.

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Grrr, needs rebase, sorry about that.

Custom TLVs allow users to send extra application-specific data with
a payment. These have the additional flexibility compared to
`payment_metadata` that they don't have to reflect recipient generated
data provided in an invoice, in which `payment_metadata` could be
reused.
We ensure provided type numbers are unique, increasing, and within the
experimental range with the `RecipientOnionFields::with_custom_tlvs`
method.
This begins sender-side support for custom TLVs.
When serialized, the TLVs in `OutboundOnionPayload`, unlike a normal
TLV stream, are prefixed with the length of the stream. To allow a user
to add arbitrary custom TLVs, we aren't able to communicate to our
serialization macros exactly which fields to expect, so this commit
adds new macro variants to allow appending an extra set of bytes (and
modifying the prefixed length accordingly).
Because the keysend preimage TLV has a type number in the custom type
range, and a user's TLVs may have type numbers above and/or below
keysend's type number, and because TLV streams must be serialized in
increasing order by type number, this commit also ensures the keysend
TLV is properly sorted/serialized amongst the custom TLVs.
This completes basic receiver-side support for custom TLVs and adds
functional testing for sending and receiving.
Upon receiving multiple payment parts with custom TLVs, we fail payments
if they have any non-matching or missing even TLVs, and otherwise just
drop non-matching TLVs if they're odd.
When a user decodes custom TLVs, if they fail to recognize even type
numbers they should fail back with the correct failure code and fail
data. This new variant adds the proper failure variant for the user to
pass into `ChannelManager::fail_htlc_backwards_with_reason`.
Note that the enum discriminants were removed because when adding a
struct variant we can no longer make use of the discriminant through
casting like we previously did, and instead have to manually define the
associated failure code anyway.
Because we don't know which custom TLV type numbers the user is
expecting (and it would be cumbersome for them to tell us), instead of
failing unknown even custom TLVs on deserialization, we accept all
custom TLVs, and pass them to the user to check whether they recognize
them and choose to fail back if they don't. However, a user may not
check for custom TLVs, in which case we should reject any even custom
TLVs as unknown.
This commit makes sure a user must explicitly accept a payment with
even custom TLVs, by (1) making the default
`ChannelManager::claim_funds` fail if the payment had even custom TLVs
and (2) adding a new function
`ChannelManager::claim_funds_with_known_custom_tlvs` that accepts them.
This commit also refactors our custom TLVs test and updates various
documentation to account for this.
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Rebased

}

#[cfg(debug_assertions)] {
let mut last_seen: Option<u64> = None;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

it'd be nice to have this in one macro body with the above non-custom TLVs so that we can debug_assert!() that the ordering including custom TLVs is correct.

let tlvs = &mut self.custom_tlvs;
let further_tlvs = &mut further_htlc_fields.custom_tlvs;

let even_tlvs: Vec<&(u64, Vec<u8>)> = tlvs.iter().filter(|(typ, _)| *typ % 2 == 0).collect();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You should be able to do the comparison here without collecting into a Vec.

let preimage = if let Some(ref preimage) = keysend_preimage {
Some((5482373484, preimage.encode()))
} else { None };
let mut custom_tlvs: Vec<&(u64, Vec<u8>)> = custom_tlvs.iter().chain(preimage.iter()).collect();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We are trying to build an interator, we shouldn't have to collect here (though the macro may want it twice, so we may have to do the iter().chain() in the macro argument rather than here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Though AFAIK it wouldn't be possible to sort the tlvs as an iterator?

match &purpose {
PaymentPurpose::InvoicePayment { payment_secret, .. } => {
assert_eq!(our_payment_secret, *payment_secret);
assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: just for your reference, if we're copying test util bits into a test, we can usually skip a bunch of the assertions - the test utility methods tend to be a bit verbose and check everything, which is great in the general code, but in an individual test we don't need to test too much more than we care about for the purpose of the specific test.

@TheBlueMatt
TheBlueMatt merged commit 9e4a35a into lightningdevkit:mainAug 10, 2023
if let Some(expected_tlvs) = expected_receive_tlvs {
// Claim and match expected
let events = nodes[3].node.get_and_clear_pending_events();
println!("events: {:?}", events);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oops, I missed this before hitting merge, let's do a followup and remove this (and maybe hit a few other nits, though no real pressure on those).

@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Thanks for all the review everybody, will get a follow up up soon :)

Sign up for freeto 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.

Custom HTLC TLVs

6 participants

@alecchendev@codecov-commenter@TheBlueMatt@ariard@dunxen@wpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add support for custom HTLC TLVs - #2308

Merged
TheBlueMatt merged 7 commits into
lightningdevkit:mainfrom
alecchendev:2023-05-custom-htlc-tlvs
Aug 10, 2023
Merged

Add support for custom HTLC TLVs#2308
TheBlueMatt merged 7 commits into
lightningdevkit:mainfrom
alecchendev:2023-05-custom-htlc-tlvs

Conversation

@alecchendev

@alecchendevalecchendev commented May 19, 2023

Copy link
Copy Markdown
Contributor

Closes#1298. This PR adds support for sending and receiving custom HTLC TLVs.

Custom TLVs allow users to send extra application-specific data with a payment. These have the additional flexibility compared to payment_metadata that they don't have to reflect recipient generated data provided in an invoice, in which payment_metadata could (probably) be reused.

On the send side, a user can provide their serialized TLVs as a Vec<(u64, Vec<u8>)> to RecipientOnionFields::with_custom_tlvs which checks whether the type numbers are unique, increasing, and in the range reserved for custom values. They'll then pass this into whichever send payment function they use, it'll be serialized in the onion payload, and sent with the payment.

On the receive side, when deserializing the onion payload, we just add the bytes back into this type, then pipe it from the onion through to Event::PaymentClaimable, dropping non-matching TLVs between payment parts.

@alecchendevalecchendev left a comment

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

A couple questions for reviewers:

Comment threadlightning/src/offers/merkle.rs Outdated
Comment threadlightning/src/offers/merkle.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 2 times, most recently from 87ec6b0 to 4cb0a4bCompareMay 20, 2023 21:49
Comment threadlightning/src/ln/msgs.rs
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 4cb0a4b to 07a9910CompareMay 20, 2023 22:22
@codecov-commenter

codecov-commenter commented May 20, 2023

Copy link
Copy Markdown

Codecov Report

Patch coverage: 95.32% and project coverage change: +0.34% 🎉

Comparison is base (e13ff10) 90.24% compared to head (93a8fb6) 90.58%.
Report is 21 commits behind head on main.

❗ Current head 93a8fb6 differs from pull request most recent head 1db481f. Consider uploading reports for the commit 1db481f to get more accurate results

❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

Additional details and impacted files
@@ Coverage Diff @@## main #2308 +/- ##
==========================================
+ Coverage 90.24% 90.58% +0.34% 
==========================================
Files 106 106 Lines 55817 59617 +3800 Branches 55817 59617 +3800 ==========================================
+ Hits 50370 54007 +3637 - Misses 5447 5610 +163 
Files ChangedCoverage Δ
lightning/src/events/mod.rs41.98% <ø> (+0.37%)⬆️
lightning/src/util/ser_macros.rs67.75% <0.00%> (-2.81%)⬇️
lightning/src/ln/onion_route_tests.rs98.51% <85.71%> (+0.01%)⬆️
lightning/src/ln/payment_tests.rs97.38% <95.04%> (-0.28%)⬇️
lightning/src/ln/msgs.rs85.10% <96.55%> (+0.36%)⬆️
lightning/src/ln/channelmanager.rs86.73% <97.91%> (+1.28%)⬆️
lightning-invoice/src/payment.rs88.59% <100.00%> (-0.08%)⬇️
lightning/src/ln/functional_test_utils.rs88.93% <100.00%> (+0.01%)⬆️
lightning/src/ln/onion_utils.rs90.90% <100.00%> (-0.16%)⬇️
lightning/src/ln/outbound_payment.rs92.77% <100.00%> (+3.57%)⬆️

... and 4 files with indirect coverage changes

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

@wpaulino
wpaulino self-requested a review May 21, 2023 02:11
@dunxen
dunxen self-requested a review May 26, 2023 07:05

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sorry for the delay here, just getting caught up post-travels.

Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/offers/merkle.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 07a9910 to 3d848a6CompareJune 2, 2023 04:00
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/outbound_payment.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 4 times, most recently from 3483289 to 59f3fb6CompareJune 8, 2023 18:53
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/msgs.rs
@alecchendev
alecchendev marked this pull request as ready for review June 8, 2023 18:59
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 2 times, most recently from a7a2162 to ad4376eCompareJune 10, 2023 23:02
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Rebased due to conflicts.

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This basically looks good, I think, needs another reviewer.

Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 3 times, most recently from 751c245 to a0d10a3CompareJune 14, 2023 05:44

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good! Since a user can now include arbitrary data, do we know if the router can handle restricting the number of hops based on the existing recipient payload?

Comment threadlightning/src/util/ser_macros.rs Outdated
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

do we know if the router can handle restricting the number of hops based on the existing recipient payload?

It currently cannot, though this is an issue that was really introduced in payment metadata, this just makes it worse. Tracked at #2201.

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Feel free to squash fixups when you next push, I think.

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from a0d10a3 to fdbcbffCompareJune 20, 2023 23:35
@wpaulinowpaulino added this to the 0.0.117 milestone Jul 5, 2023
@TheBlueMattTheBlueMatt added the blocked on next release Should Wait Until Next Release To Land label Jul 8, 2023
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

While we're still debating nits on the docs, can you go ahead and squash so we're set up to land? @wpaulino or @dunxen might want to take a look thereafter.

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 93a8fb6 to e8eedd3CompareJuly 31, 2023 02:03

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from e8eedd3 to 9a77843CompareAugust 1, 2023 02:26
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Fixed and squashed immediately since they were just small nits

@ariard

Copy link
Copy Markdown

this is why blinded paths have no error returned at all.

yes, though i’m not sure no returning error is workable on the long-term due to onion bandwidth cost and payment reliability (at least end-to-end), though here more conversation at the spec-level.

answered on the two comments:

  • i still wish we do our best to mask user agent and version from deanonymization attacks like done for browser / tor services
  • i still think “authentication” should be a strong suggestion, seen example of multiple payer not compatible with current payment_secret

though overall i won’t insist and if / when we have users privacy screwed up on those vectors, i’ll just pointed it back to you guys :)

@ariard

Copy link
Copy Markdown

i still wish we do our best to mask user agent and version from deanonymization attacks like done for browser / tor services

here the code is good in fact after looking (though doc confusing), just good if we don’t change it in the future to match BOLT4 bad suggestion imho

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 9a77843 to 1db481fCompareAugust 3, 2023 17:33
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Squashed immediately for minor doc change:

diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index 968b0765..daa0b34f 100644
--- a/lightning/src/ln/channelmanager.rs+++ b/lightning/src/ln/channelmanager.rs@@ -371,7 +371,7 @@ pub enum FailureCode {
/// We failed to process the payload after the onion was decrypted. You may wish to
/// use this when receiving custom HTLC TLVs with even type numbers that you don't recognize.
///
- /// If available, the tuple data should include the type number and byte offset in the+ /// If available, the tuple data may include the type number and byte offset in the
/// decrypted byte stream where the failure occurred.
InvalidOnionPayload(Option<(u64, u16)>),
}

@ariard

Copy link
Copy Markdown

Happy after following diff applied, payment_secret does not work for N-payer / N-payee flows, though it sounds reasonable for one payer / one payer flow, as far as I know about things like cancellable payments

diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index daa0b34f..db1108b4 100644
--- a/lightning/src/ln/channelmanager.rs
+++ b/lightning/src/ln/channelmanager.rs
@@ -4769,6 +4769,8 @@ where
/// You MUST check you've understood all even TLVs before using this to
/// claim, otherwise you may unintentionally agree to some protocol you do not understand.
///
+ /// You MAY authenticate the even TLVs additionally of `payment_secret` if the protocol
+ /// flow is more sophisticated than one payer / one payee.
/// [`claim_funds`]: Self::claim_funds
pub fn claim_funds_with_known_custom_tlvs(&self, payment_preimage: PaymentPreimage) {
self.claim_payment_internal(payment_preimage, true);

wpaulino
wpaulino previously approved these changes Aug 4, 2023

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review ACK 1db481f

Nevermind the above comment effectively multi-payer scheme would need additional code changes in our MPP validation and as such wider custom HTLC support (though they’re the ones more exposed in term of potential deanonymization attacks)

FailureCode::InvalidOnionPayload(data) => {
let fail_data = match data {
Some((typ, offset)) => [BigSize(typ).encode(), offset.encode()].concat(),
None => Vec::new(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: I think the debug_assert(data.is_none()) could be added due to its only usage in claim_payment_internal with a None value given to InvalidOnionPayload.

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Grrr, needs rebase, sorry about that.

Custom TLVs allow users to send extra application-specific data with
a payment. These have the additional flexibility compared to
`payment_metadata` that they don't have to reflect recipient generated
data provided in an invoice, in which `payment_metadata` could be
reused.
We ensure provided type numbers are unique, increasing, and within the
experimental range with the `RecipientOnionFields::with_custom_tlvs`
method.
This begins sender-side support for custom TLVs.
When serialized, the TLVs in `OutboundOnionPayload`, unlike a normal
TLV stream, are prefixed with the length of the stream. To allow a user
to add arbitrary custom TLVs, we aren't able to communicate to our
serialization macros exactly which fields to expect, so this commit
adds new macro variants to allow appending an extra set of bytes (and
modifying the prefixed length accordingly).
Because the keysend preimage TLV has a type number in the custom type
range, and a user's TLVs may have type numbers above and/or below
keysend's type number, and because TLV streams must be serialized in
increasing order by type number, this commit also ensures the keysend
TLV is properly sorted/serialized amongst the custom TLVs.
This completes basic receiver-side support for custom TLVs and adds
functional testing for sending and receiving.
Upon receiving multiple payment parts with custom TLVs, we fail payments
if they have any non-matching or missing even TLVs, and otherwise just
drop non-matching TLVs if they're odd.
When a user decodes custom TLVs, if they fail to recognize even type
numbers they should fail back with the correct failure code and fail
data. This new variant adds the proper failure variant for the user to
pass into `ChannelManager::fail_htlc_backwards_with_reason`.
Note that the enum discriminants were removed because when adding a
struct variant we can no longer make use of the discriminant through
casting like we previously did, and instead have to manually define the
associated failure code anyway.
Because we don't know which custom TLV type numbers the user is
expecting (and it would be cumbersome for them to tell us), instead of
failing unknown even custom TLVs on deserialization, we accept all
custom TLVs, and pass them to the user to check whether they recognize
them and choose to fail back if they don't. However, a user may not
check for custom TLVs, in which case we should reject any even custom
TLVs as unknown.
This commit makes sure a user must explicitly accept a payment with
even custom TLVs, by (1) making the default
`ChannelManager::claim_funds` fail if the payment had even custom TLVs
and (2) adding a new function
`ChannelManager::claim_funds_with_known_custom_tlvs` that accepts them.
This commit also refactors our custom TLVs test and updates various
documentation to account for this.
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Rebased

}

#[cfg(debug_assertions)] {
let mut last_seen: Option<u64> = None;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

it'd be nice to have this in one macro body with the above non-custom TLVs so that we can debug_assert!() that the ordering including custom TLVs is correct.

let tlvs = &mut self.custom_tlvs;
let further_tlvs = &mut further_htlc_fields.custom_tlvs;

let even_tlvs: Vec<&(u64, Vec<u8>)> = tlvs.iter().filter(|(typ, _)| *typ % 2 == 0).collect();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You should be able to do the comparison here without collecting into a Vec.

let preimage = if let Some(ref preimage) = keysend_preimage {
Some((5482373484, preimage.encode()))
} else { None };
let mut custom_tlvs: Vec<&(u64, Vec<u8>)> = custom_tlvs.iter().chain(preimage.iter()).collect();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We are trying to build an interator, we shouldn't have to collect here (though the macro may want it twice, so we may have to do the iter().chain() in the macro argument rather than here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Though AFAIK it wouldn't be possible to sort the tlvs as an iterator?

match &purpose {
PaymentPurpose::InvoicePayment { payment_secret, .. } => {
assert_eq!(our_payment_secret, *payment_secret);
assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: just for your reference, if we're copying test util bits into a test, we can usually skip a bunch of the assertions - the test utility methods tend to be a bit verbose and check everything, which is great in the general code, but in an individual test we don't need to test too much more than we care about for the purpose of the specific test.

@TheBlueMatt
TheBlueMatt merged commit 9e4a35a into lightningdevkit:mainAug 10, 2023
if let Some(expected_tlvs) = expected_receive_tlvs {
// Claim and match expected
let events = nodes[3].node.get_and_clear_pending_events();
println!("events: {:?}", events);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oops, I missed this before hitting merge, let's do a followup and remove this (and maybe hit a few other nits, though no real pressure on those).

@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Thanks for all the review everybody, will get a follow up up soon :)

Sign up for freeto 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.

Custom HTLC TLVs

6 participants

@alecchendev@codecov-commenter@TheBlueMatt@ariard@dunxen@wpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add support for custom HTLC TLVs - #2308

Merged
TheBlueMatt merged 7 commits into
lightningdevkit:mainfrom
alecchendev:2023-05-custom-htlc-tlvs
Aug 10, 2023
Merged

Add support for custom HTLC TLVs#2308
TheBlueMatt merged 7 commits into
lightningdevkit:mainfrom
alecchendev:2023-05-custom-htlc-tlvs

Conversation

@alecchendev

@alecchendevalecchendev commented May 19, 2023

Copy link
Copy Markdown
Contributor

Closes#1298. This PR adds support for sending and receiving custom HTLC TLVs.

Custom TLVs allow users to send extra application-specific data with a payment. These have the additional flexibility compared to payment_metadata that they don't have to reflect recipient generated data provided in an invoice, in which payment_metadata could (probably) be reused.

On the send side, a user can provide their serialized TLVs as a Vec<(u64, Vec<u8>)> to RecipientOnionFields::with_custom_tlvs which checks whether the type numbers are unique, increasing, and in the range reserved for custom values. They'll then pass this into whichever send payment function they use, it'll be serialized in the onion payload, and sent with the payment.

On the receive side, when deserializing the onion payload, we just add the bytes back into this type, then pipe it from the onion through to Event::PaymentClaimable, dropping non-matching TLVs between payment parts.

@alecchendevalecchendev left a comment

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

A couple questions for reviewers:

Comment threadlightning/src/offers/merkle.rs Outdated
Comment threadlightning/src/offers/merkle.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 2 times, most recently from 87ec6b0 to 4cb0a4bCompareMay 20, 2023 21:49
Comment threadlightning/src/ln/msgs.rs
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 4cb0a4b to 07a9910CompareMay 20, 2023 22:22
@codecov-commenter

codecov-commenter commented May 20, 2023

Copy link
Copy Markdown

Codecov Report

Patch coverage: 95.32% and project coverage change: +0.34% 🎉

Comparison is base (e13ff10) 90.24% compared to head (93a8fb6) 90.58%.
Report is 21 commits behind head on main.

❗ Current head 93a8fb6 differs from pull request most recent head 1db481f. Consider uploading reports for the commit 1db481f to get more accurate results

❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

Additional details and impacted files
@@ Coverage Diff @@## main #2308 +/- ##
==========================================
+ Coverage 90.24% 90.58% +0.34% 
==========================================
Files 106 106 Lines 55817 59617 +3800 Branches 55817 59617 +3800 ==========================================
+ Hits 50370 54007 +3637 - Misses 5447 5610 +163 
Files ChangedCoverage Δ
lightning/src/events/mod.rs41.98% <ø> (+0.37%)⬆️
lightning/src/util/ser_macros.rs67.75% <0.00%> (-2.81%)⬇️
lightning/src/ln/onion_route_tests.rs98.51% <85.71%> (+0.01%)⬆️
lightning/src/ln/payment_tests.rs97.38% <95.04%> (-0.28%)⬇️
lightning/src/ln/msgs.rs85.10% <96.55%> (+0.36%)⬆️
lightning/src/ln/channelmanager.rs86.73% <97.91%> (+1.28%)⬆️
lightning-invoice/src/payment.rs88.59% <100.00%> (-0.08%)⬇️
lightning/src/ln/functional_test_utils.rs88.93% <100.00%> (+0.01%)⬆️
lightning/src/ln/onion_utils.rs90.90% <100.00%> (-0.16%)⬇️
lightning/src/ln/outbound_payment.rs92.77% <100.00%> (+3.57%)⬆️

... and 4 files with indirect coverage changes

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

@wpaulino
wpaulino self-requested a review May 21, 2023 02:11
@dunxen
dunxen self-requested a review May 26, 2023 07:05

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sorry for the delay here, just getting caught up post-travels.

Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/offers/merkle.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 07a9910 to 3d848a6CompareJune 2, 2023 04:00
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/outbound_payment.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 4 times, most recently from 3483289 to 59f3fb6CompareJune 8, 2023 18:53
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/msgs.rs
@alecchendev
alecchendev marked this pull request as ready for review June 8, 2023 18:59
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 2 times, most recently from a7a2162 to ad4376eCompareJune 10, 2023 23:02
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Rebased due to conflicts.

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This basically looks good, I think, needs another reviewer.

Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 3 times, most recently from 751c245 to a0d10a3CompareJune 14, 2023 05:44

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good! Since a user can now include arbitrary data, do we know if the router can handle restricting the number of hops based on the existing recipient payload?

Comment threadlightning/src/util/ser_macros.rs Outdated
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

do we know if the router can handle restricting the number of hops based on the existing recipient payload?

It currently cannot, though this is an issue that was really introduced in payment metadata, this just makes it worse. Tracked at #2201.

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Feel free to squash fixups when you next push, I think.

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from a0d10a3 to fdbcbffCompareJune 20, 2023 23:35
@wpaulinowpaulino added this to the 0.0.117 milestone Jul 5, 2023
@TheBlueMattTheBlueMatt added the blocked on next release Should Wait Until Next Release To Land label Jul 8, 2023
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

While we're still debating nits on the docs, can you go ahead and squash so we're set up to land? @wpaulino or @dunxen might want to take a look thereafter.

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 93a8fb6 to e8eedd3CompareJuly 31, 2023 02:03

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from e8eedd3 to 9a77843CompareAugust 1, 2023 02:26
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Fixed and squashed immediately since they were just small nits

@ariard

Copy link
Copy Markdown

this is why blinded paths have no error returned at all.

yes, though i’m not sure no returning error is workable on the long-term due to onion bandwidth cost and payment reliability (at least end-to-end), though here more conversation at the spec-level.

answered on the two comments:

  • i still wish we do our best to mask user agent and version from deanonymization attacks like done for browser / tor services
  • i still think “authentication” should be a strong suggestion, seen example of multiple payer not compatible with current payment_secret

though overall i won’t insist and if / when we have users privacy screwed up on those vectors, i’ll just pointed it back to you guys :)

@ariard

Copy link
Copy Markdown

i still wish we do our best to mask user agent and version from deanonymization attacks like done for browser / tor services

here the code is good in fact after looking (though doc confusing), just good if we don’t change it in the future to match BOLT4 bad suggestion imho

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 9a77843 to 1db481fCompareAugust 3, 2023 17:33
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Squashed immediately for minor doc change:

diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index 968b0765..daa0b34f 100644
--- a/lightning/src/ln/channelmanager.rs+++ b/lightning/src/ln/channelmanager.rs@@ -371,7 +371,7 @@ pub enum FailureCode {
/// We failed to process the payload after the onion was decrypted. You may wish to
/// use this when receiving custom HTLC TLVs with even type numbers that you don't recognize.
///
- /// If available, the tuple data should include the type number and byte offset in the+ /// If available, the tuple data may include the type number and byte offset in the
/// decrypted byte stream where the failure occurred.
InvalidOnionPayload(Option<(u64, u16)>),
}

@ariard

Copy link
Copy Markdown

Happy after following diff applied, payment_secret does not work for N-payer / N-payee flows, though it sounds reasonable for one payer / one payer flow, as far as I know about things like cancellable payments

diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index daa0b34f..db1108b4 100644
--- a/lightning/src/ln/channelmanager.rs
+++ b/lightning/src/ln/channelmanager.rs
@@ -4769,6 +4769,8 @@ where
/// You MUST check you've understood all even TLVs before using this to
/// claim, otherwise you may unintentionally agree to some protocol you do not understand.
///
+ /// You MAY authenticate the even TLVs additionally of `payment_secret` if the protocol
+ /// flow is more sophisticated than one payer / one payee.
/// [`claim_funds`]: Self::claim_funds
pub fn claim_funds_with_known_custom_tlvs(&self, payment_preimage: PaymentPreimage) {
self.claim_payment_internal(payment_preimage, true);

wpaulino
wpaulino previously approved these changes Aug 4, 2023

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review ACK 1db481f

Nevermind the above comment effectively multi-payer scheme would need additional code changes in our MPP validation and as such wider custom HTLC support (though they’re the ones more exposed in term of potential deanonymization attacks)

FailureCode::InvalidOnionPayload(data) => {
let fail_data = match data {
Some((typ, offset)) => [BigSize(typ).encode(), offset.encode()].concat(),
None => Vec::new(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: I think the debug_assert(data.is_none()) could be added due to its only usage in claim_payment_internal with a None value given to InvalidOnionPayload.

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Grrr, needs rebase, sorry about that.

Custom TLVs allow users to send extra application-specific data with
a payment. These have the additional flexibility compared to
`payment_metadata` that they don't have to reflect recipient generated
data provided in an invoice, in which `payment_metadata` could be
reused.
We ensure provided type numbers are unique, increasing, and within the
experimental range with the `RecipientOnionFields::with_custom_tlvs`
method.
This begins sender-side support for custom TLVs.
When serialized, the TLVs in `OutboundOnionPayload`, unlike a normal
TLV stream, are prefixed with the length of the stream. To allow a user
to add arbitrary custom TLVs, we aren't able to communicate to our
serialization macros exactly which fields to expect, so this commit
adds new macro variants to allow appending an extra set of bytes (and
modifying the prefixed length accordingly).
Because the keysend preimage TLV has a type number in the custom type
range, and a user's TLVs may have type numbers above and/or below
keysend's type number, and because TLV streams must be serialized in
increasing order by type number, this commit also ensures the keysend
TLV is properly sorted/serialized amongst the custom TLVs.
This completes basic receiver-side support for custom TLVs and adds
functional testing for sending and receiving.
Upon receiving multiple payment parts with custom TLVs, we fail payments
if they have any non-matching or missing even TLVs, and otherwise just
drop non-matching TLVs if they're odd.
When a user decodes custom TLVs, if they fail to recognize even type
numbers they should fail back with the correct failure code and fail
data. This new variant adds the proper failure variant for the user to
pass into `ChannelManager::fail_htlc_backwards_with_reason`.
Note that the enum discriminants were removed because when adding a
struct variant we can no longer make use of the discriminant through
casting like we previously did, and instead have to manually define the
associated failure code anyway.
Because we don't know which custom TLV type numbers the user is
expecting (and it would be cumbersome for them to tell us), instead of
failing unknown even custom TLVs on deserialization, we accept all
custom TLVs, and pass them to the user to check whether they recognize
them and choose to fail back if they don't. However, a user may not
check for custom TLVs, in which case we should reject any even custom
TLVs as unknown.
This commit makes sure a user must explicitly accept a payment with
even custom TLVs, by (1) making the default
`ChannelManager::claim_funds` fail if the payment had even custom TLVs
and (2) adding a new function
`ChannelManager::claim_funds_with_known_custom_tlvs` that accepts them.
This commit also refactors our custom TLVs test and updates various
documentation to account for this.
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Rebased

}

#[cfg(debug_assertions)] {
let mut last_seen: Option<u64> = None;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

it'd be nice to have this in one macro body with the above non-custom TLVs so that we can debug_assert!() that the ordering including custom TLVs is correct.

let tlvs = &mut self.custom_tlvs;
let further_tlvs = &mut further_htlc_fields.custom_tlvs;

let even_tlvs: Vec<&(u64, Vec<u8>)> = tlvs.iter().filter(|(typ, _)| *typ % 2 == 0).collect();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You should be able to do the comparison here without collecting into a Vec.

let preimage = if let Some(ref preimage) = keysend_preimage {
Some((5482373484, preimage.encode()))
} else { None };
let mut custom_tlvs: Vec<&(u64, Vec<u8>)> = custom_tlvs.iter().chain(preimage.iter()).collect();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We are trying to build an interator, we shouldn't have to collect here (though the macro may want it twice, so we may have to do the iter().chain() in the macro argument rather than here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Though AFAIK it wouldn't be possible to sort the tlvs as an iterator?

match &purpose {
PaymentPurpose::InvoicePayment { payment_secret, .. } => {
assert_eq!(our_payment_secret, *payment_secret);
assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: just for your reference, if we're copying test util bits into a test, we can usually skip a bunch of the assertions - the test utility methods tend to be a bit verbose and check everything, which is great in the general code, but in an individual test we don't need to test too much more than we care about for the purpose of the specific test.

@TheBlueMatt
TheBlueMatt merged commit 9e4a35a into lightningdevkit:mainAug 10, 2023
if let Some(expected_tlvs) = expected_receive_tlvs {
// Claim and match expected
let events = nodes[3].node.get_and_clear_pending_events();
println!("events: {:?}", events);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oops, I missed this before hitting merge, let's do a followup and remove this (and maybe hit a few other nits, though no real pressure on those).

@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Thanks for all the review everybody, will get a follow up up soon :)

Sign up for freeto 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.

Custom HTLC TLVs

6 participants

@alecchendev@codecov-commenter@TheBlueMatt@ariard@dunxen@wpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Add support for custom HTLC TLVs - #2308

Merged
TheBlueMatt merged 7 commits into
lightningdevkit:mainfrom
alecchendev:2023-05-custom-htlc-tlvs
Aug 10, 2023
Merged

Add support for custom HTLC TLVs#2308
TheBlueMatt merged 7 commits into
lightningdevkit:mainfrom
alecchendev:2023-05-custom-htlc-tlvs

Conversation

@alecchendev

@alecchendevalecchendev commented May 19, 2023

Copy link
Copy Markdown
Contributor

Closes#1298. This PR adds support for sending and receiving custom HTLC TLVs.

Custom TLVs allow users to send extra application-specific data with a payment. These have the additional flexibility compared to payment_metadata that they don't have to reflect recipient generated data provided in an invoice, in which payment_metadata could (probably) be reused.

On the send side, a user can provide their serialized TLVs as a Vec<(u64, Vec<u8>)> to RecipientOnionFields::with_custom_tlvs which checks whether the type numbers are unique, increasing, and in the range reserved for custom values. They'll then pass this into whichever send payment function they use, it'll be serialized in the onion payload, and sent with the payment.

On the receive side, when deserializing the onion payload, we just add the bytes back into this type, then pipe it from the onion through to Event::PaymentClaimable, dropping non-matching TLVs between payment parts.

@alecchendevalecchendev left a comment

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

A couple questions for reviewers:

Comment threadlightning/src/offers/merkle.rs Outdated
Comment threadlightning/src/offers/merkle.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 2 times, most recently from 87ec6b0 to 4cb0a4bCompareMay 20, 2023 21:49
Comment threadlightning/src/ln/msgs.rs
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 4cb0a4b to 07a9910CompareMay 20, 2023 22:22
@codecov-commenter

codecov-commenter commented May 20, 2023

Copy link
Copy Markdown

Codecov Report

Patch coverage: 95.32% and project coverage change: +0.34% 🎉

Comparison is base (e13ff10) 90.24% compared to head (93a8fb6) 90.58%.
Report is 21 commits behind head on main.

❗ Current head 93a8fb6 differs from pull request most recent head 1db481f. Consider uploading reports for the commit 1db481f to get more accurate results

❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

Additional details and impacted files
@@ Coverage Diff @@## main #2308 +/- ##
==========================================
+ Coverage 90.24% 90.58% +0.34% 
==========================================
Files 106 106 Lines 55817 59617 +3800 Branches 55817 59617 +3800 ==========================================
+ Hits 50370 54007 +3637 - Misses 5447 5610 +163 
Files ChangedCoverage Δ
lightning/src/events/mod.rs41.98% <ø> (+0.37%)⬆️
lightning/src/util/ser_macros.rs67.75% <0.00%> (-2.81%)⬇️
lightning/src/ln/onion_route_tests.rs98.51% <85.71%> (+0.01%)⬆️
lightning/src/ln/payment_tests.rs97.38% <95.04%> (-0.28%)⬇️
lightning/src/ln/msgs.rs85.10% <96.55%> (+0.36%)⬆️
lightning/src/ln/channelmanager.rs86.73% <97.91%> (+1.28%)⬆️
lightning-invoice/src/payment.rs88.59% <100.00%> (-0.08%)⬇️
lightning/src/ln/functional_test_utils.rs88.93% <100.00%> (+0.01%)⬆️
lightning/src/ln/onion_utils.rs90.90% <100.00%> (-0.16%)⬇️
lightning/src/ln/outbound_payment.rs92.77% <100.00%> (+3.57%)⬆️

... and 4 files with indirect coverage changes

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

@wpaulino
wpaulino self-requested a review May 21, 2023 02:11
@dunxen
dunxen self-requested a review May 26, 2023 07:05

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sorry for the delay here, just getting caught up post-travels.

Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/offers/merkle.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 07a9910 to 3d848a6CompareJune 2, 2023 04:00
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/outbound_payment.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 4 times, most recently from 3483289 to 59f3fb6CompareJune 8, 2023 18:53
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/msgs.rs
@alecchendev
alecchendev marked this pull request as ready for review June 8, 2023 18:59
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 2 times, most recently from a7a2162 to ad4376eCompareJune 10, 2023 23:02
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Rebased due to conflicts.

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This basically looks good, I think, needs another reviewer.

Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 3 times, most recently from 751c245 to a0d10a3CompareJune 14, 2023 05:44

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good! Since a user can now include arbitrary data, do we know if the router can handle restricting the number of hops based on the existing recipient payload?

Comment threadlightning/src/util/ser_macros.rs Outdated
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

do we know if the router can handle restricting the number of hops based on the existing recipient payload?

It currently cannot, though this is an issue that was really introduced in payment metadata, this just makes it worse. Tracked at #2201.

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Feel free to squash fixups when you next push, I think.

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from a0d10a3 to fdbcbffCompareJune 20, 2023 23:35
@wpaulinowpaulino added this to the 0.0.117 milestone Jul 5, 2023
@TheBlueMattTheBlueMatt added the blocked on next release Should Wait Until Next Release To Land label Jul 8, 2023
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

While we're still debating nits on the docs, can you go ahead and squash so we're set up to land? @wpaulino or @dunxen might want to take a look thereafter.

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 93a8fb6 to e8eedd3CompareJuly 31, 2023 02:03

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from e8eedd3 to 9a77843CompareAugust 1, 2023 02:26
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Fixed and squashed immediately since they were just small nits

@ariard

Copy link
Copy Markdown

this is why blinded paths have no error returned at all.

yes, though i’m not sure no returning error is workable on the long-term due to onion bandwidth cost and payment reliability (at least end-to-end), though here more conversation at the spec-level.

answered on the two comments:

  • i still wish we do our best to mask user agent and version from deanonymization attacks like done for browser / tor services
  • i still think “authentication” should be a strong suggestion, seen example of multiple payer not compatible with current payment_secret

though overall i won’t insist and if / when we have users privacy screwed up on those vectors, i’ll just pointed it back to you guys :)

@ariard

Copy link
Copy Markdown

i still wish we do our best to mask user agent and version from deanonymization attacks like done for browser / tor services

here the code is good in fact after looking (though doc confusing), just good if we don’t change it in the future to match BOLT4 bad suggestion imho

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 9a77843 to 1db481fCompareAugust 3, 2023 17:33
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Squashed immediately for minor doc change:

diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index 968b0765..daa0b34f 100644
--- a/lightning/src/ln/channelmanager.rs+++ b/lightning/src/ln/channelmanager.rs@@ -371,7 +371,7 @@ pub enum FailureCode {
/// We failed to process the payload after the onion was decrypted. You may wish to
/// use this when receiving custom HTLC TLVs with even type numbers that you don't recognize.
///
- /// If available, the tuple data should include the type number and byte offset in the+ /// If available, the tuple data may include the type number and byte offset in the
/// decrypted byte stream where the failure occurred.
InvalidOnionPayload(Option<(u64, u16)>),
}

@ariard

Copy link
Copy Markdown

Happy after following diff applied, payment_secret does not work for N-payer / N-payee flows, though it sounds reasonable for one payer / one payer flow, as far as I know about things like cancellable payments

diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index daa0b34f..db1108b4 100644
--- a/lightning/src/ln/channelmanager.rs
+++ b/lightning/src/ln/channelmanager.rs
@@ -4769,6 +4769,8 @@ where
/// You MUST check you've understood all even TLVs before using this to
/// claim, otherwise you may unintentionally agree to some protocol you do not understand.
///
+ /// You MAY authenticate the even TLVs additionally of `payment_secret` if the protocol
+ /// flow is more sophisticated than one payer / one payee.
/// [`claim_funds`]: Self::claim_funds
pub fn claim_funds_with_known_custom_tlvs(&self, payment_preimage: PaymentPreimage) {
self.claim_payment_internal(payment_preimage, true);

wpaulino
wpaulino previously approved these changes Aug 4, 2023

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review ACK 1db481f

Nevermind the above comment effectively multi-payer scheme would need additional code changes in our MPP validation and as such wider custom HTLC support (though they’re the ones more exposed in term of potential deanonymization attacks)

FailureCode::InvalidOnionPayload(data) => {
let fail_data = match data {
Some((typ, offset)) => [BigSize(typ).encode(), offset.encode()].concat(),
None => Vec::new(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: I think the debug_assert(data.is_none()) could be added due to its only usage in claim_payment_internal with a None value given to InvalidOnionPayload.

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Grrr, needs rebase, sorry about that.

Custom TLVs allow users to send extra application-specific data with
a payment. These have the additional flexibility compared to
`payment_metadata` that they don't have to reflect recipient generated
data provided in an invoice, in which `payment_metadata` could be
reused.
We ensure provided type numbers are unique, increasing, and within the
experimental range with the `RecipientOnionFields::with_custom_tlvs`
method.
This begins sender-side support for custom TLVs.
When serialized, the TLVs in `OutboundOnionPayload`, unlike a normal
TLV stream, are prefixed with the length of the stream. To allow a user
to add arbitrary custom TLVs, we aren't able to communicate to our
serialization macros exactly which fields to expect, so this commit
adds new macro variants to allow appending an extra set of bytes (and
modifying the prefixed length accordingly).
Because the keysend preimage TLV has a type number in the custom type
range, and a user's TLVs may have type numbers above and/or below
keysend's type number, and because TLV streams must be serialized in
increasing order by type number, this commit also ensures the keysend
TLV is properly sorted/serialized amongst the custom TLVs.
This completes basic receiver-side support for custom TLVs and adds
functional testing for sending and receiving.
Upon receiving multiple payment parts with custom TLVs, we fail payments
if they have any non-matching or missing even TLVs, and otherwise just
drop non-matching TLVs if they're odd.
When a user decodes custom TLVs, if they fail to recognize even type
numbers they should fail back with the correct failure code and fail
data. This new variant adds the proper failure variant for the user to
pass into `ChannelManager::fail_htlc_backwards_with_reason`.
Note that the enum discriminants were removed because when adding a
struct variant we can no longer make use of the discriminant through
casting like we previously did, and instead have to manually define the
associated failure code anyway.
Because we don't know which custom TLV type numbers the user is
expecting (and it would be cumbersome for them to tell us), instead of
failing unknown even custom TLVs on deserialization, we accept all
custom TLVs, and pass them to the user to check whether they recognize
them and choose to fail back if they don't. However, a user may not
check for custom TLVs, in which case we should reject any even custom
TLVs as unknown.
This commit makes sure a user must explicitly accept a payment with
even custom TLVs, by (1) making the default
`ChannelManager::claim_funds` fail if the payment had even custom TLVs
and (2) adding a new function
`ChannelManager::claim_funds_with_known_custom_tlvs` that accepts them.
This commit also refactors our custom TLVs test and updates various
documentation to account for this.
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Rebased

}

#[cfg(debug_assertions)] {
let mut last_seen: Option<u64> = None;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

it'd be nice to have this in one macro body with the above non-custom TLVs so that we can debug_assert!() that the ordering including custom TLVs is correct.

let tlvs = &mut self.custom_tlvs;
let further_tlvs = &mut further_htlc_fields.custom_tlvs;

let even_tlvs: Vec<&(u64, Vec<u8>)> = tlvs.iter().filter(|(typ, _)| *typ % 2 == 0).collect();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You should be able to do the comparison here without collecting into a Vec.

let preimage = if let Some(ref preimage) = keysend_preimage {
Some((5482373484, preimage.encode()))
} else { None };
let mut custom_tlvs: Vec<&(u64, Vec<u8>)> = custom_tlvs.iter().chain(preimage.iter()).collect();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We are trying to build an interator, we shouldn't have to collect here (though the macro may want it twice, so we may have to do the iter().chain() in the macro argument rather than here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Though AFAIK it wouldn't be possible to sort the tlvs as an iterator?

match &purpose {
PaymentPurpose::InvoicePayment { payment_secret, .. } => {
assert_eq!(our_payment_secret, *payment_secret);
assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: just for your reference, if we're copying test util bits into a test, we can usually skip a bunch of the assertions - the test utility methods tend to be a bit verbose and check everything, which is great in the general code, but in an individual test we don't need to test too much more than we care about for the purpose of the specific test.

@TheBlueMatt
TheBlueMatt merged commit 9e4a35a into lightningdevkit:mainAug 10, 2023
if let Some(expected_tlvs) = expected_receive_tlvs {
// Claim and match expected
let events = nodes[3].node.get_and_clear_pending_events();
println!("events: {:?}", events);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oops, I missed this before hitting merge, let's do a followup and remove this (and maybe hit a few other nits, though no real pressure on those).

@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Thanks for all the review everybody, will get a follow up up soon :)

Sign up for freeto 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.

Custom HTLC TLVs

6 participants

@alecchendev@codecov-commenter@TheBlueMatt@ariard@dunxen@wpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add support for custom HTLC TLVs - #2308

Merged
TheBlueMatt merged 7 commits into
lightningdevkit:mainfrom
alecchendev:2023-05-custom-htlc-tlvs
Aug 10, 2023
Merged

Add support for custom HTLC TLVs#2308
TheBlueMatt merged 7 commits into
lightningdevkit:mainfrom
alecchendev:2023-05-custom-htlc-tlvs

Conversation

@alecchendev

@alecchendevalecchendev commented May 19, 2023

Copy link
Copy Markdown
Contributor

Closes#1298. This PR adds support for sending and receiving custom HTLC TLVs.

Custom TLVs allow users to send extra application-specific data with a payment. These have the additional flexibility compared to payment_metadata that they don't have to reflect recipient generated data provided in an invoice, in which payment_metadata could (probably) be reused.

On the send side, a user can provide their serialized TLVs as a Vec<(u64, Vec<u8>)> to RecipientOnionFields::with_custom_tlvs which checks whether the type numbers are unique, increasing, and in the range reserved for custom values. They'll then pass this into whichever send payment function they use, it'll be serialized in the onion payload, and sent with the payment.

On the receive side, when deserializing the onion payload, we just add the bytes back into this type, then pipe it from the onion through to Event::PaymentClaimable, dropping non-matching TLVs between payment parts.

@alecchendevalecchendev left a comment

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

A couple questions for reviewers:

Comment threadlightning/src/offers/merkle.rs Outdated
Comment threadlightning/src/offers/merkle.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 2 times, most recently from 87ec6b0 to 4cb0a4bCompareMay 20, 2023 21:49
Comment threadlightning/src/ln/msgs.rs
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 4cb0a4b to 07a9910CompareMay 20, 2023 22:22
@codecov-commenter

codecov-commenter commented May 20, 2023

Copy link
Copy Markdown

Codecov Report

Patch coverage: 95.32% and project coverage change: +0.34% 🎉

Comparison is base (e13ff10) 90.24% compared to head (93a8fb6) 90.58%.
Report is 21 commits behind head on main.

❗ Current head 93a8fb6 differs from pull request most recent head 1db481f. Consider uploading reports for the commit 1db481f to get more accurate results

❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

Additional details and impacted files
@@ Coverage Diff @@## main #2308 +/- ##
==========================================
+ Coverage 90.24% 90.58% +0.34% 
==========================================
Files 106 106 Lines 55817 59617 +3800 Branches 55817 59617 +3800 ==========================================
+ Hits 50370 54007 +3637 - Misses 5447 5610 +163 
Files ChangedCoverage Δ
lightning/src/events/mod.rs41.98% <ø> (+0.37%)⬆️
lightning/src/util/ser_macros.rs67.75% <0.00%> (-2.81%)⬇️
lightning/src/ln/onion_route_tests.rs98.51% <85.71%> (+0.01%)⬆️
lightning/src/ln/payment_tests.rs97.38% <95.04%> (-0.28%)⬇️
lightning/src/ln/msgs.rs85.10% <96.55%> (+0.36%)⬆️
lightning/src/ln/channelmanager.rs86.73% <97.91%> (+1.28%)⬆️
lightning-invoice/src/payment.rs88.59% <100.00%> (-0.08%)⬇️
lightning/src/ln/functional_test_utils.rs88.93% <100.00%> (+0.01%)⬆️
lightning/src/ln/onion_utils.rs90.90% <100.00%> (-0.16%)⬇️
lightning/src/ln/outbound_payment.rs92.77% <100.00%> (+3.57%)⬆️

... and 4 files with indirect coverage changes

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

@wpaulino
wpaulino self-requested a review May 21, 2023 02:11
@dunxen
dunxen self-requested a review May 26, 2023 07:05

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sorry for the delay here, just getting caught up post-travels.

Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/offers/merkle.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 07a9910 to 3d848a6CompareJune 2, 2023 04:00
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/outbound_payment.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 4 times, most recently from 3483289 to 59f3fb6CompareJune 8, 2023 18:53
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/msgs.rs
@alecchendev
alecchendev marked this pull request as ready for review June 8, 2023 18:59
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 2 times, most recently from a7a2162 to ad4376eCompareJune 10, 2023 23:02
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Rebased due to conflicts.

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This basically looks good, I think, needs another reviewer.

Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 3 times, most recently from 751c245 to a0d10a3CompareJune 14, 2023 05:44

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good! Since a user can now include arbitrary data, do we know if the router can handle restricting the number of hops based on the existing recipient payload?

Comment threadlightning/src/util/ser_macros.rs Outdated
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

do we know if the router can handle restricting the number of hops based on the existing recipient payload?

It currently cannot, though this is an issue that was really introduced in payment metadata, this just makes it worse. Tracked at #2201.

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Feel free to squash fixups when you next push, I think.

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from a0d10a3 to fdbcbffCompareJune 20, 2023 23:35
@wpaulinowpaulino added this to the 0.0.117 milestone Jul 5, 2023
@TheBlueMattTheBlueMatt added the blocked on next release Should Wait Until Next Release To Land label Jul 8, 2023
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

While we're still debating nits on the docs, can you go ahead and squash so we're set up to land? @wpaulino or @dunxen might want to take a look thereafter.

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 93a8fb6 to e8eedd3CompareJuly 31, 2023 02:03

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from e8eedd3 to 9a77843CompareAugust 1, 2023 02:26
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Fixed and squashed immediately since they were just small nits

@ariard

Copy link
Copy Markdown

this is why blinded paths have no error returned at all.

yes, though i’m not sure no returning error is workable on the long-term due to onion bandwidth cost and payment reliability (at least end-to-end), though here more conversation at the spec-level.

answered on the two comments:

  • i still wish we do our best to mask user agent and version from deanonymization attacks like done for browser / tor services
  • i still think “authentication” should be a strong suggestion, seen example of multiple payer not compatible with current payment_secret

though overall i won’t insist and if / when we have users privacy screwed up on those vectors, i’ll just pointed it back to you guys :)

@ariard

Copy link
Copy Markdown

i still wish we do our best to mask user agent and version from deanonymization attacks like done for browser / tor services

here the code is good in fact after looking (though doc confusing), just good if we don’t change it in the future to match BOLT4 bad suggestion imho

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 9a77843 to 1db481fCompareAugust 3, 2023 17:33
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Squashed immediately for minor doc change:

diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index 968b0765..daa0b34f 100644
--- a/lightning/src/ln/channelmanager.rs+++ b/lightning/src/ln/channelmanager.rs@@ -371,7 +371,7 @@ pub enum FailureCode {
/// We failed to process the payload after the onion was decrypted. You may wish to
/// use this when receiving custom HTLC TLVs with even type numbers that you don't recognize.
///
- /// If available, the tuple data should include the type number and byte offset in the+ /// If available, the tuple data may include the type number and byte offset in the
/// decrypted byte stream where the failure occurred.
InvalidOnionPayload(Option<(u64, u16)>),
}

@ariard

Copy link
Copy Markdown

Happy after following diff applied, payment_secret does not work for N-payer / N-payee flows, though it sounds reasonable for one payer / one payer flow, as far as I know about things like cancellable payments

diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index daa0b34f..db1108b4 100644
--- a/lightning/src/ln/channelmanager.rs
+++ b/lightning/src/ln/channelmanager.rs
@@ -4769,6 +4769,8 @@ where
/// You MUST check you've understood all even TLVs before using this to
/// claim, otherwise you may unintentionally agree to some protocol you do not understand.
///
+ /// You MAY authenticate the even TLVs additionally of `payment_secret` if the protocol
+ /// flow is more sophisticated than one payer / one payee.
/// [`claim_funds`]: Self::claim_funds
pub fn claim_funds_with_known_custom_tlvs(&self, payment_preimage: PaymentPreimage) {
self.claim_payment_internal(payment_preimage, true);

wpaulino
wpaulino previously approved these changes Aug 4, 2023

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review ACK 1db481f

Nevermind the above comment effectively multi-payer scheme would need additional code changes in our MPP validation and as such wider custom HTLC support (though they’re the ones more exposed in term of potential deanonymization attacks)

FailureCode::InvalidOnionPayload(data) => {
let fail_data = match data {
Some((typ, offset)) => [BigSize(typ).encode(), offset.encode()].concat(),
None => Vec::new(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: I think the debug_assert(data.is_none()) could be added due to its only usage in claim_payment_internal with a None value given to InvalidOnionPayload.

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Grrr, needs rebase, sorry about that.

Custom TLVs allow users to send extra application-specific data with
a payment. These have the additional flexibility compared to
`payment_metadata` that they don't have to reflect recipient generated
data provided in an invoice, in which `payment_metadata` could be
reused.
We ensure provided type numbers are unique, increasing, and within the
experimental range with the `RecipientOnionFields::with_custom_tlvs`
method.
This begins sender-side support for custom TLVs.
When serialized, the TLVs in `OutboundOnionPayload`, unlike a normal
TLV stream, are prefixed with the length of the stream. To allow a user
to add arbitrary custom TLVs, we aren't able to communicate to our
serialization macros exactly which fields to expect, so this commit
adds new macro variants to allow appending an extra set of bytes (and
modifying the prefixed length accordingly).
Because the keysend preimage TLV has a type number in the custom type
range, and a user's TLVs may have type numbers above and/or below
keysend's type number, and because TLV streams must be serialized in
increasing order by type number, this commit also ensures the keysend
TLV is properly sorted/serialized amongst the custom TLVs.
This completes basic receiver-side support for custom TLVs and adds
functional testing for sending and receiving.
Upon receiving multiple payment parts with custom TLVs, we fail payments
if they have any non-matching or missing even TLVs, and otherwise just
drop non-matching TLVs if they're odd.
When a user decodes custom TLVs, if they fail to recognize even type
numbers they should fail back with the correct failure code and fail
data. This new variant adds the proper failure variant for the user to
pass into `ChannelManager::fail_htlc_backwards_with_reason`.
Note that the enum discriminants were removed because when adding a
struct variant we can no longer make use of the discriminant through
casting like we previously did, and instead have to manually define the
associated failure code anyway.
Because we don't know which custom TLV type numbers the user is
expecting (and it would be cumbersome for them to tell us), instead of
failing unknown even custom TLVs on deserialization, we accept all
custom TLVs, and pass them to the user to check whether they recognize
them and choose to fail back if they don't. However, a user may not
check for custom TLVs, in which case we should reject any even custom
TLVs as unknown.
This commit makes sure a user must explicitly accept a payment with
even custom TLVs, by (1) making the default
`ChannelManager::claim_funds` fail if the payment had even custom TLVs
and (2) adding a new function
`ChannelManager::claim_funds_with_known_custom_tlvs` that accepts them.
This commit also refactors our custom TLVs test and updates various
documentation to account for this.
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Rebased

}

#[cfg(debug_assertions)] {
let mut last_seen: Option<u64> = None;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

it'd be nice to have this in one macro body with the above non-custom TLVs so that we can debug_assert!() that the ordering including custom TLVs is correct.

let tlvs = &mut self.custom_tlvs;
let further_tlvs = &mut further_htlc_fields.custom_tlvs;

let even_tlvs: Vec<&(u64, Vec<u8>)> = tlvs.iter().filter(|(typ, _)| *typ % 2 == 0).collect();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You should be able to do the comparison here without collecting into a Vec.

let preimage = if let Some(ref preimage) = keysend_preimage {
Some((5482373484, preimage.encode()))
} else { None };
let mut custom_tlvs: Vec<&(u64, Vec<u8>)> = custom_tlvs.iter().chain(preimage.iter()).collect();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We are trying to build an interator, we shouldn't have to collect here (though the macro may want it twice, so we may have to do the iter().chain() in the macro argument rather than here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Though AFAIK it wouldn't be possible to sort the tlvs as an iterator?

match &purpose {
PaymentPurpose::InvoicePayment { payment_secret, .. } => {
assert_eq!(our_payment_secret, *payment_secret);
assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: just for your reference, if we're copying test util bits into a test, we can usually skip a bunch of the assertions - the test utility methods tend to be a bit verbose and check everything, which is great in the general code, but in an individual test we don't need to test too much more than we care about for the purpose of the specific test.

@TheBlueMatt
TheBlueMatt merged commit 9e4a35a into lightningdevkit:mainAug 10, 2023
if let Some(expected_tlvs) = expected_receive_tlvs {
// Claim and match expected
let events = nodes[3].node.get_and_clear_pending_events();
println!("events: {:?}", events);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oops, I missed this before hitting merge, let's do a followup and remove this (and maybe hit a few other nits, though no real pressure on those).

@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Thanks for all the review everybody, will get a follow up up soon :)

Sign up for freeto 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.

Custom HTLC TLVs

6 participants

@alecchendev@codecov-commenter@TheBlueMatt@ariard@dunxen@wpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add support for custom HTLC TLVs - #2308

Merged
TheBlueMatt merged 7 commits into
lightningdevkit:mainfrom
alecchendev:2023-05-custom-htlc-tlvs
Aug 10, 2023
Merged

Add support for custom HTLC TLVs#2308
TheBlueMatt merged 7 commits into
lightningdevkit:mainfrom
alecchendev:2023-05-custom-htlc-tlvs

Conversation

@alecchendev

@alecchendevalecchendev commented May 19, 2023

Copy link
Copy Markdown
Contributor

Closes#1298. This PR adds support for sending and receiving custom HTLC TLVs.

Custom TLVs allow users to send extra application-specific data with a payment. These have the additional flexibility compared to payment_metadata that they don't have to reflect recipient generated data provided in an invoice, in which payment_metadata could (probably) be reused.

On the send side, a user can provide their serialized TLVs as a Vec<(u64, Vec<u8>)> to RecipientOnionFields::with_custom_tlvs which checks whether the type numbers are unique, increasing, and in the range reserved for custom values. They'll then pass this into whichever send payment function they use, it'll be serialized in the onion payload, and sent with the payment.

On the receive side, when deserializing the onion payload, we just add the bytes back into this type, then pipe it from the onion through to Event::PaymentClaimable, dropping non-matching TLVs between payment parts.

@alecchendevalecchendev left a comment

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

A couple questions for reviewers:

Comment threadlightning/src/offers/merkle.rs Outdated
Comment threadlightning/src/offers/merkle.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 2 times, most recently from 87ec6b0 to 4cb0a4bCompareMay 20, 2023 21:49
Comment threadlightning/src/ln/msgs.rs
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 4cb0a4b to 07a9910CompareMay 20, 2023 22:22
@codecov-commenter

codecov-commenter commented May 20, 2023

Copy link
Copy Markdown

Codecov Report

Patch coverage: 95.32% and project coverage change: +0.34% 🎉

Comparison is base (e13ff10) 90.24% compared to head (93a8fb6) 90.58%.
Report is 21 commits behind head on main.

❗ Current head 93a8fb6 differs from pull request most recent head 1db481f. Consider uploading reports for the commit 1db481f to get more accurate results

❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

Additional details and impacted files
@@ Coverage Diff @@## main #2308 +/- ##
==========================================
+ Coverage 90.24% 90.58% +0.34% 
==========================================
Files 106 106 Lines 55817 59617 +3800 Branches 55817 59617 +3800 ==========================================
+ Hits 50370 54007 +3637 - Misses 5447 5610 +163 
Files ChangedCoverage Δ
lightning/src/events/mod.rs41.98% <ø> (+0.37%)⬆️
lightning/src/util/ser_macros.rs67.75% <0.00%> (-2.81%)⬇️
lightning/src/ln/onion_route_tests.rs98.51% <85.71%> (+0.01%)⬆️
lightning/src/ln/payment_tests.rs97.38% <95.04%> (-0.28%)⬇️
lightning/src/ln/msgs.rs85.10% <96.55%> (+0.36%)⬆️
lightning/src/ln/channelmanager.rs86.73% <97.91%> (+1.28%)⬆️
lightning-invoice/src/payment.rs88.59% <100.00%> (-0.08%)⬇️
lightning/src/ln/functional_test_utils.rs88.93% <100.00%> (+0.01%)⬆️
lightning/src/ln/onion_utils.rs90.90% <100.00%> (-0.16%)⬇️
lightning/src/ln/outbound_payment.rs92.77% <100.00%> (+3.57%)⬆️

... and 4 files with indirect coverage changes

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

@wpaulino
wpaulino self-requested a review May 21, 2023 02:11
@dunxen
dunxen self-requested a review May 26, 2023 07:05

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sorry for the delay here, just getting caught up post-travels.

Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/offers/merkle.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 07a9910 to 3d848a6CompareJune 2, 2023 04:00
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/outbound_payment.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 4 times, most recently from 3483289 to 59f3fb6CompareJune 8, 2023 18:53
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/msgs.rs
@alecchendev
alecchendev marked this pull request as ready for review June 8, 2023 18:59
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 2 times, most recently from a7a2162 to ad4376eCompareJune 10, 2023 23:02
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Rebased due to conflicts.

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This basically looks good, I think, needs another reviewer.

Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 3 times, most recently from 751c245 to a0d10a3CompareJune 14, 2023 05:44

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good! Since a user can now include arbitrary data, do we know if the router can handle restricting the number of hops based on the existing recipient payload?

Comment threadlightning/src/util/ser_macros.rs Outdated
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

do we know if the router can handle restricting the number of hops based on the existing recipient payload?

It currently cannot, though this is an issue that was really introduced in payment metadata, this just makes it worse. Tracked at #2201.

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Feel free to squash fixups when you next push, I think.

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from a0d10a3 to fdbcbffCompareJune 20, 2023 23:35
@wpaulinowpaulino added this to the 0.0.117 milestone Jul 5, 2023
@TheBlueMattTheBlueMatt added the blocked on next release Should Wait Until Next Release To Land label Jul 8, 2023
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

While we're still debating nits on the docs, can you go ahead and squash so we're set up to land? @wpaulino or @dunxen might want to take a look thereafter.

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 93a8fb6 to e8eedd3CompareJuly 31, 2023 02:03

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from e8eedd3 to 9a77843CompareAugust 1, 2023 02:26
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Fixed and squashed immediately since they were just small nits

@ariard

Copy link
Copy Markdown

this is why blinded paths have no error returned at all.

yes, though i’m not sure no returning error is workable on the long-term due to onion bandwidth cost and payment reliability (at least end-to-end), though here more conversation at the spec-level.

answered on the two comments:

  • i still wish we do our best to mask user agent and version from deanonymization attacks like done for browser / tor services
  • i still think “authentication” should be a strong suggestion, seen example of multiple payer not compatible with current payment_secret

though overall i won’t insist and if / when we have users privacy screwed up on those vectors, i’ll just pointed it back to you guys :)

@ariard

Copy link
Copy Markdown

i still wish we do our best to mask user agent and version from deanonymization attacks like done for browser / tor services

here the code is good in fact after looking (though doc confusing), just good if we don’t change it in the future to match BOLT4 bad suggestion imho

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 9a77843 to 1db481fCompareAugust 3, 2023 17:33
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Squashed immediately for minor doc change:

diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index 968b0765..daa0b34f 100644
--- a/lightning/src/ln/channelmanager.rs+++ b/lightning/src/ln/channelmanager.rs@@ -371,7 +371,7 @@ pub enum FailureCode {
/// We failed to process the payload after the onion was decrypted. You may wish to
/// use this when receiving custom HTLC TLVs with even type numbers that you don't recognize.
///
- /// If available, the tuple data should include the type number and byte offset in the+ /// If available, the tuple data may include the type number and byte offset in the
/// decrypted byte stream where the failure occurred.
InvalidOnionPayload(Option<(u64, u16)>),
}

@ariard

Copy link
Copy Markdown

Happy after following diff applied, payment_secret does not work for N-payer / N-payee flows, though it sounds reasonable for one payer / one payer flow, as far as I know about things like cancellable payments

diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index daa0b34f..db1108b4 100644
--- a/lightning/src/ln/channelmanager.rs
+++ b/lightning/src/ln/channelmanager.rs
@@ -4769,6 +4769,8 @@ where
/// You MUST check you've understood all even TLVs before using this to
/// claim, otherwise you may unintentionally agree to some protocol you do not understand.
///
+ /// You MAY authenticate the even TLVs additionally of `payment_secret` if the protocol
+ /// flow is more sophisticated than one payer / one payee.
/// [`claim_funds`]: Self::claim_funds
pub fn claim_funds_with_known_custom_tlvs(&self, payment_preimage: PaymentPreimage) {
self.claim_payment_internal(payment_preimage, true);

wpaulino
wpaulino previously approved these changes Aug 4, 2023

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review ACK 1db481f

Nevermind the above comment effectively multi-payer scheme would need additional code changes in our MPP validation and as such wider custom HTLC support (though they’re the ones more exposed in term of potential deanonymization attacks)

FailureCode::InvalidOnionPayload(data) => {
let fail_data = match data {
Some((typ, offset)) => [BigSize(typ).encode(), offset.encode()].concat(),
None => Vec::new(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: I think the debug_assert(data.is_none()) could be added due to its only usage in claim_payment_internal with a None value given to InvalidOnionPayload.

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Grrr, needs rebase, sorry about that.

Custom TLVs allow users to send extra application-specific data with
a payment. These have the additional flexibility compared to
`payment_metadata` that they don't have to reflect recipient generated
data provided in an invoice, in which `payment_metadata` could be
reused.
We ensure provided type numbers are unique, increasing, and within the
experimental range with the `RecipientOnionFields::with_custom_tlvs`
method.
This begins sender-side support for custom TLVs.
When serialized, the TLVs in `OutboundOnionPayload`, unlike a normal
TLV stream, are prefixed with the length of the stream. To allow a user
to add arbitrary custom TLVs, we aren't able to communicate to our
serialization macros exactly which fields to expect, so this commit
adds new macro variants to allow appending an extra set of bytes (and
modifying the prefixed length accordingly).
Because the keysend preimage TLV has a type number in the custom type
range, and a user's TLVs may have type numbers above and/or below
keysend's type number, and because TLV streams must be serialized in
increasing order by type number, this commit also ensures the keysend
TLV is properly sorted/serialized amongst the custom TLVs.
This completes basic receiver-side support for custom TLVs and adds
functional testing for sending and receiving.
Upon receiving multiple payment parts with custom TLVs, we fail payments
if they have any non-matching or missing even TLVs, and otherwise just
drop non-matching TLVs if they're odd.
When a user decodes custom TLVs, if they fail to recognize even type
numbers they should fail back with the correct failure code and fail
data. This new variant adds the proper failure variant for the user to
pass into `ChannelManager::fail_htlc_backwards_with_reason`.
Note that the enum discriminants were removed because when adding a
struct variant we can no longer make use of the discriminant through
casting like we previously did, and instead have to manually define the
associated failure code anyway.
Because we don't know which custom TLV type numbers the user is
expecting (and it would be cumbersome for them to tell us), instead of
failing unknown even custom TLVs on deserialization, we accept all
custom TLVs, and pass them to the user to check whether they recognize
them and choose to fail back if they don't. However, a user may not
check for custom TLVs, in which case we should reject any even custom
TLVs as unknown.
This commit makes sure a user must explicitly accept a payment with
even custom TLVs, by (1) making the default
`ChannelManager::claim_funds` fail if the payment had even custom TLVs
and (2) adding a new function
`ChannelManager::claim_funds_with_known_custom_tlvs` that accepts them.
This commit also refactors our custom TLVs test and updates various
documentation to account for this.
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Rebased

}

#[cfg(debug_assertions)] {
let mut last_seen: Option<u64> = None;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

it'd be nice to have this in one macro body with the above non-custom TLVs so that we can debug_assert!() that the ordering including custom TLVs is correct.

let tlvs = &mut self.custom_tlvs;
let further_tlvs = &mut further_htlc_fields.custom_tlvs;

let even_tlvs: Vec<&(u64, Vec<u8>)> = tlvs.iter().filter(|(typ, _)| *typ % 2 == 0).collect();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You should be able to do the comparison here without collecting into a Vec.

let preimage = if let Some(ref preimage) = keysend_preimage {
Some((5482373484, preimage.encode()))
} else { None };
let mut custom_tlvs: Vec<&(u64, Vec<u8>)> = custom_tlvs.iter().chain(preimage.iter()).collect();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We are trying to build an interator, we shouldn't have to collect here (though the macro may want it twice, so we may have to do the iter().chain() in the macro argument rather than here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Though AFAIK it wouldn't be possible to sort the tlvs as an iterator?

match &purpose {
PaymentPurpose::InvoicePayment { payment_secret, .. } => {
assert_eq!(our_payment_secret, *payment_secret);
assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: just for your reference, if we're copying test util bits into a test, we can usually skip a bunch of the assertions - the test utility methods tend to be a bit verbose and check everything, which is great in the general code, but in an individual test we don't need to test too much more than we care about for the purpose of the specific test.

@TheBlueMatt
TheBlueMatt merged commit 9e4a35a into lightningdevkit:mainAug 10, 2023
if let Some(expected_tlvs) = expected_receive_tlvs {
// Claim and match expected
let events = nodes[3].node.get_and_clear_pending_events();
println!("events: {:?}", events);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oops, I missed this before hitting merge, let's do a followup and remove this (and maybe hit a few other nits, though no real pressure on those).

@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Thanks for all the review everybody, will get a follow up up soon :)

Sign up for freeto 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.

Custom HTLC TLVs

6 participants

@alecchendev@codecov-commenter@TheBlueMatt@ariard@dunxen@wpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Add support for custom HTLC TLVs - #2308

Merged
TheBlueMatt merged 7 commits into
lightningdevkit:mainfrom
alecchendev:2023-05-custom-htlc-tlvs
Aug 10, 2023
Merged

Add support for custom HTLC TLVs#2308
TheBlueMatt merged 7 commits into
lightningdevkit:mainfrom
alecchendev:2023-05-custom-htlc-tlvs

Conversation

@alecchendev

@alecchendevalecchendev commented May 19, 2023

Copy link
Copy Markdown
Contributor

Closes#1298. This PR adds support for sending and receiving custom HTLC TLVs.

Custom TLVs allow users to send extra application-specific data with a payment. These have the additional flexibility compared to payment_metadata that they don't have to reflect recipient generated data provided in an invoice, in which payment_metadata could (probably) be reused.

On the send side, a user can provide their serialized TLVs as a Vec<(u64, Vec<u8>)> to RecipientOnionFields::with_custom_tlvs which checks whether the type numbers are unique, increasing, and in the range reserved for custom values. They'll then pass this into whichever send payment function they use, it'll be serialized in the onion payload, and sent with the payment.

On the receive side, when deserializing the onion payload, we just add the bytes back into this type, then pipe it from the onion through to Event::PaymentClaimable, dropping non-matching TLVs between payment parts.

@alecchendevalecchendev left a comment

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

A couple questions for reviewers:

Comment threadlightning/src/offers/merkle.rs Outdated
Comment threadlightning/src/offers/merkle.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 2 times, most recently from 87ec6b0 to 4cb0a4bCompareMay 20, 2023 21:49
Comment threadlightning/src/ln/msgs.rs
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 4cb0a4b to 07a9910CompareMay 20, 2023 22:22
@codecov-commenter

codecov-commenter commented May 20, 2023

Copy link
Copy Markdown

Codecov Report

Patch coverage: 95.32% and project coverage change: +0.34% 🎉

Comparison is base (e13ff10) 90.24% compared to head (93a8fb6) 90.58%.
Report is 21 commits behind head on main.

❗ Current head 93a8fb6 differs from pull request most recent head 1db481f. Consider uploading reports for the commit 1db481f to get more accurate results

❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

Additional details and impacted files
@@ Coverage Diff @@## main #2308 +/- ##
==========================================
+ Coverage 90.24% 90.58% +0.34% 
==========================================
Files 106 106 Lines 55817 59617 +3800 Branches 55817 59617 +3800 ==========================================
+ Hits 50370 54007 +3637 - Misses 5447 5610 +163 
Files ChangedCoverage Δ
lightning/src/events/mod.rs41.98% <ø> (+0.37%)⬆️
lightning/src/util/ser_macros.rs67.75% <0.00%> (-2.81%)⬇️
lightning/src/ln/onion_route_tests.rs98.51% <85.71%> (+0.01%)⬆️
lightning/src/ln/payment_tests.rs97.38% <95.04%> (-0.28%)⬇️
lightning/src/ln/msgs.rs85.10% <96.55%> (+0.36%)⬆️
lightning/src/ln/channelmanager.rs86.73% <97.91%> (+1.28%)⬆️
lightning-invoice/src/payment.rs88.59% <100.00%> (-0.08%)⬇️
lightning/src/ln/functional_test_utils.rs88.93% <100.00%> (+0.01%)⬆️
lightning/src/ln/onion_utils.rs90.90% <100.00%> (-0.16%)⬇️
lightning/src/ln/outbound_payment.rs92.77% <100.00%> (+3.57%)⬆️

... and 4 files with indirect coverage changes

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

@wpaulino
wpaulino self-requested a review May 21, 2023 02:11
@dunxen
dunxen self-requested a review May 26, 2023 07:05

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sorry for the delay here, just getting caught up post-travels.

Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/offers/merkle.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 07a9910 to 3d848a6CompareJune 2, 2023 04:00
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/outbound_payment.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 4 times, most recently from 3483289 to 59f3fb6CompareJune 8, 2023 18:53
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/msgs.rs
@alecchendev
alecchendev marked this pull request as ready for review June 8, 2023 18:59
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 2 times, most recently from a7a2162 to ad4376eCompareJune 10, 2023 23:02
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Rebased due to conflicts.

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This basically looks good, I think, needs another reviewer.

Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/util/ser_macros.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch 3 times, most recently from 751c245 to a0d10a3CompareJune 14, 2023 05:44

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good! Since a user can now include arbitrary data, do we know if the router can handle restricting the number of hops based on the existing recipient payload?

Comment threadlightning/src/util/ser_macros.rs Outdated
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

do we know if the router can handle restricting the number of hops based on the existing recipient payload?

It currently cannot, though this is an issue that was really introduced in payment metadata, this just makes it worse. Tracked at #2201.

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Feel free to squash fixups when you next push, I think.

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from a0d10a3 to fdbcbffCompareJune 20, 2023 23:35
@wpaulinowpaulino added this to the 0.0.117 milestone Jul 5, 2023
@TheBlueMattTheBlueMatt added the blocked on next release Should Wait Until Next Release To Land label Jul 8, 2023
@TheBlueMatt

Copy link
Copy Markdown
Collaborator

While we're still debating nits on the docs, can you go ahead and squash so we're set up to land? @wpaulino or @dunxen might want to take a look thereafter.

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 93a8fb6 to e8eedd3CompareJuly 31, 2023 02:03

@wpaulinowpaulino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

Comment threadlightning/src/ln/outbound_payment.rs Outdated
Comment threadlightning/src/ln/outbound_payment.rs Outdated
@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from e8eedd3 to 9a77843CompareAugust 1, 2023 02:26
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Fixed and squashed immediately since they were just small nits

@ariard

Copy link
Copy Markdown

this is why blinded paths have no error returned at all.

yes, though i’m not sure no returning error is workable on the long-term due to onion bandwidth cost and payment reliability (at least end-to-end), though here more conversation at the spec-level.

answered on the two comments:

  • i still wish we do our best to mask user agent and version from deanonymization attacks like done for browser / tor services
  • i still think “authentication” should be a strong suggestion, seen example of multiple payer not compatible with current payment_secret

though overall i won’t insist and if / when we have users privacy screwed up on those vectors, i’ll just pointed it back to you guys :)

@ariard

Copy link
Copy Markdown

i still wish we do our best to mask user agent and version from deanonymization attacks like done for browser / tor services

here the code is good in fact after looking (though doc confusing), just good if we don’t change it in the future to match BOLT4 bad suggestion imho

@alecchendev
alecchendevforce-pushed the 2023-05-custom-htlc-tlvs branch from 9a77843 to 1db481fCompareAugust 3, 2023 17:33
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Squashed immediately for minor doc change:

diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index 968b0765..daa0b34f 100644
--- a/lightning/src/ln/channelmanager.rs+++ b/lightning/src/ln/channelmanager.rs@@ -371,7 +371,7 @@ pub enum FailureCode {
/// We failed to process the payload after the onion was decrypted. You may wish to
/// use this when receiving custom HTLC TLVs with even type numbers that you don't recognize.
///
- /// If available, the tuple data should include the type number and byte offset in the+ /// If available, the tuple data may include the type number and byte offset in the
/// decrypted byte stream where the failure occurred.
InvalidOnionPayload(Option<(u64, u16)>),
}

@ariard

Copy link
Copy Markdown

Happy after following diff applied, payment_secret does not work for N-payer / N-payee flows, though it sounds reasonable for one payer / one payer flow, as far as I know about things like cancellable payments

diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index daa0b34f..db1108b4 100644
--- a/lightning/src/ln/channelmanager.rs
+++ b/lightning/src/ln/channelmanager.rs
@@ -4769,6 +4769,8 @@ where
/// You MUST check you've understood all even TLVs before using this to
/// claim, otherwise you may unintentionally agree to some protocol you do not understand.
///
+ /// You MAY authenticate the even TLVs additionally of `payment_secret` if the protocol
+ /// flow is more sophisticated than one payer / one payee.
/// [`claim_funds`]: Self::claim_funds
pub fn claim_funds_with_known_custom_tlvs(&self, payment_preimage: PaymentPreimage) {
self.claim_payment_internal(payment_preimage, true);

wpaulino
wpaulino previously approved these changes Aug 4, 2023

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review ACK 1db481f

Nevermind the above comment effectively multi-payer scheme would need additional code changes in our MPP validation and as such wider custom HTLC support (though they’re the ones more exposed in term of potential deanonymization attacks)

FailureCode::InvalidOnionPayload(data) => {
let fail_data = match data {
Some((typ, offset)) => [BigSize(typ).encode(), offset.encode()].concat(),
None => Vec::new(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: I think the debug_assert(data.is_none()) could be added due to its only usage in claim_payment_internal with a None value given to InvalidOnionPayload.

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

Grrr, needs rebase, sorry about that.

Custom TLVs allow users to send extra application-specific data with
a payment. These have the additional flexibility compared to
`payment_metadata` that they don't have to reflect recipient generated
data provided in an invoice, in which `payment_metadata` could be
reused.
We ensure provided type numbers are unique, increasing, and within the
experimental range with the `RecipientOnionFields::with_custom_tlvs`
method.
This begins sender-side support for custom TLVs.
When serialized, the TLVs in `OutboundOnionPayload`, unlike a normal
TLV stream, are prefixed with the length of the stream. To allow a user
to add arbitrary custom TLVs, we aren't able to communicate to our
serialization macros exactly which fields to expect, so this commit
adds new macro variants to allow appending an extra set of bytes (and
modifying the prefixed length accordingly).
Because the keysend preimage TLV has a type number in the custom type
range, and a user's TLVs may have type numbers above and/or below
keysend's type number, and because TLV streams must be serialized in
increasing order by type number, this commit also ensures the keysend
TLV is properly sorted/serialized amongst the custom TLVs.
This completes basic receiver-side support for custom TLVs and adds
functional testing for sending and receiving.
Upon receiving multiple payment parts with custom TLVs, we fail payments
if they have any non-matching or missing even TLVs, and otherwise just
drop non-matching TLVs if they're odd.
When a user decodes custom TLVs, if they fail to recognize even type
numbers they should fail back with the correct failure code and fail
data. This new variant adds the proper failure variant for the user to
pass into `ChannelManager::fail_htlc_backwards_with_reason`.
Note that the enum discriminants were removed because when adding a
struct variant we can no longer make use of the discriminant through
casting like we previously did, and instead have to manually define the
associated failure code anyway.
Because we don't know which custom TLV type numbers the user is
expecting (and it would be cumbersome for them to tell us), instead of
failing unknown even custom TLVs on deserialization, we accept all
custom TLVs, and pass them to the user to check whether they recognize
them and choose to fail back if they don't. However, a user may not
check for custom TLVs, in which case we should reject any even custom
TLVs as unknown.
This commit makes sure a user must explicitly accept a payment with
even custom TLVs, by (1) making the default
`ChannelManager::claim_funds` fail if the payment had even custom TLVs
and (2) adding a new function
`ChannelManager::claim_funds_with_known_custom_tlvs` that accepts them.
This commit also refactors our custom TLVs test and updates various
documentation to account for this.
@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Rebased

}

#[cfg(debug_assertions)] {
let mut last_seen: Option<u64> = None;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

it'd be nice to have this in one macro body with the above non-custom TLVs so that we can debug_assert!() that the ordering including custom TLVs is correct.

let tlvs = &mut self.custom_tlvs;
let further_tlvs = &mut further_htlc_fields.custom_tlvs;

let even_tlvs: Vec<&(u64, Vec<u8>)> = tlvs.iter().filter(|(typ, _)| *typ % 2 == 0).collect();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You should be able to do the comparison here without collecting into a Vec.

let preimage = if let Some(ref preimage) = keysend_preimage {
Some((5482373484, preimage.encode()))
} else { None };
let mut custom_tlvs: Vec<&(u64, Vec<u8>)> = custom_tlvs.iter().chain(preimage.iter()).collect();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We are trying to build an interator, we shouldn't have to collect here (though the macro may want it twice, so we may have to do the iter().chain() in the macro argument rather than here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Though AFAIK it wouldn't be possible to sort the tlvs as an iterator?

match &purpose {
PaymentPurpose::InvoicePayment { payment_secret, .. } => {
assert_eq!(our_payment_secret, *payment_secret);
assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: just for your reference, if we're copying test util bits into a test, we can usually skip a bunch of the assertions - the test utility methods tend to be a bit verbose and check everything, which is great in the general code, but in an individual test we don't need to test too much more than we care about for the purpose of the specific test.

@TheBlueMatt
TheBlueMatt merged commit 9e4a35a into lightningdevkit:mainAug 10, 2023
if let Some(expected_tlvs) = expected_receive_tlvs {
// Claim and match expected
let events = nodes[3].node.get_and_clear_pending_events();
println!("events: {:?}", events);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oops, I missed this before hitting merge, let's do a followup and remove this (and maybe hit a few other nits, though no real pressure on those).

@alecchendev

Copy link
Copy Markdown
ContributorAuthor

Thanks for all the review everybody, will get a follow up up soon :)

Sign up for freeto 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.

Custom HTLC TLVs

6 participants

@alecchendev@codecov-commenter@TheBlueMatt@ariard@dunxen@wpaulino