The Feature Flag That Determines Which Proving Backend Runs Your Filecoin Proofs
Introduction
In the course of a deep-dive investigation into the SUPRASEAL_C2 Groth16 proof generation pipeline for Filecoin PoRep, a seemingly mundane command was issued — a grep across a Cargo.toml file to check feature flag definitions. Yet this single command, message 69 in the conversation, represents a pivotal moment of architectural discovery. It confirmed that the Supraseal C++ proving backend, despite being the primary focus of the investigation, is not used for all proof types in the Filecoin ecosystem. This article examines that message in detail: why it was written, what assumptions it tested, what knowledge it required, and what insights it produced.
The Message Itself
The message is a bash command executed by the assistant, followed by its output:
[assistant] [bash] grep -n "feature\|supraseal\|cuda\|opencl" /home/theuser/.cargo/registry/src/index.crates.io-6f17d22bba15001f/storage-proofs-update-18.1.0/Cargo.toml 2>&1 | head -20
36:features = [
40:default-features = false
44:default-features = false
63:features = [
79:features = ["derive"]
83:default-features = false
87:default-features = false
98:[features]
99:cuda = [
100: "storage-proofs-core/cuda",
101: "storage-proofs-porep/cuda",
102: "filecoin-hashers/cuda",
103: "neptune/cuda",
104: "bellperson/cuda",
107: "opencl",
116:opencl = [
117: "storage-proofs-core/opencl",
118: "storage-proofs-porep/opencl",
119: "filecoin-hashers/opencl",
120...
At first glance, this is just a developer checking which Cargo features are defined in a Rust crate. But in the context of the broader investigation, this output carried enormous weight.
The Reasoning and Motivation: Why This Message Was Written
To understand why this grep was necessary, we must trace the investigation that led to it. The assistant had been systematically mapping the call chain from Curio's Go task layer, through Rust FFI, into bellperson's Groth16 prover, and ultimately down to C++/CUDA kernels. The central question was: which proving backend does each Filecoin proof type actually use?
Earlier in the conversation ([msg 50], [msg 51]), the assistant had discovered the critical dispatch mechanism in bellperson's groth16/prover/mod.rs:
#[cfg(not(feature = "cuda-supraseal"))]
mod native;
#[cfg(feature = "cuda-supraseal")]
mod supraseal;
#[cfg(not(feature = "cuda-supraseal"))]
use self::native as prover;
#[cfg(feature = "cuda-supraseal")]
use self::supraseal as prover;
This is a compile-time switch: when cuda-supraseal is enabled, bellperson compiles in the Supraseal C++ prover; otherwise, it uses the native Rust prover (which itself can use GPU acceleration via cuda or opencl features).
The natural next question was: which crates in the dependency tree enable bellperson/cuda-supraseal? The assistant traced the feature propagation upward through the stack:
filecoin-proofsdefinescuda-suprasealwhich enablesbellperson/cuda-supraseal([msg 67])- But critically,
filecoin-proofs'scuda-suprasealfeature enables different sub-features for different sub-crates: - For
storage-proofs-porep: it enablesstorage-proofs-porep/cuda(not cuda-supraseal) - For
storage-proofs-post: it enablesstorage-proofs-post/cuda(not cuda-supraseal) - For
storage-proofs-update: it enablesstorage-proofs-update/cuda(not cuda-supraseal) This meant that PoRep proofs might use Supraseal (becausefilecoin-proofs-poreppresumably has its owncuda-suprasealfeature that propagates to bellperson), but PoSt and Update proofs might not. Message 69 was written to confirm this hypothesis by checking whetherstorage-proofs-updateeven defines acuda-suprasealfeature. The absence of such a feature in the grep output would be definitive evidence that Update proofs (SnapDeals) never use the Supraseal backend, regardless of how the top-levelfilecoin-proofscrate is configured.## The Output: What It Revealed The grep output forstorage-proofs-update-18.1.0/Cargo.tomlshows the following features: cuda— enablesstorage-proofs-core/cuda,storage-proofs-porep/cuda,filecoin-hashers/cuda,neptune/cuda,bellperson/cudaopencl— enablesstorage-proofs-core/opencl,storage-proofs-porep/opencl,filecoin-hashers/opencl, ... There is nocuda-suprasealfeature defined instorage-proofs-update. This is the crucial finding. The Update proof crate only knows aboutcudaandopencl— it has no concept of Supraseal at all. Even if the top-levelfilecoin-proofscrate is compiled withcuda-supraseal, the Update proof path will usebellperson/cuda(the native Rust prover with GPU acceleration) rather thanbellperson/cuda-supraseal(the Supraseal C++ backend). This finding was immediately compared with the earlier result forstorage-proofs-post([msg 68]), which also lacked acuda-suprasealfeature. The pattern was clear: only PoRep proofs (viastorage-proofs-porep) could potentially use the Supraseal backend, while PoSt and Update/SnapDeals proofs always used the native GPU prover.
Assumptions Tested and Corrected
This message tested several implicit assumptions that had been building throughout the investigation:
Assumption 1: Supraseal is the default GPU proving backend for all Filecoin proof types. This was a natural assumption given that the investigation's central focus was the SUPRASEAL_C2 pipeline and its ~200 GiB memory footprint. The grep results disproved this: Supraseal is only reachable through storage-proofs-porep, not through storage-proofs-post or storage-proofs-update.
Assumption 2: The feature flag propagates uniformly. One might assume that enabling cuda-supraseal at the top level would cause all downstream crates to use Supraseal. But the feature definitions in filecoin-proofs show a selective propagation: PoRep gets cuda-supraseal, while PoSt and Update get only cuda. This is a deliberate design choice, likely because Supraseal was specifically optimized for the PoRep circuit structure.
Assumption 3: SnapDeals (Update proofs) would benefit most from the Supraseal investigation. Since the investigation was motivated by memory optimization for large proofs, and SnapDeals involve updating sector data, one might think SnapDeals would be the primary consumer of Supraseal optimizations. The grep result showed the opposite: SnapDeals use the native prover, and any memory optimizations for Supraseal would primarily benefit PoRep, not SnapDeals.
Input Knowledge Required
To understand this message, several layers of context are necessary:
- Rust/Cargo feature system: The reader must understand that Cargo features are compile-time flags that conditionally include code. The
#[cfg(feature = "...")]attribute gates compilation of entire modules. - The Filecoin proof stack architecture: The dependency chain is:
filecoin-proofs-api→filecoin-proofs→storage-proofs-{core,porep,post,update}→bellperson→supraseal-c2(C++ library). Each layer can define its own features and propagate them selectively. - The bellperson dispatch mechanism: The critical insight from [msg 51] that
mod nativevsmod suprasealis selected at compile time based on thecuda-suprasealfeature. - The proof type distinction: Filecoin has three main proof types — PoRep (Proof-of-Replication, for sealing), PoSt (Proof-of-Spacetime, for window/sector proving), and Update/SnapDeals (for updating committed sector data). Each has different circuit sizes and performance characteristics.
- Previous grep results: The assistant had already checked
storage-proofs-post([msg 68]) and found nocuda-suprasealfeature. Message 69 was the parallel check forstorage-proofs-updateto complete the picture.
Output Knowledge Created
This message produced several concrete pieces of knowledge:
- SnapDeals/Update proofs never use Supraseal. The absence of a
cuda-suprasealfeature instorage-proofs-updatemeans that even when the top-level crate is compiled with Supraseal support, Update proofs will use the native Rust prover with GPU acceleration viabellperson/cuda. - The native prover is the universal fallback. For any proof type that doesn't explicitly enable
cuda-supraseal, the native prover is used. This means the native prover's GPU capabilities (viaLockedMultiexpKernelandLockedFftKernel) are the common denominator across all proof types. - PoRep is the only Supraseal consumer. This focuses the optimization effort: if you want to reduce the ~200 GiB peak memory of Supraseal, you're optimizing for PoRep. PoSt and SnapDeals would need separate optimization efforts targeting the native prover.
- A mapping of proof type to proving backend: PoRep → Supraseal (when
cuda-suprasealis enabled), PoSt → Native GPU, SnapDeals → Native GPU. This mapping is essential for understanding where to invest optimization resources.
The Thinking Process Visible in This Message
The assistant's reasoning is visible in the sequence of commands leading up to and following message 69. The investigation followed a systematic pattern:
- Discover the dispatch point: Find where bellperson chooses between native and Supraseal ([msg 51]).
- Trace the feature upward: Check how
filecoin-proofsdefines and propagatescuda-supraseal([msg 67]). - Check each sub-crate: Verify whether
storage-proofs-post([msg 68]) andstorage-proofs-update(message 69) define their owncuda-suprasealfeature. - Synthesize the conclusion: The pattern is clear — only PoRep gets Supraseal. The assistant didn't stop at the feature definitions. After message 69, it immediately proceeded to examine the actual constraint count definitions in
storage-proofs-post([msg 70]), moving from "which backend is used" to "how big are the circuits for each proof type." This shows a methodical approach: first establish the architectural boundaries, then drill into the quantitative details.
Mistakes and Incorrect Assumptions
The most significant incorrect assumption that this message helped correct was the belief that Supraseal was the primary GPU proving path for all proof types. The investigation had been framed around "the SUPRASEAL_C2 Groth16 proof generation pipeline for Filecoin PoRep," but the memory and performance characteristics being studied were specific to PoRep. The grep results in message 69 and its predecessor [msg 68] revealed that PoSt and SnapDeals operate on a completely different proving backend, with different memory profiles, different GPU kernel implementations, and different optimization opportunities.
Another subtle mistake was the assumption that the feature name cuda-supraseal would be consistently defined across all sub-crates. The Rust/Cargo ecosystem allows each crate to define its own feature set independently. The fact that storage-proofs-update doesn't define cuda-supraseal doesn't prevent it from being compiled with Supraseal — it simply means the crate's own code doesn't conditionally use Supraseal. But since bellperson is where the dispatch happens, and bellperson's cuda-supraseal feature is enabled by filecoin-proofs's cuda-supraseal feature, the dispatch could still happen at the bellperson level. The key insight is that storage-proofs-update doesn't propagate cuda-supraseal to bellperson — it only propagates cuda. So bellperson receives cuda from the Update path, not cuda-supraseal.
Broader Implications
This finding has significant implications for the optimization proposals being developed in the broader investigation. The "Persistent Prover Daemon" and "Sequential Partition Synthesis" proposals were designed around Supraseal's memory characteristics. If PoSt and SnapDeals don't use Supraseal, those proposals would need to be adapted for the native prover's architecture, or the optimization scope would need to be explicitly limited to PoRep.
Furthermore, the finding explains why the investigation's memory accounting showed ~200 GiB for PoRep but didn't find equivalent peaks for PoSt. The native prover, while still GPU-accelerated, has a different memory management model — it uses LockedMultiexpKernel and LockedFftKernel with priority-based GPU access, rather than Supraseal's approach of loading the entire SRS (Structured Reference String) into GPU memory upfront.
Conclusion
Message 69 is a textbook example of how a simple grep command, in the right context, can produce an architectural insight that reshapes an entire investigation. By confirming that storage-proofs-update lacks a cuda-supraseal feature, the assistant established that SnapDeals proofs never use the Supraseal C++ backend — they always fall through to the native Rust prover with GPU acceleration. This finding corrected a significant assumption, focused the optimization effort on PoRep, and provided a clear map of which proving backend serves which proof type. In a codebase spanning Go, Rust, C++, and CUDA, with a dependency chain six layers deep, such architectural clarity is invaluable.