Optimized Groth16 verifier contract for BCH (Verifier.cash initiative)

BCH native Groth16 verifier contract

Earlier this week I launched a new initiative to build optimized Groth16 verifier contracts for Bitcoin Cash called Verifier.cash.

It’s a collaborative, open research project and competition to build the smallest Groth16 zero-knowledge proof verifier that runs on Bitcoin Cash. The initiative is inspired by ecdsa.fail which has seen great success and participation but uses it to try and break crypto. This mirror-image initiative is instead to build up and strengthen crypto.

Benchmarking

I started the leaderboards with the sCrypt BN254 verifier they built in 2022 and the nChain BLS12-381 verifier built in 2024 but neither of these verifiers fit within BCH’s VM limits or leverage the new BCH primitives like bounded loops and reusable functions.

First I built a verifier benchmark using Libauth to test against the BCH VM (with and without VM limits/contract limits enforced). then I used Opus 4.8 to build the first BCH Groth16 verifiers which leverage the new upgrades.

Categories

The leaderboard has 3 categories: a “single-input” version which is the most optimized ideal but does not fit in the contract or VM limits, a “single non-standard transaction” version which uses many contract inputs and only disregard the maximum transaction size limit, and thirdly a “standard transaction” version which ends up needing to split/chunk the verifier over 3 separate transactions, each with many contract inputs.

Results

From the website (as of writing), the smallest BN254 verifier built in BCH is the following size for each category

  • ~16 KB single input for the category ignoring VM and contract limits
  • ~288 KB single transaction, 33 inputs for category ignoring transaction size standardness
  • ~288 KB 3 transactions, 33 inputs for category with standard BCH transactions

The same Groth16 verifier shows up as two very different numbers. On BN254, as one input it is just 16 KB , the smallest and simplest form, but it busts Bitcoin Cash’s per-input limits and can’t run on chain. To actually fit, the work is split across 33 inputs, which brings the total to 258 KB .

That ~16× difference is the chunking overhead : the price of splitting one computation across many inputs, not extra cryptographic work. Entries are scored on total on-chain bytes, since bytes are what a user pays in fees.

Upgrades in action

The initiative highlights how Bitcoin Cash’s recent upgrades unlocked the power to run a Groth16 verifier on chain. BCH is entering the space age, and I don’t think people are realizing it.

Screenshots

8 Likes

Further Opcode optimizations

I asked Opus 4.8 to hand-optimize the opcodes directly for the smallest theoretical BN254 Groth16 verifier. It got the bytecode size down to under 10 KB, to 9.1 down from the prior 15 KB when using a compiler. This means the relative gap between the best single script input and VM limit compatible versions increased (from 16x to 28x) But this is mainly due to the need for further compiler optimizations

The same Groth16 verifier shows up as two very different numbers. On BN254, as one input it is just 9.1 KB , the smallest and simplest form, but it busts Bitcoin Cash’s per-input limits and can’t run on chain. To actually fit, the work is split across 33 inputs, which brings the total to 258 KB .

That ~28× difference is the chunking overhead : the price of splitting one computation across many inputs, not extra cryptographic work. Entries are scored on total on-chain bytes, since bytes are what a user pays in fees.

Solutions for the chunking overhead

next to the section on “What this measures:” there’s a subpage on solutions explaining how we could improve on this overhead. The solutions page talks about script size limits, base opcost, computation padding, read-only inputs and ‘Store & fetch off-stack constants’.

The solutions page has a section “Why not native curve opcodes?” , it is exactly opposite to the point of doing general cryptography in script to do local optimizations for EC ops and seeing this makes me wish i picked another ZKP

verifier.cash/solutions

2 Likes

Toorik set the new record for smallest Groth16 verifier in BCH when ignoring the VM limits, the smallest verifier is now only 4.6 kb for the BN254 curve, and only 3.7 kb BLS12-381!

An important asterisk for the Verifier.cash project is that while these are the record smallest verifiers and win on that metric, Tooriks new smallest verifiers balloon the opcost (compute cost metric) to 5 Billion and 20 Billion respectively.

With the new verifier highlighting how size and opcost represent a trade-off, the “score history” graphs now display the Pareto Frontier which shows what the best trade-off points are for the opcost vs bytesize tradeoffs.

The pareto frontier cleanly demonstrates that the chunking overhead is not the same as the naive bytesize gap from the best theorethical verifier to the BCH native verifier:

That ~52× gap is the full price of the VM limits. The chunking overhead itself is ~3.6×: the same split measured against the op-cost-optimized single input (67 KB), so both sides carry comparable compute.

The binding constraint to make a ZKP verifier which fits within the VM limits is the compute limits, so the implementation minimizing the opcost is the practical target to make the smallest VM limits compatible verifier.

3 Likes

Toorik announced on X today:

Achieved a milestone today: First ever full zk-SNARK, verified on-chain in a single standard Bitcoin Cash transaction — It attests Satoshi’s whitepaper title line. Here is the transaction This was inspired by the competition happening at verifier.cash. Check it out and join the fun!

interesting stats from the transaction: 95 KB in size and at 1sat/byte fee rate that’s 0.00095 BCH for the transaction fee (~0.22 USD at current prices)


Independently @kzKallisti achieved the same item with a different set of improvements, as part of the Verifier.cash challenge using GPT 5.6 Sol in loop-mode. The verifier is also mainnet-compatible and uses 13 inputs in a single transaction

what makes this breakthrough extra remarkable is that yesterday the best BCH compatible verifier in the competition was still 230 KB in size, so over a 55% improvement! AI is clearly making these types of rapid improvements and optimizations possible like it never was before.

Here is a screenshot of the current standing, but with the current progress the live stats may look even better

4 Likes