groth16-zorch
A Groth16 prover implementation in Python using Zorch. This is the Python counterpart of RabbitSNARK, which implements the Groth16 proving scheme using HLO via PrimeIR and ZKX.
| Project | Language | Backend |
|---|---|---|
| rapidsnark | C++ | Native |
| RabbitSNARK | C++ | HLO (ZKIR/ZKX) |
| groth16-zorch | Python | FRX |
Features
- Parse circom proving key (
.zkey) files - Circom witness from a pre-computed
.wtnsfile (e.g. produced by snarkjs) - Load gnark binary exports for circuit proving
- Az/Bz evaluated in pure FRX (
frx.ops.segment_sumover the BN254 field dtype), so they run on the GPU alongside the prover — no native library needed - Groth16 proof generation with snarkjs-compatible JSON output
Installation
Python 3.11 on Linux x86_64 only.
CPU
pip install groth16-zorch
GPU (CUDA 12)
pip install groth16-zorch 'frx[cuda12]' \
--extra-index-url https://fractalyze.github.io/pypi/simple/
The extra index carries the CUDA plugin wheels, which are too large for PyPI's per-file limit. It is not needed for the CPU tier.
Verify
python -c "import frx, groth16_zorch; print(frx.devices()); print(groth16_zorch.__version__)"
[CpuDevice(id=0)] means the CPU tier; a CUDA install prints the GPU devices.
How to build
-
Clone the repository
git clone https://github.com/fractalyze/groth16-zorch.git
-
Navigate to the project directory
cd groth16-zorch
-
Install the package
pip install -e .
For development with test dependencies:
pip install -e ".[dev]"
How to run
CLI
Circom
# Witness is a pre-computed .wtns (e.g. `snarkjs wtns calculate`)
groth16-zorch circom prove <circuit.zkey> <witness.wtns> <proof.json> <public.json>
groth16-zorch circom verify <vkey.json> <public.json> <proof.json>
Gnark
groth16-zorch gnark prove <export_dir> <proof.json> <public.json> [--no-zk] [--deterministic]
groth16-zorch gnark verify <export_dir> <public.json> <proof.json>
Python API
Circom (.zkey + .wtns)
import numpy as np
from zk_dtypes import bn254_sf_mont
from groth16_zorch.circom.wtns import parse_wtns
from groth16_zorch.circom.zkey import parse_zkey
from groth16_zorch.circom.zkey_to_terms import zkey_to_terms
from groth16_zorch.groth16 import compile_circom, write_public_signals
from groth16_zorch.r1cs import compute_abc
zkey = parse_zkey("path/to/circuit.zkey")
compiled = compile_circom(zkey) # one-time: parse zkey, build term matrices + arrays
wtns = parse_wtns("path/to/circuit.wtns")
witness_mont = wtns.data._witnesses.view(np.dtype(bn254_sf_mont))
_terms, coefficients = zkey_to_terms(zkey)
az_mont, bz_mont = compute_abc(
witness_mont, compiled.terms, coefficients, compiled.domain_size
)
z_std = wtns.data._witnesses
public_signals = write_public_signals(wtns.witnesses, compiled.config.num_public)
proof, public_signals = compiled.prove(z_std, az_mont, bz_mont, public_signals)
Gnark binary export
import numpy as np
from frx import lax
from zk_dtypes import bn254_sf, bn254_sf_mont
from groth16_zorch.gnark import load_gnark_export
from groth16_zorch.groth16 import compile_gnark
# The export carries the solved witness and Az/Bz (solution_a/b), both
# produced by gnark's Go solver — nothing is recomputed here.
data = load_gnark_export("path/to/export/")
compiled = compile_gnark(data)
z_std = np.asarray(
lax.convert_element_type(data.witness_full.view(bn254_sf_mont), bn254_sf)
)
public_signals = [str(int(z_std[i])) for i in range(compiled.config.num_public)]
proof, public_signals = compiled.prove(
z_std, data.az_mont, data.bz_mont, public_signals
)
The output proof.json and public.json follow the same JSON schema as
snarkjs, so you can verify with:
snarkjs groth16 verify verification_key.json public.json proof.json
Compatibility
Circom / snarkjs
groth16-zorch is input/output compatible with the circom/snarkjs ecosystem:
| snarkjs | rapidsnark | groth16-zorch | |
|---|---|---|---|
Input .zkey |
yes | yes | yes |
Input .wtns |
yes | yes | yes |
Output proof.json |
snarkjs format | snarkjs format | snarkjs format |
Verify with snarkjs groth16 verify |
yes | yes | yes |
Gnark
groth16-zorch loads binary exports produced by a gnark Go program (see
tests/gnark/gen_fixture for a minimal example). The export must include
witness_full.bin and solution_a/b.bin — the witness and Az/Bz that gnark's
r1csTyped.Solve computes natively:
| gnark (Go) | groth16-zorch | |
|---|---|---|
Binary export (metadata.json + *.bin) |
produces | consumes |
| Proving key points | setup | loaded from export |
| Witness + Az/Bz | Go solver | loaded from export |
| Proof generation | groth16.Prove() |
compiled.prove() |
| Verification | groth16.Verify() |
verify(vk, proof, signals) |
Benchmark
Prove time for SP1's final Groth16 verifier circuit — BN254, 15,965,950
constraints, domain 2²⁴ — on an RTX 5090. The reference is gnark's
ICICLE GPU Groth16 prover on the same
circuit and GPU. groth16-zorch's proof verifys and is deterministic (fixed
output across runs).
Both provers consume the same gnark export, which already carries the solved witness and Az/Bz (gnark's Go solver produces them at export time). So this is a prove-only comparison — it excludes witness solving on both sides:
| prover | prove (median) | speedup |
|---|---|---|
| groth16-zorch (FRX, GPU) | 1573 ms | 1.50× |
| gnark ICICLE (GPU) | 2355 ms | 1.00× |
gnark's end-to-end run additionally re-solves the witness on every proof (~2.2 s), for ~4.5 s total; groth16-zorch loads that pre-solved witness/Az/Bz straight from the export. One-time setup for groth16-zorch (not counted in the prove time): ~4.4 s to load the 19 GB export and ~5.0 s to compile the 2²⁴ executable.
Reproduce with //benchmark:sp1_groth16 (see .github/workflows/benchmark.yml):
FRX_PLATFORMS=cuda,cpu bazel run //benchmark:sp1_groth16 -- \
--export_dir=<sp1-groth16-export> --deterministic --circuit=sp1
How to test
bazel test //...
Test organization:
//tests/circom:e2e_test— Circom prove/verify via.wtns//tests/gnark:e2e_test— Gnark export prove/verify//tests/circom:zkey_test—.zkeyparser unit tests//tests/circom:wtns_test—.wtnsparser unit tests
License
Licensed under the Apache License, Version 2.0 (see LICENSE).
Metadata
Release files for groth16-zorch 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| groth16_zorch-0.1.2.tar.gz | 33.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| groth16_zorch-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 78.8 kB
Release files / groth16_zorch-0.1.2.tar.gz
| Download URL | groth16_zorch-0.1.2.tar.gz |
|---|---|
| Size | 33.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3128b8430588eaebf0d7fda306f9b22e0ec87cb5f2d88c338ae145d32c52540c
|
|
BLAKE2b-256 checksum How to use checksums |
80c549955782c281b8ee88a53fbb38ca06093a2c1be7b18131e2a22a87db84fc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 26, 2026.
Transparency logRelease files / groth16_zorch-0.1.2-py3-none-any.whl
| Download URL | groth16_zorch-0.1.2-py3-none-any.whl |
|---|---|
| Size | 45.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
001a9eba36902b347b7327df4de056abd2ec382337e53ccbabc92abbfc801e0b
|
|
BLAKE2b-256 checksum How to use checksums |
ad6aaacc6c9b580172f79f8f453b9ccfc284797e9b85115ddcbf221082064596
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 26, 2026.
Transparency log