ROOTVIELROOTVIEL
← Academy

Module 5 · Research case studies

Evaluation deep-dive: what is actually established

The paper establishes security not with performance numbers but with a negative-test matrix: each property is stated as an invariant and exercised by the input that must violate it, labeled with the assurance level at which it is checked. This lesson works through that method — what a passing [V] test on the real on-chain Groth16 verifier actually proves, why an in-circuit-only [C] result is weaker, why mock-verifier [M] results are excluded from soundness entirely, and how the before-fix/after-fix pair turns the Proposition-1 bug into a reproducible regression test. It closes on the performance table, which the paper explicitly disclaims as indicative component-level estimates, not a benchmark harness.

Learning objective

Read the paper's evidence the way the paper itself frames it: a negative-test matrix with explicit assurance levels. Understand what [V] (real on-chain verifier), [C] (in-circuit only) and [M] (mock) each prove, why the paper excludes [C] and [M] from its soundness claims, and why the performance figures are indicative, not benchmarks.

Track
Research
Module
5 · Research case studies
Prerequisites
Architecture & algorithms deep-dive (case study, part 4) · What is a zero-knowledge proof

The method: negative tests, not benchmarks

The paper's evaluation philosophy is that a security property is established by the case that must fail. Each property is written as an invariant and exercised by an input designed to violate it; a correct system must reject that input. This is deliberately not a performance study — the paper says its claims are established by the negative-test matrix, not by timing numbers.

Two mechanisms do the rejecting, and they correspond to the two strong assurance levels. On-chain, a violating proof is submitted to the real deployed Groth16 verifier and must revert or return false. In-circuit, a violating witness must fail constraint satisfaction, so no valid proof exists to submit. The distinction between "the deployed contract rejects it" and "no proof could be built" is exactly the distinction between the two labels below.

Note

A negative test proves a specific violating input is rejected. It does not prove the absence of all vulnerabilities, and it is not a benchmark. Keep "the stated bad input fails" separate from "the system is secure in general" — the paper is careful about this and so is this lesson.

The three assurance levels

Every reported result carries one of three labels. Their strength is not equal, and the paper is explicit that only two of them support soundness claims.

[V] — real on-chain verifier
The violating proof is submitted to the real, snarkjs-generated Groth16 verifier contract under Foundry, and must revert or return false. Strongest reported level: it exercises the deployed verification path, not a stand-in. Still conditional on the development trusted setup.
[C] — in-circuit
The violating witness fails constraint satisfaction, so no valid proof exists. This proves the constraint is binding in the circuit — but NOT that a deployed contract path exercises it. The paper notes some [C] properties have verifier contracts that are not yet wired on-chain.
[M] — mock verifier
Only the contract state machine is exercised, with a proof accepted by a mock. An [M] test attests state-flow plumbing and NEVER a zero-knowledge property. The paper EXCLUDES [M] from all soundness claims.
Note

Why exclude [C] and [M] from the strongest claims? [M] uses a mock that accepts anything, so it cannot witness any cryptographic property. [C] proves the math binds but not that the deployed system routes a transaction through it — a contract could be correct in-circuit yet not wire the facet on-chain. The paper keeps each property at its own level and claims "no higher."

The negative-test matrix, read honestly

The properties and their reported levels, grouped by what they actually establish. These are the paper's reported results under its development setup — read them with the labels attached, not as a blanket "verified" stamp.

reported negative-test matrix (property -> must-fail case -> level)
WITHDRAWAL-PATH PROPERTIES (reported at [V], real on-chain verifier) double-spend same nullifierHash twice -> reverts [V] replay pool/chain-swapped proof -> returns false [V] proof-of-innocence PoI of note A reused on nh of B -> reverts [V] PoI integrity tampered public input -> reverts [V] VALUE / DISCLOSURE PROPERTIES (reported at [C], in-circuit only; not yet wired on-chain) value conservation over-withdraw / inflated change -> no valid proof [C] selective disclosure range faked vs. leaf amount -> no valid proof [C] shielded transfer minted output -> no valid proof [C]

The grouping is the point. The three withdrawal-path properties — single-nullifier, proof-of-innocence binding, replay — are the ones the paper verifies on the real verifier [V]. Value conservation, selective disclosure, and shielded transfer are in-circuit [C]: the constraints bind, but the paper states these facets are not yet wired on-chain. A reader who collapses both groups into "all verified" overstates the deployed assurance.

The before-fix / after-fix pair (TESTED)

For the Proposition-1 bug specifically, the paper runs the test twice: once against the vulnerable dual-nullifier circuit and once against the corrected single-nullifier circuit. This is what turns a claimed bug into a demonstrated, reproducible one.

synthetic — the regression pattern the paper reports
# BEFORE the fix (dual-nullifier circuit): deposit once; withdraw nh_decoy; withdraw nh_real reported: the SECOND withdrawal SUCCEEDS # the bug is real, on the real verifier [V] # AFTER the fix (single-nullifier circuit): deposit once; withdraw nh; withdraw nh (same note) reported: the SECOND withdrawal REVERTS # "Nullifier used" [V] (same note yields one deterministic nullifierHash)

The before-fix run must NOT reject — demonstrating the bug was real rather than hypothetical — and the after-fix run must reject. Running both on the real verifier is why the double-withdrawal claim is TESTED on the deployed path, not merely argued. The paper notes an early prototype instantiated exactly this pitfall; the single-nullifier construction supersedes it.

Note

TESTED is narrower than PROVEN. The [V] run shows the deployed verifier behaves as the invariant requires under the development setup. It does not by itself establish production security (which needs a multi-party ceremony) or any anonymity property. Theorem 1 is the proof; the [V] tests are its experimental confirmation.

The performance table: INDICATIVE, not a benchmark

The paper reports component-level figures, and is unusually explicit that they are NOT evidence of anything. The paper states the figures indicate feasibility only, are not from an N-run benchmark harness, and are "not used to support any security or performance contribution." They are reproduced here solely so you can recognize them — and recognize the disclaimer that must travel with them.

reported indicative component-level estimates (the paper disclaims these as NOT benchmarks)
Operation Proof time Gas (indicative) single-nullifier withdraw ~1.5 s ~2.9 x 10^5 partial withdraw ~2.0 s ~1.4 x 10^6 shielded transfer ~1.6 s ~0.6x of withdraw+redeposit proof of innocence ~2.1 s +~10^5 over base Circuit sizes (engineering context, not a result): partial-withdraw circuit ~13.6k constraints selective-disclosure circuit ~22.5k constraints

How to use these responsibly: the constraint counts are stable structural facts about the circuits and are fine as engineering context. The proof-time and gas numbers are single-run, environment-specific estimates the paper refuses to lean on; quoting them as "the system achieves X" would misrepresent the paper. If you need performance claims, the honest statement is "the paper reports feasibility but no benchmarked performance result."

Note

INDICATIVE is a third, weaker tier below TESTED and PROVEN. The paper also reports no classifier-based indistinguishability experiment — so there is no measured anonymity result either; the relevant metric (anonymity-set size on a populated deployment) is left to future work.

How to read the evaluation as a whole

Assembling the tiers gives a precise picture of what the paper does and does not establish:

  • ▸PROVEN (under trusted setup): Proposition 1 (in-protocol decoy unsoundness), Theorem 1 (one note, one spend), Theorem 2 (relayer binding). Conditional on assumptions H1–H4; "exactly as strong as the trusted setup."
  • ▸TESTED [V]: double-spend, replay, proof-of-innocence binding and integrity — rejected by the real on-chain Groth16 verifier under Foundry, including the before-fix/after-fix regression for the dual-nullifier bug.
  • ▸TESTED [C] (weaker): value conservation, selective disclosure, shielded transfer — binding in-circuit but with facets not yet wired on-chain.
  • ▸EXCLUDED [M]: mock-verifier results attest contract state-flow only and support no soundness claim.
  • ▸INDICATIVE only: proof time, gas, and circuit sizes — feasibility signals the paper explicitly declines to use as a performance contribution.
  • ▸OPEN / not measured: empirical anonymity (no indistinguishability experiment); production security (needs a multi-party ceremony and an independent audit).
Note

The single most important honesty move: never flatten these tiers into one word. "Proven," "tested on the real verifier," "binding in-circuit only," "indicative estimate," and "open" are five different strengths of claim, and the paper's credibility comes from keeping them apart. This case study does the same.

Exercise

Note

A summary of this paper says: "The construction is fully verified and achieves ~1.5 s proofs." Identify two ways this sentence misrepresents the paper's own evaluation, and rewrite it honestly.

Expected direction: First, "fully verified" collapses the assurance tiers: only the three withdrawal-path properties are at [V] (real on-chain verifier); value conservation, selective disclosure, and shielded transfer are in-circuit [C] with facets not yet wired on-chain, and mock [M] results are excluded from soundness. Second, "achieves ~1.5 s proofs" presents an indicative component-level estimate as a result, which the paper explicitly disclaims as not from a benchmark harness and not supporting any performance contribution. An honest version: "The withdrawal-path properties (double-spend, replay, proof-of-innocence) are tested as rejected on the real on-chain Groth16 verifier under a development trusted setup; value/disclosure properties are established in-circuit only; reported proof times are indicative feasibility estimates, not benchmarks."

Check your understanding

What does a [V] result prove that a [C] result does not?
That the real deployed Groth16 verifier contract rejects the violating input on-chain. A [C] result only proves the constraint is binding in-circuit (no valid proof exists); it does not show a deployed contract path exercises it, and some [C] facets are not yet wired on-chain.
Why does the paper exclude mock-verifier [M] results from soundness claims?
A mock verifier accepts proofs without real verification, so an [M] test exercises only the contract state machine, never a zero-knowledge property. It attests plumbing, not cryptographic soundness.
What is the purpose of running the dual-nullifier test both before and after the fix?
Before the fix the second withdrawal must succeed, demonstrating the bug is real on the deployed verifier; after the fix it must revert ("Nullifier used"). The pair turns the Proposition-1 bug into a reproducible regression on the real verifier.
How should the reported proof-time and gas numbers be cited?
As indicative component-level feasibility estimates that the paper explicitly disclaims as not from a benchmark harness and not used to support any performance contribution — never as a measured performance result.

References

  1. [1]J. Groth — On the Size of Pairing-Based Non-Interactive Arguments (Groth16), EUROCRYPT 2016
  2. [2]Grassi, Khovratovich, Rechberger, Roy, Schofnegger — Poseidon: A New Hash Function for Zero-Knowledge Proof Systems, USENIX Security 2021
  3. [3]Buterin, Illum, Nadler, Schär, Soleimani — Privacy Pools: Making Blockchain Privacy Compliant

References point to public, well-known technical sources for further study.

Related articles