Support mint-backed L402 receiving with explicit payer preimage requirements #20

Closed
opened 2026-10-09 14:47:46 +00:00 by thesimplekid · 0 comments
Owner

Geata can offer L402 invoices backed by a trusted Cashu mint, allowing an operator to receive payments as ecash without running an LDK node. Satsettle's public LightningOptions.receiver currently requires LdkConfig, so replacing Geata's payment implementation would lose this receiver option.

Add a mint-backed receiver for automatic L402 settlement. This is distinct from direct Cashu settlement to a trusted mint: the payer receives a Lightning invoice and authenticates with an L402 credential.

Expected flow:

  1. Create a mint quote at the configured trusted mint and durably associate its quote ID and invoice with the intent.
  2. Issue an L402 macaroon bound to that invoice's payment hash and the request context.
  3. Accept the payer's macaroon:preimage credential and verify its binding, restrictions, and preimage.
  4. Collect and durably store the ecash from the associated mint quote before recording a successful receipt.
  5. Recover interrupted issuance/collection across cancellation and restart without creating replacement payments or crediting the same payment twice.

Preimage limitation

The receiving mint does not need to expose the preimage to satsettle: standard L402 gets it from the payer, whose Lightning wallet obtains it when paying the invoice.

A payer using a Cashu mint to melt tokens may not receive a preimage from that mint. In that case payment can succeed while the payer cannot complete L402 authentication. Document this limitation explicitly; do not treat a mint's PAID response as a replacement for the payer's L402 credential. Those Cashu clients should use satsettle's direct Cashu submission/settlement flow, which confirms settlement at the destination without requiring a payer-supplied preimage. Changing the receiver to LDK does not fix this payer-side limitation.

Acceptance criteria

  • Public configuration supports a trusted Cashu mint as an automatic L402 receiver, alongside LDK.
  • Quote IDs remain private; quote/invoice/intent associations and wallet state survive restarts.
  • A valid preimage alone does not produce a receipt before ecash issuance is verified and durably stored.
  • Tests cover successful collection, wrong preimages and request bindings, repeated submissions, interrupted collection, and restart recovery without duplicate credit.
  • Tests cover a paid quote without a valid payer credential: recovery can safeguard funds, but must not authorize an unauthenticated L402 request.
  • Unsupported manual capture is rejected before creating a quote; this receiver does not provide application-controlled hold invoices.
  • Documentation explains the payer-side preimage requirement and points Cashu payers without preimage support to direct Cashu settlement.

Reference implementation: Geata's mint-backed invoice and collection flow and L402 verification. Geata's single-use request admission remains application-owned; satsettle receipts should retain their idempotent retry behavior.

Geata can offer L402 invoices backed by a trusted Cashu mint, allowing an operator to receive payments as ecash without running an LDK node. Satsettle's public `LightningOptions.receiver` currently requires `LdkConfig`, so replacing Geata's payment implementation would lose this receiver option. Add a mint-backed receiver for automatic L402 settlement. This is distinct from direct Cashu settlement to a trusted mint: the payer receives a Lightning invoice and authenticates with an L402 credential. Expected flow: 1. Create a mint quote at the configured trusted mint and durably associate its quote ID and invoice with the intent. 2. Issue an L402 macaroon bound to that invoice's payment hash and the request context. 3. Accept the payer's `macaroon:preimage` credential and verify its binding, restrictions, and preimage. 4. Collect and durably store the ecash from the associated mint quote before recording a successful receipt. 5. Recover interrupted issuance/collection across cancellation and restart without creating replacement payments or crediting the same payment twice. ### Preimage limitation The receiving mint does not need to expose the preimage to satsettle: standard L402 gets it from the payer, whose Lightning wallet obtains it when paying the invoice. A payer using a Cashu mint to melt tokens may not receive a preimage from that mint. In that case payment can succeed while the payer cannot complete L402 authentication. Document this limitation explicitly; do not treat a mint's `PAID` response as a replacement for the payer's L402 credential. Those Cashu clients should use satsettle's direct Cashu submission/settlement flow, which confirms settlement at the destination without requiring a payer-supplied preimage. Changing the receiver to LDK does not fix this payer-side limitation. ### Acceptance criteria - Public configuration supports a trusted Cashu mint as an automatic L402 receiver, alongside LDK. - Quote IDs remain private; quote/invoice/intent associations and wallet state survive restarts. - A valid preimage alone does not produce a receipt before ecash issuance is verified and durably stored. - Tests cover successful collection, wrong preimages and request bindings, repeated submissions, interrupted collection, and restart recovery without duplicate credit. - Tests cover a paid quote without a valid payer credential: recovery can safeguard funds, but must not authorize an unauthenticated L402 request. - Unsupported manual capture is rejected before creating a quote; this receiver does not provide application-controlled hold invoices. - Documentation explains the payer-side preimage requirement and points Cashu payers without preimage support to direct Cashu settlement. Reference implementation: [Geata's mint-backed invoice and collection flow](https://git.cashu.dev/thesimplekid/geata/src/commit/3d85aaee/crates/geata/src/payments/lightning/cashu.rs) and [L402 verification](https://git.cashu.dev/thesimplekid/geata/src/commit/3d85aaee/crates/geata/src/payments/lightning/l402.rs). Geata's single-use request admission remains application-owned; satsettle receipts should retain their idempotent retry behavior.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
thesimplekid/satsettle#20
No description provided.