Skip to content

fix: reject offers with offer_amount=0 per BOLT 12#253

Open
vincenzopalazzo wants to merge 3 commits intolndk-org:masterfrom
vincenzopalazzo:claude/hardcore-mclaren
Open

fix: reject offers with offer_amount=0 per BOLT 12#253
vincenzopalazzo wants to merge 3 commits intolndk-org:masterfrom
vincenzopalazzo:claude/hardcore-mclaren

Conversation

@vincenzopalazzo
Copy link
Copy Markdown

Summary

  • Enforce BOLT 12 spec clarification from bolts #1316: offer_amount must be > 0 when present, readers must reject offers with offer_amount=0
  • Fix reader side: validate_amount() now rejects amount=0 unconditionally instead of treating it as "no amount"
  • Fix writer side: CreateOfferRequest without an amount now omits offer_amount entirely instead of writing offer_amount=0 via unwrap_or(0)
  • Update rust-lightning dependency to include cherry-pick of lightningdevkit/rust-lightning#4487 which rejects offer_amount=0 at the TLV parsing level

Context

Backport reference: lightningdevkit/rust-lightning#4324 (comment)

The LNDK fork of rust-lightning (based on 0.1.3) did not include the offer_amount=0 fix. Additionally, LNDK's own gRPC handler converted None amounts to 0, producing spec-noncompliant offers that other implementations would reject.

Test plan

  • test_reject_offer_with_zero_amount: verifies OfferBuilder normalizes amount_msats(0) to None, and validate_amount rejects Amount::Bitcoin { amount_msats: 0 } both with and without user-provided amounts
  • test_create_offer_no_amount: verifies offer created without an amount has offer.amount() == None (omitted from TLV)
  • All 82 existing tests pass

🤖 Generated with Claude Code

Per the spec clarification in lightning/bolts#1316:
- Writers MUST set offer_amount greater than zero when present
- Readers MUST NOT respond to offers where offer_amount is zero

Reader side (parse.rs):
  validate_amount() now rejects Amount::Bitcoin { amount_msats: 0 }
  unconditionally at the top of the match arm, before checking
  user-provided amounts. Previously it treated amount=0 as "no amount
  set" and allowed payment if the user provided an amount.

Writer side (server.rs, handler.rs, lnd_requests.rs):
  The gRPC CreateOfferRequest previously did `unwrap_or(0)` on the
  optional amount field, causing offers created without an amount to
  write offer_amount=0 into the TLV stream. Changed amount_msats to
  Option<u64> through the full chain (CreateOfferParams ->
  CreateOfferArgs -> create_offer), so offer_amount is omitted entirely
  when no amount is specified.

Dependency (Cargo.toml):
  Updated rust-lightning to include the cherry-pick of
  lightningdevkit/rust-lightning#4487 which normalizes amount_msats(0)
  to None in the OfferBuilder and rejects offer_amount=0 during TLV
  deserialization. Added [patch] section to ensure ldk-sample uses the
  same fork, avoiding duplicate crate versions.

Previous test failure (before fix):

  ---- offers::parse::tests::test_reject_offer_with_zero_amount stdout ----
  thread 'offers::parse::tests::test_reject_offer_with_zero_amount'
  panicked at src/offers/parse.rs:140:9:
  Offers with amount=0 must be rejected per BOLT 12 spec (bolts #1316)

  test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured;
  80 filtered out

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 6.88%. Comparing base (971f69f) to head (a0a9078).

Additional details and impacted files
@@          Coverage Diff           @@
##           master    #253   +/-   ##
======================================
  Coverage    6.88%   6.88%           
======================================
  Files           1       1           
  Lines         218     218           
======================================
  Hits           15      15           
  Misses        203     203           

☔ 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.

vincenzopalazzo and others added 2 commits March 20, 2026 11:50
…tall

The amount_msats field on CreateOfferParams was changed to Option<u64>
but integration tests were not updated. Also fix security_audit CI by
adding --locked to cargo install to avoid MSRV conflicts with transitive
dependencies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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