Skip to content

NUT-10: Spending conditions

optional

used in: NUT-11, NUT-14


An ordinary ecash token is a set of Proofs each with a random string secret. To spend such a token in a swap or a melt 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 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.

Caution: 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 endpoint.

Basic components

An ecash transaction, i.e., a swap or a melt 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 Secrets 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:

[
kind <str>,
  {
    "nonce": <str>,
    "data": <str>,
    "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: Pay-to-Public-Key (P2PK)