feat(interop): snarkjs-compatible JSON export and bidirectional verification CI (#31) - #58
Merged
Merged
Conversation
…ication CI (#31) ADR-0047. Adds SnarkjsGroth16Json / SnarkjsPlonkJson in zeroj-crypto (package crypto.snarkjs) that write proof.json, verification_key.json and public.json byte-identical to snarkjs 0.7.6 (bfj writer), failing closed on any non-canonical value; KATs pin the format against every snarkjs-written BLS12-381 artifact in the repo. Live interop suites in zeroj-integration-tests (it.snarkjs.*) verify both directions for Groth16 and PlonK against the pinned snarkjs CLI with tamper negatives, and a new snarkjs-interop assurance job runs them with -PrequireSnarkjs so a missing or wrong-version oracle fails. Findings pinned by tests and documented in the ADR: snarkjs' vk_alphabeta_12 is the cube of ZeroJ's pairing (wasmcurves cyclotomic final exponentiation); snarkjs writes an empty public.json as "[\n]" (bfj, not JSON.stringify); snarkjs plonk verify ignores vk.w, so the exporter requires the canonical root and ZeroJ's root-of-unity chain is pinned against ffjavascript; the snarkjs CLI exits 1 for both a rejection and a crash, so verdicts are classified by output. The shared SnarkjsProver runner now redirects output before its timed wait so a hung child cannot bypass the timeout. The snarkjs PlonK vector moves to zeroj-test-vectors as the single shared copy. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WRtUQPK45PkawH22huhT1K
22 tasks
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.
Closes #31 (Phase 1 of #54). Design and evidence: ADR-0047.
What
zeroj-crypto, new packagecrypto.snarkjs):SnarkjsGroth16JsonandSnarkjsPlonkJsonwriteproof.json,verification_key.json,public.jsonbyte-identical to snarkjs 0.7.6, failing closed on any non-canonical value (infinity, off-curve, off-subgroup, scalar outside[0, r), non-canonical PlonKw). No new module dependencies; hand-written writer, no Jackson.zeroj-crypto): byte-identical re-export of every snarkjs-written BLS12-381 artifact in the repo, thevk_alphabeta_12relation, JVM round trips through the snarkjs codec + ZeroJ verifiers, egress rejections.zeroj-integration-tests,it.snarkjs.*, defaulttesttask, skip without snarkjs): ZeroJ Groth16/PlonK proofs and ZeroJ-native keys verified bysnarkjs groth16/plonk verifywith ten tamper negatives; live snarkjs proofs verified by pure-Java and blst Groth16 verifiers and the PlonK verifier; an offline differential test pins the exporter's selector-infinity policy againstPlonkBLS12381Verifier.snarkjs-interopjob inassurance.yml(Node 22,snarkjs@0.7.6,-PrequireSnarkjsmakes a missing or wrong-version oracle a failure, 45 min timeout).ci.ymlstays pure Java.zeroj-verifier-plonktest resources tozeroj-test-vectors(single copy;.gitattributespins LF on the vectors).SnarkjsProverredirects output before its timed wait so a hung child cannot bypass the timeout, with descendant cleanup and two process regression tests.Findings worth a reviewer's attention
vk_alphabeta_12equalse_ZeroJ(alpha, beta)^3: wasmcurves uses the cyclotomic final exponentiation (3x the hard part), ZeroJ the exact(p^12-1)/r. Pinned by KAT on three snarkjs keys, a live key, and the generator; the KAT also asserts the uncubed value does not match.JSON.stringify: an emptypublic.jsonis[\n].snarkjs plonk verifyignoresvk.wand derivesFr.w[power]; ZeroJ's verifier reads it. The exporter requires the canonical root, and ZeroJ's root-of-unity chain is pinned against ffjavascript at powers 3, 8, 16, 24, 32.OK!vs the pinned rejection strings), so a negative test cannot pass on a crash.Risk / scope
R2 for the exporter (egress serialization boundary), R1 for CI and docs. Additive: no prover, verifier, transcript or maturity claim changes. Known gap: a ZeroJ proof under a snarkjs PlonK zkey is not covered because
PlonKZkeyImporterBLS381does not expose the A/B/C wire maps.Verification
./gradlew build verifyDefaultModuleSurfaceit.snarkjs.*+ process regressions0.1.0-pre12-7bf569d-SNAPSHOTThe assurance job has run only as a local emulation of its exact command line; this PR is its first run on GitHub Actions.
🤖 Generated with Claude Code