ByAUJay
ZK in the CI/CD Loop: Automating Proof Generation for Every Release
Short summary: This guide shows decision‑makers how to wire zero‑knowledge (ZK) proving into modern CI/CD so every tagged release ships with verifiable proofs. It includes concrete pipeline blueprints, toolchain pinning, GPU/remote proving choices, caching strategies, security attestations, and emerging practices across Circom/snarkjs, RISC Zero, SP1, and zkSync Boojum.
Why “proofs per release” is worth doing now
In 2025, ZK moved from research to operations. Three shifts make automating proofs in CI/CD both feasible and valuable:
- Commodity hardware for production‑grade proving. zkSync’s Boojum proves batches on consumer GPUs (≥16 GB VRAM for GPU provers) or CPUs, with clear minimums and a one‑command enablement path in zkStack. That removes the “only A100s” blocker and makes GPU self‑hosted runners viable for many teams. (docs.zksync.io)
- Production zkVMs with real performance. Succinct’s SP1 reports 4–28× zkVM performance improvements on realistic programs (e.g., a ZK Tendermint light client dropped from 2.2 hours to ~4.6 minutes), plus a workflow that separates fast execution from slower proving—ideal for CI/CD. (blog.succinct.xyz)
- Prover networks and hosted services. You can burst proofs off your CI into RISC Zero’s Bonsai (99.9% uptime target) or decentralize via Succinct’s Prover Network (mainnet, auction‑based parallel proving). These options give predictable latency/SLA pathways when on‑prem resources are scarce. (risczero.com)
The rest of this post shows exactly how to plug ZK into release engineering without turning every build into an HPC project.
What “ZK in the CI/CD loop” means
- Every release tag triggers:
- Compile circuits or zkVM programs deterministically.
- Generate one or more proofs from canonical test vectors or fixture inputs.
- Verify locally (and optionally on-chain for Groth16/PLONK verifiers).
- Attach proof artifacts (receipts, public inputs, verification keys) and signed provenance to the release.
- Every PR runs a cheaper “execution-only” or “dev-mode” path that ensures correctness without paying full proving cost. SP1’s “execute only” and RISC Zero’s
are built for this. (docs.succinct.xyz)RISC0_DEV_MODE
Choose an proving path per workload
- Circuits (domain‑specific constraints)
- Tooling: Circom + snarkjs (Groth16, PLONK/FFLONK). Export Solidity verifiers for on‑chain checks. (docs.circom.io)
- SRS considerations: KZG schemes need a trusted setup (Powers of Tau). Manage SRS artifacts like any regulated dependency. (plonkbook.org)
- zkVMs (general‑purpose code in Rust/LLVM)
- RISC Zero zkVM: proofs are “receipts” with a public journal and sealed proof; install via
, develop inrzup
, flip to real proving on release. Bonsai provides scalable remote proving. (dev.risczero.com)RISC0_DEV_MODE - SP1 zkVM: write in Rust, benchmark cycles during execution‑only in CI, outsource proofs to the Succinct Prover Network for parallelized latency when you tag a release. (docs.succinct.xyz)
- RISC Zero zkVM: proofs are “receipts” with a public journal and sealed proof; install via
- High‑throughput rollups
- zkSync Boojum: plan GPU (≥16 GB VRAM) or CPU proving boxes; enable with
when moving from dummy to real proofs. Budget runner specs accordingly. (docs.zksync.io)zkstack prover init/run
- zkSync Boojum: plan GPU (≥16 GB VRAM) or CPU proving boxes; enable with
CI/CD blueprint: end‑to‑end
The patterns below are production‑hardened at 7Block Labs across GitHub Actions and GitLab CI.
1) Reproducible toolchains
- Pin versions:
- Circom/snarkjs: lock npm versions; store chosen
hash + source URL..ptau - RISC Zero: pin
channel/release andrzup
; verify that ImageID stays stable across builds. (dev.risczero.com)cargo-risczero - SP1: pin Rust toolchain (MSRV ≥1.79) and SP1 crate versions. (github.com)
- Circom/snarkjs: lock npm versions; store chosen
- Cache compiles:
- Rust:
for host + guest crates in matrix builds. (github.com)Swatinem/rust-cache - General artifacts:
foractions/cache@v4
,target/
,.wasm
,.zkey
keyed by hash of circuit + tool versions. (github.com).ptau
- Rust:
2) Witness and proof generation
- Circom/snarkjs (Groth16 example)
- Compile and compute witness; run setup once per circuit; generate proof and verify; export verifier for Solidity.
- CLI is stable and scriptable for CI. (docs.circom.io)
- RISC Zero
- Run host binary with
in PRs (fast),RISC0_DEV_MODE=1
on releases (real receipts). Publish receipts and journals as artifacts. (dev.risczero.com)=0
- Run host binary with
- SP1
- In PRs, run “execution only” and log cycle counts; in releases, call the prover network or GPU cluster for proofs. (docs.succinct.xyz)
3) GPU vs remote proving
- Self‑hosted GPU runners
- GitLab SaaS exposes GPU‑enabled runners by tag; pick a CUDA image and confirm with
. (docs.gitlab.com)nvidia-smi
- GitLab SaaS exposes GPU‑enabled runners by tag; pick a CUDA image and confirm with
- Remote proving
- RISC Zero Bonsai for API‑driven proving with uptime target and recursive/composition features behind the zkVM. (dev.risczero.com)
- Succinct Prover Network on mainnet to parallelize large jobs; expect auction‑based pricing and staking for provers. (theblock.co)
4) Attestations and provenance
- Generate signed build provenance for proof artifacts using GitHub’s
(Sigstore‑issued cert, in‑toto SLSA predicate). Enforce in clusters with Sigstore Policy Controller. (github.com)actions/attest-build-provenance
Concrete pipeline examples (copy‑paste friendly)
A. GitHub Actions: Circom + snarkjs (Groth16) with cached SRS
name: zk-circuits on: push: tags: ["v*"] pull_request: jobs: groth16: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 20 - name: Install circom + snarkjs run: | npm i -g circom@2 snarkjs@0.7.4 - name: Cache SRS and artifacts uses: actions/cache@v4 with: path: | ./.zk/ptau ./artifacts key: ${{ runner.os }}-circom-${{ hashFiles('circuits/**/*.circom') }}-snarkjs-0.7.4 restore-keys: | ${{ runner.os }}-circom- - name: Ensure ptau (Powers of Tau) present run: | mkdir -p .zk/ptau test -f .zk/ptau/powersOfTau28_hez_final_17.ptau || \ curl -L -o .zk/ptau/powersOfTau28_hez_final_17.ptau \ https://hermezptau.s3.eu-central-1.amazonaws.com/powersOfTau28_hez_final_17.ptau - name: Compile circuit run: | mkdir -p artifacts circom circuits/multiplier.circom --r1cs --wasm --sym -o artifacts - name: Compute witness run: | node artifacts/multiplier_js/generate_witness.js \ artifacts/multiplier_js/multiplier.wasm inputs/input.json \ artifacts/witness.wtns - name: Groth16 setup (idempotent) run: | test -f artifacts/multiplier_0001.zkey || ( snarkjs groth16 setup artifacts/multiplier.r1cs \ .zk/ptau/powersOfTau28_hez_final_17.ptau artifacts/multiplier_0000.zkey snarkjs zkey contribute artifacts/multiplier_0000.zkey \ artifacts/multiplier_0001.zkey -e="dev-beacon" ) - name: Prove and verify run: | snarkjs groth16 prove artifacts/multiplier_0001.zkey artifacts/witness.wtns \ artifacts/proof.json artifacts/public.json snarkjs groth16 verify artifacts/verification_key.json \ artifacts/public.json artifacts/proof.json # See Circom/snarkjs docs for exact commands and semantics.
This mirrors the documented snarkjs flow (compile → witness → setup → prove → verify), which is stable for CI scripting. Export
verifier.sol on release tags and attach it to the repo or deploy via Hardhat. (docs.circom.io)
- name: Export Solidity verifier (release only) if: startsWith(github.ref, 'refs/tags/') run: | snarkjs zkey export solidityverifier artifacts/multiplier_0001.zkey \ contracts/Verifier.sol
Tip: If you use
hardhat-circom, the plugin can generate verifiers and supports a deterministic Groth16 beacon for dev builds to reduce churn in .zkey files. Don’t ship deterministic beacons to production. (github.com)
B. GitHub Actions: RISC Zero zkVM receipts with reproducible ImageID
name: risc0-proofs on: push: tags: ["v*"] pull_request: jobs: zkvm: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - name: Install RISC Zero toolchain run: | curl -L https://risczero.com/install | bash ~/.rzup/bin/rzup # installs toolchain and cargo-risczero - name: Build guest + host and print ImageIDs run: | cargo risczero build --manifest-path guest/Cargo.toml rustup toolchain list | grep risc0 || true - name: Fast checks (PRs) with dev-mode if: github.event_name == 'pull_request' env: RISC0_DEV_MODE: "1" run: cargo run --release -p host - name: Generate real proof (tags) if: startsWith(github.ref, 'refs/tags/') env: RISC0_DEV_MODE: "0" run: cargo run --release -p host -- --out artifacts/receipt.cbor - name: Verify receipt and publish artifacts if: startsWith(github.ref, 'refs/tags/') run: | cargo test -p verifier mkdir -p artifacts && cp -v target/**/*.id artifacts/ || true # Verifier crate confirms receipt against ImageID and journal.
This follows RISC Zero’s quickstart/dev‑mode guidance and the receipt/journal model. You can swap the local “real proof” step for a Bonsai API call to outsource heavy proving. (dev.risczero.com)
C. GitLab CI: GPU‑enabled jobs (for Boojum or heavy zkVM proving)
stages: [build, prove] prove-gpu: stage: prove tags: [saas-linux-medium-amd64-gpu-standard] # GitLab SaaS GPU runner image: nvcr.io/nvidia/cuda:12.1.1-base-ubuntu22.04 script: - nvidia-smi - ./scripts/prove.sh
GitLab mounts the GPU into your job; choose a CUDA image and verify access with
nvidia-smi. Use this for Boojum prover nodes or GPU‑accelerated proof steps. (docs.gitlab.com)
Build outputs you should publish on every release
Per proving system, attach these to GitHub/GitLab releases:
- Circom/snarkjs
,proof.json
,public.jsonverification_key.json
(final, with contributions) and.zkey
hash.r1cs
(or deployed address + commit of template)verifier.sol
- RISC Zero
- Receipt file (e.g., CBOR), the journal (JSON), ImageID(s) list
- Host/guest crate SHAs;
/toolchain versionrzup
- SP1
- Proof artifact, public values, crate SHAs
- Cycle counts from execution‑only benchmarking
Then generate signed provenance for all proof artifacts:
- uses: actions/attest-build-provenance@v3 with: subject-path: 'artifacts/**'
This produces Sigstore‑signed in‑toto/SLSA attestations and uploads them to GitHub’s Attestations API; enforce these at deploy time via a Kubernetes policy controller if you ship containers that embed verifiers. (github.com)
Performance and cost controls that matter in CI
- Split “execution” vs “proof” phases:
- PRs: run fast execution‑only (SP1) or
to validate logic and public outputs.RISC0_DEV_MODE=1 - Releases: run proofs once, then cache artifacts. (docs.succinct.xyz)
- PRs: run fast execution‑only (SP1) or
- Cache aggressively:
foractions/cache@v4
,.ptau
,.zkey
,.wasm
.target/
for Rust builds. (github.com)Swatinem/rust-cache@v2
- GPU provisioning:
- For Boojum’s low‑TPS scenarios: plan ≥16 GB VRAM (GPU path) or ≥32–128 cores/64–128 GB RAM (CPU path). Scope your runner size to target batch sizes. (docs.zksync.io)
- Remote burst:
- When proofs exceed CI time budget, send to Bonsai or Succinct Prover Network and block release on a callback/webhook. The network parallelizes proving rather than relying on a single GPU. (dev.risczero.com)
- Timeouts and retries:
- For hosted runners, set a max runtime per job and adopt a “local → remote fallback” pattern to avoid stuck releases.
Security, compliance, and governance
- Attestations + policy
- Signed provenance with
(Sigstore short‑lived certs) and enforce via cluster admission policies. (github.com)actions/attest-build-provenance
- Signed provenance with
- Reproducibility
- For RISC Zero, reproduce ImageID from source; your verifier checks receipt against that ImageID and journal. Keep ImageID as a first‑class artifact in releases. (dev.risczero.com)
- SRS lifecycle (Circom/KZG)
- Treat
and ceremony transcripts like third‑party cryptographic dependencies with explicit provenance and hashes. Reference the ceremony source and version in release notes. (plonkbook.org).ptau
- Treat
Advanced: aggregation and recursion strategy in 2025
If verification cost or proof fan‑out grows, plan for folding/aggregation:
- Folding systems (Nova, SuperNova, HyperNova) compress long computations into succinct verifiers; MicroNova and HyperKZG target improved on‑chain efficiency. These are increasingly practical but be mindful of evolving security caveats and parameter choices. (github.com)
- Security notes: several papers analyzed Nova variants (cycles of curves, bounded recursion assumptions). If you deploy folding in production, track the exact instantiation/security arguments and pin versions in CI to avoid drift. (eprint.iacr.org)
- Plonky2/aggregation architectures (e.g., ZKM) demonstrate multi‑stage aggregation stacks for Plonkish tables—useful when you have many micro‑proofs per commit. (zkm.io)
Emerging best practices we’re applying for clients
- Circuit semantics versioning
- Adopt semver for circuits/zkVM programs. Break changes bump MAJOR;
or ImageID changes are release‑blocking events.verifier.sol
- Adopt semver for circuits/zkVM programs. Break changes bump MAJOR;
- Proof budgets
- Publish target SLAs: “<15 min wall‑clock proving per release on N×L4 GPUs” or a fixed spend cap through a prover network. (docs.succinct.xyz)
- Dual‑path proving
- Keep both a “local GPU” path (fast feedback) and a “remote prover” path (scalability/SLA), selectable via env flags in the same pipeline.
- Deterministic dev builds
- For Groth16 dev iterations, use deterministic beacons via
to minimize zkey churn; never ship those beacons to production. (github.com)hardhat-circom
- For Groth16 dev iterations, use deterministic beacons via
- On‑chain sanity checks in CI
- For Groth16/PLONK, spin up a local EVM and call
with CI‑generated calldata prior to deployment, catching ABI ordering/regression before mainnet. (docs.circom.io)verifyProof
- For Groth16/PLONK, spin up a local EVM and call
A “release checklist” you can adopt tomorrow
- Toolchains pinned:
- circom/snarkjs versions,
hash.ptau - RISC Zero toolchain via
tag; ImageID recordedrzup - SP1 crate versions + Rust MSRV pinned
- circom/snarkjs versions,
- Proofs generated:
- Circom: r1cs hash, zkey, proof/public, verifier.sol exported
- RISC Zero: receipt + journal verified against ImageID
- SP1: proof + public values; cycles logged
- Artifacts attached:
- Proofs + public inputs
- Verification keys / verifiers or deployed address
- Attestations (Sigstore/SLSA) for all artifacts
- Gates passed:
- Local verify steps green
- Optional on‑chain local EVM verify tests pass
- Time/cost within budgets or offloaded per policy
Putting it together: one pipeline to rule them all
- PRs
- Circom/snarkjs: compile + witness only; skip full Groth16 if unchanged
- RISC Zero:
runRISC0_DEV_MODE=1 - SP1: execute only + cycles report
- Tags
- Circom/snarkjs: full proof + export verifier + verify in local EVM
- RISC Zero: full receipt; verify; attach ImageID map
- SP1: dispatch to prover network; block release on webhook
- Attest artifacts; publish
This approach lets your org ship cryptographically verifiable releases without making every developer machine a prover.
Where we see the space heading (next 12 months)
- Lower device floors: Boojum‑class GPU minima make “ZK runners” a standard CI resource class rather than a special project. (docs.zksync.io)
- Networked proving as default: With Succinct’s mainnet prover network live, more teams will treat proving like a workload to schedule, not a machine to own. (theblock.co)
- zkVM maturity: SP1’s speed and reproducibility workflows push more teams to unify circuit logic in Rust and let the VM do the heavy lifting—especially for complex, branching logic. (blog.succinct.xyz)
7Block Labs can help
We design, implement, and harden ZK CI/CD for startups and enterprises—from choosing proving stacks to wiring GPU/remote provers, versioning SRS, authoring verifiers, and enforcing attestations. If you want “every release ships with proofs,” we’ll make it both fast and boring.
Sources and further reading
- circom/snarkjs proving and Solidity verifier export (commands and flow). (docs.circom.io)
- zkSync Boojum prover requirements and enablement via zkStack. (docs.zksync.io)
- RISC Zero quickstart,
, receipts/journal, dev‑mode vs real proving; Bonsai overview. (dev.risczero.com)rzup - Succinct SP1 performance and recommended workflow; Prover Network context. (blog.succinct.xyz)
- Halo2 IPA background; KZG SRS background. (zcash.github.io)
- GitLab GPU runner usage; GitHub artifact attestations/provenance. (docs.gitlab.com)
Like what you're reading? Let's build together.
Get a free 30‑minute consultation with our engineering team.

