research: Poseidon2 vs Poseidon benchmark for transfer/withdraw circuits - #41
Open
alexandre-mrt wants to merge 1 commit into
Open
research: Poseidon2 vs Poseidon benchmark for transfer/withdraw circuits#41alexandre-mrt wants to merge 1 commit into
alexandre-mrt wants to merge 1 commit into
Conversation
Queue item #2. Forks transfer.circom and withdraw.circom under scripts/bench/poseidon2/ (not wired into the deployed protocol) with every circomlib Poseidon call replaced by a capacity-domain-separated Poseidon2 sponge (vendored from @taceo/circom-lib, cross-checked bit-for-bit against the independent @taceo/poseidon2 JS reference). Measured, real, verifying (groth16.verify = true) results at --O2 (full R1CS simplification): non-linear constraints -1.7% (transfer) / -7.7% (withdraw); Groth16 proving time -9.7% / -17.1% (mean of 10 real fullProve runs each). At Veil's actual default compile flags (--O1, no --O2 - same as circuits/scripts/compile.sh), the identical swap makes both circuits worse (+10-12% total constraints) due to unswept linear intermediates in Poseidon2's matrix-multiplication gadgets - a real compiler-flag sensitivity discovered mid-experiment. One hash shape (compliance's leafHash, needs t=5) is a net loss with the available Poseidon2 parameter sets (forced to t=8). Verdict: PARK, not KEEP - not a clean sweep, needs a fresh trusted-setup ceremony to ever deploy, and the O1-vs-O2 build-flag question deserves its own measurement first (now queued). Also re-attempted on-chain gas (queue item #1): still BLOCKED, now precisely diagnosed as a sandbox proxy allowlist (403 at the CONNECT layer), not a retriable denial. And discovered former queue item 13 (npm test hang) was already fixed upstream (PR #17) - removed as stale. Full suite green: 108/108 circuit tests, 109/109 converter, 67/67 compliance-utils, 19/19 frontend, 6/6 fuzz properties. Move tests not run (sui CLI still unavailable; no Move code touched). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014DYmywv78PsjAesXgGzToe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Nightly research loop, queue item #2 (
docs/research/EXPERIMENTS.md). Follows up on openquestion #4 from the 2026-07-22 baseline report: what would swapping circomlib's Poseidon for
Poseidon2 actually cost/save, measured, not guessed.
transfer.circomandwithdraw.circomunderscripts/bench/poseidon2/— not wiredinto the deployed protocol (
pool.move, verifying keys, and the frontend are untouched) — withevery Poseidon call replaced by a capacity-domain-separated Poseidon2 sponge
(
Poseidon2Hash(N, T, DS), vendored@taceo/circom-libpermutation, cross-checked bit-for-bitagainst the independent
@taceo/poseidon2JS reference).--O2(full R1CS simplification): non-linear constraints −1.7% (transfer) /−7.7% (withdraw); Groth16 proving time −9.7% / −17.1% (mean of 10 real
groth16.fullProveruns each, both circuits' proofsgroth16.verifydtrue).--O1, same ascircuits/scripts/compile.sh), theidentical swap makes both circuits worse (+10–12% total constraints) — unswept linear
intermediates in Poseidon2's matrix-multiplication gadgets. A real, previously-unknown
compiler-flag sensitivity, now its own queued follow-up (item feat: Tier 3 — KYC compliance circuit + ElGamal auditor pattern #2 in
EXPERIMENTS.md).leafHash, needst=5) is a net loss — the available Poseidon2parameter sets skip
t=5/t=6, forcing a jump tot=8.oldCommitment + 1) is rejected outright atwitness-generation time (
Assert Failed, not just "verification later fails").sandbox network-proxy allowlist (403 at the CONNECT layer for both
api.github.comandfullnode.testnet.sui.io) rather than a retriable tool-approval denial.circuits' chainednpm testhang) was already fixed upstream(fix(circuits): exit test runners explicitly after the last proof #17, 2026-07-28) — re-confirmed working, removed as stale rather than left inaccurate.
Verdict: PARK (not KEEP — not a clean sweep across all three circuits, and any real adoption
needs a fresh Groth16 trusted-setup ceremony this PR doesn't attempt; not REJECT — the core
hypothesis measured true for the dominant hash shapes). Full write-up, every raw command and its
output:
docs/research/2026-08-23-poseidon2-benchmark.md.docs/research/LEDGER.mdgets tonight's row;docs/research/EXPERIMENTS.mdis re-ranked with twonew follow-up items ahead of the old queue.
Test plan
Full suite run this session, everything that could run is green:
cd circuits && npm test→ 108/108 pass (43 transfer + 30compliance + 35 withdraw)
cd scripts && bun run src/test-converter.ts→ 109/109 passcd scripts && bun run src/test-compliance-utils.ts→ 67/67 passcd frontend && bunx vitest run→ 19/19 passcd scripts && bun run src/fuzz-tests.ts→ 6/6 properties pass (500runs each)
sui move test) — not run,suiCLI unavailable this session (samepre-existing gap as the 2026-07-22 baseline report); no Move code touched by this PR
@taceo/poseidon2JS reference (t=3, input
[1,2,3])oldCommitmentrejected at witness generation(
Assert Failed. Error in template TransferPoseidon2_29 line: 41)Generated by Claude Code