-
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
base: main
Are you sure you want to change the base?
Changes from 2 commits
601143b
0140f9a
5a895b9
9a1ba50
ad90e00
dbb313c
ce8539c
a40a5ab
f1281ca
2f09720
e5cb468
84a34a8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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 | ||
|
|
@@ -28,7 +28,7 @@ The wallet includes the following body in its request: | |
|
|
||
| where `quotes` is an array of _unique_ mint quote IDs. | ||
|
|
||
| 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. | ||
| The mint returns a JSON array of mint quote objects as defined by the payment method's NUT specification. The mint MUST omit quote IDs that it does not know or cannot parse. The quotes that are returned MUST be in the same relative order as their quote IDs in the request. | ||
|
Egge21M marked this conversation as resolved.
Outdated
|
||
|
|
||
| #### Example | ||
|
|
||
|
|
@@ -55,7 +55,6 @@ Content-Type: application/json | |
| "amount_paid": 100, | ||
| "amount_issued": 0, | ||
| "updated_at": 1234567800, | ||
| "state": "PAID", | ||
| "unit": "sat", | ||
| "amount": 100, | ||
| "expiry": 1234567890 | ||
|
|
@@ -66,20 +65,16 @@ 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: | ||
|
|
||
| - 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 | ||
| 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 omit it from the response and continue processing the other quote IDs. If none of the quote IDs can be handled, the mint MUST return an empty JSON array. | ||
|
Egge21M marked this conversation as resolved.
Outdated
|
||
|
|
||
| --- | ||
|
Egge21M marked this conversation as resolved.
|
||
|
|
||
|
|
@@ -192,7 +187,7 @@ 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) | ||
| 6. **Mintable amount**: All quotes MUST have a positive currently mintable amount (`amount_paid - amount_issued`) | ||
|
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. Dropping the PAID-state rule also drops any mention of expiry from mint validation: nothing in this list says whether an expired (but paid) quote can still be batch-minted. Some mints will reject, some won't — should be stated explicitly, especially since the check section now requires returning expired quotes. |
||
| 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) | ||
|
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. With rule 6 loosened to "positive mintable amount", a batch can now include an already partially-minted bolt11 quote — but this equality check doesn't say what the target is in that case: the quote's original amount, or its currently mintable amount ( |
||
| 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 | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -20,23 +20,35 @@ The following is the corresponding response with a blind signature. | |||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| ## Check endpoint with unknown quotes | ||||||
| ## Check endpoint omits unknown and malformed quotes | ||||||
|
Egge21M marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| The following is an invalid check request containing an unknown quote ID. | ||||||
| The following check request contains two known quote IDs, one malformed quote ID, and one unknown quote ID. | ||||||
|
|
||||||
| ```json | ||||||
| { "quotes": ["known-1", "bogus", "unknown-2"] } | ||||||
| { "quotes": ["known-1", "not-a-valid-quote-id", "unknown-2", "known-2"] } | ||||||
| ``` | ||||||
|
|
||||||
| Per NUT-29, quote check uses all-or-nothing error handling. If any quote is unknown, the entire request must be rejected. | ||||||
| The mint omits the malformed and unknown quote IDs. It returns the known quotes in the same relative order as their IDs in the request. | ||||||
|
Egge21M marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| ```json | ||||||
| { | ||||||
| "code": "UNKNOWN_QUOTE", | ||||||
| "error": "one or more quote IDs are unknown" | ||||||
| } | ||||||
| [ | ||||||
| { | ||||||
| "quote": "known-1", | ||||||
| "amount_paid": 5, | ||||||
| "amount_issued": 0, | ||||||
| "updated_at": 1234567800 | ||||||
| }, | ||||||
| { | ||||||
| "quote": "known-2", | ||||||
| "amount_paid": 0, | ||||||
| "amount_issued": 0, | ||||||
| "updated_at": 1234567800 | ||||||
| } | ||||||
| ] | ||||||
|
Egge21M marked this conversation as resolved.
|
||||||
| ``` | ||||||
|
|
||||||
| If the mint cannot handle any of the requested quote IDs, it returns an empty JSON array. | ||||||
|
Collaborator
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.
Suggested change
Collaborator
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. In CTS, I have a failIf(quotes.length != responses.length), so if the view is to make an exception for fully failed lookup, I will need to loosen that.
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. This contradicts 29.md: the spec now says a successful response always has exactly one entry per requested ID, but this line still says an empty array is returned. An empty response to a non-empty request breaks the positional contract. Shouldn't this read that every entry is an EDIT: just needs to be updated ig |
||||||
|
|
||||||
| ## Batch mint atomic failure | ||||||
|
|
||||||
| The following is an invalid batch mint request containing one unknown quote ID, causing the entire batch to fail atomically with no partial minting. | ||||||
|
|
@@ -52,7 +64,7 @@ Expected behavior: | |||||
|
|
||||||
| - The mint rejects the whole request with an error. | ||||||
| - No outputs are signed. | ||||||
| - No quote state is consumed/changed by partial processing. | ||||||
| - No quote's `amount_issued` is increased by partial processing. | ||||||
|
|
||||||
| ## Batch mint rejects empty quotes array | ||||||
|
|
||||||
|
|
||||||
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.
For the check endpoint specifically: is an empty
quotesarray allowed (→ empty response)? And are duplicate IDs rejected like in batch mint (11016), or answered positionally? Both are undefined for check.