flock-zorch
A GPU prover for flock's binary-field R1CS PIOP — the scheme from Flock: Fast Proving for Batch Boolean Computations (eprint 2026/1329) — built on Fractalyze's zorch stack. The whole prover is authored once in Python/FRX (Fractalyze's JAX fork), and the compiler emits the hardware code: the same readable source targets CPU and GPU, and its output matches the reference flock prover bit-for-bit.
The point is a single FRX/MLIR codebase, not a GPU rewrite of the proving
logic. flock's prover is written as a clean statement of the math; FRX lowers
it to StableHLO/MLIR, and the compiler — carrying native finite-field dtypes
(zk_dtypes) and the carryless-multiply lowerings for GF(2¹²⁸) — compiles that
down to each target. The expensive field-arithmetic optimization lives in
compiler passes, out of the prover, and the byte-match gate guarantees those
transforms never change the output. The same program can shard across multiple
devices (GSPMD) without hand-written communication.
flock is an R1CS-over-GF(2¹²⁸) prover: two sumcheck PIOPs (zerocheck + lincheck)
over a Ligerito polynomial commitment, with a SHA-256 Fiat-Shamir
transcript, targeting hash-circuit statements (Keccak-f[1600], Keccak3, SHA-256,
BLAKE3). flock-zorch assembles that specific prover from zorch's scheme-agnostic
blocks (Round, Fiat-Shamir, Polynomial, PCS, fold, zero-check) and adds
only the flock-specific pieces the byte-match needs (GHASH-basis field, the
round-1 URM, the ∞-trick round loop, F128↔bytes serialization). The full prover
prover.prove_fast produces the complete R1csProof — commit → bind →
zerocheck → lincheck → batched dual-claim open, one shared challenger,
device-resident — reproducing flock prove's proof bit-for-bit.
Installation
Python 3.11 on Linux x86_64 only.
Run with JAX_ENABLE_X64=true — the GF(2¹²⁸) dtypes are 64-bit lane pairs and
x32 truncates them.
CPU
pip install flock-zorch
GPU (CUDA 12)
pip install flock-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
JAX_ENABLE_X64=true python -c \
"import frx, flock_zorch.prover; print(frx.devices()); print(flock_zorch.__version__)"
[CpuDevice(id=0)] means the CPU tier; a CUDA install prints the GPU devices.
Importing flock_zorch.prover rather than the package is deliberate: the package
__init__ is a docstring, so a bare import stays green on an x32 interpreter and
on a zk-dtypes too old for the binary-field dtypes.
Setup
No submodules and nothing to clone by hand — both pinned deps are fetched by the build:
| dep | how |
|---|---|
| flock — the reference prover + byte-compare oracle | a cargo git rev dep (flock-core / flock-prover in Cargo.toml); cargo build fetches it at the pinned rev, and examples/dump_*.rs drive it to dump the golden fixtures |
zorch — the scheme-agnostic spine (zorch.hash.sha256, the device Fiat-Shamir transcript, the Round/Bridge/Stage chain roles, pcs.ligerito) |
a bazel git_override in MODULE.bazel; bazel fetches it |
Prerequisites — an NVIDIA GPU (CUDA; RTX 5090 / sm_120 reference), a Rust
toolchain (flock-core is edition 2024), Python 3.11. For the GPU fast path, a CUDA 13.3
ptxas at ~/.local/cuda13/bin: with it on PATH the pinned frx wheel's
compiler emits the hardware clmad GF(2¹²⁸) multiply; without it, the software
binary_field_ghash multiply — same output, just slower.
git clone https://github.com/fractalyze/flock-zorch.git && cd flock-zorch
Reproduction has three tiers with independent deps: a Rust toolchain regenerates the golden fixtures by driving the pinned flock (no GPU, no Python); the CPU byte-match checks the frx port against them under Bazel (deps from the pip lock, zorch from the git_override — no venv); the GPU byte-match runs the port on-device from a venv. Build the venv once (the other two tiers need nothing installed):
python3.11 -m venv .venv
.venv/bin/pip install -r requirements.in --extra-index-url https://fractalyze.github.io/pypi/simple/
Bumping the pins
- flock — bump the
revon theflock-core/flock-provergit deps inCargo.toml; cargo re-fetches on the next build. - zorch — bump the
git_overridecommit inMODULE.bazel, and moverequirements.in'sfrx/frxlib/frx-cuda12wheels to the SAME version as zorch's ownrequirements.in— the binary-field GPU kernels must match, and CPU-only CI can't catch a desync.
Then re-verify before pushing:
scripts/dump_goldens.sh core && bazel test //python:all
Reproduce
The oracle is the pinned flock itself: examples/dump_*.rs dump fixtures from
flock-core, and the *_oracle_test.py gates byte-compare the FRX port's
serialized proofs against them. The gates are proof-level: every field of a
full serialized proof is compared, which transitively pins every layer under it
(FS framing, NTT, Merkle/octopus, zerocheck, lincheck, ring-switch — one
diverging byte anywhere flips every Fiat-Shamir draw after it). Primitives are
covered by python-native tests (no goldens); the retired per-layer golden gates
live in git history.
Bazel tests (CPU)
Run under bazel — deps from the pip lock, zorch from the MODULE.bazel
git_override, goldens from //artifacts runfiles. One byte-match gate (the
full LigeritoProof — flock's fused prove has no config below m=22, so the e2e
gate can't come down to CPU) plus the native tests:
scripts/dump_goldens.sh core # goldens the gates byte-compare against
bazel test //python:all # (JAX_PLATFORMS=cpu + x64 pinned in .bazelrc)
bazel test //python:ligerito_oracle_test # the CPU byte-match anchor alone
Proof gates (GPU, venv)
The full-prove gates — the identity e2e and the hash-circuit provers
(keccak/sha2/blake3, hundreds-of-MB goldens) — are not bazel targets (the
CUDA wheels aren't hermetic). Run them on the venv, resolving the same
git_override'd zorch via scripts/zorch_pythonpath.sh:
export JAX_PLATFORMS=cuda
export XLA_PYTHON_CLIENT_PREALLOCATE=false # don't grab ~75% of VRAM up front
export PYTHONPATH="python:$(scripts/zorch_pythonpath.sh)"
export PATH="$HOME/.local/cuda13/bin:$PATH" # CUDA 13.3 ptxas -> compiler emits clmad
VENV=.venv/bin/python
scripts/dump_goldens.sh all # + the real hash circuits
$VENV python/flock_zorch/testing/e2e_ligerito_oracle_test.py # fused prove (identity R1CS)
$VENV python/flock_zorch/testing/keccak3_ligerito_oracle_test.py # Keccak full prove (Ligerito)
$VENV python/flock_zorch/testing/blake3_ligerito_oracle_test.py
The full proof-gate list is the *_oracle_test.py set under
python/flock_zorch/testing/. artifacts/ is gitignored (regenerable, and
blake3_golden.bin alone is ~118 MB); scripts/dump_goldens.sh [core|all]
rebuilds it from the pinned flock.
One benchmark point (SHA-256, m=26)
VENV=.venv/bin/python # the venv from Setup
cargo run --release --example dump_sha2_ligerito -- 2048 artifacts/sha2_ligerito_golden.bin # real R1CS, m=26
cargo build --release --example bench_sha2_ligerito_cpu # CPU anchor
export JAX_PLATFORMS=cuda XLA_PYTHON_CLIENT_PREALLOCATE=false
export PYTHONPATH="python:$(scripts/zorch_pythonpath.sh)"
export PATH="$HOME/.local/cuda13/bin:$PATH"
CPU=$(target/release/examples/bench_sha2_ligerito_cpu 2048 | grep -oE '[0-9.]+ ms' | head -1)
$VENV python/flock_zorch/testing/prove_phase_bench.py sha2 --cpu-ms "${CPU%% ms}" # GPU vs CPU
prove_phase_bench.py also splits the prove into commit / zerocheck / lincheck /
open and reports hashes/second, and refuses to print absolute numbers when
another process is using the GPU — a neighbour saturating the SMs inflates a warm
prove ~28× here, which is enough to invent a result. Swap sha2 for blake3 or
keccak3; --golden points it at an m-variant dump.
Benchmark
Apple-to-apple: unmodified flock CPU vs flock-zorch GPU on the same idle
machine (RTX 5090, Ryzen 9 9950X), same-instance both sides. The golden is
dumped from flock-core, the CPU bench (bench_*_cpu, thin-LTO /
codegen-units=1 / target-cpu=native — flock's honest x86 best) proves it, and
the GPU bench ingests the same golden. GPU uses the hardware clmad multiply;
timing is warm best-of-3 (JIT compile excluded), GPU verified idle. Every
instance is a real flock hash-circuit R1CS at flock's shipped size, swept over
the witness size m to locate the GPU/CPU crossover. The CPU baseline is x86
scalar (flock's NEON paths are aarch64-gated), so Apple silicon would shift
the crossover right. Measured with zorch 650b1cf and FRX
dev20260720085939 on 2026-07-21.
Keccak3 (Ligerito) — crossover ≈ m=24
| m | n_keccaks | flock CPU (ms) | GPU (ms) | speedup |
|---|---|---|---|---|
| 22 | 49 | 25.8 | 48.0 | 0.54× |
| 24 | 384 | 70.9 | 56.7 | 1.25× |
| 26 | 1536 | 266.4 | 76.1 | 3.50× |
| 28 | 6144 | 1,123.7 | 123.7 | 9.08× |
| 30† | 24576 | 4,706.1 | 316.7 | 14.86× |
| 31† | 49152 | 9,724.2 | 586.4 | 16.58× |
† m≥30 uses XLA_PYTHON_CLIENT_ALLOCATOR=cuda_async; the default BFC arena
fragments on the large proof phases (#131).
The Ligerito open runs device-resident — zorch's recursive open compiles to one device program (#479) and query positions are sampled on-device (#104) — while the packed-byte zerocheck fold avoids expanding the retained witness. GPU wins from m=24 and reaches 16.58× at m=31.
BLAKE3 (Ligerito)
| m | n_comp | flock CPU (ms) | GPU (ms) | speedup |
|---|---|---|---|---|
| 26 | 4096 | 316.5 | 66.8 | 4.73× |
| 31† | 131072 | 10,724.9 | 621.1 | 17.27× |
BLAKE3 uses the generic sparse CSC lincheck rather than Keccak3's procedural walker. The same packed zerocheck path keeps its high-end curve nearly identical: the GPU proof grows 9.3× while the batch grows 32× from m=26 to m=31.
Reading the numbers. flock's prover is a sequential SHA-256 Fiat-Shamir
chain; at small m the per-round data-parallel work (NTT / URM / recursive fold)
is too small to amortize GPU launch overhead, so the CPU wins. The bulk work
grows with m and the GPU overtakes at m≈24, and the advantage keeps growing
above the crossover (16–17× by m=31). Reproduce any point with the
SHA-256 recipe above (swap dump_sha2_ligerito /
bench_sha2_ligerito_cpu and the sha2 argument for the blake3 / keccak3
variants).
Acknowledgments
The proving scheme and the reference implementation are
flock by Succinct Labs — the
flock paper (eprint 2026/1329). flock-zorch
is an independent GPU implementation of that scheme on the zorch stack; the
unmodified succinctlabs/flock prover is pinned as the flock-core /
flock-prover git rev dep and is the byte-compare oracle every gate checks
against. All credit for the scheme and the R1CS PIOP design is theirs.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flock_zorch-0.1.0.tar.gz.
File metadata
- Download URL: flock_zorch-0.1.0.tar.gz
- Upload date:
- Size: 61.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9c86b4cddad6bd19e796fdd94ae81c6c4fec08d4fdf1db972370267253bdb22f
|
|
| MD5 |
0177ba7a165903d78fca46253b912cb5
|
|
| BLAKE2b-256 |
875d5d5308811df6939fbafa95bf7989c35cc86dfe0d3229e3e088cb555e692b
|
Provenance
The following attestation bundles were made for flock_zorch-0.1.0.tar.gz:
Publisher:
release.yml on fractalyze/flock-zorch
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
flock_zorch-0.1.0.tar.gz -
Subject digest:
9c86b4cddad6bd19e796fdd94ae81c6c4fec08d4fdf1db972370267253bdb22f - Sigstore transparency entry: 2255783520
- Sigstore integration time:
-
Permalink:
fractalyze/flock-zorch@47af64fc78bf104c35eade1fb0eb81b5c218e41d -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/fractalyze
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@47af64fc78bf104c35eade1fb0eb81b5c218e41d -
Trigger Event:
release
-
Statement type:
File details
Details for the file flock_zorch-0.1.0-py3-none-any.whl.
File metadata
- Download URL: flock_zorch-0.1.0-py3-none-any.whl
- Upload date:
- Size: 68.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6e7494a8174247070f48b5083e1a4ccdf1f3dbaaf467d2b5b6e38f3273d6c74
|
|
| MD5 |
e9e98a83dd09d3179f7c5e0e24f1d12e
|
|
| BLAKE2b-256 |
c2d2fae7468057a5735dca943e3e9259feae2fbec8534252038c80b6604386e6
|
Provenance
The following attestation bundles were made for flock_zorch-0.1.0-py3-none-any.whl:
Publisher:
release.yml on fractalyze/flock-zorch
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
flock_zorch-0.1.0-py3-none-any.whl -
Subject digest:
a6e7494a8174247070f48b5083e1a4ccdf1f3dbaaf467d2b5b6e38f3273d6c74 - Sigstore transparency entry: 2255783540
- Sigstore integration time:
-
Permalink:
fractalyze/flock-zorch@47af64fc78bf104c35eade1fb0eb81b5c218e41d -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/fractalyze
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@47af64fc78bf104c35eade1fb0eb81b5c218e41d -
Trigger Event:
release
-
Statement type: