-
Notifications
You must be signed in to change notification settings - Fork 85
Loosen NUT-29 batch quote checks #422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Egge21M
wants to merge
12
commits into
cashubtc:main
Choose a base branch
from
Egge21M:agent/nut-29-omit-unhandled-quote-checks
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+164
−23
Open
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
601143b
Loosen NUT-29 batch quote checks
Egge21M 0140f9a
Align NUT-29 with quote accounting fields
Egge21M 5a895b9
Update 29.md
Egge21M 9a1ba50
Update tests/29-tests.md
Egge21M ad90e00
Update 29.md
Egge21M dbb313c
format
Egge21M ce8539c
fix mangled suggestion merge
robwoodgate a40a5ab
more fixes to mangled suggestion merge
robwoodgate f1281ca
Update 29.md
Egge21M 2f09720
Update tests/29-tests.md
Egge21M e5cb468
Update tests/29-tests.md
Egge21M 84a34a8
Clarify NUT-29 batch quote semantics
Egge21M File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,7 +12,7 @@ This spec describes how a wallet can mint multiple quotes in one batched operati | |
|
|
||
| ## 1. Batch Checking Mint Quotes | ||
|
|
||
| Before minting, the wallet SHOULD verify each mint quote's current accounting state. It does this by sending: | ||
| Before minting, the wallet SHOULD verify each mint quote's current accounting data. It does this by sending: | ||
|
|
||
| ```http | ||
| POST https://mint.host:3338/v1/mint/quote/{method}/check | ||
|
|
@@ -26,15 +26,23 @@ The wallet includes the following body in its request: | |
| } | ||
| ``` | ||
|
|
||
| where `quotes` is an array of _unique_ mint quote IDs. | ||
| where `quotes` is an array of _unique_ mint quote IDs. The array MAY be empty, in which case the mint MUST return an empty JSON array. | ||
|
|
||
| The mint returns a JSON array of mint quote objects as defined by the payment method's NUT specification. The quotes in this array MUST be in the same order as in the request. | ||
| If `quotes` contains duplicate IDs, the mint MUST reject the entire request with error `11016`. | ||
|
|
||
| #### Example | ||
| The mint returns a JSON array with exactly one entry per requested quote ID, in request order. Entry `i` corresponds to `quotes[i]`, and its `quote` field **MUST** equal the requested ID. | ||
|
|
||
| Known quotes are returned as mint quote objects as defined by the payment method's NUT specification. A requested ID is known only if it identifies a mint quote for the `{method}` in the endpoint path. All other IDs, including melt quote IDs and mint quote IDs for another payment method, MUST be returned as [unknown entries](#unknown-or-malformed-quote-ids). | ||
|
|
||
| Mints **MUST** return every mint quote they hold for `{method}`, including quotes whose `expiry` has passed. An unknown entry indicates that the ID does not identify a mint quote within this endpoint's `{method}` scope. | ||
|
|
||
| Mints **MUST NOT** delete a quote for which ecash is still owed (`amount_paid - amount_issued > 0`). | ||
|
|
||
| ### Example | ||
|
|
||
| Below is an example for checking two bolt11 mint quotes. | ||
|
|
||
| ##### Request | ||
| #### Request | ||
|
|
||
| ```http | ||
| POST https://mint.host:3338/v1/mint/quote/bolt11/check | ||
|
|
@@ -45,7 +53,7 @@ Content-Type: application/json | |
| } | ||
| ``` | ||
|
|
||
| ##### Response | ||
| #### Response | ||
|
|
||
| ```json | ||
| [ | ||
|
|
@@ -55,7 +63,6 @@ Content-Type: application/json | |
| "amount_paid": 100, | ||
| "amount_issued": 0, | ||
| "updated_at": 1234567800, | ||
| "state": "PAID", | ||
| "unit": "sat", | ||
| "amount": 100, | ||
| "expiry": 1234567890 | ||
|
|
@@ -66,20 +73,27 @@ Content-Type: application/json | |
| "amount_paid": 0, | ||
| "amount_issued": 0, | ||
| "updated_at": 1234567800, | ||
| "state": "UNPAID", | ||
| "unit": "sat", | ||
| "amount": 50, | ||
| "expiry": 1234567890 | ||
| } | ||
| ] | ||
| ``` | ||
|
|
||
| #### Error Handling | ||
| ### Unknown or Malformed Quote IDs | ||
|
|
||
| This is a query endpoint that uses all-or-nothing error handling, matching the behavior of the batch mint endpoint: | ||
| This is a query endpoint and does not use the all-or-nothing error handling of the batch mint endpoint. If a quote ID is unknown or cannot be parsed, the mint **MUST** return an `unknown` entry for it as below and continue processing the remaining IDs. | ||
|
|
||
| - If any `quote_id` is not known by the mint, the mint MUST reject the entire request and return an appropriate error | ||
| - If any `quote_id` cannot be parsed (invalid format), the mint MUST reject the entire request and return an appropriate error | ||
| ```json | ||
| { | ||
| "quote": <str>, | ||
| "unknown": true | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest stating that unknown entries contain exactly |
||
| ``` | ||
|
|
||
| An unknown entry MUST contain exactly the `quote` and `unknown` fields shown above. A known quote entry MUST NOT contain the `unknown` field. | ||
|
|
||
| `max_batch_size` (see [Batch Size Limits](#batch-size-limits)) applies to this endpoint. A request that exceeds it **MUST** be rejected in full with error `11017` rather than answered partially, so a successful response always has exactly one entry per requested quote ID. | ||
|
|
||
| --- | ||
|
Egge21M marked this conversation as resolved.
|
||
|
|
||
|
|
@@ -107,8 +121,10 @@ The wallet includes the following body in its request: | |
| ``` | ||
|
|
||
| - `quotes`: array of _unique_ quote IDs. | ||
| - `quote_amounts`: array of expected amounts to mint per quote, in the same order as `quotes`. | ||
| - `quote_amounts`: array of amounts to issue from each quote in this batch, in the same order as `quotes`. | ||
| - Required for payment methods that demand an amount like bolt12; Optional for other methods like bolt11. | ||
| - If it is an array, its length MUST equal the length of `quotes`, and `quote_amounts[i]` corresponds to `quotes[i]`. | ||
| - For payment methods where `quote_amounts` is optional, if it is omitted or `null`, the amount to issue from each quote is its full currently mintable amount, `amount_paid - amount_issued`. | ||
| - `outputs`: array of blinded messages (see [NUT-00][00]). | ||
| - `signatures`: array of signatures for NUT-20 locked quotes. See [NUT-20 Support][nut-20-support] | ||
|
|
||
|
|
@@ -192,12 +208,15 @@ The mint MUST validate the following before processing a batch mint request: | |
| 3. **Valid quote IDs**: All quote IDs MUST exist in the mint's database | ||
| 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 a mintable amount for payment methods that allow multiple mint operations like bolt12) | ||
| 7. **Amount balance**: The sum of amounts contained in the `outputs` MUST equal the sum of `quote_amounts` (bolt11) or MUST NOT exceed it (bolt12) | ||
| 8. **Signature validation (NUT-20)**: The `signatures` array length MUST match the `quotes` array length; locked quotes MUST include a valid signature; unlocked quotes MUST NOT include one | ||
| 6. **Per-quote amount**: All quotes MUST have a positive currently mintable amount (`amount_paid - amount_issued`). If `quote_amounts` is an array, each `quote_amounts[i]` MUST be positive and MUST NOT exceed the currently mintable amount of `quotes[i]`. | ||
| 7. **Expiry**: A quote with a positive currently mintable amount remains mintable after its `expiry` has passed. The mint MUST NOT reject issuance solely because the quote has expired. | ||
| 8. **Amount balance**: The sum of amounts contained in the `outputs` MUST equal the sum of the amounts to issue from the quotes. For payment methods where `quote_amounts` is optional, when it is omitted or `null`, this is the sum of each quote's currently mintable amount. | ||
| 9. **Signature validation (NUT-20)**: The `signatures` array length MUST match the `quotes` array length; locked quotes MUST include a valid signature; unlocked quotes MUST NOT include one | ||
|
|
||
| Implementations MAY impose additional constraints such as maximum batch size based on their resource limitations. If any validation fails, the mint MUST reject the entire batch and return an appropriate error without minting any quotes. | ||
|
|
||
| If all validations succeed, the mint MUST atomically increase each quote's `amount_issued` by the corresponding amount issued from that quote. For payment methods where `quote_amounts` is optional, if it was omitted or `null`, the mint increases each quote's `amount_issued` by its full currently mintable amount before the batch. | ||
|
|
||
| ### NUT-20 support | ||
|
|
||
| Per [NUT-20][20], quotes can require authentication via signatures. When using batch minting with NUT-20 locked quotes: | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we should name the return type, as we do for other response shapes.