7Block Labs
Blockchain Technology

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
    RISC0_DEV_MODE
    are built for this. (docs.succinct.xyz)

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
      rzup
      , develop in
      RISC0_DEV_MODE
      , flip to real proving on release. Bonsai provides scalable remote proving. (dev.risczero.com)
    • 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)
  • High‑throughput rollups
    • zkSync Boojum: plan GPU (≥16 GB VRAM) or CPU proving boxes; enable with
      zkstack prover init/run
      when moving from dummy to real proofs. Budget runner specs accordingly. (docs.zksync.io)

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
      .ptau
      hash + source URL.
    • RISC Zero: pin
      rzup
      channel/release and
      cargo-risczero
      ; verify that ImageID stays stable across builds. (dev.risczero.com)
    • SP1: pin Rust toolchain (MSRV ≥1.79) and SP1 crate versions. (github.com)
  • Cache compiles:
    • Rust:
      Swatinem/rust-cache
      for host + guest crates in matrix builds. (github.com)
    • General artifacts:
      actions/cache@v4
      for
      target/
      ,
      .wasm
      ,
      .zkey
      ,
      .ptau
      keyed by hash of circuit + tool versions. (github.com)

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
      RISC0_DEV_MODE=1
      in PRs (fast),
      =0
      on releases (real receipts). Publish receipts and journals as artifacts. (dev.risczero.com)
  • 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
      nvidia-smi
      . (docs.gitlab.com)
  • 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
    actions/attest-build-provenance
    (Sigstore‑issued cert, in‑toto SLSA predicate). Enforce in clusters with Sigstore Policy Controller. (github.com)

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.json
      ,
      verification_key.json
    • .zkey
      (final, with contributions) and
      .r1cs
      hash
    • verifier.sol
      (or deployed address + commit of template)
  • RISC Zero
    • Receipt file (e.g., CBOR), the journal (JSON), ImageID(s) list
    • Host/guest crate SHAs;
      rzup
      /toolchain version
  • 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
      RISC0_DEV_MODE=1
      to validate logic and public outputs.
    • Releases: run proofs once, then cache artifacts. (docs.succinct.xyz)
  • Cache aggressively:
    • actions/cache@v4
      for
      .ptau
      ,
      .zkey
      ,
      .wasm
      ,
      target/
      .
    • Swatinem/rust-cache@v2
      for Rust builds. (github.com)
  • 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
      actions/attest-build-provenance
      (Sigstore short‑lived certs) and enforce via cluster admission policies. (github.com)
  • 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
      .ptau
      and ceremony transcripts like third‑party cryptographic dependencies with explicit provenance and hashes. Reference the ceremony source and version in release notes. (plonkbook.org)

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;
      verifier.sol
      or ImageID changes are release‑blocking events.
  • 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
      hardhat-circom
      to minimize zkey churn; never ship those beacons to production. (github.com)
  • On‑chain sanity checks in CI
    • For Groth16/PLONK, spin up a local EVM and call
      verifyProof
      with CI‑generated calldata prior to deployment, catching ABI ordering/regression before mainnet. (docs.circom.io)

A “release checklist” you can adopt tomorrow

  • Toolchains pinned:
    • circom/snarkjs versions,
      .ptau
      hash
    • RISC Zero toolchain via
      rzup
      tag; ImageID recorded
    • SP1 crate versions + Rust MSRV pinned
  • 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:
      RISC0_DEV_MODE=1
      run
    • 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,
    rzup
    , receipts/journal, dev‑mode vs real proving; Bonsai overview. (dev.risczero.com)
  • 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.

Related Posts

7BlockLabs

Full-stack blockchain product studio: DeFi, dApps, audits, integrations.

7Block Labs is a trading name of JAYANTH TECHNOLOGIES LIMITED.

Registered in England and Wales (Company No. 16589283).

Registered Office address: Office 13536, 182-184 High Street North, East Ham, London, E6 2JA.

© 2025 7BlockLabs. All rights reserved.