From 41dc819132eb9ae67ce69b8d95f4ecf26b1a6651 Mon Sep 17 00:00:00 2001 From: Egge Date: Wed, 9 Jul 2025 12:41:41 +0200 Subject: [PATCH 1/5] docs: Add NUT-XX for batched minting 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. --- README.md | 2 ++ error_codes.md | 3 +- xx.md | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 xx.md diff --git a/README.md b/README.md index acc0c9c8..1fffece5 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ Wallets and mints `MUST` implement all mandatory specs and `CAN` implement optio | [22][22] | Blind authentication | [Nutshell][py], [cdk-cli] | [Nutshell][py], [cdk-mintd], [nutmix] | | [23][23] | Payment Method: BOLT11 | [Nutshell][py], [cdk-cli] | [Nutshell][py], [cdk-mintd], [nutmix] | | [24][24] | HTTP 402 Payment Required | - | - | +| [XX][xx] | Batched Mint | - | - | #### Wallets: @@ -97,3 +98,4 @@ Wallets and mints `MUST` implement all mandatory specs and `CAN` implement optio [22]: 22.md [23]: 23.md [24]: 24.md +[XX]: xx.md diff --git a/error_codes.md b/error_codes.md index 8ef94754..dd4b7a00 100644 --- a/error_codes.md +++ b/error_codes.md @@ -20,7 +20,7 @@ | 20002 | Tokens have already been issued for quote | [NUT-04][04] | | 20003 | Minting is disabled | [NUT-04][04] | | 20004 | Lightning payment failed | [NUT-05][05] | -| 20005 | Quote is pending | [NUT-04][04], [NUT-05][05] | +| 20005 | Quote is pending | [NUT-04][04], [NUT-05][05], [NUT-XX][xx] | | 20006 | Invoice already paid | [NUT-05][05] | | 20007 | Quote is expired | [NUT-04][04], [NUT-05][05] | | 20008 | Signature for mint request invalid | [NUT-20][20] | @@ -48,3 +48,4 @@ [20]: 20.md [21]: 21.md [22]: 22.md +[XX]: xx.md diff --git a/xx.md b/xx.md new file mode 100644 index 00000000..342a1d6e --- /dev/null +++ b/xx.md @@ -0,0 +1,81 @@ +# NUT-XX: Batched Mint + +`optional` + +`depends on: NUT-04` + +This spec describes how a wallet can mint multiple proofs in one batch operation. + +--- + +## 1. Checking Quote Status + +Before minting, the wallet must verify that each mint quote has been paid. +It does this by sending: + +```http +POST https://mint.host:3338/v1/mint/{method}/check +Content-Type: application/json + +{ + "quote": [ "quote_id_1", "quote_id_2", … ] +} +``` + +- **quote**: an array of quote IDs previously obtained via the [NUT-04 creation process][04-creation]. + +The mint returns a JSON array of quote objects, each containing: + +```json +[ + { + "quote": "quote_id_1", + "request": "payment_request_1", + "unit": "UNIT_NAME" + // …plus any additional fields specific to {method} + }, + { + "quote": "quote_id_2", + "request": "payment_request_2", + "unit": "UNIT_NAME" + // … + } +] +``` + +- **quote**: the original quote ID +- **request**: the payment request string for that quote +- **unit**: the unit type, matching what was requested + +--- + +## 2. Executing the Batched Mint + +Once all quoted payments are confirmed, the wallet mints the tokens by calling: + +```http +POST https://mint.host:3338/v1/mint/{method} +Content-Type: application/json + +{ + "quote": [ "quote_id_1", "quote_id_2", … ], + "outputs": [ BlindedMessage_1, BlindedMessage_2, … ] +} +``` + +- **quote**: an array of quote IDs previously obtained via the [NUT-04 creation process][04-creation]. +- **outputs**: an array of blinded messages (see [NUT-00][00]). + - The total value represented by these blinded messages must equal the sum of the quote amounts. + +The mint responds with: + +```json +{ + "signatures": [ BlindSignature_1, BlindSignature_2, … ] +} +``` + +- **signatures**: blind signatures corresponding to each provided blinded message. + +[00]: 00.md +[04-creation]: 04.md#requesting-a-mint-quote From 00d0c08e1f9e2a2388dbe194a81b926060d8fcd2 Mon Sep 17 00:00:00 2001 From: Egge Date: Sat, 2 Aug 2025 06:35:02 +0200 Subject: [PATCH 2/5] docs: added nut-20 support to xx.md --- xx.md | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/xx.md b/xx.md index 342a1d6e..f558933f 100644 --- a/xx.md +++ b/xx.md @@ -59,15 +59,16 @@ Content-Type: application/json { "quote": [ "quote_id_1", "quote_id_2", … ], - "outputs": [ BlindedMessage_1, BlindedMessage_2, … ] + "outputs": [ BlindedMessage_1, BlindedMessage_2, … ], + "signature": [signature_1, signature_2, ... ] } ``` - **quote**: an array of quote IDs previously obtained via the [NUT-04 creation process][04-creation]. - **outputs**: an array of blinded messages (see [NUT-00][00]). - The total value represented by these blinded messages must equal the sum of the quote amounts. - -The mint responds with: +- signature: The signature for a NUT-20 locked quote. See + The mint responds with: ```json { @@ -77,5 +78,24 @@ The mint responds with: - **signatures**: blind signatures corresponding to each provided blinded message. +## NUT-20 support + +The `signature` field of the request can be used to add matching NUT-20 signatures to a batch mint. Signatures can be mapped to their quotes using both indexes in the request body. As long as there is a single NUT-20 quote in the request this field is mandatory, otherwise it can be fully omitted. + +- Signatures for NUT-20 quotes can be added to the `signature` key of the request. +- Signatures need to be in the same index as the matching quote_id in the `quote` key. +- If a request contains both signed and unsigned quotes, all unsigned quotes need to map to `null` in the `signature` array. +- As soon as there is a single signed quote in the request: `quote.length === signature.length` + +Example: + +```json +{ + "quote": [ "locked_quote_id_1", "quote_id_2", "locked_quote_id_3" ], + "outputs": [ BlindedMessage_1, BlindedMessage_2, ... ], + "signature": [signature_1, null, signature_3 ] +} +``` + [00]: 00.md [04-creation]: 04.md#requesting-a-mint-quote From f71defc7ccb01aa8ec0526bb1f128752ceb807db Mon Sep 17 00:00:00 2001 From: Egge Date: Sat, 2 Aug 2025 06:43:49 +0200 Subject: [PATCH 3/5] docs: clarified uniqueness --- xx.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/xx.md b/xx.md index f558933f..24afdaa9 100644 --- a/xx.md +++ b/xx.md @@ -22,7 +22,7 @@ Content-Type: application/json } ``` -- **quote**: an array of quote IDs previously obtained via the [NUT-04 creation process][04-creation]. +- **quote**: an array of **unique** quote IDs previously obtained via the [NUT-04 creation process][04-creation]. The mint returns a JSON array of quote objects, each containing: @@ -47,6 +47,8 @@ The mint returns a JSON array of quote objects, each containing: - **request**: the payment request string for that quote - **unit**: the unit type, matching what was requested +NOTE: If a `quote_id` is not known by the mint it SHOULD omit it from the response. + --- ## 2. Executing the Batched Mint @@ -64,10 +66,10 @@ Content-Type: application/json } ``` -- **quote**: an array of quote IDs previously obtained via the [NUT-04 creation process][04-creation]. +- **quote**: an array of **unique** quote IDs previously obtained via the [NUT-04 creation process][04-creation]. - **outputs**: an array of blinded messages (see [NUT-00][00]). - The total value represented by these blinded messages must equal the sum of the quote amounts. -- signature: The signature for a NUT-20 locked quote. See +- **signature**: The signature for a NUT-20 locked quote. See [NUT-20 Support][nut-20-support] The mint responds with: ```json @@ -99,3 +101,4 @@ Example: [00]: 00.md [04-creation]: 04.md#requesting-a-mint-quote +[nut-20-support]: #nut-20-support From 648ad0c0d62265cbd30ae92a9f38d329ab14eb39 Mon Sep 17 00:00:00 2001 From: tsk Date: Tue, 18 Nov 2025 10:21:47 +0000 Subject: [PATCH 4/5] Apply suggestion from @vnprc Co-authored-by: vnprc <9425366+vnprc@users.noreply.github.com> --- xx.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xx.md b/xx.md index 24afdaa9..6656c33f 100644 --- a/xx.md +++ b/xx.md @@ -4,7 +4,7 @@ `depends on: NUT-04` -This spec describes how a wallet can mint multiple proofs in one batch operation. +This spec describes how a wallet can mint multiple quotes in one batch operation. --- From ba4543f1daa2020e0f8479497dedaea2b5f00130 Mon Sep 17 00:00:00 2001 From: tsk Date: Tue, 18 Nov 2025 10:22:23 +0000 Subject: [PATCH 5/5] Apply suggestions from code review Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com> --- xx.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xx.md b/xx.md index 6656c33f..dca7f485 100644 --- a/xx.md +++ b/xx.md @@ -18,7 +18,7 @@ POST https://mint.host:3338/v1/mint/{method}/check Content-Type: application/json { - "quote": [ "quote_id_1", "quote_id_2", … ] + "quotes": [ "quote_id_1", "quote_id_2", … ] } ``` @@ -60,7 +60,7 @@ POST https://mint.host:3338/v1/mint/{method} Content-Type: application/json { - "quote": [ "quote_id_1", "quote_id_2", … ], + "quotes": [ "quote_id_1", "quote_id_2", … ], "outputs": [ BlindedMessage_1, BlindedMessage_2, … ], "signature": [signature_1, signature_2, ... ] } @@ -93,7 +93,7 @@ Example: ```json { - "quote": [ "locked_quote_id_1", "quote_id_2", "locked_quote_id_3" ], + "quotes": [ "locked_quote_id_1", "quote_id_2", "locked_quote_id_3" ], "outputs": [ BlindedMessage_1, BlindedMessage_2, ... ], "signature": [signature_1, null, signature_3 ] }