Reading the Build Scripts: A Critical Decision Point in GPU Backend Selection for the cuzk Proving Daemon
Introduction
In the course of implementing Phase 0 of the cuzk pipelined SNARK proving daemon for Filecoin, the assistant reached a critical juncture: selecting the correct CUDA backend for the RTX 5070 Ti (Blackwell architecture, compute capability 12.0) available on the test machine. Message <msg id=200> captures this decision point — a brief but consequential investigation into two build scripts that would determine whether the proving pipeline could execute at all.
The message is deceptively simple: the assistant reads two build.rs files, one from supraseal-c2-0.1.2 and one from bellperson-0.26.0. But this act sits at the intersection of hardware compatibility, build system architecture, and the practical realities of deploying zero-knowledge proof infrastructure on modern GPU hardware. Understanding why this message was written, what assumptions it carries, and what knowledge it produces reveals the careful reasoning that underpins production-grade SNARK proving systems.
Context: The State of the cuzk Project
To appreciate message <msg id=200>, we must understand where the project stood at that moment. The cuzk proving daemon had been designed and implemented across six crates in extern/cuzk/, with a complete gRPC API, priority scheduler, and real seal_commit_phase2 integration. The workspace compiled cleanly with --no-default-features (a CPU-only build that avoids CUDA entirely). The 45 GiB SRS parameters had been laboriously fetched and copied to /data/zk/params/. A 51 MB golden C1 test file sat ready at /data/32gbench/c1.json.
The next milestone was unambiguous: run a real proof end-to-end. This would be the first time the full pipeline — deserialization, SRS loading, constraint synthesis, GPU computation, and proof verification — would execute on actual hardware. The assistant had already confirmed the environment: an RTX 5070 Ti with 16 GB VRAM, CUDA 13.1, compute capability 12.0 (Blackwell).
But between the assistant and that milestone lay a build configuration decision. The cuzk-core crate exposed two feature flags: cuda (using bellperson's native CUDA prover) and cuda-supraseal (using the specialized supraseal-c2 GPU prover). The question was: which one supports Blackwell GPUs?
Why This Message Was Written: The Blackwell Compatibility Question
The assistant's reasoning, visible in the preceding messages, follows a clear chain:
- Message
<msg id=194>: Plans to "Build with CUDA features for GPU proving" and "Run daemon with FIL_PROOFS_PARAMETER_CACHE=/data/zk/params and test real PoRep C2 proof." - Message
<msg id=195>: Confirms the test data and GPU availability. - Message
<msg id=196>: Notes the "RTX 5070 Ti available with 16 GB VRAM." - Message
<msg id=197>: Reads the workspace and crate Cargo.toml files to understand the feature flag structure. - Message
<msg id=198>: Discovers compute capability 12.0 (Blackwell) and asks: "Let me check if supraseal supports it, or if we need the regular bellperson CUDA backend." - Message
<msg id=199>: Locates the build.rs files for both supraseal-c2 and bellperson. Message<msg id=200>is the direct follow-through: reading those build scripts to determine architecture support. The motivation is practical. Blackwell (sm_120 / compute cap 12.0) is NVIDIA's newest architecture as of early 2026. GPU compute libraries and CUDA kernel collections often lag behind new architectures — a library compiled for sm_80 (Ampere) or sm_89 (Ada Lovelace) may not contain the machine code needed to run on Blackwell. If supraseal-c2's build system doesn't target Blackwell, the daemon would crash at runtime with a "no kernel image for device" error, or fail to compile at all.
What the Build Scripts Reveal
The assistant reads two files. The first is supraseal-c2-0.1.2/build.rs:
use std::env;
fn main() {
let mut nvcc = sppark::build::ccmd();
nvcc.define("FEATURE_BLS12_381", None);
apply_blst_flags(&mut nvcc);
nvcc.file("cuda/groth16_cuda.cu").compile("groth16_cuda");
println!("cargo:rerun-if-changed=cuda");
println!("cargo:rerun-if-env-changed=CXXFLAGS");
}
This is a thin wrapper around sppark::build::ccmd(), which is a helper from the sppark library (supraseal's CUDA support library). The architecture targeting is entirely abstracted into sppark::build::ccmd() — the build script itself doesn't specify -arch=sm_XX flags. This means the answer to "does supraseal support Blackwell?" depends on what sppark's build helper does internally.
The second file is bellperson-0.26.0/build.rs:
fn main() {
cfg_if_nightly();
gpu_kernel();
}
Bellperson's build script is even simpler — it conditionally enables nightly Rust features and calls gpu_kernel() to generate CUDA/OpenCL kernels at compile time. The architecture targeting here is handled inside gpu_kernel(), which likely probes the system for available GPUs or uses environment variables.
The Unanswered Question
Crucially, message <msg id=200> does not resolve the Blackwell compatibility question. The assistant reads the build scripts but does not yet determine the answer. The investigation is incomplete — the assistant would need to either:
- Inspect the
spparklibrary'sbuild::ccmd()implementation to see what architectures it targets, - Check the compiled
.cubinor.fatbinobjects for sm_120 code, - Or simply try building with
--features cuda-suprasealand see if it compiles and runs. This incompleteness is not a mistake — it reflects a deliberate investigative strategy. The assistant is gathering information before making a decision. Reading the build scripts is a reconnaissance step that narrows the search space. The next logical step would be to examinesppark's build helper or attempt a build.
Assumptions Embedded in the Investigation
Several assumptions underpin this message:
Assumption 1: Architecture support is determined at build time. The assistant assumes that reading the build script will reveal which GPU architectures are targeted. This is generally true for CUDA projects — architecture flags like -arch=sm_89 or -gencode=arch=compute_89,code=sm_89 appear in build scripts or CMakeLists. However, sppark::build::ccmd() abstracts this away, making the assumption less productive.
Assumption 2: The build.rs files are the right place to look. For a Rust crate that compiles CUDA code, build.rs is indeed where CUDA compilation is orchestrated. This assumption is correct.
Assumption 3: There might be a compatibility issue. The assistant implicitly assumes that Blackwell support might be missing. This is a reasonable assumption given that Blackwell GPUs were only announced in late 2024 and the supraseal-c2 crate is version 0.1.2 — likely developed before Blackwell hardware was widely available.
Assumption 4: The two backends (supraseal vs bellperson) have different architecture support. This is plausible — supraseal-c2 is a specialized, optimized prover that may target specific architectures, while bellperson's CUDA backend is more general.
Input Knowledge Required
To understand this message, a reader needs:
- Knowledge of the cuzk project architecture: That there are two CUDA backends (
cudaandcuda-supraseal), and that the choice affects GPU compatibility. - Understanding of CUDA compute capabilities: That Blackwell = sm_120 = compute cap 12.0, and that older code may not support it.
- Familiarity with Rust build scripts: That
build.rsfiles run at compile time and can invoke external compilers likenvcc. - Knowledge of the sppark library: That
sppark::build::ccmd()is a helper that configures the NVCC command with architecture flags. - Context from the preceding messages: That the assistant is trying to run the first real proof and needs to choose the right feature flag.
Output Knowledge Created
This message produces several pieces of knowledge:
- The exact content of supraseal-c2's build.rs: It uses
sppark::build::ccmd()and compiles a single CUDA file (groth16_cuda.cu). The architecture targeting is delegated to sppark. - The exact content of bellperson's build.rs: It conditionally enables nightly features and calls
gpu_kernel(), which handles kernel generation at compile time. - Confirmation that both build scripts are relatively thin: Neither directly specifies architecture flags, meaning the architecture support question must be answered by examining their dependencies (sppark for supraseal, and the
gpu_kernel()implementation for bellperson). - A narrowing of the investigation: The assistant now knows where to look next — into sppark's build helper and bellperson's kernel generation.
The Thinking Process
The assistant's reasoning, visible across messages <msg id=194> through <msg id=200>, demonstrates a systematic, layered approach to build configuration:
- Goal identification: "Run a real proof" → requires GPU build.
- Feature discovery: Read Cargo.toml to find available CUDA features.
- Hardware characterization: Check
nvidia-smifor GPU model and compute capability. - Compatibility assessment: Compare hardware (compute cap 12.0) against software (supraseal-c2 v0.1.2).
- Source investigation: Read build scripts to understand architecture targeting.
- (Next) Deeper investigation or trial build: Depending on what the build scripts reveal. This mirrors how a experienced systems engineer would approach an unfamiliar build: gather facts about the hardware, examine the build configuration, and only then attempt a build. The alternative — blindly building with
--features cuda-suprasealand debugging a cryptic linker or runtime error — would be far less efficient.
Broader Significance
Message <msg id=200> illustrates a recurring pattern in systems engineering: the moment when abstract design meets concrete hardware. The cuzk project had been designed with clean abstractions — gRPC APIs, priority schedulers, configurable backends. But at the point of deployment, the assistant must confront the messy reality of GPU architecture compatibility, build system quirks, and version dependencies.
This message also highlights the value of investigative reading in software development. Rather than guessing or trial-and-error, the assistant reads the actual source code of dependencies to understand their behavior. This approach produces reliable knowledge that can be referenced later and avoids the pitfalls of assuming documentation is accurate or complete.
Conclusion
Message <msg id=200> is a small but pivotal moment in the cuzk implementation. It represents the transition from "the code compiles" to "the code will run on this specific hardware." By reading the build scripts of both supraseal-c2 and bellperson, the assistant gathers the information needed to make an informed decision about which CUDA backend to use. The investigation is not yet complete — the architecture support question remains open — but the search space has been narrowed, and the next steps are clear.
This message exemplifies the careful, methodical approach required when deploying zero-knowledge proof infrastructure on modern GPU hardware. Every abstraction must eventually be grounded in the specifics of the silicon, and every build configuration must be validated against the actual hardware it will run on. The cuzk proving daemon is one step closer to producing its first real proof.