verifier.cash
← back

Which limits to raise

Bitcoin Cash caps the script that unlocks each input (each coin a transaction spends) at 10,000 bytes, and those same bytes set how much computation the input may do, so today a proof verifier has to be split across many inputs or padded with filler bytes just to buy computation. Raising the limits would let a whole verifier run in one input, which makes it simpler and easier to review, and for most proof systems smaller.

Larger inputs help every proof system: every verifier becomes one program, and PLONK and the post-quantum STARK also get smaller. A larger fixed compute budget per input (the op-cost base) mainly helps Groth16, and it is the one change that needs proof it cannot be abused to overload nodes. A larger transaction size only matters for the biggest proofs: the post-quantum STARK private spend already fits in one standard transaction today.

changeGroth16PLONKpost-quantum STARKconsensus or relay
Today27.6 KB, 3 inputs83–90 KB, 10 inputs98.7 KB, 12 inputs–
Per-input limits to 100 KBone input, slightly larger: 29.3–29.5 KB63–70 KB, one input91–95 KB, one inputunlocking: consensus and relay; stack item: consensus
+ larger fixed compute budget (op-cost base)21.9 KB, one input59–66 KBno changeconsensus and relay
Transaction size above 100 KBnot needednot neededonly the largest test proof (156–160 KB)relay

Total on-chain bytes to verify one proof, all measured. Each row adds to the one above it.

Details and sources

Groth16: the smallest sound BN254 verifier on the leaderboard that runs on BCH today, and the reviewed single-input build sound-si-gls-single (live from the leaderboard data). Its one-input figure is measured with padding on the shipped proofs, up to an estimate for the heaviest known honest witness. PLONK: four gnark circuits on the Aztec Ignition setup, five proofs each; for example mul2 is 83.2 KB today, 63.3 KB in one 100 KB input and 59.3 KB with the higher base (PLONK report, Track 7). STARK: the 128-bit zero-knowledge private spend (M1, 24 statements): today 1 transaction, 12 inputs, 98,690 B; in one 100 KB input its unlocking is 91.4–95.0 KB at 47–49% of the input’s compute budget, so the higher base buys nothing. The largest test proof (M2, two tables) needs two 100 KB inputs and a 156–160 KB transaction (STARK report, Track 8).

Raise the per-input limits to 100 KB

Two limits stop a verifier at 10,000 bytes per input: the unlocking script and the largest single item on the stack. Both are consensus rules, which decide what a valid block may contain. The unlocking limit is also a relay rule: node policy, which decides what nodes pass on and so what a wallet can broadcast. If only consensus rises, a larger input is valid but has to go to a miner directly.

With 100 KB inputs, every verifier we measured fits in one input. PLONK shrinks by about a quarter and the STARK by several kilobytes. Groth16 even grows slightly (27.6 → 29.3 KB): in one input it still has to add filler bytes to pay for its compute.

Details and sources

An existing transaction-format proposal sets these per-input limits to 100,000 B but keeps today’s compute rule. Groth16 grading under that rule is described in how the competition works.

Raise the op-cost base

Op-cost is the VM’s count of computation. Each input may spend an amount proportional to its own length, so a script that needs more compute than its bytes buy adds padding: filler bytes that do nothing but raise the budget. A Groth16 verifier is such a script. Adding a large fixed amount to every input’s budget removes the padding: the BN254 verifier drops to 21.9 KB. PLONK gains about 4 KB; the STARK uses under half its budget and gains nothing.

This is what the leaderboard’s bch-spec section tests, using an experimental mode of the libauth library. No upgrade proposal includes it.

Details and sources

An input’s budget is (base + unlocking length) × 800. Today the base is 41; bch-spec sets it to 10,000, which gives every input 8 million op-cost whatever its size. That breaks the link between work and bytes paid for: bench issue #35 shows a 454-byte transaction carrying 220× today’s op-cost per byte. A real proposal would need a per-transaction or per-byte bound as well.

A smaller step would also help. If each unlocking byte bought k times today’s op-cost, builds that recombine reviewed techniques would shrink the smallest verifier like this (size caps aside; frontier report, 2026-10-28):

budgetBN254 before → afterBLS12-381 before → after
2×21.9 → 20.0 KB26.5 → 23.0 KB
5–10×21.9 → 16.6 KB26.5 → 18.9 KB
25×21.9 → 9.1 KB26.5 → 9.6 KB
100×9.6 → 9.1 KB12.4 → 8.7 KB

These builds are on the leaderboard, but each is over the compute budget of the rules it targets, so none is deployable yet.

Raise the transaction size

A standard transaction may be at most 100,000 bytes. This is a relay limit, and it only binds the largest proofs: our two-table STARK test proof needs 156–160 KB. The STARK private spend already fits today, in one transaction of 98,690 bytes, accepted by a Bitcoin Cash Node with default relay policy.

Details and sources

Relay policy also caps a pay-to-script locking script at 201 B. Node acceptance: node check.

What it costs nodes

On a Bitcoin Cash Node, checking one proof took about 3.5 ms for Groth16, 10.7–11.7 ms for PLONK and 16.6–17.0 ms for the STARK private spend. Today every unit of op-cost is paid for in bytes, so a node’s worst case per byte stays bounded. Larger inputs keep that rule. Raising the base breaks it, so it needs a denial-of-service argument, which we have not made.

Details and sources

Times from the node check (stock BCHN 29.1.0, one machine, today’s rules). BCHN charges the body bytes of each OP_DEFINE as op-cost on top of what libauth counts; the figures above include it. For scale, the worst signature-heavy standard transaction among the published VM benchmarks takes about 0.1 s, and op-cost charges this big-number arithmetic 5–18× more per nanosecond than signature checks (op-cost timing report, one machine).

Simpler to build, simpler to review

A verifier split across inputs is several programs plus a protocol that links them, and every seam is a place for a bug. In one input, a review can follow the math from start to finish. The headroom also allows a cleaner construction: the single-input BN254 build commits every intermediate value to its proof transcript, which makes its soundness argument more direct (see the soundness review). In our view, easier to trust matters more than smaller.

Why not native opcodes?

Curve opcodes would fix one curve and more pre-quantum cryptography into consensus, while larger limits help every contract and proof system. With those limits, a script verifier already fits in one input, which leaves an opcode little to win.