Skip to content

Add a payment_metadata map in blinded * path contexts#4584

Open
TheBlueMatt wants to merge 4 commits intolightningdevkit:mainfrom
TheBlueMatt:2026-04-bolt12-custom-data
Open

Add a payment_metadata map in blinded * path contexts#4584
TheBlueMatt wants to merge 4 commits intolightningdevkit:mainfrom
TheBlueMatt:2026-04-bolt12-custom-data

Conversation

@TheBlueMatt
Copy link
Copy Markdown
Collaborator

Similar to how BOLT 11 payments can use a `payment_metadata` to
provide arbitrary bytes in the invoice to be communicated back to
them when receiving, its useful to be able to provide some bytes
which are communicated back upon receiving a payment.

Here we do so in the BOLT 12 blinded * contexts, offering a
`BTreeMap<u64, Vec<u8>>` instead to enable more easily including
multiple sets of data.

Also note that a `Router` building a blinded path is allowed to
modify the `payment_metadata` without breaking the payment.

Tests by claude

We do so both in the blinded message and payment paths, supporting async payments when data is injected in the blinded payment paths (eg via the Router). We don't expose building offers with metadata yet.

We almost certainly don't want to be moving `option` TLVs during
serialization, and while we had logic elsewhere to work around this
previously its nice not to have to in the future.
Similar to how BOLT 11 payments can use a `payment_metadata` to
provide arbitrary bytes in the invoice to be communicated back to
them when receiving, its useful to be able to provide some bytes
which are communicated back upon receiving a payment.

Here we do so in the BOLT 12 blinded path contexts, offering a
`BTreeMap<u64, Vec<u8>>` instead to enable more easily including
multiple sets of data.

Also note that a `Router` building a blinded path is allowed to
modify the `payment_metadata` without breaking the payment.

Tests by claude
@TheBlueMatt TheBlueMatt requested a review from tnull May 1, 2026 02:04
@ldk-reviews-bot
Copy link
Copy Markdown

ldk-reviews-bot commented May 1, 2026

👋 Thanks for assigning @tnull 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.

@TheBlueMatt TheBlueMatt force-pushed the 2026-04-bolt12-custom-data branch from f876c82 to 7c4e653 Compare May 1, 2026 02:04
Similar to how BOLT 11 payments can use a `payment_metadata` to
provide arbitrary bytes in the invoice to be communicated back to
them when receiving, its useful to be able to provide some bytes
which are communicated back upon receiving a payment.

Here we do so in the BOLT 12 blinded message path contexts,
offering a `BTreeMap<u64, Vec<u8>>` instead to enable more easily
including multiple sets of data.

We don't yet wire it up to the public `ChannelManager` API, but do
allow selecting values for those using the manual
`OffersMessageFlow`.

Tests by claude
@TheBlueMatt TheBlueMatt force-pushed the 2026-04-bolt12-custom-data branch from 7c4e653 to ee6ba89 Compare May 1, 2026 02:05
Comment on lines +474 to +475
/// [`OffersContext::InvoiceRequest::payment_metadata`] prior to blinded path construction is
/// allowed.
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.

Bug: OffersContext::StaticInvoiceRequested::payment_metadata does not exist. The StaticInvoiceRequested variant only has recipient_id, invoice_slot, and path_absolute_expiry fields — no payment_metadata was added to it in this PR.

This will either be a broken rustdoc link or misleading documentation. Either add payment_metadata to StaticInvoiceRequested or remove this reference.

/// needs to be "stored" by a payment recipient for their own internal use, provided back to
/// them with the payment.
///
/// Note that because this is included in the payment onion, its size must be tighly
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.

Typo: "tighly" → "tightly"

/// provided to payers via [`Bolt11Invoice::payment_metadata`]) and can be used any time data
/// needs to be "stored" by a payment recipient for their own internal use, provided back to
/// them with the payment.
///
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.

Typo: "tighly" → "tightly" (same typo appears in all four payment_metadata doc comments in this file — Bolt12OfferContext, AsyncBolt12OfferContext, and Bolt12RefundContext)

@ldk-claude-review-bot
Copy link
Copy Markdown
Collaborator

ldk-claude-review-bot commented May 1, 2026

Review Summary

No new issues found beyond what was flagged in the prior review pass.

Previously flagged issues (still applicable):

  1. lightning/src/blinded_path/message.rs:407 — Typo: "tighly" should be "tightly"
  2. lightning/src/blinded_path/payment.rs:618 — Same "tighly" typo repeated in all four payment_metadata doc comments

Verification of correctness across the PR:

  • TLV backwards compatibility: All new payment_metadata fields use odd TLV type numbers (1), correctly making them optional for old readers. Ascending order is maintained in all serialization definitions.
  • _encode_tlv .as_ref() fix: The macro change from $field.map(...) to $field.as_ref().map(|f| $encoding(f)) is correct and necessary for non-Copy types like BTreeMap. All required Writeable wrapper impls exist: BigSizeKeyedMap<&BTreeMap<...>>, AccountableBool<&bool>, HighZeroBytesDroppedBigSize<&T>, WithoutLength<&&String>, WithoutLength<&&Features>, and WithoutLength<&Vec<T>> (via AsWriteableSlice).
  • Propagation completeness: payment_metadata flows correctly through all paths: OffersContext::InvoiceRequestchannelmanager extraction → flow.rs invoice builders → PaymentContext in blinded payment paths → Event::PaymentClaimable. The async payment path (AsyncBolt12OfferContextBolt12OfferContext conversion in channelmanager.rs:8668-8710) also correctly preserves the metadata.
  • BigSizeKeyedMap safety: Deserialization uses LengthReadable (read_from_fixed_length_buffer) with a LengthLimitedRead, so total read bytes are bounded by the TLV length. BTreeMap doesn't pre-allocate, and duplicate keys are rejected. No DoS vector.
  • All pattern matches updated: Every construction and destructuring of OffersContext::InvoiceRequest, Bolt12OfferContext, AsyncBolt12OfferContext, and Bolt12RefundContext includes the new payment_metadata field.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 1, 2026

Codecov Report

❌ Patch coverage is 82.95455% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.14%. Comparing base (42e198c) to head (ee6ba89).

Files with missing lines Patch % Lines
lightning/src/blinded_path/payment.rs 41.66% 7 Missing ⚠️
lightning/src/util/ser.rs 75.86% 1 Missing and 6 partials ⚠️
lightning/src/util/test_utils.rs 91.66% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4584      +/-   ##
==========================================
- Coverage   87.15%   87.14%   -0.01%     
==========================================
  Files         161      161              
  Lines      109251   109322      +71     
  Branches   109251   109322      +71     
==========================================
+ Hits        95215    95270      +55     
- Misses      11560    11571      +11     
- Partials     2476     2481       +5     
Flag Coverage Δ
fuzzing-fake-hashes 31.13% <15.66%> (-0.02%) ⬇️
fuzzing-real-hashes 22.91% <1.20%> (-0.01%) ⬇️
tests 86.21% <82.95%> (-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.

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