# 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)**.

| Property         | Hex Patricia Trie | QMTree          |
| ---------------- | ----------------- | --------------- |
| 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.

{% hint style="info" %}
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.
{% endhint %}

## 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.

```mermaid
flowchart TD
    subgraph "Per-Block (Tier 1)"
        B1["Block N"] --> L1["QMTree Leaf\n(preState, stateChange,\ntransition, prevLeaf)"]
        B2["Block N+1"] --> L2["QMTree Leaf"]
        B3["Block N+2"] --> L3["QMTree Leaf"]
        L1 & L2 & L3 --> ROOT["QMTree Root\n(per-block commitment)"]
    end

    subgraph "Per-Batch (Tier 2)"
        ROOT -->|"batch of blocks"| WIT["Witness Generation\n(debug_getWitness)"]
        WIT --> PROVER["External Prover\n(Zilkworm / SP1 / RISC0 / ZisK / SGX)"]
        PROVER --> ZKP["ZK Proof\n(full soundness)"]
        ZKP --> SEG["Proof Segment (.seg file)"]
    end

    subgraph "Settlement"
        ROOT -->|"range proof binds\npre-proofs to ZK proof"| RANGE["Range Proof"]
        ZKP --> RANGE
        RANGE --> L1C["L1 Rollup Contract"]
    end
```

**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:

1. Receive a proof request for a block range
2. Call `debug_getWitness` on the local Erigon node to generate the execution witness
3. Dispatch witness to the configured external prover backend
4. Receive the proof and proof metadata
5. Publish the proof as a `.seg` file via the snapshot infrastructure

Supported backends:

| Backend  | Type         | Notes                                          |
| -------- | ------------ | ---------------------------------------------- |
| 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.

{% hint style="warning" %}
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.
{% endhint %}

## 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](/components/fraud-proofs.md)).

**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

| Method           | Description                                                              |
| ---------------- | ------------------------------------------------------------------------ |
| `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)                    |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://cocoon.erigon.tech/components/zk-proving.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
