gnark icon indicating copy to clipboard operation
gnark copied to clipboard

feat: export Verifying Key and Proof to snarkjs-compatible JSON

Open mysteryon88 opened this issue 4 months ago • 2 comments

Is your feature request related to a problem? Please describe.

Hi! I needed to integrate proofs generated in gnark with the Circom + snarkjs stack on curves BLS12-381 (and also BN254).
I couldn’t find any existing issues covering the gnark → snarkjs direction.
Therefore, I would like to add to gnark the ability to generate JSON files for the verification key and proof, compatible with snarkjs.

Describe the solution you'd like

I forked gnark and implemented export of:

  • verification_key.json (compatible with snarkjs groth16 verify),
  • proof.json (RAW → JSON in snarkjs format) for curves BLS12-381 and BN254. I would like this improvement to be merged into the main repository.

Proposed API (example)

// Export VK to snarkjs JSON format
func (vk *VerifyingKey) ExportVerifyingKey(w io.Writer) error 

// Export Proof to snarkjs JSON format
func (proof *Proof) ExportProof(publicSignals []string, w io.Writer) error 

Describe alternatives you've considered

  • Generating TON contracts directly from gnark (my original plan), but for production they still require further development and optimization.
  • Using external tools for format conversion, which adds extra steps and potential points of failure.

Additional context

I am working on zk-integration for the TON blockchain. On the library side I use circom + snarkjs, and for TON I generate verifier contracts (I have a separate npm package for that).
To connect this with gnark, I first implemented export to snarkjs-compatible JSON: this allows quick and reliable proof verification with a single command snarkjs groth16 verify, and then the verification key can be used to generate a smart contract for the TON blockchain.

Step-by-step description of the improvement

  1. Added a snarkjs backend for Groth16.
  2. Implemented 2 interfaces:
    1. Proof with ExportProof([]string, io.Writer) error
    2. VerifyingKey with ExportVerifyingKey(io.Writer) error
  3. Added implementations in prove.go and verify.go for each curve:
    1. Generation of files for BLS12-381 and BN254
    2. Stubs for other curves
  4. Covered with integration tests: via go test we generate verification_key.json and proof.json, and then call await groth16.verify(vkey, publicSignals, proof);
  5. go fmt
  6. go vet

Current behavior vs Expected behavior

  • Current: It is not possible to obtain verification_key.json / proof.json compatible with snarkjs directly from gnark.
  • Expected: It should be possible to call export functions in gnark and immediately verify with snarkjs groth16 verify vk.json public.json proof.json.

Why this is useful to others

  • Many projects have their pipelines built around snarkjs. Direct export from gnark will reduce glue code, minimize risk of errors, and speed up integration across ecosystems. It will also allow proofs generated in gnark to be verified directly in the browser.
  • Support for BLS12-381 and BN254 covers the vast majority of Groth16 use cases.

OS / Testing

  • OS: Windows 10
  • Testing: In the demo repository at mysteryon88/gnark-example/cubic, the cubic circuit from gnark examples is used. After running tests, keys/verification_key.json and proofs/proof.json are generated, which can be verified using snarkjs groth16 verify (see verify-snarkjs.test.ts).
  • Used: replace github.com/consensys/gnark => C:/.../GitHub/gnark (gnark-fork) or the package: https://github.com/mysteryon88/gnark-to-snarkjs (main)

I’ll be glad to get feedback. I haven’t created a PR yet, but you can already check the finished code in the forked repository mysteryon88/gnark.

mysteryon88 avatar Aug 20 '25 11:08 mysteryon88

This is nice, snarkJs/gnark compatibility is a topic we have also been working on. Here you have the "opposite" (verify a Circom proof using Gnark) https://github.com/vocdoni/circom2gnark

However, take into account that you might encounter some issues with the related tooling (depending on your use case). For instance, snarkJs uses a babyjubjub twisted edwards form, and gnark a reduced version (so each point must be transformed).

p4u avatar Sep 09 '25 16:09 p4u

Yes, I know this project — it actually inspired me partly. In parallel I wrote and published my own Go package: gnark-to-snarkjs

Until the PR gets accepted, I’ll keep maintaining it there.

mysteryon88 avatar Sep 09 '25 18:09 mysteryon88