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 InvertibleLadder Diagram
Fields
| Field | Data Type | Size | Side | Description |
|---|---|---|---|---|
| until_height | NUMERIC | 1-4 B | Conditions | Absolute 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. |
Wire Format Breakdown
0x0403
0
1
NUMERIC · until_height
Conditions = 9 bytes
0x0403
0
0
Witness = 4 bytes
Total
15 bytes
Evaluation Logic
1.Locate the conditions NUMERIC field. Missing → ERROR. ReadNumeric →
until_height; undecodable → ERROR2.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_height → SATISFIED 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 → UNSATISFIED5.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 → UNSATISFIED6.No covenant context: structural check passed → SATISFIED (used by tooling). Otherwise root checks satisfied → SATISFIED
Worked Example
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)
JSON Wire Format
{
"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.
Use Cases
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.