Skip to content

Conversation

@shaavan
Copy link
Member

@shaavan shaavan commented Dec 6, 2025

This PR adds support for attaching custom TLVs to the BOLT 11 payment flow, giving callers a more ergonomic way to embed arbitrary metadata into the payment onion. These TLVs can carry auxiliary, application-specific information without requiring callers to drop down to lower-level APIs.

What this PR does

Adds custom TLV support to pay_for_bolt11_invoice.

While BOLT 11 already allowed custom TLVs via send_payment, the higher-level and more commonly used pay_for_bolt11_invoice path lacked this capability. This PR brings it to feature parity, allowing callers to attach custom TLVs without manually handling payment hashes or preimages.

Why this matters

Lightning applications often need to pass contextual, non-routing metadata alongside a payment. Prior to this change, doing so required using lower-level APIs even for straightforward BOLT 11 payments.

By exposing custom_tlvs directly on pay_for_bolt11_invoice, this PR makes it easier and safer for callers to attach additional data while preserving the existing payment flow abstractions.


Note: Support for carrying custom TLVs in BOLT 12 flows is intentionally left out of this PR and will be addressed separately by attaching such data directly to BOLT 12 messages (e.g., InvoiceRequest), rather than the payment onion.

Custom TLVs let the payer attach arbitrary data to the onion packet,
enabling everything from richer metadata to custom authentication on
the payee's side.

Until now, this flexibility existed only through `send_payment`. The
simpler `pay_for_bolt11_invoice` API offered no way to pass custom
TLVs, limiting its usefulness in flows that rely on additional context.

This commit adds custom TLV support to `pay_for_bolt11_invoice`,
bringing it to feature parity.
@ldk-reviews-bot
Copy link

ldk-reviews-bot commented Dec 6, 2025

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

@shaavan
Copy link
Member Author

shaavan commented Dec 6, 2025

cc @jkczyz

@codecov
Copy link

codecov bot commented Dec 6, 2025

Codecov Report

❌ Patch coverage is 93.02326% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.37%. Comparing base (de384ff) to head (e326fca).
⚠️ Report is 64 commits behind head on main.

Files with missing lines Patch % Lines
lightning/src/ln/outbound_payment.rs 60.00% 1 Missing and 1 partial ⚠️
lightning/src/ln/invoice_utils.rs 96.29% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4263      +/-   ##
==========================================
+ Coverage   89.33%   89.37%   +0.03%     
==========================================
  Files         180      180              
  Lines      139042   139868     +826     
  Branches   139042   139868     +826     
==========================================
+ Hits       124219   125004     +785     
- Misses      12196    12269      +73     
+ Partials     2627     2595      -32     
Flag Coverage Δ
fuzzing 35.21% <12.50%> (-0.76%) ⬇️
tests 88.70% <93.02%> (+<0.01%) ⬆️

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

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

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

@ldk-reviews-bot
Copy link

🔔 1st Reminder

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

@jkczyz jkczyz requested review from jkczyz and removed request for joostjager December 8, 2025 19:25
@ldk-reviews-bot
Copy link

🔔 1st Reminder

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

@ldk-reviews-bot
Copy link

🔔 2nd Reminder

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

@shaavan
Copy link
Member Author

shaavan commented Dec 14, 2025

Updated: .01 → .02
Addressed @jkczyz offline comments. Thanks!

Changes:

  • Expanded custom_tlvs introduction to AwaitingOffer, and StaticInvoice variants.
  • Expanded lightning-dns-resolver end-to-end test to test for custom_tlvs

@ldk-reviews-bot
Copy link

🔔 3rd Reminder

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

Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

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

I'm a bit skeptical of the utility of custom onion TLVs for BOLT 12 payments - in general ISTM we should really be preferring to include custom data in the BOLT 12 onion messages themselves, allowing them to not take up precious space in the payment onion (though the recipient can pipe them through if they want). Do we have intended use-cases for these?

@@ -13376,12 +13129,14 @@ where
/// [`InvoiceRequest::quantity`]: crate::offers::invoice_request::InvoiceRequest::quantity
pub fn pay_for_offer_with_quantity(
&self, offer: &Offer, amount_msats: Option<u64>, payment_id: PaymentId,
optional_params: OptionalOfferPaymentParams, quantity: u64,
custom_tlvs: Vec<(u64, Vec<u8>)>, optional_params: OptionalOfferPaymentParams,
Copy link
Collaborator

Choose a reason for hiding this comment

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

These should really go in OptionalOfferPaymentParams, given that exists to hide fields we expect users to never set.

@ldk-reviews-bot
Copy link

🔔 4th Reminder

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

@shaavan shaavan changed the title Add custom TLV support across Bolt11 and Bolt12 payer flows Add custom TLV in Bolt11 Payer API Dec 19, 2025
Extends the payment flow test to assert that custom TLVs passed to
`pay_for_bolt11_invoice` are preserved and delivered correctly.
@shaavan
Copy link
Member Author

shaavan commented Dec 19, 2025

Updated: .02 → .03
Thanks, @TheBlueMatt. Changes:

  • Removed BOLT 12 custom TLVs from the payment onion in favor of moving this toward a better long-term direction.

@TheBlueMatt

in general ISTM we should really be preferring to include custom data in the BOLT 12 onion messages themselves...

I agree that it makes more sense to put this data directly into the InvoiceRequest. I had an offline discussion with @jkczyz as well, and we reached the same conclusion that carrying custom TLVs in the BOLT 12 messages themselves is the better long-term direction.

As for intended use cases, the motivation is to allow passing along auxiliary, non-routing information, for example travel-rule or compliance metadata exchanged between LSPs, VASPs, or other intermediaries, without overloading core payment semantics.

For now, I’ve trimmed the branch down to just the BOLT 11 API change, exposing custom_tlvs so users can attach additional data without having to go through payment hash or preimage extraction and a manual send_payment flow.

In parallel, I’ll start working on moving custom TLVs fully into the InvoiceRequest path as discussed.

Thanks a lot for the pointer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants