Skip to content

NUT-XX: Transactions - #445

Draft
robwoodgate wants to merge 3 commits into
taproot-secretsfrom
nut-transactions
Draft

robwoodgate wants to merge 3 commits into
taproot-secretsfrom
nut-transactions

Conversation

@robwoodgate

@robwoodgate robwoodgate commented Sep 15, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #443 (base taproot-secrets), so the diff is this NUT, a NUT-00 note and one test vector.

Summary

Swap, mint and melt are fixed shapes of the nutroot transaction (#443). POST /v1/transaction takes any mix in one atomic request: proofs and paid mint quotes in, blinded messages and a melt quote out. A wallet can pay an invoice straight from a paid mint quote, or mint and consolidate in one step.

  • Change stays blinded, as on a NUT-05 melt.
  • One melt quote per transaction for now. Several need defined partial outcomes, so that waits until someone wants it.

Implementations

Ticked once each matches this revision.

@github-project-automation github-project-automation Bot moved this to Backlog in nuts Sep 15, 2026
@robwoodgate robwoodgate self-assigned this Sep 15, 2026
@robwoodgate
robwoodgate added this pull request to stack #446 September 15, 2026 18:38
@robwoodgate
robwoodgate force-pushed the nut-transactions branch 2 times, most recently from ee33f1e to ec53004 Compare September 21, 2026 18:36
@robwoodgate
robwoodgate force-pushed the nut-transactions branch 2 times, most recently from 5f737e9 to daaf699 Compare September 25, 2026 19:13
@robwoodgate
robwoodgate marked this pull request as draft September 26, 2026 09:28
@robwoodgate
robwoodgate force-pushed the nut-transactions branch 2 times, most recently from be636a7 to 2178ba5 Compare September 26, 2026 20:27
@robwoodgate
robwoodgate marked this pull request as ready for review September 26, 2026 20:50
@robwoodgate
robwoodgate force-pushed the nut-transactions branch 2 times, most recently from f3b5d83 to cd721b6 Compare September 28, 2026 15:50
@robwoodgate
robwoodgate force-pushed the nut-transactions branch 4 times, most recently from 9107781 to c2cf25d Compare October 12, 2026 15:20
robwoodgate added a commit to robwoodgate/cdk that referenced this pull request Oct 12, 2026
Add POST /v1/transaction and GET /v1/transaction/{digest}: proofs and
paid mint quotes in; blinded messages, one melt quote and a change quote
out, per cashubtc/nuts#445.

A transaction without a melt settles in one database transaction. One
with a melt runs the existing melt saga: quote inputs are issued in the
setup transaction and reversed on rollback, and the shared finalization
path settles the record instead of signing blank change. Change is the
excess less the fee paid, capped at the reserve, so it is never
negative. A melt with blinded outputs must name a change_pubkey; if the
outputs' keyset is inactivated during the payment they are not signed
and their amount goes to the change quote.

Change quotes are mint quotes with method "change", paid at creation,
served by the existing per-method mint routes. Quote inputs may draw a
quote in parts. v3 mint quote inputs now commit the amount issued
(NUT-10) in both the mint and the wallet. The shared nutroot vectors
file is added and its transcript vectors pinned.
@robwoodgate
robwoodgate force-pushed the nut-transactions branch 5 times, most recently from efbfd67 to ed6c072 Compare October 13, 2026 13:47
@robwoodgate

Copy link
Copy Markdown
Collaborator Author

Since 8 October

  • Change quote ids derive from an id_preimage the wallet supplies, or, when it is omitted, from the transaction's inputs (new vector).
  • With a melt, the melt quote is the transaction's record; the separate record and its route are gone.
  • A pending input quote refuses other draws (20005).
  • NUT-17 change_mint_quote kind.

@robwoodgate
robwoodgate marked this pull request as draft October 19, 2026 19:13
@robwoodgate
robwoodgate force-pushed the nut-transactions branch 3 times, most recently from 1c05701 to 46fc289 Compare October 20, 2026 18:38
robwoodgate added a commit to cashubtc/cashu-ts that referenced this pull request Oct 20, 2026
cashubtc/nuts#445 has neither: transactions carry proofs and mint
quote inputs in, blinded outputs and one melt out. The rotation lock
key, derived quote ids, txout quotes and error 20010 go with them.

A melt's outputs are always signed under the keyset the request named,
so a PAID melt that signs none of them now throws with the restore
hint. The vectors gain mint_quote_to_melt, matching the spec.
robwoodgate added a commit to robwoodgate/cdk that referenced this pull request Oct 20, 2026
POST /v1/transaction takes proofs and paid mint quotes in, blinded
outputs and one melt out, in one request (cashubtc/nuts#445). Inputs
equal outputs exactly; a melt returns its unspent fee reserve in NUT-08
blank outputs and settles through its melt quote.

Quote inputs commit the quote's amount_issued, may be drawn in part,
and price at popcount(amount) * quote_input_fee_ppk inside NUT-02's
single rounding. Outputs beside a melt need a keyset that outlives the
melt quote. Responses are cached (NUT-19).
robwoodgate added a commit to robwoodgate/cdk that referenced this pull request Oct 20, 2026
POST /v1/transaction takes proofs and paid mint quotes in, blinded
outputs and one melt out, in one request (cashubtc/nuts#445). Inputs
equal outputs exactly; a melt returns its unspent fee reserve in NUT-08
blank outputs and settles through its melt quote.

Quote inputs commit the quote's amount_issued, may be drawn in part,
and price at popcount(amount) * quote_input_fee_ppk inside NUT-02's
single rounding. Outputs beside a melt need a keyset that outlives the
melt quote. Responses are cached (NUT-19).
robwoodgate added a commit to robwoodgate/nutshell that referenced this pull request Oct 20, 2026
POST /v1/transaction takes proofs and paid mint quotes in, blinded
outputs and one melt out, in one request (cashubtc/nuts#445). Inputs
equal outputs exactly; a melt returns its unspent fee reserve in NUT-08
blank outputs and settles through its melt quote.

Quote inputs commit the quote's amount_issued, may be drawn in part,
and price at popcount(amount) * quote_input_fee_ppk inside NUT-02's
single rounding (MINT_QUOTE_INPUT_FEE_PPK, defaulting to the keyset
input fee). Outputs beside a melt need a keyset that outlives the melt
quote.
@robwoodgate
robwoodgate force-pushed the nut-transactions branch 2 times, most recently from 3b49416 to ac321e3 Compare October 25, 2026 20:23
A single endpoint, POST /v1/transaction, carries any NUT-00
transaction: proofs and paid mint quotes in; blinded messages and a
melt quote out.
Link NUT-00's transaction and signing rules instead of restating
them, and drop explanations and recovery guidance that change no
bytes or accept/reject.
Follows NUT-04/29: one keyset per request is no longer required, so
each blank output takes change in its own keyset's amounts.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs review new nut A new protocol NUT

Projects

Status: Needs Review

Development

Successfully merging this pull request may close these issues.

4 participants