metaspace
Protocol / Rotation

Protocol

Rotation

A one-time key signs once. The lock rotates in the same instruction that spends it.

The key is one-time. That is the price of the construction, and it is the reason the lock rotates in the same instruction that spends it.

Why a key must never sign twice

Suppose one key signs two digests, mm and m′m'. For every chain the attacker now holds the lower of the two released values:

Hmin⁡(mi, mi′)(xi),i=1,…,34.H^{\min(m_i,\, m'_i)}(x_i), \qquad i = 1, \ldots, 34.

They can sign any digest m′′m'' whose chain lengths all sit at or above that floor:

mi′′≥min⁡(mi, mi′)for every i=1,…,34.m''_i \ge \min(m_i,\, m'_i) \quad \text{for every } i = 1, \ldots, 34.

With one signature the checksum rules this set down to mm itself. With two, the floor on the checksum chains is the lower of two checksums, and digests that satisfy the condition exist. The attacker needs no preimage. The program cannot detect that a key was used twice, so rotation is not a feature. It is a requirement.

What the program enforces

  • finalize_withdrawal sets Vault.commitment to CnextC_{\mathrm{next}} and increments Vault.nonce in the same instruction that pays out. There is no path that pays without rotating.
  • open_withdrawal rejects Cnext=CC_{\mathrm{next}} = C with CommitmentReused. Rotating to the same commitment would mean signing twice with one key.
  • init_vault and open_withdrawal both reject a zero commitment with ZeroCommitment. A zero commitment is a vault that can be funded and never emptied.
  • Vault.rotations counts completed rotations, so a wallet can show how many times a lock has turned.

What the client must do

The client derives chain secrets deterministically from the seed, so the key for state n+1n + 1 is computable before the key for state nn is revealed. See Recovery words for the derivation.

C(n)=H ⁣(metaspace:commitment:v1 ∥ H255(x1(n)) ∥ ⋯ ∥ H255(x34(n)))C^{(n)} = H\!\left(\texttt{metaspace:commitment:v1} \,\|\, H^{255}(x^{(n)}_1) \,\|\, \cdots \,\|\, H^{255}(x^{(n)}_{34})\right)