NUT-XX: Get quotes by pubkeys #341
No reviewers
Labels
No labels
breaking change
bug
documentation
enhancement
needs discussion
needs implementation
new nut
ready
wallet-only
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo-admin/nuts!341
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "get-quotes-by-pubkeys"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
supersedes #329
Get NUT-20 quotes by
pubkeys. Requires signatures to prove possession of the corresponding private keys.The signature scheme is a bit worrying, but otherwise just some nit/questions for clarity.
@ -0,0 +1,60 @@# NUT-29: Mint Quote Lookup by Public Key28 now taken... 29?
28 now taken... 29?
@ -0,0 +21,4 @@```json{"pubkeys": <Array[str]>,"pubkey_signatures": <Array[str]>Would it be useful to group quotes by pubkey?
@ -0,0 +28,4 @@- `pubkeys` is an array of hex-encoded compressed secp256k1 NUT-20 public keys (33 bytes each)- `pubkey_signatures` is an array of hex-encoded Schnorr signatures on `pubkeys` in the same order (64 bytes each)The wallet **MUST** provide a valid signature in `pubkey_signatures` for each public key in `pubkeys` with the corresponding private key in the same order as the `pubkeys` array. The message to sign is the byte representation of the public key.I think signature on the plain public key is pretty risky, as it allows signature replay in any "proof of key ownership" context, or even for future uses on other endpoints and other mints.
It would be better defined as a signature on a domain separated message like we do in P2BK / keyset v2
or
)
@ -0,0 +39,4 @@"quotes": <Array[MintQuoteResponse]>}```We should probably specify what happens if any signature is invalid. Does entire op fail, or does mint return only the valid ones? What happens if more/fewer sigs are provided than pubkeys?
@ -0,0 +21,4 @@```json{"pubkeys": <Array[str]>,"pubkey_signatures": <Array[str]>in the mint response? I think best to not define the ordering and let the wallet figure it out.
@ -0,0 +21,4 @@```json{"pubkeys": <Array[str]>,"pubkey_signatures": <Array[str]>Yeah, I don't mind, a flat array is easy to sort by a wallet. Simpler response. And pubkey is in the quote.
@ -0,0 +39,4 @@"quotes": <Array[MintQuoteResponse]>}```I think we should match the plan for batched minting where if any are invalid the whole op fails.
@ -0,0 +39,4 @@"quotes": <Array[MintQuoteResponse]>}```Agree. It lowers the abuse surface too, because a mint can reject at first invalid signature (or on mismatch key/sig count), rather than continue processing.
@ -0,0 +28,4 @@- `pubkeys` is an array of hex-encoded compressed secp256k1 NUT-20 public keys (33 bytes each)- `pubkey_signatures` is an array of hex-encoded Schnorr signatures on `pubkeys` in the same order (64 bytes each)The wallet **MUST** provide a valid signature in `pubkey_signatures` for each public key in `pubkeys` with the corresponding private key in the same order as the `pubkeys` array. The message to sign is the byte representation of the public key.@ -0,0 +39,4 @@"quotes": <Array[MintQuoteResponse]>}```I added a suggestion to the request section above, but it could be moved to response section if preferred.
@ -0,0 +28,4 @@- `pubkeys` is an array of hex-encoded compressed secp256k1 NUT-20 public keys (33 bytes each)- `pubkey_signatures` is an array of hex-encoded Schnorr signatures on `pubkeys` in the same order (64 bytes each)The wallet **MUST** provide a valid signature in `pubkey_signatures` for each public key in `pubkeys` with the corresponding private key in the same order as the `pubkeys` array. The message to sign is the byte representation of the public key.good point!
@ -0,0 +1,60 @@# NUT-29: Mint Quote Lookup by Public KeyThis needs a new NUT number, NUT-29 is already defined in NUT-29: Batched Minting
@ -0,0 +48,4 @@```json{"29": {Same thing here
@ -0,0 +1,60 @@# NUT-29: Mint Quote Lookup by Public KeyGenerally we us XX and just define before merge
@ -0,0 +28,4 @@- `pubkeys` is an array of hex-encoded compressed secp256k1 NUT-20 public keys (33 bytes each)- `pubkey_signatures` is an array of hex-encoded Schnorr signatures on `pubkeys` in the same order (64 bytes each)The wallet **MUST** provide a valid signature in `pubkey_signatures` for each public key in `pubkeys` with the corresponding private key in the same order as the `pubkeys` array. The message to sign is the byte representation of the public key.A static schnorr signature allows replay attacks: if I observe a signature i can use it to query the status of a quote again and again.
Following the suggestion from @robwoodgate :
My suggestion is create a GET request for the same path to mint generate a nonce that wallet can be use for sign a hash message, this will prevent replay attacks.
@ -0,0 +10,4 @@## RequestTo query quotes assigned to a public key, the wallet makes a `POST /v1/mint/quote/{method}/pubkey` request.@ -0,0 +29,4 @@- `pubkey_signatures` is an array of hex-encoded Schnorr signatures on `pubkeys` in the same order (64 bytes each)The wallet **MUST** provide a valid signature in `pubkey_signatures` for each public key in `pubkeys` with the corresponding private key in the same order as the `pubkeys` array. The message to sign is the byte representation of the public key.@ -0,0 +32,4 @@## ResponseThe mint responds with a `PostMintQuotesByPubkeyResponse`:I've opened a PR with the updated signature logic and test vectors here: #363
@ -0,0 +10,4 @@## RequestTo query quotes assigned to a public key, the wallet makes a `POST /v1/mint/quote/{method}/pubkey` request.A nonce doesn't need to be mint-supplied. It can just be a random string.
I support @a1denvalu3 's approach in #363 - using a timestamp also allows a mint to prevent reuse of the signature after xx minutes too.
It would be even better with a domain prefix, in case a similar scheme is used later on elsewhere:
But with a timestamp max age specified, the reuse window would be minimal in any case.
Thanks for opening this — it's great to see this direction being taken seriously. I'm building an ESP32-based captive portal (TollGate) that provides WiFi access in exchange for ecash payments. My use case: a mining proxy on the ESP32 connects to a hashpool translator via SV1 stratum. The translator mints ehash tokens for the miner's locking pubkey and currently pushes them downstream via a custom
mining.tokennotification.This NUT ("Get quotes by pubkeys") would let me eliminate the translator middleman — the ESP32 could directly query the mint for quotes attributed to its pubkey, receive tokens without the push notification hack. This is especially important for resource-constrained devices where running a full translator is impractical.
The domain-separated signature scheme in #363 (timestamp + mint pubkey) looks solid. I'm really looking forward to using this functionality — happy to test with my ESP32 implementation once the spec stabilizes.
View command line instructions
Manual merge helper
Use this merge commit message when completing the merge manually.
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.