Add Cashu charge method (draft-cashu-charge-01)#1
Conversation
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>
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>
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
left a comment
There was a problem hiding this comment.
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
- 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>
|
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>
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
left a comment
There was a problem hiding this comment.
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.
… 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>
|
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>
059fd11 to
f3183d2
Compare
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>
Adds
specs/methods/cashu/draft-cashu-charge-01.md— the Cashu method binding for the MPPchargeintent (HTTP 402 payment authentication settled with Cashu ecash).Covers:
{ amount, currency, methodDetails: { request, mints } }requestobjectPayment-Receiptresponse header on successexpiresenforcementapplication/problem+jsonerror responsesInternal review on the orveth fork before any upstream (tempoxyz) submission. Author / IANA Contact frontmatter still
TODO.