Skip to content
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

NUT-XX and NUT-XX+1: Mint / Melt Bitcoin On-Chain #107

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 201 additions & 0 deletions 17.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
NUT-17: Mint tokens Bitcoin On-Chain
==========================

`optional`

---

This NUT describes the process of minting tokens on Bitcoin On-Chain analog to NUT-04 for Bitcoin Lightning.

# 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 `btconchain`).

```http
POST https://mint.host:3338/v1/mint/quote/btconchain
```

The wallet of `Alice` includes the following `PostMintQuoteBtcOnchainRequest` data in its request:

```json
{
"amount": <int>,
"unit": <str_enum["sat"]>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"unit": <str_enum["sat"]>

Note: All PostMintQuoteBtcOnchainRequest's are denominated in sat.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should we remove the unit-field from the PostMintQuoteOnchainRequest? If the mint uses blink as a backend for handling the onchain transactions it can support onchain snd/receive with usd as a currency. Hopefully in the future there will be similar services. https://dev.blink.sv/api/usd-onchain-send

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a question of scoping this NUT. To support other units where a conversion rate is involved how expiration is handled as well as how confirmation time is defined is much more important as the conversion rate could change outside an acceptable slippage. So in order to support other units how confirmation and expiration is defined needs to be included as well.

}
```
with the requested `amount` and the `unit`.

The mint `Bob` then responds with a `PostMintQuoteBtcOnchainResponse`:

```json
{
"quote": <str>,
"address": <str>,
thesimplekid marked this conversation as resolved.
Show resolved Hide resolved
"paid": <bool>,
"expiry": <int>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This expiry field might be problematic (cf @gandlafbtc's comment).

}
```
ngutech21 marked this conversation as resolved.
Show resolved Hide resolved

Where `quote` is the quote ID and `address` is the payment request to fulfill. `paid` indicates whether the request as been paid and `expiry` is the Unix timestamp until which the mint quote is valid.

Note: `quote` is a **unique and random** id generated by the mint to internally look up the payment state. `quote` **MUST** remain a secret between user and mint and **MUST NOT** be derivable from the payment request. A third party who knows the `quote` ID can front-run and steal the tokens that this operation mints.
ngutech21 marked this conversation as resolved.
Show resolved Hide resolved

## Example

Request of `Alice` with curl:

```bash
curl -X POST https://mint.host:3338/v1/mint/quote/btconchain -d '{"amount": 10, "unit": "sat"}' -H "Content-Type: application/json"
```

Response of `Bob`:

```json
{
"quote": "DSGLX9kevM...",
"address": "bc1qkyfgd7mus7ykfd7qkwakq75qsf7rtm...",
"paid": false,
"expiry": 1701704757
}
```
ngutech21 marked this conversation as resolved.
Show resolved Hide resolved

The wallet **MUST** store the `amount` in the request and the `quote` id in the response in its database so it can later request the tokens after paying the request. After payment, the wallet continues with the next section.

## Check mint quote state

To check whether a mint quote has been paid, `Alice` makes a `GET /v1/mint/quote/btconchain/{quote_id}`.

```http
GET https://mint.host:3338/v1/mint/quote/btconchain/{quote_id}
```

Like before, the mint `Bob` responds with a `PostMintQuoteBtcOnchainResponse`.

Example request of `Alice` with curl:

```bash
curl -X GET https://mint.host:3338/v1/mint/quote/btconchain/DSGLX9kevM...
```

# 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 `btconchain`).

```http
POST https://mint.host:3338/v1/mint/btconchain
```

The wallet `Alice` includes the following `PostMintBtcOnchainRequest` data in its request

```json
{
"quote": <str>,
"outputs": <Array[BlindedMessage]>
}
```
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.

The mint `Bob` then responds with a `PostMintBtcOnchainResponse`:

```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/btconchain -H "Content-Type: application/json" -d \
'{
"quote": "DSGLX9kevM...",
"outputs": [
{
"amount": 8,
"id": "009a1f293253e41e",
"B_": "035015e6d7ade60ba8426cefaf1832bbd27257636e44a76b922d78e79b47cb689d"
},
{
"amount": 2,
"id": "009a1f293253e41e",
"B_": "0288d7649652d0a83fc9c966c969fb217f15904431e61a44b14999fabc1b5d9ac6"
}
]
}'
```

Response of `Bob`:

```json
{
"signatures": [
{
"id": "009a1f293253e41e",
"amount": 2,
"C_": "0224f1c4c564230ad3d96c5033efdc425582397a5a7691d600202732edc6d4b1ec"
},
{
"id": "009a1f293253e41e",
"amount": 8,
"C_": "0277d1de806ed177007e5b94a8139343b6382e472c752a74e99949d511f7194f6c"
}
]
}
```

## Unblinding signatures

Upon receiving the `BlindSignatures` from the mint `Bob`, the wallet of `Alice` unblinds them to generate `Proofs` (using the blinding factor `r` and the mint's public key `K`, see BDHKE [NUT-00][00]). The wallet then stores these `Proofs` in its database:

```json
[
{
"id": "009a1f293253e41e",
"amount": 2,
"secret": "407915bc212be61a77e3e6d2aeb4c727980bda51cd06a6afc29e2861768a7837",
"C": "02bc9097997d81afb2cc7346b5e4345a9346bd2a506eb7958598a72f0cf85163ea"
},
{
"id": "009a1f293253e41e",
"amount": 8,
"secret": "fe15109314e61d7756b0f8ee0f23a624acaa3f4e042f61433c728c7057b931be",
"C": "029e8e5050b890a7d6c0968db16bc1d5d5fa040ea1de284f6ec69d61299f671059"
}
]
```

## Settings
The settings for this nut indicate the supported method-unit pairs for minting and whether minting is supported or not. They are part of the info response of the mint ([NUT-06][06]) which in this case reads
```json
{
"14": {
ngutech21 marked this conversation as resolved.
Show resolved Hide resolved
"supported": true,
"methods": [
{
"method": "btconchain",
"unit": "sat",
"min_amount": 10000,
"max_amount": 1000000
}
]
}
}
```

[00]: 00.md
[01]: 01.md
[02]: 02.md
[03]: 03.md
[04]: 04.md
[05]: 05.md
[06]: 06.md
[07]: 07.md
[08]: 08.md
[09]: 09.md
[10]: 10.md
[11]: 11.md
[12]: 12.md
Loading