Toward Comparable PQ Signature Benchmarks on EVM: Surface Taxonomy + Shared XOF/Test Vector Suite

On the mainnet ZK-from-PQ lane: my default “representative today” would be Groth16 on BN254 (widely deployed verifier shape on Ethereum L1), and optionally a second point for a PLONK/Halo2-style verifier if you think that’s the direction we should anchor for future-proofing. If you had to pick one to benchmark first, which would you choose?

On the L2/appchain / system-contract lane: I’m currently treating the minimal surface as ERC-7913-style verifier ABI, plus AA-facing validateUserOp (EntryPoint-bound) and ERC-1271 as adapters — with explicit message lanes to prevent replay-by-interpretation across surfaces. Do you think ERC-7913 is the right “lowest common denominator” ABI for this lane, or is there a better canonical interface you’d prefer?

(For context: I’ve now tagged the dataset rows with lane_assumption + wiring_lane so ZK-from-PQ vs native-PQ vs legacy don’t get mixed.)

Hey @Madeindreams — fully aligned that direct PQ verify on Ethereum L1 (in Solidity) isn’t a production path. That’s exactly how I’m framing it now: a worst-case stress test / upper bound, not a recommendation.

What changed since the earlier thread is that we turned this from “feels too expensive” into measured, reproducible numbers with explicit lanes, so people don’t mix enforcement surfaces.

1) L1 native PQ verify = upper bound (measured)

We actually benchmarked an ML-DSA-65 verify() POC in Solidity:

  • verify() POC: 68,901,612 gas (Foundry snapshot)

  • inner primitive (PreA compute_w_fromPacked_A_ntt): 1,499,354 gas

These are now recorded in a public dataset with provenance (pinned refs / harness needles / regen scripts).
So yes: not mainnet-viable — but now it’s a quantified ceiling that makes the “precompile/system-contract wins” tangible.

2) Mainnet realistic enforcement today = ZK-from-PQ lane

Agreed: the enforceable path on L1 is “PQ attestation via ZK”, not native verification.
For a first representative benchmark I’m using Groth16 on BN254 (widely deployed verifier shape on mainnet). I also keep room for a PLONK/Halo2-style point as a future anchor, but Groth16 seems like the best “today’s reality” baseline.

3) L2/appchain realistic enforcement = native primitive lane

Also aligned: the clean deployment target for native PQ verification is an L2/appchain where PQ verify is a system primitive (precompile/system contract equivalent) and the AA-facing flows are meaningful.

On the interface side I’m currently treating ERC-7913-style verifier ABI as the lowest-common-denominator surface, and layering AA/Wallet adapters (validateUserOp + ERC-1271) on top.

4) Why the Solidity POC is still useful

Not to claim viability — but to answer:

  • “How bad is it if we don’t have a primitive?” (now measured)

  • “What should a precompile/system-contract save?” (now quantifiable)

  • “How do we compare ZK-from-PQ vs native PQ without apples-to-oranges?” (lanes)

We’ve now added dataset markers to enforce that separation:

  • lane_assumption + wiring_lane so ZK-from-PQ vs native-PQ vs legacy envelope don’t get mixed in reports.

If you’re open: I’d love your preference on which single ZK verifier shape is the most representative to anchor first (Groth16 BN254 vs a PLONK/Halo2-style). My current default is Groth16-first purely because it’s deployed and comparable.