mandatory
A keyset is a set of public keys that the mint Bob
generates and shares with its users. It refers to the set of public keys that each correspond to the amount values that the mint supports (e.g. 1, 2, 4, 8, ...
) respectively.
Each keyset additionally indicates its keyset id
, the currency unit
, and whether the keyset is active
or not.
Mints can have multiple keysets at the same time but MUST have at least one active
keyset (see NUT-01). Proofs
from inactive keysets are still accepted but new outputs (BlindedMessages
and BlindSignatures
) MUST be redeemed from active
keysets only.
Mints MUST generate a keysets for each unit
they support.
Wallets SHOULD store keysets the first time they encounter them along with the URL of the mint they are from. That way, wallets can choose Proofs
of all keysets of a mint from their database when selecting inputs for an operation. Wallets SHOULD spend Proofs
of inactive keysets first. When constructing outputs for an operation, wallets MUST choose only active
keysets (see NUT-00).
A wallet can ask the mint for a list of all keyset IDs via the GET /v1/keysets
endpoint.
Request of Alice
:
GET https://mint.host:3338/v1/keysets
With curl:
curl -X GET https://mint.host:3338/v1/keysets
Response GetKeysetsResponse
of Bob
:
{
"keysets": [
{
"id": <keyset_id_hex_str>,
"unit": <currency_unit_str>,
"active": <bool>
},
...
]
}
{
"keysets": [
{
"id": "009a1f293253e41e",
"unit": "sat",
"active": True
},
{
"id": "0042ade98b2a370a",
"unit": "sat",
"active": False
},
{
"id": "00c074b96c7e2b0e",
"unit": "usd",
"active": True
}
]
}
Wallets can request the list of keyset IDs from the mint upon startup and load only tokens from its database that have a keyset ID supported by the mint it interacts with. This also helps wallets to determine whether the mint has rotated to a new current keyset (i.e. added new active keysets and inactivated old ones) and whether the wallet should recycle all tokens from inactive keysets to currently active
ones.
A keyset id
is an identifier for a specific keyset. It can be derived by anyone who knows the set of public keys of a mint. Wallets CAN compute the keyset id
for a given keyset by themselves to confirm that the mint is supplying the correct keyset ID.
The keyset id
is in each Proof
so it can be used by wallets to identify which mint and keyset it was generated from. The keyset id
is also stored in BlindedMessages
sent to the mint and BlindSignatures
returned from the mint (see NUT-00).
Keyset IDs have a version byte (two hexadecimal characters). The currently used version byte is 00
.
The mint and the wallets of its users can derive a keyset ID from the keyset of the mint. The keyset ID is a lower-case hex string. To derive the keyset ID of a keyset, execute the following steps:
1 - sort public keys by their amount in ascending order
2 - concatenate all public keys to one byte array
3 - HASH_SHA256 the concatenated public keys
4 - take the first 14 characters of the hex-encoded hash
5 - prefix it with a keyset ID version byte
An example implementation in Python:
def derive_keyset_id(keys: Dict[int, PublicKey]) -> str:
sorted_keys = dict(sorted(keys.items()))
pubkeys_concat = b"".join([p.serialize() for p in sorted_keys.values()])
return "00" + hashlib.sha256(pubkeys_concat).hexdigest()[:14]
To receive the public keys of a specific keyset, a wallet can call the GET /v1/keys/{keyset_id}
endpoint where keyset_id
is the keyset ID.
Request of Alice
:
We request the keys for the keyset 009a1f293253e41e
.
GET https://mint.host:3338/v1/keys/009a1f293253e41e
With curl:
curl -X GET https://mint.host:3338/v1/keys/009a1f293253e41e
Response of Bob
(same as NUT-01):
{
"keysets": [{
"id": "009a1f293253e41e",
"unit": "sat",
"keys": {
"1": "02194603ffa36356f4a56b7df9371fc3192472351453ec7398b8da8117e7c3e104",
"2": "03b0f36d6d47ce14df8a7be9137712c42bcdd960b19dd02f1d4a9703b1f31d7513",
"4": "0366be6e026e42852498efb82014ca91e89da2e7a5bd3761bdad699fa2aec9fe09",
"8": "0253de5237f189606f29d8a690ea719f74d65f617bb1cb6fbea34f2bc4f930016d",
...
}
}, ...
]
}