The Smoke Test: Validating a Self-Contained Build for the cuzk Proving Daemon
In any software integration effort, there comes a moment when theory meets reality. All the careful planning, the vendoring of dependencies, the modification of build scripts, and the staging of files culminates in a single, unambiguous question: does it actually build from scratch? Message [msg 3550] in this opencode session captures exactly that moment for the cuzk proving daemon — a GPU-accelerated Groth16 proof generator being upstreamed into the Curio Filecoin storage provider codebase.
The message itself is deceptively brief. It contains two shell commands and their output:
Clean build from scratch in 1m51s. Let me verify the binary: [bash] ./cuzk --help 2>&1 && file ./cuzk cuzk proving engine daemon
>
Usage: cuzk [OPTIONS]
>
Options: -c, --config <CONFIG> Path to configuration file (TOML) [default: /data/zk/cuzk.toml] -l, --listen <LISTEN> Override listen address (e.g. "0.0.0.0:9820" or "unix:///run/curio/cuzk.sock") --log-level <LOG_LEVEL> Override log level -h, --help Print help ./cuzk: ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1...
But this brevity belies the weight of what is being confirmed. To understand why this message matters, we must trace the chain of reasoning that led to it.
The Context: Upstreaming a Complex Foreign Codebase
The cuzk proving daemon is no ordinary binary. It is a Rust application with CUDA kernel dependencies, linking against blst (a BLS12-381 signature library), sppark (a GPU-accelerated multiscalar multiplication library), and supraseal-c2 (the core Groth16 prover with custom CUDA kernels). It depends on forked versions of bellpepper-core (a constraint system library) and supraseal-c2 itself — forks that live in the Curio repository's extern/ directory. The entire pipeline consumes approximately 200 GiB of peak memory and involves a chain of Go, Rust, C++, and CUDA code spanning from Curio's task orchestrator down to GPU kernel launches.
The user's instruction in [msg 3533] was clear: "Add all cuzk code such that git clone -> make curio cuzk; builds both correctly from a fresh clone." This is a stringent requirement. It means that every source file, every build configuration, every license file, and every dependency manifest must be present in the repository. A developer should be able to clone the repo, run make curio cuzk, and have both the Curio Go binary and the cuzk Rust/CUDA binary emerge without any manual intervention, without fetching from unlisted remote repositories, and without any missing files causing cryptic build failures.
The Audit That Preceded the Build
The assistant's work in the messages leading up to [msg 3550] reveals the meticulousness required. In [msg 3536], the assistant ran git status --porcelain across all the relevant directories and discovered that extern/bellpepper-core/ and extern/supraseal-c2/ were only partially tracked. The originally checked-in commit had only stored the diff files — the modified source code relative to the upstream — but not the foundational files that Cargo needs to build: Cargo.toml, build.rs, src/lib.rs, license files, and README. Without these, cargo build would fail immediately with "no package found" errors.
The assistant then performed a systematic audit (<msg id=3540-3543>), comparing git ls-tree output against the actual files on disk for each vendored crate. For extern/bellperson/, all 70 files matched. For extern/cuzk/, all 35 files matched. But for bellpepper-core and supraseal-c2, the diffs revealed dozens of missing files — the very files that make a Cargo workspace buildable. This was the critical finding that justified the entire staging operation.
The assistant also checked for .gitignore interference ([msg 3538]). The root .gitignore contained **/*.a and **/*.pc patterns that could potentially block static library artifacts. However, the assistant verified that all .a files lived inside target/ directories, which were already excluded by extern/cuzk/.gitignore. No source files were being accidentally blocked.
The Decision to Vendor In‑Repo
A key architectural decision underpinning this work was the choice to vendor the forked Rust crates directly inside the Curio repository rather than pushing branches to external GitHub repositories. This was Option B from the earlier analysis in [chunk 0.0]. The reasoning was pragmatic: vendoring ensures a self-contained, reproducible build that does not depend on upstream coordination, CI access to external repos, or the risk of a remote repository disappearing or changing. It also means that the exact version of every dependency is pinned in the commit history — any clone at a given commit will produce byte-identical binaries (assuming the same toolchain).
This decision had consequences for the build system. The Makefile targets added in <msg id=3514-3516> were designed around this vendored structure. The make cuzk target runs cd extern/cuzk && cargo build --release --bin cuzk-daemon, relying on Cargo's [patch.crates-io] mechanism in extern/cuzk/Cargo.toml to redirect bellpepper-core and supraseal-c2 to the local extern/ directories. The Makefile also includes pre-flight checks for cargo and nvcc, failing with clear error messages if either is missing.
Crucially, the assistant made a deliberate choice to exclude cuzk from the BINS variable ([msg 3525]). This means make buildall — a convenience target that builds all binaries — does not attempt to build cuzk. This is essential because CI environments typically lack CUDA toolkits and Rust toolchains. The cuzk build is opt-in: only storage providers with GPU hardware explicitly run make cuzk on their proving machines. This design avoids breaking CI while still providing a seamless build experience for production deployments.
What the Smoke Test Actually Proves
When the assistant ran cargo clean in [msg 3548], it removed 17,616 files totaling 12.5 GiB of build artifacts. This was not mere housekeeping — it was a deliberate act to simulate a truly clean build. By wiping the entire Cargo build cache, the assistant ensured that the subsequent make cuzk would have to recompile every dependency from source, exactly as a developer cloning the repository for the first time would experience.
The build completed in 1 minute and 51 seconds. This timing is itself meaningful. It tells us that the vendored crates compile without errors, that the CUDA kernels compile and link correctly, and that the Cargo dependency resolution succeeds using only the local [patch.crates-io] overrides. Any missing file, any incorrect path in a Cargo.toml, or any broken build.rs would have surfaced during this build.
The assistant then performed two verification steps. First, ./cuzk --help confirmed that the binary runs and produces the expected usage output. The help text reveals the daemon's interface: it accepts a TOML configuration file (defaulting to /data/zk/cuzk.toml), supports both TCP and Unix domain socket listeners, and has a --log-level flag. Second, file ./cuzk confirmed that the output is a standard ELF 64-bit pie executable, dynamically linked — the kind of binary that would run on any modern Linux system with the appropriate CUDA runtime libraries installed.
Assumptions and Their Validity
The smoke test validates several implicit assumptions:
- All source files are now tracked. The assumption that
git addof the entireextern/bellpepper-core/andextern/supraseal-c2/directories captured everything needed was confirmed by the successful build. Had any file been missed (e.g., abuild.rsor a CUDA header), Cargo would have failed with a missing file error. - The
.gitignoredoes not block essential files. The assistant verified this explicitly ([msg 3538]), but the build confirmation provides stronger evidence: no.aor.pcfiles in source trees caused issues. - The
[patch.crates-io]mechanism works with vendored paths. Cargo's patch system is powerful but finicky — incorrect path specifications or missing workspace members can cause silent fallback to the upstream crate. The fact thatcargo buildsucceeded with all dependencies resolved from local paths confirms the patching is correct. - The CUDA toolchain is discoverable. The
nvcccheck in the Makefile is a prerequisite guard, but the actual proof is that the CUDA kernels insupraseal-c2/cuda/compiled and linked into the final binary. - The Rust toolchain version is compatible. The
rust-toolchain.tomlinextern/cuzk/specifies channel1.86.0. The build's success confirms that no language features or library APIs used by the code have been deprecated or changed incompatibly.
What This Message Creates
The output of this message is not just a binary on disk — it is confidence. Confidence that the upstreaming effort is complete. Confidence that a future developer (or CI system) can reproduce the build. Confidence that the vendoring approach works end-to-end.
This message also creates a checkpoint in the session's narrative. Before it, the assistant was in "construction mode" — auditing files, editing Makefiles, staging changes. After it, the assistant shifts to "polishing mode" — verifying Go vet passes ([msg 3551]), writing documentation ([msg 3559]), updating the SUMMARY.md ([msg 3560]), and performing a final comprehensive review of the staging area (<msg id=3564-3569>). The smoke test is the gate that separates these two phases.
The Broader Significance
In the context of the entire 34-segment session, this message represents the culmination of a months-long engineering effort to build a GPU-accelerated proving pipeline for Filecoin storage providers. The session had progressed through architecture design, implementation of the split GPU proving API, memory optimization with backpressure mechanisms, low-memory benchmark sweeps, and integration with Curio's task orchestrator. But all of that work would be useless if it could not be reliably built and deployed.
The final commit (3c53695c on the feat/cuzk branch) would include 37 files spanning Go, Rust, CUDA, TOML, Markdown, and Makefile changes. The smoke test in [msg 3550] is the moment when those 37 files were proven to work together as a coherent whole. It is the difference between "the code compiles on my machine" and "the code compiles from a clean clone" — a distinction that matters enormously for production deployments, open-source contributions, and long-term maintainability.
The article also notes that the assistant added /cuzk to .gitignore in [msg 3567] to prevent the built binary from being accidentally committed, and staged the cuzk-project.md documentation. These final touches complete the upstreaming picture: the repository is now in a state where a developer can clone, build, and understand the cuzk proving daemon without any external coordination or manual steps.
Conclusion
Message [msg 3550] is a textbook example of a "smoke test" in software integration — a quick, high-signal verification that the entire build pipeline works from a clean state. But its significance extends beyond the 1 minute and 51 seconds of compilation time. It validates a series of careful decisions about vendoring, build system design, CI compatibility, and dependency management. It transforms the cuzk proving daemon from a collection of files on disk into a reproducible, buildable artifact. And it marks the transition from construction to documentation, from implementation to integration, from "it works" to "it ships."