Skip to content

Commit to payment_metadata in inbound payment HMAC#4528

Open
TheBlueMatt wants to merge 2 commits intolightningdevkit:mainfrom
TheBlueMatt:2026-03-commit-to-metadata
Open

Commit to payment_metadata in inbound payment HMAC#4528
TheBlueMatt wants to merge 2 commits intolightningdevkit:mainfrom
TheBlueMatt:2026-03-commit-to-metadata

Conversation

@TheBlueMatt
Copy link
Copy Markdown
Collaborator

When payment_metadata is set in a BOLT 11 invoice, users expect to
receive it back as-is in the payment onion. In order to ensure it
isn't tampered with, they presumably will add an HMAC, or worse, not
add one and forget that it can be tampered with.

Instead, here we include it in the HMAC computation for the payment
secret. This ensures that the sender must relay the correct
metadata for the payment to be accepted by the receiver, binding
the metadata to the payment cryptographically.

The metadata is only included in the HMAC when present, so existing
payments without metadata continue to verify correctly. However,
this does break receiving payments with metadata today. On an
upgrade this seems acceptable to me given we have seen almost no
use of payment metadata in practice.

TheBlueMatt and others added 2 commits March 31, 2026 19:18
`payment_metadata` is a separate concept at the BOLT 11 layer
(similar to payment secret, but arbitrary-sized) and at the BOLT 12
layer, so referring to payment information as "payment metadata" is
confusing. Instead, use simply "payment info".
When payment_metadata is set in a BOLT 11 invoice, users expect to
receive it back as-is in the payment onion. In order to ensure it
isn't tampered with, they presumably will add an HMAC, or worse, not
add one and forget that it can be tampered with.

Instead, here we include it in the HMAC computation for the payment
secret. This ensures that the sender must relay the correct
metadata for the payment to be accepted by the receiver, binding
the metadata to the payment cryptographically.

The metadata is only included in the HMAC when present, so existing
payments without metadata continue to verify correctly. However,
this does break receiving payments with metadata today. On an
upgrade this seems acceptable to me given we have seen almost no
use of payment metadata in practice.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ldk-reviews-bot
Copy link
Copy Markdown

ldk-reviews-bot commented Mar 31, 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.

Comment thread pending_changelog/matt-commit-to-metadata.txt
Comment thread lightning/src/ln/inbound_payment.rs
Comment thread lightning/src/ln/channelmanager.rs
Comment thread lightning/src/ln/channelmanager.rs
@ldk-claude-review-bot
Copy link
Copy Markdown
Collaborator

Review Summary

Inline comments posted:

  1. pending_changelog/matt-commit-to-metadata.txt:2 — Typo: "comitted" → "committed"

  2. lightning/src/ln/inbound_payment.rs:174-176None vs Some(&[]) metadata are cryptographically indistinguishable since hmac.input(&[]) is a no-op. This applies to all HMAC sites (create, create_from_hash, verify, derive_ldk_payment_preimage). Not a security issue in practice, but a design consideration.

  3. lightning/src/ln/channelmanager.rs:14983-14985get_payment_preimage public API lacks documentation for the new payment_metadata parameter. Callers who created payments with metadata must pass the same metadata here or get an opaque error.

  4. lightning/src/ln/channelmanager.rs:14904create_inbound_payment public API lacks documentation for the new payment_metadata parameter.

Cross-cutting observations:

  • The core cryptographic change is correct: metadata is consistently included in HMAC computation during creation (create, create_from_hash) and verification (verify, derive_ldk_payment_preimage, get_payment_preimage).

  • create_inbound_payment_for_hash (line 14963-14966) similarly lacks docs for its new payment_metadata parameter.

  • The _create_phantom_invoice function (invoice_utils.rs:194, 207) hardcodes None for payment_metadata. This is fine for now but means phantom invoices cannot use the metadata commitment feature.

  • All test changes correctly thread the new parameter. The get_payment_hash! macro in max_payment_path_len_tests.rs properly generates committed payment secrets for each metadata variant.

@ldk-reviews-bot
Copy link
Copy Markdown

🔔 1st Reminder

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

Copy link
Copy Markdown
Contributor

@valentinewallace valentinewallace left a comment

Choose a reason for hiding this comment

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

LGTM aside from CI and one or two of Claude's doc nits

///
/// Note that because it is exposed to the sender in the invoice you should consider encrypting
/// it. It is committed to, however, so cannot be modified by the sender.
pub payment_metadata: Option<Vec<u8>>,
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.

nit: this could've been a separate commit

Comment on lines +14209 to +14210
let raw_invoice = if let Some(payment_metadata) = payment_metadata {
invoice.payment_metadata(payment_metadata).build_raw()
Copy link
Copy Markdown
Contributor

@elnosh elnosh Apr 23, 2026

Choose a reason for hiding this comment

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

check length of payment_metadata and return error if greater than max allowed length of field in invoice?

@tnull
Copy link
Copy Markdown
Contributor

tnull commented May 6, 2026

@TheBlueMatt any chance to get this into 0.3 still? We'd need it to make lightningdevkit/ldk-node#899 safe, which we want to do given we're now doing #4584 ^^

And, given this PR breaks backwards compat. for payment metadata users, we'll probably want to have the breakage happen before we start using payment metadata in LDK Node (i.e. lightningdevkit/ldk-node#899).

Feel free to object, but for that reason I'm adding this to the 0.3 milestone.

@tnull tnull self-requested a review May 6, 2026 12:33
@tnull tnull added this to the 0.3 milestone May 6, 2026
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.

6 participants