Skip to content

Accept LNURL-pay invoices without matching description_hash#2

Merged
martinsaposnic merged 1 commit into
2025-12-ldk-node-basefrom
lnurl-skip-desc-hash-on-ldk-base
May 18, 2026
Merged

Accept LNURL-pay invoices without matching description_hash#2
martinsaposnic merged 1 commit into
2025-12-ldk-node-basefrom
lnurl-skip-desc-hash-on-ldk-base

Conversation

@martinsaposnic

Copy link
Copy Markdown

Summary

  • Removes the LUD-06 description_hash check in HTTPHrnResolver::resolve_lnurl_to_invoice so BOLT11 invoices with a plain d tag (or a mismatched h tag) are accepted instead of being rejected with "BOLT 11 invoice resolved via LNURL must have a matching description hash".
  • Motivated by real-world non-compliant LNURL-pay servers (e.g. bringin.xyz) which mint invoices with d = "Topup 22000 sats" and no h tag. Strike pays these fine; upstream bitcoin-payment-instructions does not, so moneydevkit payouts to these addresses fail.

Targets 2025-12-ldk-node-base (the branch mdkd and ldk-node pin via rev 6796e87) instead of main, so a single rev bump in those consumers picks up the fix without dragging in the LDK version drift between this branch and main.

Tradeoff

LUD-06 requires the invoice's h tag to commit to sha256(metadata) so the payer's wallet can prove the invoice it signs matches the metadata it displayed. Dropping the check means a malicious or buggy LNURL host can swap the invoice description out from under the user. We accept this here to unblock payouts. Callers that want the spec-correct behavior should use upstream.

Test plan

  • cargo build --features http clean on this branch
  • cargo build clean on lightning-js with its bitcoin-payment-instructions dep swapped to this branch (the only build error encountered was a pre-existing, unrelated LSPS4ServiceEvent::SendWebhook field mismatch in local ldk-node/rust-lightning working trees)
  • Live test against vincenzopalazzo@bringin.xyz via HTTPHrnResolver:
    Resolving vincenzopalazzo@bringin.xyz for 23000000 msat
      min=Some(22098000 milli-satoshis)
      max=Some(15453023000 milli-satoshis)
      description=Some("Payment to vincenzopalazzo@bringin.xyz")
    
    set_amount: OK
      BOLT11 invoice: lnbc230u1p4qkjf0pp5lr89jlckmwvc8vlpfxdwck6h2p79xmw9hawjka6w3qrr0q8ueyfq...
      amount_msat: Some(23000000)
      payment_hash: f8ce597f16db9983b3e1499aec5b57507c536dc5bf5d2b774e88063780fcc912
      description: Direct(Description(UntrustedString("Topup 23000 sats")))
    
    Note description: Direct(...) is exactly the case upstream rejects; this fork passes through.

Followups (not in this PR)

Some real-world LNURL-pay servers (e.g. bringin.xyz) mint BOLT11 invoices
with a plain `d` tag instead of the `h` tag = sha256(metadata) required
by LUD-06. Upstream correctly rejects these. This fork accepts them to
match the permissive behavior of wallets like Strike, so payouts from
moneydevkit to addresses on these servers go through.

Tradeoff: we lose the cryptographic binding between the LNURL metadata
the payer saw and the invoice the wallet signs. A malicious or buggy
LNURL host can swap the description after the fact. Acceptable here
because the alternative is "payouts to popular non-compliant servers
just fail".
@martinsaposnic
martinsaposnic merged commit bc7d03f into 2025-12-ldk-node-base May 18, 2026
martinsaposnic added a commit to moneydevkit/lightning-js that referenced this pull request May 18, 2026
Point at the `2025-12-ldk-node-base` branch (rev bc7d03f) of our fork,
which includes a patch to accept LNURL-pay BOLT11 invoices that ship a
plain `d` description tag instead of the LUD-06-required `h =
sha256(metadata)` tag. Unblocks payouts to Bringin lightning addresses
(e.g. vincenzopalazzo@bringin.xyz) and any other LNURL servers with the
same non-compliance.

See moneydevkit/bitcoin-payment-instructions#2.

Builds clean; verified live against vincenzopalazzo@bringin.xyz which
previously failed with "BOLT 11 invoice resolved via LNURL must have a
matching description hash" and now returns a valid invoice.

Note: ldk-node still transitively pins rev 6796e87 of the same crate,
so `cargo tree -d` shows two copies of bitcoin-payment-instructions
until ldk-node is bumped in a follow-up.
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.

1 participant