-
Notifications
You must be signed in to change notification settings - Fork 52
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
feat: nut19 signature on mint request #188
Open
thesimplekid
wants to merge
2
commits into
cashubtc:main
Choose a base branch
from
thesimplekid:sign_mint_quote
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.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
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 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 |
---|---|---|
@@ -0,0 +1,154 @@ | ||
# NUT-19: Signature on Mint Quote | ||
|
||
`optional` | ||
|
||
This NUT defines a protocol extension that enables signature-based authentication for mint quote redemption. When requesting a mint quote, clients can provide a public key. The mint will then require a valid signature from the corresponding secret key before processing the mint. | ||
Caution: If the mint does not support this NUT, anyone with the mint quote id will be able to mint even without providing a signature. | ||
|
||
# Mint quote | ||
|
||
To request a mint quote, the wallet of `Alice` makes a `POST /v1/mint/quote/{method}` request where `method` is the payment method requested (here `bolt11`). | ||
|
||
```http | ||
POST https://mint.host:3338/v1/mint/quote/bolt11 | ||
``` | ||
|
||
The wallet of `Alice` includes the following `PostMintQuoteBolt11Request` data in its request: | ||
|
||
```json | ||
{ | ||
"amount": <int>, | ||
"unit": <str_enum["sat"]>, | ||
"description": <str|null>, | ||
"pubkey": <str|null> <-- New | ||
} | ||
``` | ||
|
||
with the requested `amount` and the `unit`. An optional `description` can be passed if the mint signals support for it in `MintMethodSetting`. `pubkey` is the public key that will be required for signature verification during the minting process. The mint will only mint ecash after receiving a valid signature from the corresponding private key in the `PostMintRequest`. | ||
The mint `Bob` then responds with a `PostMintQuoteBolt11Response`: | ||
|
||
```json | ||
{ | ||
"quote": <str>, | ||
"request": <str>, | ||
"state": <str_enum[STATE]>, | ||
"expiry": <int> | ||
} | ||
``` | ||
|
||
Where `quote` is the quote ID and `request` is the payment request to fulfill. `expiry` is the Unix timestamp until which the mint quote is valid. | ||
`state` is an enum string field with possible values `"UNPAID"`, `"PAID"`, `"ISSUED"`: | ||
|
||
- `"UNPAID"` means that the quote's request has not been paid yet. | ||
- `"PAID"` means that the request has been paid. | ||
- `"ISSUED"` means that the quote has already been issued. | ||
|
||
## Example | ||
|
||
Request of `Alice` with curl: | ||
|
||
```bash | ||
curl -X POST http://localhost:3338/v1/mint/quote/bolt11 -d '{"amount": 10, "unit": "sat", "pubkey": "03d56ce4e446a85bbdaa547b4ec2b073d40ff802831352b8272b7dd7a4de5a7cac"}' -H "Content-Type: application/json" | ||
``` | ||
|
||
Response of `Bob`: | ||
|
||
```json | ||
{ | ||
"quote": "9d745270-1405-46de-b5c5-e2762b4f5e00", | ||
"request": "lnbc100n1pj4apw9...", | ||
"state": "UNPAID", | ||
"expiry": 1701704757 | ||
} | ||
``` | ||
|
||
#### Signature scheme | ||
|
||
To mint a quote where a public key was provided, the minter needs to include signatures in the `PostMintBolt11Request`. We use `libsecp256k1`'s serialized 64-byte Schnorr signatures on the SHA256 hash of the message to sign. The message to sign is the field `PostMintQuoteBolt11Response.quote`. | ||
|
||
# Minting tokens | ||
|
||
After requesting a mint quote and paying the request, the wallet proceeds with minting new tokens by calling the `POST /v1/mint/{method}` endpoint where `method` is the payment method requested (here `bolt11`). | ||
|
||
```http | ||
POST https://mint.host:3338/v1/mint/bolt11 | ||
``` | ||
|
||
The wallet `Alice` includes the following `PostMintBolt11Request` data in its request | ||
|
||
```json | ||
{ | ||
"quote": <str>, | ||
"outputs": <Array[BlindedMessage]>, | ||
"witness": <str|null> <-- New | ||
} | ||
``` | ||
|
||
with the `quote` being the quote ID from the previous step and `outputs` being `BlindedMessages` (see [NUT-00][00]) that the wallet requests signatures on whose sum is `amount` as requested in the quote. `witness` is the signature on the mint quote id as defined above. | ||
The mint `Bob` then responds with a `PostMintBolt11Response`: | ||
|
||
```json | ||
{ | ||
"signatures": <Array[BlindSignature]> | ||
} | ||
``` | ||
|
||
where `signatures` is an array of blind signatures on the outputs. | ||
|
||
## Example | ||
|
||
Request of `Alice` with curl: | ||
|
||
```bash | ||
curl -X POST https://mint.host:3338/v1/mint/bolt11 -H "Content-Type: application/json" -d \ | ||
'{ | ||
"quote": "9d745270-1405-46de-b5c5-e2762b4f5e00", | ||
"outputs": [ | ||
{ | ||
"amount": 8, | ||
"id": "009a1f293253e41e", | ||
"B_": "035015e6d7ade60ba8426cefaf1832bbd27257636e44a76b922d78e79b47cb689d" | ||
}, | ||
{ | ||
"amount": 2, | ||
"id": "009a1f293253e41e", | ||
"B_": "0288d7649652d0a83fc9c966c969fb217f15904431e61a44b14999fabc1b5d9ac6" | ||
} | ||
], | ||
"witness": "d9be080b33179387e504bb6991ea41ae0dd715e28b01ce9f63d57198a095bccc776874914288e6989e97ac9d255ac667c205fa8d90a211184b417b4ffdd24092" | ||
|
||
}' | ||
``` | ||
|
||
Response of `Bob`: | ||
|
||
```json | ||
{ | ||
"signatures": [ | ||
{ | ||
"id": "009a1f293253e41e", | ||
"amount": 2, | ||
"C_": "0224f1c4c564230ad3d96c5033efdc425582397a5a7691d600202732edc6d4b1ec" | ||
}, | ||
{ | ||
"id": "009a1f293253e41e", | ||
"amount": 8, | ||
"C_": "0277d1de806ed177007e5b94a8139343b6382e472c752a74e99949d511f7194f6c" | ||
} | ||
] | ||
} | ||
``` | ||
|
||
If the invoice was not paid yet, `Bob` responds with an error. In that case, `Alice` **CAN** repeat the same request until the Lightning invoice is settled, as in NUT04. If `Alice` does not include a witness on the `PostMintBolt11Request` but did include a `pubkey` in the `PostMintBolt11QuoteRequest` the `Bob` **MUST** respond with an error, `Alice` **CAN** repeat the request with a witness in order to mint the ecash. | ||
|
||
## Settings | ||
|
||
The settings for this NUT indicate the support for requiring a signature before minting. They are part of the info response of the mint ([NUT-06][06]) which in this case reads | ||
|
||
```json | ||
{ | ||
"19": { | ||
"supported": <bool> | ||
} | ||
} | ||
``` |
This file contains 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 |
---|---|---|
|
@@ -16,6 +16,7 @@ | |
| 20005 | Quote is pending | [NUT-04][04], [NUT-05][05] | | ||
| 20006 | Invoice already paid | [NUT-05][05] | | ||
| 20007 | Quote is expired | [NUT-04][04], [NUT-05][05] | | ||
| 20008 | Witness not provided for mint quote | [NUT-19][19] | | ||
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. We need an error for the invalid witness as well. |
||
|
||
[00]: 00.md | ||
[01]: 01.md | ||
|
@@ -30,3 +31,4 @@ | |
[10]: 10.md | ||
[11]: 11.md | ||
[12]: 12.md | ||
[19]: 19.md |
This file contains 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 |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# NUT-19 Test Vectors | ||
|
||
The following is a `PostMintBolt11Request` with a valid signature. Where the `pubkey` in the `PostMintQuoteBolt11Request` is `03d56ce4e446a85bbdaa547b4ec2b073d40ff802831352b8272b7dd7a4de5a7cac`. | ||
|
||
```json | ||
{ | ||
"quote": "9d745270-1405-46de-b5c5-e2762b4f5e00", | ||
"outputs": [], | ||
"witness": "d9be080b33179387e504bb6991ea41ae0dd715e28b01ce9f63d57198a095bccc776874914288e6989e97ac9d255ac667c205fa8d90a211184b417b4ffdd24092" | ||
} | ||
``` | ||
|
||
The following is a `PostMintBolt11Request` with an invalid signature. Where the `pubkey` in the `PostMintQuoteBolt11Request` is `03d56ce4e446a85bbdaa547b4ec2b073d40ff802831352b8272b7dd7a4de5a7cac`. | ||
|
||
```json | ||
{ | ||
"quote": "9d745270-1405-46de-b5c5-e2762b4f5e00", | ||
"outputs": [], | ||
"witness": "cb2b8e7ea69362dfe2a07093f2bbc319226db33db2ef686c940b5ec976bcbfc78df0cd35b3e998adf437b09ee2c950bd66dfe9eb64abd706e43ebc7c669c36c3" | ||
} | ||
``` |
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.
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.
Another way how to fix the issue is to add the following at the end of the file:
This seems to be preferred way used in other documents.