Conversation
This commit introduces a new specification, NUT-XX, for batched mint operations. It allows wallets to mint multiple proofs in a single transaction, improving efficiency.
- specify all quotes must share same payment method and currency - expand nut-20 signature section with detailed structure and validation - clarify signature array format and per-quote mapping - add signature message construction specification - document atomicity requirement for signature validation failures - add comprehensive mint responsibilities section - update dependencies to include nut-20
- add validation requirements for empty arrays and duplicate quotes - clarify batch quote status response format per payment method - change batch mint endpoint path to include /batch suffix - add comprehensive request validation section - add error codes table and structured error response format - restructure nut-20 signature support section for clarity - add atomic processing requirement to mint responsibilities - add implementation notes for batch size limits and bolt12 support - add note on spending conditions compatibility - expand error handling documentation with examples
|
This PR replaces #273 |
xx.md
Outdated
|
|
||
| ## 1. Checking Quote Status | ||
|
|
||
| Before minting, the wallet must verify that each mint quote has been paid. |
There was a problem hiding this comment.
I don't think this should be a must, a wallet could know the states of the quotes by ws update why must it check again?
There was a problem hiding this comment.
Should be SHOULD. I think its good to mention that this endpoint is not supposed to be a batch-check
There was a problem hiding this comment.
this endpoint is not supposed to be a batch-check
What do you mean? I thought the purpose was to ensure that a batch was ready to mint before attempting to mint it.
| Unknown quote: | ||
| ```json | ||
| { | ||
| "code": "UNKNOWN_QUOTE", | ||
| "detail": "Quote 'abc-123' does not exist", | ||
| "quote": "abc-123" | ||
| } | ||
| ``` | ||
|
|
||
| Quote not paid: | ||
| ```json | ||
| { | ||
| "code": "QUOTE_NOT_PAID", | ||
| "detail": "Quote 'xyz-789' is not in PAID state", | ||
| "quote": "xyz-789" | ||
| } | ||
| ``` |
There was a problem hiding this comment.
What if multiple quotes are unknown or unpaid? I think it maybe best to not extend out error response and leave it how it is defined in nut00 without a quote id and its up to the wallet to figure it out.
There was a problem hiding this comment.
My thinking was that debugging one failing quote ID from a batch of 100 could be a huge pain in the ass. Best effort error reporting could help in some cases. I can see an argument for improving the batch check endpoint for this purpose instead of attempting detailed error messages in the mint endpoint. If you think we shouldn't even try, you're gonna have to convince me.
There was a problem hiding this comment.
as discussed in the meeting, we should remove quote ID as a field but still allow quote IDs in the description for human consumption
| ``` | ||
| msg_to_sign = quote_id[i] || B_0 || B_1 || ... || B_(n-1) | ||
| ``` | ||
|
|
||
| Where: | ||
| - `quote_id[i]` is the UTF-8 encoded quote ID at index `i` | ||
| - `B_0 ... B_(n-1)` are **all blinded messages** from the `outputs` array (regardless of amount splitting) |
There was a problem hiding this comment.
I don't think we need to redefine it reference the existing nut.
We should add test vectors for this.
There was a problem hiding this comment.
Am I missing something here? I agree that there is no need to re-define it
There was a problem hiding this comment.
@Egge21M the outputs are for all quotes combined, but this should be an addition to NUT-20 and as @thesimplekid says, there should be test vectors.
xx.md
Outdated
| ### BOLT12 Support | ||
|
|
||
| **Partial minting support:** | ||
|
|
||
| Mints MAY support partial minting for BOLT12 quotes, where `amount_issued` can be less than `amount_paid`. This allows: | ||
| - **Multiple batch operations**: Same BOLT12 quote can be used in multiple mint requests | ||
| - **Incremental minting**: Each batch mint increments `amount_issued` by the minted amount | ||
| - **State tracking**: Quote remains in PAID state until `amount_issued >= amount_paid` | ||
|
|
||
| The mint tracks `amount_paid` and `amount_issued` separately for this purpose. |
There was a problem hiding this comment.
I think we can remove this as its defined in the bolt12 nut.
| ``` | ||
| msg_to_sign = quote_id[i] || B_0 || B_1 || ... || B_(n-1) | ||
| ``` | ||
|
|
||
| Where: | ||
| - `quote_id[i]` is the UTF-8 encoded quote ID at index `i` | ||
| - `B_0 ... B_(n-1)` are **all blinded messages** from the `outputs` array (regardless of amount splitting) |
There was a problem hiding this comment.
@Egge21M the outputs are for all quotes combined, but this should be an addition to NUT-20 and as @thesimplekid says, there should be test vectors.
|
I think the changes to the mint quote signing process should be an addition to NUT-20 under "Multi-Quote Signature" |
|
Why did we choose to invent a whole new spec for minting, instead of just generalizing what we already have n-way? For example: curl -X POST https://mint.host:3338/v1/mint/bolt11/batch -H "Content-Type: application/json" -d \
'[
{
"quote": "DSGLX9kevM...",
"outputs": [
{
"amount": 8,
"id": "009a1f293253e41e",
"B_": "035015e6d7ade60ba8426cefaf1832bbd27257636e44a76b922d78e79b47cb689d"
},
{
"amount": 2,
"id": "009a1f293253e41e",
"B_": "0288d7649652d0a83fc9c966c969fb217f15904431e61a44b14999fabc1b5d9ac6"
}
]
},
...
]'This way we don't introduce unforeseen bugs and we don't have to amend NUT-20. {
"succeeded": [PostMintResponse],
"failed": [PostMintFailure],
} |
Co-authored-by: tsk <tsk@thesimplekid.com> Co-authored-by: lollerfirst <43107113+lollerfirst@users.noreply.github.com>
|
@lollerfirst as discussed in a recent meeting, the wallet can specify the outputs they want to mint so this precludes the possibility of partial success. Atomic batch mint transactions also massively reduce complexity around partial success. |
- wallet SHOULD verify paid quotes, not must - remove redundant requirements and unnecessary statements - deduplicate request validation and mint responsibilities - remove http status from error codes
| "quotes": [ "quote_id_1", "quote_id_2", … ], | ||
| "quote_amounts": [ 50, 50 ], | ||
| "outputs": [ BlindedMessage_1, BlindedMessage_2, … ], | ||
| "signatures": [signature_1, signature_2, ... ] |
There was a problem hiding this comment.
what if some mint quotes are not locked? maybe: for a quote_id_n that does not require a NUT-20 lock, the signature at the same index should be null.
callebtc
left a comment
There was a problem hiding this comment.
good PR but text still reads AI-sloppy, could probably be compressed to 50% dense human spec.
| - **All quotes MUST be from the same payment method** (indicated by `{method}` in the URL path). | ||
| - **All quotes MUST use the same currency unit**. | ||
| - **quote_amounts**: array of expected mint amounts per quote, in the same order as `quote`. | ||
| - REQUIRED for bolt12 batches; OPTIONAL for bolt11. |
There was a problem hiding this comment.
optional quote_amounts and signatures should be annotated in the JSON itself
| { | ||
| "quotes": [ "quote_id_1", "quote_id_2", … ], | ||
| "quote_amounts": [ 50, 50 ], | ||
| "outputs": [ BlindedMessage_1, BlindedMessage_2, … ], | ||
| "signatures": [signature_1, signature_2, ... ] |
There was a problem hiding this comment.
should use the same JSON annotation format that we use in other specs
| - For bolt11, each entry MUST equal the quoted amount. For bolt12, each entry MUST NOT exceed the quote's remaining mintable amount. In all cases, the sum of `quote_amounts` MUST equal the sum of `outputs`. | ||
| - **outputs**: an array of blinded messages (see [NUT-00][00]). | ||
| - The total value represented by all blinded messages must equal the sum of all quote amounts. | ||
| - **signatures**: array of signatures for NUT-20 locked quotes. See [NUT-20 Support][nut-20-support] |
| - Array MUST NOT be empty | ||
| - All quote IDs MUST be unique (no duplicates) | ||
| - **All quotes MUST be from the same payment method** (indicated by `{method}` in the URL path). | ||
| - **All quotes MUST use the same currency unit**. |
There was a problem hiding this comment.
redundant here, there's a validation section below
| 4. **Payment method consistency**: All quotes MUST have the same payment method, matching `{method}` in the URL path | ||
| 5. **Currency unit consistency**: All quotes MUST use the same currency unit | ||
| 6. **Quote state**: All quotes MUST be in PAID state (or have mintable amount for BOLT12) | ||
| 7. **Amount balance**: The sum of output amounts MUST equal the sum of `quote_amounts` (bolt11) or MUST NOT exceed it (bolt12) |
There was a problem hiding this comment.
amounts should probably be ignored for bolt11?
| | Signature on unlocked quote | `UNEXPECTED_SIGNATURE` | | ||
| | Missing required signature | `SIGNATURE_MISSING` | | ||
|
|
||
| ### Error Response Format |
There was a problem hiding this comment.
this seems too excessive, would remove and use a simpler approach
| ### Signature Structure | ||
|
|
||
| **Array structure:** | ||
| - The `signature` field is an array with length equal to `quote.length` (one entry per quote) |
There was a problem hiding this comment.
it's called signatures (plural) above
|
|
||
| **Per-quote signatures:** | ||
| - **Locked quotes** (with `pubkey`): `signature[i]` contains the signature string | ||
| - **Unlocked quotes**: `signature[i]` is `null` |
There was a problem hiding this comment.
I suggested null above too, should be defined above.
|
|
||
| **Array structure:** | ||
| - The `signature` field is an array with length equal to `quote.length` (one entry per quote) | ||
| - `signature[i]` corresponds to `quote[i]` |
| - Total: 225 sats across 3 outputs | ||
| - Both signatures cover all 3 outputs to prevent output tampering | ||
|
|
||
| ## Mint Responsibilities |
There was a problem hiding this comment.
this section is not needed. atomicity should be mentioned very briefly in the first paragraph.
|
@vnprc are you still actively working on this? Otherwise I would offer to take over again, so that we can get this wrapped soonish |
|
@vnprc, you have been contacted by multiple people. please get in touch personally or through some other channel if you want to talk about your situation. |
|
closed for #333 where work continues |
|
closed for #333 where work continues |
This document specifies NUT-XX: Batched Mint for the Cashu ecash protocol. It defines how wallets can mint multiple ecash proofs in a single atomic operation instead of individual requests.
Key components:
The spec emphasizes atomic processing (all-or-nothing), detailed error reporting, and interoperability with existing Cashu specs (NUT-04, NUT-20, NUT-11, NUT-14, NUT-25).