Skip to content

gl-client/gl-sdk: Harden LNURL-pay against real-world services#702

Merged
cdecker merged 1 commit into2026w15-lnurlfrom
ave-lnurl-fixes
Apr 24, 2026
Merged

gl-client/gl-sdk: Harden LNURL-pay against real-world services#702
cdecker merged 1 commit into2026w15-lnurlfrom
ave-lnurl-fixes

Conversation

@angelix
Copy link
Copy Markdown
Contributor

@angelix angelix commented Apr 23, 2026

Gaps surfaced when paying stacker.news exposed several mismatches between the current implementation and what wallets need in practice. Changes align gl-sdk's LNURL-pay surface with the LUD specs and with what Breez SDK does for the convention-level gaps:

  • Parse LUD-06 service errors: callback responses with {"status":"ERROR"} are now recognised and surfaced as LnUrlPayResult::EndpointError with the service's reason, instead of failing JSON deserialization.
  • Add LnUrlPayResult::PayError { payment_hash, reason } so CLN pay-side failures return structured results rather than Error::Rpc.
  • Pre-flight amount/comment validation in gl-sdk::lnurl_pay to reject out-of-bounds requests before any network round-trip.
  • Drop the description_hash == SHA256(metadata) check that rejected compliant-enough services whose metadata embeds per-request data.
  • Skip the empty comment query param in the callback URL when the caller passes None or an empty string.
  • Enforce LUD-09/10 bounds on SuccessAction payloads (Message/Url description ≤ 144, AES description ≤ 144, ciphertext ≤ 4096, IV exactly 24 chars) before any AES decryption.
  • Validate the invoice's BOLT-11 currency prefix against the node's configured network; thread network through Node::with_signer so the check has something to compare against.
  • Validate that a URL success action's domain matches the callback domain, with an opt-out via LnUrlPayRequest.validate_success_action_url (defaults to true).

@cdecker
Copy link
Copy Markdown
Collaborator

cdecker commented Apr 23, 2026

Thanks @angelix, I'm surprised by the fact that the metadata match check is giving issues, then again, why am I surprised that the spec is not being followed? 😉
There is just a missing field in an initializer, and two match statements that are not exhaustive. Should be good to go as soon as it compiles.

@angelix angelix force-pushed the ave-lnurl-fixes branch 2 times, most recently from 83df44e to 5a5a308 Compare April 24, 2026 08:09
Gaps surfaced when paying stacker.news exposed several mismatches
between the current implementation and what wallets need in practice.
Changes align gl-sdk's LNURL-pay surface with the LUD specs and with
what Breez SDK does for the convention-level gaps:

- Parse LUD-06 service errors: callback responses with {"status":"ERROR"}
  are now recognised and surfaced as LnUrlPayResult::EndpointError with
  the service's reason, instead of failing JSON deserialization.
- Add LnUrlPayResult::PayError { payment_hash, reason } so CLN pay-side
  failures return structured results rather than Error::Rpc.
- Pre-flight amount/comment validation in gl-sdk::lnurl_pay to reject
  out-of-bounds requests before any network round-trip.
- Drop the description_hash == SHA256(metadata) check that rejected
  compliant-enough services whose metadata embeds per-request data.
- Skip the empty `comment` query param in the callback URL when the
  caller passes None or an empty string.
- Enforce LUD-09/10 bounds on SuccessAction payloads (Message/Url
  description ≤ 144, AES description ≤ 144, ciphertext ≤ 4096, IV
  exactly 24 chars) before any AES decryption.
- Validate the invoice's BOLT-11 currency prefix against the node's
  configured network; thread `network` through Node::with_signer so
  the check has something to compare against.
- Validate that a URL success action's domain matches the callback
  domain, with an opt-out via LnUrlPayRequest.validate_success_action_url
  (defaults to true).
- Sync the gl-sdk-napi (Node.js bindings) shapes: add
  validate_success_action_url to the NAPI LnUrlPayRequest, add
  LnUrlPayErrorData and the "pay_error" discriminator on LnUrlPayResult,
  wire the new variant through napi_lnurl_pay_result_from_gl.
@cdecker
Copy link
Copy Markdown
Collaborator

cdecker commented Apr 24, 2026

Fixed the error in #701 and rebased on top of it. Merging as soon as green.

@cdecker cdecker merged commit b64558a into 2026w15-lnurl Apr 24, 2026
16 checks passed
@cdecker cdecker deleted the ave-lnurl-fixes branch April 24, 2026 14:37
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.

2 participants