The Fork That Enabled GPU-Level Optimization: Creating a Local supraseal-c2 Fork in the cuzk Proving Pipeline

Introduction

In the course of optimizing a Groth16 proof generation pipeline for Filecoin's Proof of Replication (PoRep), a single, deceptively simple command marks the transition from CPU-level optimizations to the GPU-level work that would define the remainder of Phase 4. Message [msg 788] in this opencode session contains just one bash invocation: a cp command that copies the supraseal-c2 crate from the Cargo registry into a local extern/ directory. Yet this operation represents a critical architectural decision — the creation of a local fork that would enable the assistant to modify CUDA kernel code, tune GPU Multi-Scalar Multiplication (MSM) window sizes, and instrument phase-level timing in the proving pipeline. Understanding why this fork was necessary, how it fits into the broader optimization strategy, and what assumptions underpinned its creation reveals the careful engineering discipline behind performance optimization in complex Rust+CUDA systems.

The Message

The subject message is brief but consequential:

Message 788 (assistant): Now let me also create the supraseal-c2 fork for the CUDA optimizations. Let me do that while also verifying the bellpepper-core change compiles. `` cp -r /home/theuser/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/supraseal-c2-0.1.2 /home/theuser/curio/extern/supraseal-c2 && echo "Copied supraseal-c2" Copied supraseal-c2 ``

The assistant copies the entire supraseal-c2 v0.1.2 crate from the local Cargo registry into the project's extern/ directory, creating a local fork that can be modified and then patched into the workspace via Cargo's [patch.crates-io] mechanism.

Context: Phase 4 of the cuzk Optimization Campaign

To understand why this message was written, one must understand the project's trajectory. The cuzk project is a Rust-based SNARK proving engine for Filecoin's Curio storage mining software. It had already completed three phases of optimization: Phase 1 established the pipeline architecture, Phase 2 implemented async overlap between synthesis and GPU proving, and Phase 3 introduced cross-sector batching that achieved a 1.46× throughput improvement. Phase 4, titled "Compute Quick Wins," aimed to reduce the computational cost of individual proof operations — both on the CPU (synthesis) and GPU (proving).

The optimization proposals were documented in c2-optimization-proposal-4.md and organized into waves. Wave 1 included five optimizations:

Why a Fork Was Necessary

The assistant had already discovered this constraint through a series of reconnaissance tasks. In [msg 772], four parallel tasks explored the codebase to understand where each dependency lived. The critical finding came in [msg 773]: bellpepper-core is a crates.io dependency, not a local fork. A follow-up task in [msg 774] confirmed the same for supraseal-c2 — despite there being two local copies of the source in extern/supra_seal/ and extern/supraseal/, neither was actually used by the build. The actual dependency resolved to supraseal-c2 v0.1.2 from the Cargo registry.

This created an immediate problem: the GPU optimizations (A4, B1, D4) required modifying groth16_cuda.cu and related CUDA files, but those files lived inside an immutable crate downloaded by Cargo. The solution was the same approach the project had already used for bellperson: create a local fork in extern/, make the desired modifications, and use Cargo's [patch.crates-io] mechanism to redirect the dependency.

The Decision-Making Process

The assistant's decision to fork supraseal-c2 was not made in isolation in message [msg 788]. It was the culmination of a deliberate reasoning chain visible across the preceding messages. In [msg 775], after discovering that supraseal-c2 came from crates.io, the assistant explicitly laid out the plan:

For GPU/CUDA optimizations (A4, B1, B2, B3, D2, D4): - Need to fork supraseal-c2 locally (copy from crates.io registry, patch, add to [patch.crates-io])

The assistant then executed the CPU-side fork first. Messages [msg 776] through [msg 787] show the complete workflow for bellpepper-core: copying the crate from the registry, adding the smallvec dependency to Cargo.toml, modifying lc.rs to use SmallVec, and patching the workspace Cargo.toml to redirect the dependency. Message [msg 787] confirms the workspace patch was applied successfully.

Message [msg 788] is the natural next step: repeat the same fork workflow for supraseal-c2. The assistant explicitly states the dual purpose: "create the supraseal-c2 fork for the CUDA optimizations" and "verify the bellpepper-core change compiles" — the latter referring to a planned cargo check that would follow in [msg 790].

Assumptions Underlying the Fork

Several assumptions are embedded in this seemingly simple copy operation. First, the assistant assumes that copying the crate from the registry preserves all necessary build infrastructure, including the CUDA build scripts (build.rs and cuda/ directory) that compile the .cu files. The registry source at ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/supraseal-c2-0.1.2/ was confirmed in [msg 774] to contain the full source tree including CUDA files, so this assumption was well-founded.

Second, the assistant assumes that the [patch.crates-io] mechanism will correctly redirect the dependency for all downstream consumers. The dependency chain is cuzk-core → bellperson → supraseal-c2. Since the workspace Cargo.toml at extern/cuzk/Cargo.toml already contains the [patch.crates-io] section (as modified in [msg 787] for bellpepper-core), adding a supraseal-c2 entry should work identically.

Third, the assistant assumes that the local fork's version number (0.1.2) matches the registry version exactly. Cargo's patch mechanism requires an exact version match, and the copy preserves the original Cargo.toml which declares version 0.1.2.

Input Knowledge Required

To understand this message, one needs knowledge of several domains. First, Cargo's dependency resolution and patching mechanism: the [patch.crates-io] section in workspace Cargo.toml overrides a crates.io dependency with a local path, but only if the version numbers match exactly. Second, the project's dependency graph: cuzk-core depends on bellperson, which in turn depends on supraseal-c2 for GPU proving. Third, the CUDA build process: supraseal-c2 uses a build.rs script that invokes nvcc to compile .cu files, and this script must be preserved in the fork. Fourth, the optimization taxonomy from c2-optimization-proposal-4.md: the letter-number codes (A1, A4, B1, D4) correspond to specific optimization proposals targeting different layers of the proving pipeline.

Output Knowledge Created

The immediate output of message [msg 788] is a local fork of supraseal-c2 at /home/theuser/curio/extern/supraseal-c2/. This fork is a byte-for-byte copy of the registry crate, preserving all source files, build scripts, and metadata. The subsequent messages show the fork being patched into the workspace ([msg 789]) and validated with a successful compilation check (<msg id=790-791>).

More broadly, this fork enables all the GPU-level optimizations that follow. Without it, the assistant could not modify groth16_cuda.cu to add parallel B_G2 MSMs (A4), pin a/b/c vectors with cudaHostRegister (B1), or split the monolithic msm_t into per-MSM tuned instances (D4). The fork is the enabling infrastructure for the entire GPU optimization campaign.

The Broader Significance

Message [msg 788] is a hinge point in the optimization workflow. Before it, the assistant was working entirely in Rust code — modifying lc.rs for SmallVec, planning pre-sizing changes to ProvingAssignment. After it, the assistant would enter the CUDA codebase, adding std::chrono instrumentation, tuning MSM window sizes, and ultimately discovering that the B1 optimization (cudaHostRegister) caused a performance regression that required reverting.

The fork also reveals an important pattern in open-source performance engineering: when optimizing a system built on external dependencies, the ability to fork and modify those dependencies is essential. The Rust ecosystem's [patch.crates-io] mechanism makes this pattern ergonomic, allowing developers to maintain local forks without forking the entire upstream repository. The assistant leveraged this mechanism twice in the span of a few messages — first for bellpepper-core, then for supraseal-c2 — demonstrating a systematic approach to dependency modification.

Conclusion

A single cp command, executed in message [msg 788], represents the transition from CPU to GPU optimization in the cuzk proving pipeline. By creating a local fork of supraseal-c2, the assistant enabled a series of CUDA-level optimizations that would ultimately be benchmarked, measured, and iterated upon. The message exemplifies a key skill in systems optimization: recognizing when a dependency boundary must be crossed, and knowing the tooling (Cargo's [patch.crates-io]) that makes crossing it possible. In the broader narrative of Phase 4, this fork is the foundation upon which all GPU work was built — including the discovery that not every optimization works as expected, and that careful instrumentation is required to separate genuine improvements from regressions.