Hi everyone,
I’m proposing [EIP-0045] https:// github. com/ergoplatform/eips/pull/103 : a native verifyStark opcode for Ergo, enabling post-quantum zero-knowledge proof verification as a first-class L1 primitive.
The Problem
Implementing a STARK verifier in ErgoScript is theoretically possible but practically infeasible. The JIT cost of interpreting hundreds of hash operations and field arithmetic instructions through the bytecode interpreter exceeds the per-block budget. Empirical testing shows a full FRI verification at 128-bit PQ security requires ~784,000 JIT units of hashing alone, before accounting for field arithmetic and interpretation overhead.
The Solution
A native verifyStark opcode that runs as compiled JVM code, eliminating interpretation overhead and reducing cost by an estimated 10–100×. One opcode, entire zkVM ecosystem unlocked.
verifyStark(
proofChunks: Coll[Coll[Byte]],
publicInputs: Coll[Byte],
imageId: Coll[Byte],
vmType: Int,
costParams: Coll[Int]
): Boolean
Key Design Decisions
Registry-based zkVM architecture. The opcode does not accept arbitrary AIR constraints (which would be an unbounded DoS vector). Instead, each vmType maps to a hardcoded, audited set of transition constraints (e.g., RISC Zero’s RISC-V CPU, SP1, Valida). Adding a new zkVM requires a node update but not a new hard fork.
Post-quantum by default. BabyBear field with degree-16 extension (Ext16), Blake2b-256 with tweakable hashing, Q=35 queries, blowup 2048. No grinding. All security comes from cryptographic parameters. Poseidon2 is explicitly rejected due to subspace trail attacks (Grassi et al. 2025), only Poseidon1 with dense Cauchy MDS is used.
AOT-safe costing. The costParams argument lets the node compute JIT cost in O(1) before execution begins, with a fail-fast mechanism if actual proof parameters exceed declared values.
Proof delivery via Context Extensions. STARK proofs are chunked across Var(0)–Var(7) as Coll[Coll[Byte]], bypassing both ErgoScript concatenation penalties and SigmaSerializer OOM bounds.
Why eUTXO + Native ZK Is Unique
In the eUTXO model, each box is an independent state object. There is no shared global state between ZK-verified boxes. This means:
- No state contention: multiple users can submit ZK proofs concurrently without conflicting
- Atomic multi-proof transactions: a single TX can consume multiple boxes, each with its own independently verified ZK proof
- Permissionless by default: no centralized verifier contract to deploy, verification is a node-level primitive
This is something no account-model chain can offer.
Network Parameter: maxTransactionSize → 256 KB
With production optimizations (Batched Merkle Openings + Radix-8 FRI Folding):
- Minimal STARKs (D=16): ~69 KB → fits in current 96 KB
- Full zkVM RISC-V traces (D=27): ~237 KB → requires 256 KB
256 KB is exactly 50% of the current 512 KB maxBlockSize, preserving ample space for standard L1 operations. The proof size math is detailed in the EIP with a reproducible Rust benchmark.
At 360 nanoERGs/byte minimum relay fee, a full-scale zkVM transaction yields ~0.085 ERG baseline miner fee just for byte weight, directly incentivizing miners to vote for the soft-fork.
Use Cases
- Privacy pools (single-TX withdrawal instead of multi-TX FSM)
- ZK rollups (batch settlement in independent boxes)
- Anonymous credentials (prove set membership without revealing identity)
- Verifiable computation (ML inference, cross-chain state proofs)
- Cross-chain light clients (trustless bridges)
Activation
Soft-fork via miner voting (new treeVersion, following EIP-0050’s version 3). No hard fork required.
Full Specification
The complete EIP with cryptographic parameters, AOT cost model, proof size analysis, and ErgoScript example: [PR #103] https:// github .com/ergoplatform/eips/pull/103
Looking forward to community feedback, especially on the cryptographic parameter choices, the registry architecture, and the maxTransactionSize governance question.