TYPE 0x0403 · RECURSION FAMILY

RECURSE_UNTIL

Time-bounded covenant. Must re-encumber the output with identical conditions until block height reaches the specified threshold, at which point the covenant terminates and the UTXO is free. No Tapscript equivalent.

Recursion Invertible
RECURSE_UNTIL height ≥ until_height ? free : re-encumber covenant terminates at target block height absolute height gate Time-bounded covenant — auto-expires at until_height
FieldData TypeSizeSideDescription
until_heightNUMERIC1-4 BConditionsAbsolute block height at which the covenant terminates. Before this height, the output must re-encumber with the same conditions; at or after, the spend is unconditionally satisfied. Compared against max(ctx.block_height, tx.lock_time) — spenders can use nLockTime to assert "this spend will be confirmed at height ≥ X" the same way CLTV does.
0x0403 0 1 NUMERIC · until_height Conditions = 9 bytes
0x0403 0 0 Witness = 4 bytes
Total 15 bytes
1.Locate the conditions NUMERIC field. Missing → ERROR. ReadNumericuntil_height; undecodable → ERROR
2.Compute effective_height = ctx.block_height. If a spending tx is present and its nLockTime < LOCKTIME_THRESHOLD (height-mode), substitute max(ctx.block_height, tx.lock_time). This lets the spender assert a future inclusion height the same way CLTV does.
3.If effective_height ≥ until_heightSATISFIED immediately. The covenant terminates; the output is free.
4.Otherwise (covenant still active): same identity check as RECURSE_SAME. If ctx.verified_leaves is set and ctx.spending_output present, call OutputRootMatchesInput; mismatch → UNSATISFIED
5.Else if ctx.input_conditions is set (fallback): extract MLSC root from the spending output, compare against ComputeConditionsRootMLSC(ctx.input_conditions, ctx.rung_pubkeys); mismatch → UNSATISFIED
6.No covenant context: structural check passed → SATISFIED (used by tooling). Otherwise root checks satisfied → SATISFIED

Vesting covenant: until_height = 850,000

Current block height: 849,500. Spend must re-encumber.

849,500 < 850,000 → must re-encumber
Output carries identical conditions → SATISFIED

Same covenant at block 850,000:

850,000 ≥ 850,000 → SATISFIED (covenant terminates, output is free)
{
  "type": "RECURSE_UNTIL",
  "fields": [
    { "type": "NUMERIC", "value": 850000 }
  ]
}

The until_height is an absolute block height. For a ~6-month lockup from current height ~840,000: use 840,000 + 26,280 = 866,280.

Vesting Schedules with Unlock Date
Employee token vesting that enforces re-encumbrance until a future block height. Before the cliff, funds can be moved but must remain covenanted. After the cliff, the covenant drops and funds are fully liquid.
Temporary Covenants
Restrictions that are useful only during a specific period (e.g., a governance vote window). The covenant enforces rules during the active period and automatically dissolves afterward.
Auto-Expiring Restrictions
Spending restrictions imposed by a counterparty that expire after a known block height. Useful for escrow arrangements where restrictions must not persist indefinitely.