Ladder Script

A proposal to replace Bitcoin Script with typed, structured spending conditions

The problem

Bitcoin Script is a stack-based language from 2009. It works, but it has real limitations. Writing correct scripts is hard. Analysing them requires execution simulation. There is no way to express covenants, recursive conditions, or transaction-level constraints without ugly workarounds. The opcode model allows arbitrary data embedding (inscriptions, stamps), and there is no native path to post-quantum signatures.

Every proposal to fix one of these problems (CTV, APO, OP_VAULT, OP_CAT) adds individual opcodes that interact in unpredictable ways with each other and with the existing opcode set. The result is a growing pile of narrow fixes with no coherent model underneath.

What Ladder Script does

Ladder Script replaces the opcode model entirely. Instead of a stack machine that executes arbitrary instructions, spending conditions are declared as typed blocks arranged in rungs. Each block has a fixed type, fixed fields with enforced sizes, and a single evaluation function. No loops, no stack manipulation, no arbitrary data.

The name comes from ladder logic, the programming model used in industrial automation for decades. A ladder diagram has two vertical rails (power in, power out) connected by horizontal rungs. Each rung contains contacts (conditions) and a coil (output). Power flows left to right through a rung only if every contact is closed. If a rung fails, the next one is tried.

In Ladder Script, blocks within a rung are AND (all must pass) and rungs are OR (first passing rung wins). This gives you the same expressiveness as Bitcoin Script's IF/ELSE branching but with a deterministic, bounded evaluation model.

How it works

A simple example: a vault with a hot key for daily spending and a multisig fallback for recovery.

Rung 0: SIG(hot_key) AND CSV(144 blocks) → UNLOCK Rung 1: MULTISIG(2-of-3) → UNLOCK // Try rung 0 first: hot key signs, but must wait 144 blocks. // If rung 0 fails, try rung 1: any 2 of 3 recovery keys, no delay.

Ladder Script introduces a new transaction type, v4 RUNG_TX, which uses the TX_MLSC wire format. Outputs are 8 bytes each (value only, no script). One conditions_root per transaction defines a shared condition tree across every output, so an attacker writing arbitrary data can only choose 32 bytes per transaction (not 32 per output). The actual condition structure is only revealed at spend time in the witness — unrevealed rungs stay private. Structural anti-spam: per-tx caps (16 rungs, 8 blocks per rung, 16 fields per block), implicit field layouts on every block type, and a default-deny on raw HASH256 fields at the RPC layer.

You can describe conditions in a compact notation. or() emits one rung per branch; and() conjoins blocks within a rung; each rung's coil binds it to its target output:

ladder(or( and(sig(@hot_key), csv(144)), multisig(2, @key_a, @key_b, @key_c) ))
Up to 12× smaller per coin in chainstate, 3.5× smaller 100-output batch transactions, no regression at single-payment size. Post-quantum sigs amortise to ~17.8 vB per input via PQ_BATCH at N=100. See the sizing breakdown →
What you can build

Ladder Script has 65 block types across 11 families. Here are some things they enable that Bitcoin Script cannot do today:

Vaults with clawback. Lock funds with a hot key + timelock on rung 0, cold key sweep (no delay) on rung 1. The VAULT_LOCK block handles this in a single block.

Rate-limited wallets. RATE_LIMIT restricts how many satoshis per block can be spent. Even if your key is compromised, the attacker can only drain at the rate you set.

Recursive covenants. RECURSE_SAME forces the output to carry the same conditions as the input. RECURSE_COUNT counts down each hop. RECURSE_SPLIT lets a UTXO split into multiple re-encumbered outputs. All with bounded depth.

Per-output governance. OUTPUT_CHECK verifies that a specific output has the right value and script. Enforce that treasury spends route funds to the correct address.

Cross-input dependencies. COSIGN requires that another UTXO (identified by its script hash) is spent in the same transaction. Creates physical "key" UTXOs that must be present to authorise spending.

Post-quantum migration. Any signature block works with Schnorr, ECDSA, FALCON-512, FALCON-1024, Dilithium3, or SPHINCS+ by changing a single SCHEME byte. No new opcodes needed.

Post-quantum batch consolidation. PQ_BATCH commits SHA256(falcon_pubkey) per output. One "anchor" input in the spend tx reveals the pubkey + signature once; every other input gated by the same hash short-circuits via a tx-local cache. ~17.8 vB per input amortised at N=100 — about 22× cheaper than per-input FALCON-512 signatures (~400 vB each). No coordinator, no priming round. Built for exchange sweeps, co-owned UTXO pools, recurring subscription drains.

N-party atomic batches. QABIO commits a coordinator FALCON-512 pubkey, the full participant set, and the output set at fund time. Each participant primes their UTXO independently; the coordinator then signs a single FALCON aggregate covering every input. One verify per transaction, on-chain output-set binding, ~143 vB per participant at N=100. Built for exchange settlement, atomic issuance, pooled custody.

How small is the change

Ladder Script adds ~1,600 lines of changes to existing Bitcoin Core code across 32 modified files. Everything else is a self-contained library of ~21,900 lines in 39 new files (38 under src/rung/ plus the src/rung_shims.h boundary header). The patch does not modify any existing Bitcoin Script evaluation, signature verification, or consensus logic.

~1,600Lines patched
~21,900New lines
65Block types
665Unit tests
143Functional tests
27TLA+ specs

There is no contiguous attacker-chosen data block in a RUNG_TX transaction — every output shares one 32-byte conditions_root, every condition field has a fixed type and length, and inscriptions are structurally impossible. Per-tx witness data is bounded by hard caps on rungs, blocks, fields, and preimage count.

27 TLA+ specifications cover the consensus surface — evaluation semantics, anti-spam, wire format, Merkle proof security, sighash binding, covenant termination, cross-input rules. Full model-checking pass at consensus-level constants is in progress; smaller-constant runs verify the same properties on bounded state spaces.

Try it

Ladder Script is live on a dedicated signet. You can try it right now: