zorch
SNARK = Σ IOP Round
FRX-native building blocks for proof systems. zorch sits between FRX —
Fractalyze's fork of JAX — and the proof systems
that consume it: FRX provides tracing and codegen, lowered through Fractalyze
XLA, its fork of stock XLA that adds native
field and elliptic-curve types. zorch provides the reusable pieces a proof
system is assembled from.
The banner is a mnemonic for where the work is, not a definition: repeated IOP rounds are the core interactive computation, and a non-interactive argument adds its relation, a Fiat–Shamir transform, and commitment machinery around them. Folding and other families reuse the same pieces without fitting the equation literally. So zorch's two units are the round — one step of a repeated recurrence — and the stage — one claim reduction with paired prover and verifier roles.
Installation
Python 3.11 on Linux x86_64, or macOS on Apple Silicon. (frxlib ships a
cp311 wheel for those two platforms only — not 3.12/3.13, not Intel Macs.)
Install as pyzorch, import as zorch — the zorch name on PyPI belongs to an
unrelated project.
CPU
pip install pyzorch
GPU (CUDA 12)
pip install pyzorch '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, zorch; print(frx.devices()); print(zorch.__version__)"
[CpuDevice(id=0)] means the CPU tier; a CUDA install prints the GPU devices.
Design Philosophy
- Proving-scheme-agnostic. The blocks are reusable across proving schemes,
rather than encoding a single one.
Round, Fiat-Shamir,Polynomial,PCS, fold, and zero-check compose into FRI, sumcheck, GKR, STARK, Basefold, WHIR, …; pairing-based schemes plug in by swapping thePCSblock (e.g. a KZG-style commitment). - Implementation-agnostic.
zorchtargets the proving scheme, not any one downstream implementation — a zkVM, a zkML prover, a zkTLS prover. Each plugs in as a consumer; nothing implementation-specific leaks into a block. - Fusion-first. Each
Round— and eachcommit/open, eachabsorb/squeeze, each fold step, and a hash permutation's internal rounds — must lower to one replayable device unit. We get there by construction, not by a per-primitive pattern-matcher in the compiler. The fusion north star is where that unit is defined and measured. - Easy to assemble. These are building blocks; the API optimizes for snapping them together.
Building blocks
The two units differ in kind, not size. A round is directional and repeated: one step of a homogeneous recurrence, driven in a loop. A stage is paired and whole: a claim reduction with a prover role and a verifier role that can be deployed separately. A whole sumcheck stage may be cheaper than one GKR round — repetition versus pairing decides, never scale.
ProverRound: (carry, transcript) -> (carry, transcript, message)
VerifierRound: (carry, transcript, message) -> (carry, transcript, ok)
ProverStage.prove(claim, witness, transcript) -> ProveResult
VerifierStage.verify(claim, reduction_proof, ...) -> VerifyResult
The claim is the public assertion entering the stage; the witness is the prover's private evidence. Both roles derive the same reduced claim, and the reduction proof does not establish it — it establishes the source claim conditional on it:
reduced claim is true => source claim is true
That conditional is what lets stages chain: each one's reduced claim is the
next one's source claim, so a proof system is a sequence of reductions ending at
TrivialClaim, which holds by construction and leaves nothing left to prove. An
argument of knowledge is exactly a reduction to the trivial claim, and a PCS
opening is the usual terminal one.
Dense sumcheck is the smallest complete stage, entire:
@dataclass(frozen=True)
class SumClaim: # public: this polynomial sums to `value` over the cube
value: Array
rounds: int
@dataclass(frozen=True)
class EvaluationClaim: # reduced: ...provided it evaluates to `value` at `point`
point: Array
value: Array
class SumcheckProver(ProverStage[SumClaim, SumcheckWitness, EvaluationClaim, Array]):
def prove(self, claim, witness, transcript):
pre = transcript
# the rounds live inside the stage — one per variable, driven in a loop
_, _, messages = fold_rounds(
self.prover_round, witness.state, transcript, claim.rounds
)
reduction_proof = fnp.stack(messages)
# The prover's carry is the folded tables: each round squeezes its
# challenge, folds with it, and drops it. The point and running value
# accumulate in the verifier's carry instead, so replaying is how the
# prover obtains a reduced claim it never built. The transcript comes
# back with it and matches the one fold_rounds discarded.
point, value, replayed, _ = verify(
self.verifier_round, claim.value, reduction_proof, pre
)
return ProveResult(EvaluationClaim(point, value), reduction_proof, replayed)
SumcheckVerifier.verify is that same replay against the proof alone. Nothing
here knows where the sum came from: zerocheck, lincheck and LogUp-GKR each
configure this stage and export their own claim type.
A proof system is those reductions chained until the claim is trivial.
SpartanProver / SpartanVerifier are the worked composite — four stages, a
transcript-only batching step, and prover data that skips to the opening — in
docs/schemes/spartan.md.
Contracts, ownership rules, the round-vs-stage-vs-committer decision table, and
reuse guidance:
docs/composition/stage-composition.md.
Development
zorch is pure Python on FRX, run against its GPU plugin. A virtualenv with
the pinned toolchain:
python3.11 -m venv .venv && . .venv/bin/activate
pip install -r requirements.in \
--extra-index-url https://fractalyze.github.io/pypi/simple/
Install the git hooks with both stages named. Plain pre-commit install wires
only the pre-commit stage, which leaves the commit-message linter inactive —
formatting hooks fire while a malformed commit message sails through to CI:
pre-commit install --install-hooks --hook-type pre-commit --hook-type commit-msg
Commit messages follow Conventional Commits:
a valid type, a lowercase summary with no trailing period, a header of at most
80 characters, and a body on everything but docs. The same linter runs in CI
over every commit in a pull request and over the PR title, which matters here
because this repo squash-merges with the title as the subject.
The dev loop — per-workspace venvs, developing against a local Fractalyze XLA
build, the FRX compile-cache rule — lives in docs/reference/development.md.
Documentation
- Task-indexed docs hub:
docs/README.md— indexes every design doc by what you're trying to do.
Agent skill
skills/using-zorch packages this guide for AI coding
agents — install commands, block import paths, field-dtype rules, and the
consumer boundary — so an agent writing code against zorch in your repo has
them on hand. Install with any agent via skills.sh:
npx skills add fractalyze/zorch
or as a Claude Code plugin:
/plugin marketplace add fractalyze/zorch
/plugin install zorch@zorch
License
Licensed under the Apache License, Version 2.0 (see LICENSE).
Metadata
Release files for pyzorch 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pyzorch-0.2.0.tar.gz | 304.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyzorch-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 701.3 kB
Release files / pyzorch-0.2.0.tar.gz
| Download URL | pyzorch-0.2.0.tar.gz |
|---|---|
| Size | 304.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e19e4abaa2a87484bcc5f13b4b52c5d2ddabb4f8253e882266bee22777e40e55
|
|
BLAKE2b-256 checksum How to use checksums |
c2228e1bfec1a536439f34bd31dd6ee6821ee96a17697bc64e5b744178cc198e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.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 Aug 3, 2026.
Transparency logRelease files / pyzorch-0.2.0-py3-none-any.whl
| Download URL | pyzorch-0.2.0-py3-none-any.whl |
|---|---|
| Size | 396.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
aeaffc37759d0e9099f49457e687888585e08c451a3a90bad9e10d3b112d0ec3
|
|
BLAKE2b-256 checksum How to use checksums |
3e7e1e701e90f13a9c38614f4651b647ef79b72b2e61b7de449bf76415cfeb54
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.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 Aug 3, 2026.
Transparency log