Skip to content

NUT-14: Hashed Timelock Contracts (HTLCs)

optional

depends on: NUT-10


This NUT describes the use of Hashed Timelock Contracts (HTLCs) which defines a spending condition based on NUT-10's well-known Secret format. Using HTLCs, ecash tokens can be locked to the hash of a preimage or a timelock. This enables use cases such as atomic swaps of ecash between users, and atomic coupling of an ecash spending condition to a Lightning HTLC.

HTLC spending conditions can be thought of as an extension of P2PK locks NUT-11 but with a hash lock in Secret.data and a new Proof.witness.preimage witness in the locked inputs to be spent. The preimage that was used to spend a locked token can be retrieved using NUT-07. Caution: applications that rely on being able to retrieve the witness independent from the spender must check via the mint's info endpoint that NUT-07 is supported.

Caution: If the mint does not support this type 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.

HTLC

NUT-10 Secret kind: HTLC

If for a Proof, Proof.secret is a Secret of kind HTLC, the hash of the lock is in Proof.secret.data. The preimage for unlocking the HTLC is in the witness Proof.witness.preimage. All additional tags from P2PK locks are used here as well, allowing us to add a locktime, signature flag, and use multisig (see NUT-11).

Here is a concrete example of a Secret of kind HTLC:

[
  "HTLC",
  {
    "nonce": "da62796403af76c80cd6ce9153ed3746",
    "data": "023192200a0cfd3867e48eb63b03ff599c7e46c8f4e41146b2d281173ca6c50c54",
    "tags": [
      [
        "pubkeys",
        "02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904"
      ],
      ["locktime", "1689418329"],
      [
        "refund",
        "033281c37677ea273eb7183b783067f5244933ef78d8c3f15b1a77cb246099c26e"
      ]
    ]
  }
]

A Proof with this Secret can be spent in two ways. To spend the hash lock, the witness in Proof.witness includes the preimage to Secret.data and a signature from the key in Secret.tag.pubkeys. Additionally, if the current system time is later than Secret.tag.locktime, the Proof can be spent if Proof.witness includes a signature from the key in Secret.tags.refund.

The hash lock in Secret.data and the preimage in Proof.witness.preimage is treated as 32 byte data encoded as 64 character hex strings.

See NUT-11 for a description of the signature scheme, the additional use of signature flags, and how to require signature from multiple public keys (multisig).

Witness format

HTLCWitness is a serialized JSON string of the form

{
  "preimage": <hex_str>,
  "signatures": <Array[<hex_str>]>
}