{"id":"905ad895c0a9f0f65417490e65b852a649f06f4ddfa357705e21b22acc3aae10","pubkey":"d1678e7ef965374bbea308a1215609a78376dc158277a7d657680f9d5efd5c38","created_at":1765882093,"kind":30817,"tags":[["d","nut-10"],["title","NUT-10: Spending conditions"],["summary","The well-known secret format that turns a proof's secret into a spending condition the mint enforces."],["s","optional"],["t","cashu"],["t","ecash"],["t","nut"],["alt","A specification: NUT-10: Spending conditions"],["client","openspecs-import"],["published_at","1697225092"],["proxy","https://github.com/cashubtc/nuts/blob/a845dfc998abae501fc3419592d53dc995d34b12/10.md","web"],["x","25160fd37f745b8b0e8fa8a29ad36fb8301ac9f1e07557a329c43483c6a2af1a"]],"content":"# NUT-10: Spending conditions\n\n`optional`\n\n`used in: NUT-11, NUT-14`\n\n---\n\nAn ordinary ecash token is a set of `Proofs` each with a random string `secret`. To spend such a token in a [swap][03] or a [melt][05] operation, wallets include `proofs` in their request each with a unique `secret`. To authorize 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.\n\nIn 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.\n\nSpending conditions are enforced 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.\n\nCaution: If the mint does not support spending conditions or a specific `kind` of spending condition, proofs may be treated as a regular anyone-can-spend tokens. Applications need to make sure to check whether the mint supports a specific `kind` of spending condition by checking the mint's [info][06] endpoint.\n\n## Basic components\n\nAn ecash transaction, i.e., a [swap][03] or a [melt][05] operation, with a spending condition consists of the following components:\n\n- Inputs referring to the `Proofs` being spent\n- `Secret` containing the rules for unlocking a `Proof`\n- Additional witness data satisfying the unlock conditions such as signatures\n- Outputs referring to the `BlindMessages` with new unlock conditions to which the `Proofs` are spent to\n\nSpending 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.\n\nNew `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.\n\n## Well-known Secret\n\nSpending 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.\n\nThe well-known `Secret` stored in `Proof.secret` is a JSON of the format:\n\n```json\n[\nkind <str>,\n  {\n    \"nonce\": <str>,\n    \"data\": <str>,\n    \"tags\": [[ \"key\", \"value1\", \"value2\", ...],  ... ], // (optional)\n  }\n]\n```\n\n- `kind` is the kind of the spending condition\n- `nonce` is a unique random string\n- `data` expresses the spending condition specific to each kind\n- `tags` hold additional data committed to and can be used for feature extensions\n\n### Tag format\n\nThe optional `tags` field, is an array of arrays of non-empty strings.\n\nEach individual tag is an array of **ONE or more strings**. The first element of the tag array is known as the tag _name_ or _key_ and the subsequent string(s) are the _tag value(s)_.\n\n**Examples of valid tags:**\n\n`[\"pubkeys\"]` - a tag with the key, `\"pubkeys\"` and no tag values.\\\n`[\"pubkeys\", \"021...\"]` - a tag with the key, `\"pubkeys\"` and ONE tag value.\\\n`[\"pubkeys\", \"021...\", \"022...\"]` - a tag with the key, `\"pubkeys\"` and TWO tag values.\n\n**Examples of invalid tags:**\n\n`[]` - a tag array must contain at least **ONE** or more strings\\\n`[\"locktime\", 1765300829]` - a tag must contain **strings** only\\\n`[\"locktime\", \"\"]` - a tag must contain **non-empty strings** only\n\n## Examples\n\nExample use cases of this secret format are\n\n- [NUT-11][11]: Pay-to-Public-Key (P2PK)\n- [NUT-14][14]: Hashed Timelock Contracts (HTLCs)\n\n## Mint info setting\n\nThe [NUT-06][06] `MintMethodSetting` indicates support for this feature:\n\n```json\n{\n  \"10\": {\n    \"supported\": true\n  }\n}\n```\n\n[00]: nostr:naddr1qvzqqqrcvypzp5t83el0jefhfwl2xz9py9tqnfurwmwptqnh5lt9w6q0n4006hpcqqrxuat595crqqpd6d9\n[01]: nostr:naddr1qvzqqqrcvypzp5t83el0jefhfwl2xz9py9tqnfurwmwptqnh5lt9w6q0n4006hpcqqrxuat595crznyve7g\n[02]: nostr:naddr1qvzqqqrcvypzp5t83el0jefhfwl2xz9py9tqnfurwmwptqnh5lt9w6q0n4006hpcqqrxuat595cry0t0uzl\n[03]: nostr:naddr1qvzqqqrcvypzp5t83el0jefhfwl2xz9py9tqnfurwmwptqnh5lt9w6q0n4006hpcqqrxuat595crxuwwl3j\n[04]: nostr:naddr1qvzqqqrcvypzp5t83el0jefhfwl2xz9py9tqnfurwmwptqnh5lt9w6q0n4006hpcqqrxuat595crg74fknc\n[05]: nostr:naddr1qvzqqqrcvypzp5t83el0jefhfwl2xz9py9tqnfurwmwptqnh5lt9w6q0n4006hpcqqrxuat595cr2dsg4q4\n[06]: nostr:naddr1qvzqqqrcvypzp5t83el0jefhfwl2xz9py9tqnfurwmwptqnh5lt9w6q0n4006hpcqqrxuat595crv3ltsuz\n[07]: nostr:naddr1qvzqqqrcvypzp5t83el0jefhfwl2xz9py9tqnfurwmwptqnh5lt9w6q0n4006hpcqqrxuat595crwz62n00\n[08]: nostr:naddr1qvzqqqrcvypzp5t83el0jefhfwl2xz9py9tqnfurwmwptqnh5lt9w6q0n4006hpcqqrxuat595crs4q9zck\n[09]: nostr:naddr1qvzqqqrcvypzp5t83el0jefhfwl2xz9py9tqnfurwmwptqnh5lt9w6q0n4006hpcqqrxuat595crjx9yptm\n[10]: nostr:naddr1qvzqqqrcvypzp5t83el0jefhfwl2xz9py9tqnfurwmwptqnh5lt9w6q0n4006hpcqqrxuat595cnqx5tye7\n[11]: nostr:naddr1qvzqqqrcvypzp5t83el0jefhfwl2xz9py9tqnfurwmwptqnh5lt9w6q0n4006hpcqqrxuat595cnz43282n\n[12]: nostr:naddr1qvzqqqrcvypzp5t83el0jefhfwl2xz9py9tqnfurwmwptqnh5lt9w6q0n4006hpcqqrxuat595cnyf7fzky\n[14]: nostr:naddr1qvzqqqrcvypzp5t83el0jefhfwl2xz9py9tqnfurwmwptqnh5lt9w6q0n4006hpcqqrxuat595cngcq0g8r\n","sig":"1ac4ebf5c85ce0088c296774304d9e7dae8538341d739b7ac5974092481b209f7318d58063bfe186e2fdc8fd9cb1ac2b8038ee5a9002edd061dead086cb70f3b"}