The Pivotal Question: How Bellperson Chooses Between Supraseal-C2 and Standard GPU Proving
Introduction
In the midst of an exhaustive deep-dive investigation into Filecoin's Groth16 proof generation pipeline, a single message stands out as a critical inflection point. Message 39 of the conversation captures the moment when the assistant, after hours of gathering data about parameter sizes, resource requirements, proof types, and system architecture, pivots to the central question that underpins the entire optimization effort: How does bellperson decide between the supraseal-c2 GPU path and the standard GPU proving path?
The message is deceptively brief. It reads:
Now let me look at how bellperson decides between supraseal-c2 and standard GPU proving. This is critical: [bash] find $(go env GOMODCACHE) -path "/bellperson-0.26.0/src/.rs" 2>/dev/null | head -20
This single query, executed as a bash command within the coding session, represents the culmination of a systematic investigative process and the gateway to understanding the most consequential architectural decision in the entire proof pipeline. This article examines why this question was the natural next step, what assumptions and knowledge it relied upon, the thinking process it reveals, and why the assistant explicitly labeled it "critical."
The Context That Led to This Question
To understand why message 39 was written, one must appreciate the investigative journey that preceded it. The assistant had been tasked with exploring SnapDeals and PoSt (Proof of SpaceTime) circuit sizes as part of a larger effort to design a pipelined SNARK proving daemon called cuzk. This was not a casual exploration—it was a forensic examination of a production system consuming approximately 200 GiB of peak memory per proof generation.
The preceding messages (18–38) reveal a systematic, multi-layered investigation:
- Task-layer analysis: The assistant examined how SnapDeals proof tasks work in Curio, reading
task_prove.goto understand theProveTask.Do()method and how it calls into the FFI layer viaGenerateUpdateProofWithVanilla. - FFI boundary exploration: It traced the call chain from Go into Rust FFI through
ffiselect.goandffi-direct.go, identifying the exact function signatures that bridge the two language worlds. - Parameter file discovery: Using
grepand Python scripts, the assistant extracted the complete parameter file inventory from Lotus'sparameters.json, identifying all.paramsand.vkfiles for WindowPoSt, WinningPoSt, SnapDeals, and PoRep across sector sizes from 2 KiB to 64 GiB. - File size verification: It checked the actual on-disk sizes of downloaded parameter files in
/var/tmp/filecoin-proof-parameters/, finding a 626 MB SnapDeals parameter file for small sectors and noting that the larger 32 GiB and 64 GiB parameter files were not yet downloaded. - Resource requirement profiling: The assistant examined
TypeDetails()methods across multiple task types—WdPostTask,ProveTask,WinPostTask,SubmitTask—extracting the precise RAM and GPU resource allocations. Notably, it found that the SnapDealsProveTaskallocates50 << 30(50 GiB) of RAM with a comment "// todo correct value," while the WindowPoSt compute task allocates25 << 30(25 GiB). This accumulated knowledge painted a detailed picture of what resources were consumed and where the code paths led, but it did not yet answer the deeper question of how the system chose its proving strategy. That is where message 39 enters.
Why This Question Was "Critical"
The assistant's own words—"This is critical"—signal that this was not merely another data point but a pivotal architectural insight. Several factors made this question essential:
1. The Two Competing GPU Paths
Filecoin's proof system has evolved through multiple generations. The original bellperson library (a fork of Zcash's bellman) provided a pure Rust implementation of Groth16 proving with optional GPU acceleration via CUDA. Later, the supraseal-c2 library emerged as a highly optimized C++/CUDA implementation that could dramatically accelerate the most computationally intensive phases of proof generation, particularly the multi-scalar multiplication (MSM) and number-theoretic transform (NTT) operations.
These two paths—bellperson's built-in GPU prover and the external supraseal-c2 prover—coexist in the codebase. Understanding how the system chooses between them is critical because:
- Performance implications: Supraseal-c2 is substantially faster for large circuits but has different memory characteristics and initialization overhead.
- Architecture implications: If the system uses supraseal-c2, the cuzk daemon must interface with C++/CUDA libraries; if it uses bellperson's GPU prover, the optimization strategy differs.
- Resource management implications: Each path loads SRS (Structured Reference String) parameters differently, affecting peak memory and initialization latency.
2. The Missing Piece in the Puzzle
The assistant had already mapped the external contours of the system: the Go task layer, the FFI bridge, the parameter files, the resource allocations. But the internal decision logic—the if-else branch that determines which proving engine executes—remained opaque. Without this knowledge, any proposed optimization (like the cuzk daemon) would be building on assumptions rather than verified facts.
3. The Design Implications for cuzk
The cuzk project aimed to create a persistent proving daemon that keeps SRS parameters loaded in GPU memory across multiple proof jobs, eliminating the repeated loading overhead. The feasibility of this design depends critically on whether supraseal-c2 is the primary proving path. If supraseal-c2 is used, the daemon can potentially keep its C++/CUDA context alive; if bellperson's internal GPU prover is used, the integration surface is different.
The Thinking Process Revealed
The message reveals a sophisticated investigative methodology. The assistant's reasoning can be deconstructed into several layers:
Deductive Reasoning
The assistant had established that:
- The FFI layer exposes
GenerateUpdateProofWithVanillaand similar functions - These functions call into Rust code that eventually invokes bellperson's prover
- Bellperson has both GPU and CPU code paths
- Supraseal-c2 exists as a separate C++/CUDA library The logical conclusion: somewhere in bellperson's source code, there must be a decision point that selects between these implementations. Finding that decision point requires examining bellperson's Rust source files.
Strategic Tool Selection
The command find $(go env GOMODCACHE) -path "*/bellperson-0.26.0/src/*.rs" is carefully crafted:
$(go env GOMODCACHE)resolves to the Go module cache path, which is where Go's dependency management system stores vendored Go source code. However, bellperson is a Rust library, not a Go library. This suggests the assistant is searching for Rust source files that may have been downloaded as part of the Rust crate registry, which would be located in a different path (under$HOME/.cargo/registry/).- The
-path "*/bellperson-0.26.0/src/*.rs"pattern targets version 0.26.0 specifically, indicating the assistant had already identified the exact version of bellperson in use (likely from theCargo.lockfile examined in earlier messages). - The
head -20limits output, suggesting the assistant expects a manageable number of source files and wants a quick overview before diving deeper. The fact that this command returned no output (as we can see from the subsequent message 40, which uses a different path pattern) reveals an important assumption that was corrected: the Go module cache does not contain Rust crate sources. The assistant immediately adapts in message 40, using a direct path under/home/theuserto find the Rust source files.
The "Critical" Framing
The assistant's explicit labeling of this question as "critical" is a metacognitive signal. It indicates that the assistant is prioritizing questions by their impact on the overall investigation. Not all data points are equally important; some are architectural keystones that, once understood, unlock the rest of the design space. The assistant is consciously triaging the investigation toward the highest-leverage questions.
Assumptions Embedded in the Message
Every investigative step carries assumptions, and message 39 is no exception:
Assumption 1: The Decision Logic Lives in Bellperson's Source
The assistant assumes that the supraseal-c2 vs. standard GPU decision is made within bellperson's Rust code, rather than at a higher level (e.g., in the FFI dispatch layer or in Curio's task logic). This is a reasonable assumption given that supraseal-c2 is integrated as a proving backend within bellperson, but it is not guaranteed. The decision could theoretically be made by environment variables, compile-time flags, or runtime configuration.
Assumption 2: The Go Module Cache Contains Rust Sources
The command uses go env GOMODCACHE to find Rust source files. This is a category error: Go's module cache stores Go modules, not Rust crate sources. Rust uses its own registry at $CARGO_HOME (typically ~/.cargo/registry/). This assumption is quickly corrected in the subsequent message, demonstrating the assistant's ability to learn from failed queries.
Assumption 3: Version 0.26.0 Is the Correct Version
The assistant targets bellperson-0.26.0 specifically. This version number was likely extracted from the Cargo.lock file examined earlier. If the version were different, the query would return no results, and the assistant would need to adjust. This assumption proved correct, as message 40 successfully finds files under the bellperson-0.26.0 path.
Input Knowledge Required
To understand message 39, the reader must possess knowledge spanning multiple domains:
Filecoin Proof Architecture
- Understanding that Filecoin uses Groth16 zk-SNARKs for proof compression
- Knowledge that proofs are generated for different purposes: PoRep (Proof of Replication), WindowPoSt (Window Proof of SpaceTime), WinningPoSt, and SnapDeals (sector updates)
- Awareness that each proof type has different circuit sizes and parameter files
The Bellperson Library
- Bellperson is a fork of the bellman zk-SNARK library, customized for Filecoin's needs
- It provides both CPU and GPU proving paths
- It supports pluggable proving backends, including supraseal-c2
Supraseal-C2
- A C++/CUDA library that implements optimized Groth16 proving
- Handles the computationally intensive MSM and NTT operations on GPU
- Has its own memory management and SRS loading
Go and Rust Build Systems
- Go modules are stored in
GOMODCACHE - Rust crates are stored in
CARGO_HOME/registry/ - The two ecosystems coexist in the Filecoin FFI boundary
Output Knowledge Created
Message 39, despite its brevity, creates several forms of knowledge:
Immediate Output
The command produces a list of bellperson source files (in the subsequent message), which the assistant can then search for the supraseal-c2 decision logic. This is the direct, tangible output.
Methodological Knowledge
The message demonstrates a systematic approach to understanding complex systems: start with the observable behavior (task types, resource allocations, parameter files), then trace inward to the decision logic. This "outside-in" methodology is itself a valuable pattern for system comprehension.
Architectural Insight
Even before the command executes, the framing of the question reveals that the assistant understands the fundamental architectural tension in the system: there are two competing GPU proving paths, and understanding their relationship is the key to optimization.
The Broader Significance
Message 39 is a microcosm of the entire investigative session. It captures the moment when data collection transitions to architectural understanding. The assistant has gathered facts about resource consumption, parameter sizes, and code paths. Now it seeks to understand the control flow—the decisions that route computation through different engines.
This transition from "what" to "how" is the hallmark of deep technical investigation. It is the difference between knowing that a system consumes 50 GiB of RAM and understanding why it must do so, and whether that consumption is inherent to the problem or an artifact of implementation choices.
The question also reveals the assistant's design orientation. It is not merely documenting the existing system; it is preparing to change it. Understanding the supraseal-c2 decision logic is prerequisite to designing the cuzk daemon that will replace or augment it. Every optimization proposal—Sequential Partition Synthesis, Persistent Prover Daemon, Cross-Sector Batching—depends on knowing which proving engine is in play and how it can be controlled.
Conclusion
Message 39 appears, on its surface, as a simple bash command to find Rust source files. But within the context of this investigation, it represents the critical pivot from data collection to architectural understanding. The assistant's explicit framing—"This is critical"—signals that this question is the key that unlocks the rest of the design space. The subsequent exploration of bellperson's source code would reveal the supraseal-c2 integration points, the GPU device selection logic, and the SRS loading patterns that directly inform the cuzk daemon's architecture.
In the broader narrative of the coding session, message 39 is the moment when the investigation sharpens from broad exploration to focused inquiry. It is the question that, once answered, transforms a collection of facts into a coherent understanding of how Filecoin's proof generation pipeline actually works—and, more importantly, how it can be made to work better.