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 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.
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 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
Proofsbeing spent Secretcontaining the rules for unlocking aProof- Additional witness data satisfying the unlock conditions such as signatures
- Outputs referring to the
BlindedMessageswith new unlock conditions to which theProofsare spent
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 are provided as BlindedMessages 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)
}
]
kindis the kind of the spending conditionnonceis a unique random stringdataexpresses the spending condition specific to each kindtagshold additional data committed to and can be used for feature extensions
Tag format
The optional tags field is an array of arrays of
non-empty strings.
Each 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).
Examples of valid tags:
["pubkeys"] - a tag with the key,
"pubkeys" and no tag values.
["pubkeys", "021..."] - a tag with the key,
"pubkeys" and ONE tag value.
["pubkeys", "021...", "022..."] - a tag with the key,
"pubkeys" and TWO tag values.
Examples of invalid tags:
[] - a tag array must contain at least
ONE or more strings
["locktime", 1765300829] - a tag must contain
strings only
["locktime", ""] - a tag must contain
non-empty strings only
Examples
Example use cases of this secret format are
Mint info setting
The NUT-06 nuts object
indicates support for this feature:
{
"10": {
"supported": true
}
}