7Block Labs
Blockchain Technology

ByAUJay

ZK in the CI/CD Loop: Automating Proof Generation for Every Release

Short Summary

In this guide, we walk decision-makers through integrating zero-knowledge (ZK) proving into today’s CI/CD processes. By doing this, every tagged release can come with verifiable proofs. You’ll find detailed pipeline blueprints, tips on toolchain pinning, options for GPU and remote proving, caching strategies, security attestations, and insights on new practices involving Circom/snarkjs, RISC Zero, SP1, and zkSync Boojum.


Why “proofs per release” is worth doing now

In 2025, ZK transitioned from being all about research to diving into operations. There are three key changes that make it both practical and worthwhile to automate proofs in CI/CD:

  • Using everyday hardware for serious proving. With zkSync’s Boojum, you can prove batches on regular consumer GPUs (just make sure they have 16 GB VRAM for the GPU provers) or CPUs. It’s super straightforward to set up in zkStack, so you can skip the “only A100s” situation and make GPU self-hosted runners a real option for a lot of teams. Check out the details here.
  • Real performance from production zkVMs. Succinct’s SP1 has shown some impressive performance boosts, with zkVM improvements of 4-28 times on practical programs. For example, a ZK Tendermint light client that took 2.2 hours now runs in about 4.6 minutes! Plus, their workflow separates speedy execution from the slower proving stuff, making it perfect for CI/CD setups. Learn more here.
  • Prover networks and hosted options. If you need to offload proofing, you can send them from your CI into RISC Zero’s Bonsai, which promises 99.9% uptime. Alternatively, you can go decentralized with Succinct’s Prover Network, which uses auction-based parallel proving on the mainnet. Both options help ensure you have reliable latency and SLA pathways, especially when your on-prem resources are a bit thin. More info can be found here.

The rest of this post will walk you through how to integrate ZK into your release engineering process without making every build feel like a high-performance computing (HPC) project.


What “ZK in the CI/CD loop” means

  • With each release tag, we make sure to:

    • Compile circuits or zkVM programs in a way that’s completely predictable.
    • Generate one or more proofs using those reliable test vectors or fixture inputs.
    • Verify everything locally (and, if you want, also on-chain for Groth16/PLONK verifiers).
    • Attach proof artifacts like receipts, public inputs, verification keys, and signed provenance to the release.
  • For every PR, we run a more budget-friendly “execution-only” or “dev-mode” route that checks for correctness without incurring the full proving costs. You’ll find SP1’s “execute only” and RISC Zero’s RISC0_DEV_MODE are designed precisely for this. (docs.succinct.xyz)

Choose an proving path per workload

  • Circuits (domain-specific constraints)

    • Tooling: Check out Circom and snarkjs for Groth16 and PLONK/FFLONK. These tools let you export Solidity verifiers for those on-chain checks. You can find more details here.
    • SRS considerations: If you're using KZG schemes, remember they require a trusted setup known as Powers of Tau. Treat SRS artifacts like any other regulated dependency. More info can be found here.
  • zkVMs (general-purpose code in Rust/LLVM)

    • RISC Zero zkVM: Think of proofs as “receipts” with a public journal and sealed proof. You can install it using rzup, and when you're developing, just switch to RISC0_DEV_MODE. When you're ready to go live, you can flip to real proving. Bonsai has got your back with scalable remote proving. For a quick start, check it out here.
    • SP1 zkVM: You’ll be writing in Rust, and don’t forget to benchmark cycles during execution only in CI. When you tag a release, you can outsource proofs to the Succinct Prover Network to handle that parallelized latency. More details can be found here.
  • High-throughput rollups

    • zkSync Boojum: If you’re planning on using GPU or CPU proving boxes, make sure your GPU has at least 16 GB VRAM. You can get started with zkstack prover init/run when transitioning from dummy to real proofs. Just keep an eye on your runner specs and budget accordingly. For further information, click here.

CI/CD blueprint: end‑to‑end

The patterns listed below have been production-hardened at 7Block Labs, using both GitHub Actions and GitLab CI.

1) Reproducible toolchains

  • Pin versions:

    • For Circom/snarkjs, make sure to lock the npm versions and save the selected .ptau hash along with the source URL.
    • For RISC Zero, pin the rzup channel/release and cargo-risczero; check that the ImageID remains constant across builds. You can find more info at (dev.risczero.com).
    • For SP1, don’t forget to pin the Rust toolchain (make sure MSRV is ≥1.79) and the versions of the SP1 crates. More details can be found on (github.com).
  • Cache compiles:

    • For Rust, use Swatinem/rust-cache for both host and guest crates in your matrix builds. Check it out on (github.com).
    • For General artifacts, leverage actions/cache@v4 to cache target/, .wasm, .zkey, and .ptau files, using a hash of the circuit and tool versions as the key. More info is available at (github.com).

2) Witness and proof generation

  • Circom/snarkjs (Groth16 example)

    • Start by compiling and computing the witness. You only need to run the setup once for each circuit, then generate the proof and verify it. Don’t forget to export the verifier for Solidity!
    • The CLI is pretty stable and can be scripted for CI. Check out the details in the docs.
  • RISC Zero

    • For PRs, kick off the host binary with RISC0_DEV_MODE=1 (it’s speedy!), and switch to =0 for releases to get the real receipts. Make sure to publish those receipts and journals as artifacts. You can find more info at dev.risczero.com.
  • SP1

    • During PRs, just run “execution only” and keep track of the cycle counts. For releases, you’ll want to call the prover network or GPU cluster for those proofs. More guidelines are available in the docs.

3) GPU vs remote proving

  • Self-hosted GPU runners

    • If you're using GitLab SaaS, you can easily access GPU-enabled runners by tagging them. Just choose a CUDA image and run nvidia-smi to confirm everything's set up. Check out the details in the GitLab documentation.
  • Remote proving

    • Take a look at RISC Zero Bonsai for some cool API-driven proving. It's got an uptime target and some neat recursive/composition features tucked away behind the zkVM. You can find more info here.
    • The Succinct Prover Network is live on the mainnet, allowing you to parallelize large tasks. Expect some auction-based pricing and staking for provers. Get the scoop here.

4) Attestations and provenance

  • Create signed build provenance for proof artifacts by leveraging GitHub’s actions/attest-build-provenance (which issues a Sigstore certificate and includes the in-toto SLSA predicate). Make sure to enforce this in your clusters using the Sigstore Policy Controller. You can check it out here.

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 follows the established snarkjs flow (compile → witness → setup → prove → verify), which works great for CI scripting. You can export verifier.sol on release tags and either attach it to the repo or deploy it using Hardhat. Check out the details here: (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: When you’re using hardhat-circom, this plugin is super handy because it creates verifiers and even has a built-in deterministic Groth16 beacon for your development builds. This helps cut down on the churn of .zkey files. Just a heads up--don’t send those deterministic beacons to production. Check it out on GitHub!


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 is based on RISC Zero’s quickstart/dev-mode guidance along with the receipt/journal model. If you want, you can replace the local “real proof” step with a call to the Bonsai API, which will handle the heavy lifting of proving for you. Check it out here: (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 lets you use the GPU for your job by mounting it right in. Just pick a CUDA image and check your access with nvidia-smi. This setup is perfect for Boojum prover nodes or for those GPU-accelerated proof steps. You can get more details here.


Build outputs you should publish on every release

For the proving system, don’t forget to attach these to your GitHub or GitLab releases:

  • Circom/snarkjs

    • You'll find proof.json, public.json, and verification_key.json here.
    • Check out the .zkey file, which is the final version that includes contributions, plus the .r1cs hash.
    • Don’t forget verifier.sol, or if it’s already been deployed, the address along with the template commit.
  • RISC Zero

    • Keep an eye out for the receipt file (like CBOR), the journal in JSON format, and a list of ImageID(s).
    • You’ll also want the SHAs for the host/guest crate and the version of rzup/toolchain.
  • SP1

    • This includes the proof artifact, the public values, and the crate SHAs.
    • Also, you’ll find the cycle counts from execution-only benchmarking.

Next up, let’s create signed provenance for all the proof artifacts:

- uses: actions/attest-build-provenance@v3
  with:
    subject-path: 'artifacts/**'

This creates Sigstore-signed in-toto/SLSA attestations and sends them over to GitHub’s Attestations API. If you're shipping containers that include verifiers, make sure to enforce these at deployment time using a Kubernetes policy controller. For more info, check out the GitHub page.


Performance and cost controls that matter in CI

  • Split “execution” vs “proof” phases:

    • For PRs, you can run a quick execution-only test (SP1) or set RISC0_DEV_MODE=1 to check the logic and public outputs.
    • When it comes to releases, run the proofs once and then cache those artifacts for efficiency. Check out the details here.
  • Cache aggressively:

    • Use actions/cache@v4 to cache files like .ptau, .zkey, .wasm, and the target/ directory.
    • For Rust builds, implement Swatinem/rust-cache@v2. You can find more info on this GitHub page.
  • GPU provisioning:

    • If you're dealing with Boojum’s low-TPS scenarios, make sure to plan for at least 16 GB of VRAM on the GPU side or go for 32-128 cores with 64-128 GB of RAM on the CPU side. Scale your runner size to fit your target batch sizes. More details can be found here.
  • Remote burst:

    • If your proofs go over the CI time budget, you might want to offload them to Bonsai or the Succinct Prover Network. Block the release until you get a callback or webhook. This way, the network can handle proving in parallel, rather than putting all the pressure on a single GPU. Check it out here.
  • Timeouts and retries:

    • For hosted runners, it's wise to set a maximum runtime for each job. Adopting a “local → remote fallback” approach can save you from those frustrating stuck releases.

Security, compliance, and governance

  • Attestations + Policy

    • Use signed provenance through actions/attest-build-provenance (these are Sigstore short-lived certs) and make sure to enforce this with cluster admission policies. Check it out here: (github.com)
  • Reproducibility

    • For RISC Zero, make sure to reproduce the ImageID straight from the source. Your verifier should check the receipt against that ImageID and journal. It’s a good idea to treat the ImageID as a top-tier artifact in your releases. More info can be found here: (dev.risczero.com)
  • SRS Lifecycle (Circom/KZG)

    • Handle .ptau files and ceremony transcripts like they’re vital third-party cryptographic dependencies. Always keep track of explicit provenance and hashes. Don’t forget to cite the ceremony source and version in your release notes. Get all the details here: (plonkbook.org)

Advanced: aggregation and recursion strategy in 2025

If the costs of verification or proof fan-out start to increase, it’s a good idea to think about implementing folding or aggregation:

  • The folding systems, like Nova, SuperNova, and HyperNova, are pretty cool because they turn lengthy computations into compact verifiers. Plus, MicroNova and HyperKZG are all about boosting on-chain efficiency. These tools are becoming more user-friendly, but just a heads up--keep an eye on the changing security aspects and the choices you make for parameters. (github.com)
  • A little security reminder: there are several papers out there that take a closer look at different Nova variants, focusing on things like cycles of curves and bounded recursion assumptions. If you’re planning to roll out folding in a production setting, make sure you monitor the specific instantiation and security claims. And don't forget to pin your versions in CI to keep everything aligned. (eprint.iacr.org)
  • On the topic of Plonky2 and aggregation architectures (like ZKM), they showcase some really neat multi-stage aggregation stacks for Plonkish tables. This setup is super handy when you’ve got a bunch of micro-proofs being generated for each commit. (zkm.io)

Emerging best practices we’re applying for clients

  • Circuit semantics versioning

    • Let's stick to semver for our circuits and zkVM programs. Any breaking changes will bump the MAJOR version, and changes to verifier.sol or ImageID are considered release-blocking events.
  • Proof budgets

    • We're going to set some target SLAs: “<15 min wall-clock proving per release on N×L4 GPUs” or we'll have a fixed spending cap through a prover network. Check out the details here.
  • Dual‑path proving

    • We’ll maintain both a “local GPU” path for quick feedback and a “remote prover” path for scalability and SLA purposes. You can choose between them using environment flags in the same pipeline.
  • Deterministic dev builds

    • For Groth16 development iterations, let’s use deterministic beacons via hardhat-circom to keep zkey churn to a minimum. Just remember, don’t send those beacons to production. You can find it on GitHub.
  • On‑chain sanity checks in CI

    • For Groth16/PLONK, we should spin up a local EVM and call verifyProof with the CI-generated calldata before we deploy. This way, we can catch any ABI ordering issues or regressions before hitting mainnet. More info is available here.

A “release checklist” you can adopt tomorrow

  • Toolchains pinned:

    • Versions for circom/snarkjs and the .ptau hash are locked in.
    • We're using the RISC Zero toolchain with the rzup tag, and I've made a note of the ImageID.
    • The SP1 crate versions and Rust MSRV are also pinned down.
  • Proofs generated:

    • For Circom, I've got the r1cs hash, zkey, proof/public, and verifier.sol all exported.
    • RISC Zero proofs? Check! The receipt and journal are verified against the ImageID.
    • SP1 has generated proof along with public values, and I’ve logged the cycles.
  • Artifacts attached:

    • Everything's here: proofs plus public inputs.
    • Verification keys or the verifiers, and the deployed address, are included.
    • All artifacts have their attestations (Sigstore/SLSA) attached.
  • Gates passed:

    • Local verification steps are all green, which is great news!
    • Optional on-chain local EVM verification tests have passed as well.
    • We've kept the time and costs within budget or offloaded them as per the policy.

Putting it together: one pipeline to rule them all

  • PRs

    • For Circom/snarkjs: Just compile and create the witness; let’s skip the full Groth16 if nothing's changed.
    • RISC Zero: Run it with RISC0_DEV_MODE=1.
    • SP1: Only execute and get a cycles report.
  • Tags

    • With Circom/snarkjs: We need to create the full proof, export the verifier, and then verify it in the local EVM.
    • For RISC Zero: Make sure to generate the full receipt, verify it, and attach the ImageID map.
    • SP1: Send it off to the prover network, and release the block when the webhook triggers.
    • Don’t forget to attest the artifacts and publish them!

This method allows your organization to deliver cryptographically verifiable releases without needing to turn every developer's machine into a prover.


Where we see the space heading (next 12 months)

  • Lower device floors: With Boojum-class GPU minima, "ZK runners" are becoming the go-to standard for CI resources instead of just being reserved for special projects. Check it out here.
  • Networked proving as default: Now that Succinct’s mainnet prover network is up and running, more teams are starting to see proving as just another workload to manage, rather than a specific machine they need to own. Dive into the details here.
  • zkVM maturity: Thanks to SP1’s fast speeds and reliable workflows, more teams are coming together to unify circuit logic in Rust. This way, they can let the VM handle the heavy lifting, especially when it comes to complex, branching logic. For more insights, head over here.

7Block Labs can help

We’re all about designing, building, and securing ZK CI/CD for both startups and big businesses. Whether you’re picking out proving stacks, connecting GPU/remote provers, managing versioning for SRS, writing up verifiers, or making sure attestations are solid, we’ve got you covered. If your goal is to have “every release ships with proofs,” we’ll ensure it gets done quickly and without all the drama.


Sources and further reading

  • Check out the circom/snarkjs proving and Solidity verifier export commands and flow over at the Circom Docs.
  • If you're diving into zkSync, don’t miss the Boojum prover requirements and how to enable it using zkStack. You can find all the info in the zkSync Docs.
  • For a quick start with RISC Zero, take a look at rzup, receipts/journal, and the differences between dev-mode and real proving. Plus, there's a neat overview of Bonsai too! Head over to the RISC Zero Dev Docs for that.
  • Get the lowdown on Succinct SP1 performance and the best workflow to follow. They also provide some context about the Prover Network. Check it out on the Succinct Blog.
  • Curious about Halo2 IPA? They have a solid background on it along with the KZG SRS. Just dive into the details on the Zcash GitHub.
  • Lastly, if you're using GitLab, you might want to learn about using the GPU runner and how GitHub handles artifact attestations and provenance. All that info is in the GitLab Docs.

Like what you're reading? Let's build together.

Get a free 30-minute consultation with our engineering team.

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.

© 2026 7BlockLabs. All rights reserved.