diff --git a/10.md b/10.md new file mode 100644 index 0000000..57da575 --- /dev/null +++ b/10.md @@ -0,0 +1,74 @@ +NUT-10: Spending conditions +========================== + +`optional` `author: calle` + +--- + +An ordinary ecash token is a set of `Proofs` each with a random string `secret`. To spend such a token in a [split][06] or a [melt][05] operation, wallets include `proofs` in their request each with a unique `secret`. To autorize a transaction, the mint requires that the `secret` has not been seen before. This is the most fundamental spending condition in Cashu, which ensures that a token can't be double-spent. + +In this NUT, we define a well-known format of `secret` that can be used to express more complex spending conditions. These conditions need to be met before the mint authorizes a transaction. Note that the specific type of spending condition is not part of this document but will be explained in other documents. Here, we describe the structure of `secret` which is expressed as a JSON `Secret` with a specific format. + +Spending conditions are enfored by the mint which means that, upon encountering a `Proof` where `Proof.secret` can be parsed into the well-known format, the mint can require additional conditions to be met. + +## Basic components +An ecash transaction, i.e., a [split][06] or a [melt][05] operation, with a spending condition consists of the following components: + +- Inputs referring to the `Proofs` being spent +- `Secret` containing the rules for unlocking a `Proof` +- Additional witness data satisfying the unlock conditions such as signatures +- Outputs referring to the `BlindMessages` with new unlock conditions to which the `Proofs` are spent to + +Spending conditions are defined for each individual `Proof` and not on a transaction level that can consist of multiple `Proofs`. Similarly, spending conditions must be satisfied by providing signatures or additional witness data for each `Proof` separately. For a transaction to be valid, all `Proofs` in that transaction must be unlocked successfully. + +New `Secret`s of the outputs to which the inputs are spent to are provided as `BlindMessages` which means that they are blind-signed and not visible to the mint until they are actually spent. + +## Well-known Secret + +Spending conditions are expressed in a well-known secret format that is revealed to the mint when spending (unlocking) a token, not when the token is minted (locked). The mint parses each `Proof`'s `secret`. If it can deserialize it into the following format it executes additional spending conditions that are further specified in additional NUTs. + +The well-known `Secret` stored in `Proof.secret` is a JSON of the format: + +```json +[ +kind , + { + "nonce": , + "data": , + "tags": [[ "key", "value1", "value2", ...], ... ], // (optional) + } +] +``` + +- `kind` is the kind of the spending condition +- `nonce` is a unique random string +- `data` expresses the spending condition specific to each kind +- `tags` hold additional data committed to and can be used for feature extensions + +## Examples + +Example use cases of this secret format are + +- [NUT-11][11]: Pay-to-Public-Key (P2PK) + +[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 +[13]: 13.md +[14]: 14.md +[15]: 15.md +[16]: 16.md +[17]: 17.md +[18]: 18.md +[19]: 19.md +[20]: 20.md \ No newline at end of file diff --git a/README.md b/README.md index 9e0662d..9aab6c2 100644 --- a/README.md +++ b/README.md @@ -12,28 +12,23 @@ Wallets and mints `MUST` implement all mandatory specs and `CAN` implement optio ### Mandatory | # | Description | Wallets | Mints | |--- | --- | --- | --- | -| [00][00] | Cryptography and Models | [Nutshell][py], [Feni][feni], [Cashu.Me][cashume], [Nutstash][ns], [JS][js] | [Nutshell][py], [Feni][feni], [LNbits] -| [01][01] | Mint public keys | [Nutshell][py], [Feni][feni], [Cashu.Me][cashume], [Nutstash][ns], [JS][js] | [Nutshell][py], [Feni][feni], [LNbits] -| [02][02] | Keysets and keyset IDs | [Nutshell][py], [Feni][feni], [Cashu.Me][cashume], [Nutstash][ns], [JS][js] | [Nutshell][py], [Feni][feni], [LNbits] -| [03][03] | Request minting | [Nutshell][py], [Feni][feni], [Cashu.Me][cashume], [Nutstash][ns], [JS][js] | [Nutshell][py], [Feni][feni], [LNbits] -| [04][04] | Minting tokens | [Nutshell][py], [Feni][feni], [Cashu.Me][cashume], [Nutstash][ns], [JS][js] | [Nutshell][py], [Feni][feni], [LNbits] -| [05][05] | Melting tokens | [Nutshell][py], [Feni][feni], [Cashu.Me][cashume], [Nutstash][ns], [JS][js] | [Nutshell][py], [Feni][feni], [LNbits] -| [06][06] | Splitting tokens | [Nutshell][py], [Feni][feni], [Cashu.Me][cashume], [Nutstash][ns], [JS][js] | [Nutshell][py], [Feni][feni], [LNbits] +| [00][00] | Cryptography and Models | [Nutshell][py], [Feni][feni], [Moksha][cashume], [Nutstash][ns], [cashu-ts][ts] | [Nutshell][py], [Feni][feni], [LNbits], [Moksha][cashume] +| [01][01] | Mint public keys | [Nutshell][py], [Feni][feni], [Moksha][cashume], [Nutstash][ns], [cashu-ts][ts] | [Nutshell][py], [Feni][feni], [LNbits], [Moksha][cashume] +| [02][02] | Keysets and keyset IDs | [Nutshell][py], [Feni][feni], [Moksha][cashume], [Nutstash][ns], [cashu-ts][ts] | [Nutshell][py], [Feni][feni], [LNbits], [Moksha][cashume] +| [03][03] | Request minting | [Nutshell][py], [Feni][feni], [Moksha][cashume], [Nutstash][ns], [cashu-ts][ts] | [Nutshell][py], [Feni][feni], [LNbits], [Moksha][cashume] +| [04][04] | Minting tokens | [Nutshell][py], [Feni][feni], [Moksha][cashume], [Nutstash][ns], [cashu-ts][ts] | [Nutshell][py], [Feni][feni], [LNbits], [Moksha][cashume] +| [05][05] | Melting tokens | [Nutshell][py], [Feni][feni], [Moksha][cashume], [Nutstash][ns], [cashu-ts][ts] | [Nutshell][py], [Feni][feni], [LNbits], [Moksha][cashume] +| [06][06] | Splitting tokens | [Nutshell][py], [Feni][feni], [Moksha][cashume], [Nutstash][ns], [cashu-ts][ts] | [Nutshell][py], [Feni][feni], [LNbits], [Moksha][cashume] ### Optional | # | Description | Wallets | Mints |--- | --- | --- | --- | -| [07][07] | Token state check | [Nutshell][py], [Feni][feni], [Cashu.Me][cashume], [Nutstash][ns] | [Nutshell][py], [Feni][feni], [LNbits] -| [08][08] | Overpaid Lightning fees | [Nutshell][py], [Feni][feni], [Cashu.Me][cashume], [Nutstash][ns] | [Nutshell][py], [LNbits] +| [07][07] | Token state check | [Nutshell][py], [Feni][feni], [Moksha][cashume], [Nutstash][ns] | [Nutshell][py], [Feni][feni], [LNbits], [Moksha][cashume] +| [08][08] | Overpaid Lightning fees | [Nutshell][py], [Feni][feni], [Moksha][cashume], [Nutstash][ns], [cashu-ts][ts] | [Nutshell][py], [LNbits], [Moksha][cashume] | [09][09] | Mint info | - | [Nutshell][py] -| TBD | Multimint support | [Nutshell][py], [Cashu.Me][cashume], [Nutstash][ns] | N/A +| [10][10] | Spending conditions | [Nutshell][py] | [Nutshell][py] | TBD | DLEQ proofs | - | - -| TBD | Bitcoin script | [Nutshell][py] | [Nutshell][py] -| TBD | Token version prefixes | - | N/A -| TBD | Cashu URI | - | N/A -| TBD | Mint LN swap | [Cashu.Me][cashume], [Nutstash][ns] | N/A -| TBD | Token comment | - | N/A -| TBD | Token sender information | - | N/A + [py]: https://github.com/cashubtc/cashu @@ -41,7 +36,7 @@ Wallets and mints `MUST` implement all mandatory specs and `CAN` implement optio [lnbits]: https://github.com/lnbits/cashu [cashume]: https://cashu.me [ns]: https://nutstash.app/ -[js]: https://github.com/cashubtc/cashu-js +[ts]: https://github.com/cashubtc/cashu-ts [00]: 00.md [01]: 01.md