Skip to content

Add Cashu charge method (draft-cashu-charge-01)#1

Open
orveth wants to merge 17 commits into
mainfrom
add-cashu-charge-method
Open

Add Cashu charge method (draft-cashu-charge-01)#1
orveth wants to merge 17 commits into
mainfrom
add-cashu-charge-method

Conversation

@orveth

@orveth orveth commented Jun 8, 2026

Copy link
Copy Markdown
Owner

Adds specs/methods/cashu/draft-cashu-charge-01.md — the Cashu method binding for the MPP charge intent (HTTP 402 payment authentication settled with Cashu ecash).

Covers:

  • Request shape { amount, currency, methodDetails: { request, mints } }
  • JCS / RFC 8785 canonicalization of the request object
  • Payment-Receipt response header on success
  • Challenge expires enforcement
  • RFC 9457 application/problem+json error responses

Internal review on the orveth fork before any upstream (tempoxyz) submission. Author / IANA Contact frontmatter still TODO.

forge-worker and others added 2 commits June 8, 2026 14:20
Backtick `pop_<ts>` placeholder in prose (line ~154) so kramdown-rfc does not emit an illegal raw <ts> element that breaks xml2rfc. Author/IANA Contact frontmatter left as TODO pending the human.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Map the Verification Procedure to the charge intent's five server responsibilities; explicitly discharge amount-match (net-settled) and recipient-match (implicit: the server is the redeeming mint). - Fix keyset id version labels: v1/v2 -> version-00 / version-01 per NUT-02 (byte lengths were already correct). - Add a Client-Side Verification security subsection (sibling parity). - Reword the Abstract for the holder-pre-funds fee model. - Classify a keyset-list fetch failure as mint-unavailable (503), distinct from an unresolvable short keyset id (verification-failed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Per gudnuf's PR review + a sibling/intent/NUT research pass: remove all Proof-of-Power / pop_ts references (unit is now service-chosen, external asset OR service-internal); drop cross-method analogies (BOLT11, lightning) and define artifacts intrinsically; DLEQ - drop input-proof DLEQ entirely (the swap is the authoritative check), keep the swap-output DLEQ MUST; rename problem-type payment-insufficient -> amount-mismatch (covers over+under); trim Fees hard (point to the NUTs, lead with no-change), remove the fee_reserve disclaimer, trim the NUT-24 relationship; remove the Future Work section; clarify currency (the unit string is the currency, sat/msat are distinct), keep the encoded creqA with justification, clarify the DoS proof bound is server-internal; reframe the DLEQ definition + privacy wording to canonical Cashu language (blind sigs unlink redemption from issuance; the mint still sees the redemption); soften the 503 wording. Net -33 lines. Coupled follow-up: the same slug rename in the pops MPP adapter.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
orveth and others added 5 commits June 9, 2026 09:48
Split several long sentences, un-strand displaced clauses, and drop two redundant restatements. Readability only — no change to any normative requirement, technical claim, number, slug, or reference.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Relationship to NUT-24 section covers it; the abstract states what the method is.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Subtract the repeated swap-fee formula (now stated once, in #fees) and two duplicated rationales; reduce the NUT-24 section to a one-liner anchored on NUT-18. Add requirement-level money-safety (byte-for-byte challenge echo for the stateless HMAC, idempotency-key reuse rejected, redemption committed as one durable state transition). Cite the NUT-06 /v1/info pubkey for mint identity (SHOULD, URL fallback) instead of the per-keyset NUT-01 keys, and note the HMAC key is a server secret.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse the exact-amount/pre-fund rule and the challenge-binding and fee-determinism points to one statement each; one-sentence the opaque-embedded-strings note; drop two request-field asides and the redundant proof-level-replay paragraph. Add a Mint terminology entry. All subtractive — no MUST/SHOULD, value, error mapping, or implementation detail removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fresh-eyes review (client/server/adversary/editor) + owner walk:
crash-recovery invariant restored; post-swap DLEQ = mint-trust
incident, not payment failure; indeterminate swaps resolved via
NUT-09/NUT-07; lost-response and payment-expired client guidance;
swap-rejection else-branch; expires REQUIRED under stateless;
problem types reworked to framework generics (cashu/ keeps
amount-mismatch, mint-unavailable); resolved-keyset unit check;
per-proof fee summation; exhaustive URL canonicalization;
JCS-valid worked example; security-section dedup.
Adversarially verified; one contradiction caught and fixed
pre-commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@gudnuf gudnuf left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

take my questions and feedback and lets discuss what you think is the best approach by you replying to each comment where questions are asked or things are unclear. Also lets remove all the emdashes

Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
- abstract: drop fee detail
- intro: drop unit-independence paragraph (currency def + example carry it)
- drop NUT-26/bech32m acceptance; creqA only
- fold step 3 into step 2 (TokenV4 makes it structural); renumber to 9 steps
- step 9: swap at configured URL of the matched entry; drop token-URL clause
- delete spending-conditions section; witness rationale inlined in step 6
- collapse client-split paragraph to client guidance
- delete input-DLEQ paragraph and security-fees section
- mint-trust: drop DNS/TLS-takeover and pubkey prose
- transport: drop P2PK forward-path sentence
- purge all em-dashes

Held for owner decision: payload.cashu_token casing; overpayment
acceptance + cashu-specific error-type removal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@orveth

orveth commented Jun 9, 2026

Copy link
Copy Markdown
Owner Author

Round 3 applied and pushed as e4819d0: every flat directive is in (abstract trim, intro paragraph, NUT-26 drop, step-3 fold + renumber to 9 steps, token-URL clause, spending-conditions section, client-split collapse, input-DLEQ paragraph, security-fees section, pubkey and P2PK material), every em-dash is gone (en-dashes too), and each of the 35 comments has an inline reply, including resolution pointers for the 6/08 batch.

Two design forks await your call before the conformance branch continues, recommendations inline on the respective threads: (1) payload.cashu_token casing (my pick: rename to payload.token), and (2) accept overpayment + drop both cashu-specific problem types (my pick: yes to both, with the 503 consumed-vs-unknown prose preserved verbatim). Both change the wire the code branch just built, so they settle first and apply to spec + code in one pass.

- rename payload.cashu_token -> payload.token (all prose, schema,
  examples; Authorization example blob re-encoded, JCS order kept)
- accept token value >= amount + swap_fee; excess retained, server
  still makes no change; client SHOULD present the exact total
- underpayment maps to the framework's payment-insufficient;
  cashu/amount-mismatch removed
- cashu/mint-unavailable type removed; mint unreachability is plain
  HTTP 503 + Retry-After with the consumed-vs-unknown rules intact
- zero method-specific problem types remain
- fees: note held-proof coin selection may not land exact and then
  overpays minimally (cashu-ts behavior)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
orveth and others added 2 commits June 10, 2026 00:36
Per NUT-02 (cashu 0.16 reference): version-00 ids are complete and
round-trip locally; only version-01 ids have prefix short forms that
require resolution against the mint's keyset list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@gudnuf gudnuf left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All right, here's some more review comments to discuss, and generally my thinking around this is based on first principles thinking where like I would rather delete as much as possible and not have stupid things in there that don't need to be in there and then only after we've kind of validated the idea do we start adding stuff based on review feedback and stuff? So based on the comments I left and everything else in the spec, let's think about What can be removed, potentially any ambiguities that need to be resolved or things that aren't clear And then also like things like nut ten and DLEQ, I feel like maybe we're adding too much complexity by saying that clients should validate the DLEQ and then also it would be much simpler if we just let any n spending condition through. So let's discuss this in discord before making any changes.

Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
Comment thread specs/methods/cashu/draft-cashu-charge-01.md Outdated
… condense

- Server MAY advertise a nut10 spending condition it can satisfy;
  payer locks to it, server supplies the witness at swap. Bearer-only
  step 6 deleted; safety rides NUT-03 swap atomicity, now stated.
- All swap rejections map to verification-failed with the cause in
  the problem detail; payment-expired is single-cause (stale
  challenge, re-present the same token).
- DLEQ reduced to one SHOULD at the swap step; terminology entry,
  security-dleq section, and orphaned NUT-06 reference deleted.
- Transport security compressed to three sentences.
- single_use MUST be true; creqA payment id MUST equal the
  challenge id; clients reject violations.
- Fees condensed; userinfo line and no-own-types sentence deleted;
  digest+opaque and service-defined-unit examples cut (siblings
  carry neither). Steps renumbered 1-8.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@orveth

orveth commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

Round 5 applied in c938991 after the Discord walk-through: advertised nut10 spending conditions allowed (bearer-only check deleted, NUT-03 swap atomicity stated as the safety basis), all swap rejections unified under verification-failed with the cause in the problem detail, payment-expired single-cause, DLEQ down to one sentence, transport security to three, fees condensed, single_use pinned true, payment id pinned to the challenge id, userinfo and no-own-types lines deleted, digest+opaque and service-defined-unit examples cut (no sibling method carries either). Net: 1102 to 1011 lines, MUST count 61, verification steps renumbered 1-8, references and anchors rebalanced, zero em-dashes. Refund-path guidance intentionally omitted pending outside feedback.

The i==id rule was unconstructible under stateless binding: the
challenge id is the HMAC over the request bytes, and the creqA
carrying i lives inside those bytes, so no embedded value can equal
the computed id. Per review: i SHOULD be omitted; the challenge id
identifies the payment. The client-side id-match rejection goes
with it. Bearer-ness is now conditioned on the absence of a
spending condition, so four unconditional bearer claims lose the
word; the general protocol description in the introduction keeps it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@orveth orveth force-pushed the add-cashu-charge-method branch from 059fd11 to f3183d2 Compare June 10, 2026 19:08
orveth and others added 3 commits June 10, 2026 18:45
The Privacy section already carries the normative rule (MUST NOT log
token secrets; MUST use the token hash as the receipt reference); the
receipt-field sentence restated it. Reference, do not restate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drop 'Implementations MUST NOT log token secrets' (unenforceable
implementation hygiene, no client/server-protocol bearing; the
receipt-reference-is-the-hash rule already lives in Receipt
Generation). Reframe the id-HMAC-key line to its protocol
consequence (compromise forges challenges, defeats binding) without
the MUST-NOT-be-logged directive. Drop the 'carries no proof-count
field' parenthetical aside.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Re-adds 'Implementations MUST NOT log token secrets, and MUST use
the token hash as a receipt reference', consistent with the
lightning charge spec's equivalent. The id-HMAC-key line stays
reframed (no lightning precedent for it).

Co-Authored-By: Claude Fable 5 <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.

2 participants