Skip to content
LogoLogo

Locks & policy locks

Every output has a lock: a kind byte and a payload. Spending it requires a witness that satisfies the lock (§4).

KindNameCommits toAddress prefix
0BURNup to 80 bytes of data; never spendablenone
1PUBKEY_HASHscheme id + key hash…1p
2MULTISIG_HASHscheme mask + m-of-n policy hash…1z
3POLICYscheme mask + hash of a spending policynone
16–127reserved1–64 bytes; rules arrive by soft forknone

Addresses are bech32m with the network's prefix: arrk (mainnet), tarrk (testnet), rarrk (regtest). Only PUBKEY_HASH and MULTISIG_HASH have addresses.

Multisig

A multisig policy is m of up to 15 distinct public keys. Keys may mix schemes (ML-DSA-65 and ML-DSA-87); the lock publishes the scheme mask so wallets can show exposure. The witness has exactly n slots with exactly m signatures, each in the position of its key.

Policy locks: a small language, not a VM

One lock kind covers the conditional spends that issuers and wallets need: vesting, escrow, cross-chain swaps, recovery paths, channel constructions.

KEY(pk)            a signature from pk
MULTI(m, pk…)      m of n signatures
AFTER(height)      tx.lock_time ≥ height            (absolute timelock)
OLDER(blocks)      the coin is at least N blocks old (relative timelock, via input sequence)
SHA3(digest)       a 32-byte preimage with sha3_256(preimage) == digest   (hashlock)
AND(p, q)  OR(p, q)  THRESH(k, p…)
  • Limits: depth ≤ 8, at most 20 distinct keys, 48 witness items, 64 KiB encoding.
  • Witness: the policy encoding followed by items consumed in pre-order (a signature, preimage or empty item per leaf).
  • No garbage: a non-empty item that fails verification invalidates the transaction, even in an unused branch.
  • Deterministic: timelocks are properties of the transaction (lock time, sequence, version), so validity never depends on which block includes it.

Because the language is fixed and non-interactive, wallets, the PST format and hardware signers can display exactly what a policy allows.

Templates

The SDKs ship policy builders (key, multi, after, older, sha3, and, or, thresh) and three templates:

TemplatePolicy (reference arrekta_core.policy)Guide
HTLCOR(AND(KEY(receiver), SHA3(digest)), AND(KEY(refund), AFTER(timeout_height)))HTLC swap
VaultOR(KEY(primary), AND(KEY(recovery), OLDER(delay_blocks)))Vault
VestingAND(KEY(holder), AFTER(unlock_height))Issue an asset

Transaction expiry and relative locks

Transaction version 2 adds valid_until (a transaction is invalid after that height, error tx-expired) and BIP 68-style relative locks through each input's sequence (tx-premature-relative). Expiry stops stale PSTs, swap offers and distributions from landing much later than intended.

Reserved kinds

Kinds 16–127 are valid to create and spendable by any non-empty witness until a soft fork gives them rules. Mempools treat them as non-standard, so nobody uses them by accident. See Soft-fork upgrades.