ZK Proving
Cocoon's proving infrastructure provides cryptographic guarantees over execution. It is built on QMTree — a new state commitment structure — combined with a two-tier proof model that separates lightweight per-block commitments from full ZK proofs used for L1 settlement.
QMTree: A Better State Commitment
Ethereum's canonical state structure is the hex patricia merkle trie (HPT). It has well-known properties: proven over 10 years, supports arbitrary key-value storage, enables proofs of inclusion and exclusion. It also has well-known costs: O(log N) updates, large proof sizes due to extension and branch nodes, and a storage footprint that compounds across state versions.
QMTree replaces the HPT for Cocoon's execution commitment with a different design philosophy: append-only, indexed by transaction number (txNum).
Append cost
O(log N)
O(1)
Proof size
~10–30 KB
~1 KB
Namespace
Arbitrary key
Flat (txNum)
Storage overhead
Baseline
~3.7x smaller
Proof type
State inclusion
Execution proof
Each leaf in the QMTree commits to four components:
preStateHash — the state root before this transaction executed
stateChangeHash — a commitment to the exact state mutations this transaction caused
transitionHash — a commitment to the full EVM execution trace (every opcode, stack, memory step)
previousLeafHash — links to the previous leaf, forming a chain
This structure makes QMTree leaves proof-of-execution commitments: a leaf does not just say "this transaction happened" but cryptographically commits to exactly how the EVM executed it.
QMTree is live on the Hoodi testnet (qmtree branch). The flat txNum namespace means proof generation and verification are deterministic and parallelizable — no trie traversal, no path encoding.
Two-Tier Proof Model
No single proof type optimizes for all requirements. Light clients and L2 validators need fast, cheap commitments. L1 settlement contracts need heavyweight ZK proofs with full soundness guarantees. Cocoon uses both in a layered model.
Tier 1 — Pre-proofs: QMTree roots are computed per block during normal execution. These are lightweight commitments — no external prover needed. L2 validators can verify the chain of QMTree roots using only the block data and the leaf components. This provides fast finality for the optimistic case.
Tier 2 — ZK full proofs: Batches of blocks are sent to an external prover. The prover receives a witness (via debug_getWitness) capturing the full EVM state needed to re-execute the batch, generates a ZK proof, and returns a proof that can be verified on L1.
Range proofs: A range proof binds a batch of per-block QMTree roots to a single ZK proof. This allows the L1 rollup contract to verify that the ZK proof covers exactly the claimed set of blocks, without re-verifying each block individually.
Prover Component
The prover orchestrates witness generation and proof dispatch. It is pluggable — the default backend is Zilkworm, but any conforming ProverBackend can be substituted.
Prover workflow:
Receive a proof request for a block range
Call
debug_getWitnesson the local Erigon node to generate the execution witnessDispatch witness to the configured external prover backend
Receive the proof and proof metadata
Publish the proof as a
.segfile via the snapshot infrastructure
Supported backends:
Zilkworm
ZK (default)
Native integration, recommended for production
SP1
ZK
Succinct's SP1 prover
RISC0
ZK
RISC Zero zkVM
ZisK
ZK
Additional ZK backend
SGX
TEE
Trusted execution environment attestation
The SGX backend provides TEE-based attestations rather than ZK proofs. This is a weaker security model than a ZK proof but is faster and can be useful as a stepping stone or for internal auditing.
The multi-proof policy (see Verifier section) is strongly recommended for production deployments. Requiring independent proofs from two or more different backends eliminates the risk of a single prover implementation bug being exploited.
Verifier Component
The verifier validates incoming proofs from the P2P network or the local prover. It integrates directly with the consensus engine and rollup driver.
Key verifier capabilities:
Multi-proof policy — following the ethproofs model, the verifier can be configured to require N independent proofs from N different prover backends before accepting a batch. A single compromised or buggy prover cannot forge acceptance.
P2P proof distribution — proofs are gossiped over the P2P network as .seg files. Nodes that have not generated a proof locally can download and verify proofs from peers, enabling proof aggregation across the network.
Settlement — once a proof meets the multi-proof policy threshold, the verifier submits the proof and range proof to the L1 rollup contract for final settlement.
Use Cases
Verifiable eth_call — qm_call executes a call against a historical state and returns a QMTree proof alongside the result. The caller can verify that the returned value was produced by legitimate EVM execution at that state root.
Fraud proof foundation — QMTree's transitionHash commits to the full EVM trace, providing the cryptographic anchor needed for the three-level bisection fraud proof protocol (see Fraud Proofs).
ZK settlement — the Tier 2 ZK proofs plus range proofs are the final artifact submitted to L1 rollup contracts, replacing the trust-based optimistic model with cryptographic finality.
Key APIs
qm_getRoot
Get the QMTree root for a given block
qm_getLeaf
Get the leaf (all four components) for a given txNum
qm_getProof
Get a Merkle inclusion proof for a leaf
qm_call
Execute an eth_call and return the result with a QMTree execution proof
qm_callProof
Get a proof for a previously executed qm_call
qm_verifyProof
Verify a QMTree proof locally (without on-chain call)
Last updated