The Final Verification: Testing WinningPoSt Bypass in the cuzk Cross-Sector Batching Pipeline

Introduction

In the course of a multi-month engineering effort to optimize Filecoin Groth16 proof generation, a single message at index 744 in the opencode conversation captures a critical moment of validation: the final test of Phase 3's cross-sector batching architecture. This message, sent by the AI assistant during an interactive coding session, executes a WinningPoSt (Winning Proof-of-Spacetime) proof against a daemon configured with max_batch_size=2 to verify that non-batchable proof types correctly bypass the newly implemented BatchCollector. While it appears to be a simple one-line bash command, this message represents the culmination of weeks of design, implementation, and iterative testing of a complex distributed proving pipeline for Filecoin storage mining.

Context: Where We Are in the Project

To understand the significance of message 744, we must first understand the broader project. The cuzk pipeline is a high-performance replacement for the Filecoin C2 proof generation stage, which produces Groth16 zero-knowledge proofs for storage proofs (PoRep), window Proofs-of-Spacetime (PoSt), and WinningPoSt. The original monolithic implementation had severe limitations: it consumed approximately 200 GiB of peak memory for a single 32 GiB sector proof, loaded the 44 GiB SRS (Structured Reference String) parameters from disk for every proof, and serialized the entire synthesis-to-GPU pipeline, leaving CPU cores idle while the GPU worked.

The project progressed through multiple phases. Phase 1 established the foundational architecture and test data generation. Phase 2 introduced pipelining — separating the CPU-bound circuit synthesis from the GPU-bound proving phase and allowing them to overlap in time via a bounded channel. Phase 3, which is the immediate context for this message, implemented cross-sector batching: instead of proving one sector at a time, the BatchCollector accumulates multiple sector proofs of the same type (e.g., two PoRep proofs) and synthesizes their circuits together in a single batch, amortizing the fixed synthesis cost across multiple sectors.

By message 744, the assistant had already executed and validated three tests against the batch-enabled daemon running on an RTX 5070 Ti with real 32 GiB PoRep data:

  1. Timeout flush test (message 735–736): A single proof submitted with batch_size=2 correctly waited ~30,258ms (the configured max_batch_wait_ms) before flushing as a batch of one.
  2. Batch=2 test (message 738–740): Two concurrent proofs were batched together, synthesizing 20 circuits (2 sectors × 10 partitions each) in 55.3 seconds — virtually identical to the 55.6 seconds for a single sector's 10 circuits, proving full synthesis amortization. The GPU time scaled linearly to 69.4 seconds (2× the single-sector 34.4s), yielding a 1.42× throughput improvement at 62.7 seconds per proof versus the 89-second baseline.
  3. 3-proof overflow test (message 741–743): Three concurrent proofs demonstrated correct batch-of-2 + overflow behavior, with the third proof's synthesis overlapping with the batch's GPU phase — the pipeline and batching working together. All three tests passed. The daemon logs confirmed every architectural stage: synth_batch_full, synthesize_porep_c2_multi{num_sectors=2}, total_circuits=20, and split_batched_proofs producing correct per-sector 1920-byte Groth16 proofs.

The Subject Message: Reasoning and Motivation

Message 744 begins with a clear statement of intent: "First I need to check if WinningPoSt SRS is loaded. The daemon was configured with preload = ["porep-32g"] only. Let me check what happens when we submit a WinningPoSt — it should lazy-load the WinningPoSt params."

This reasoning reveals several layers of concern. The daemon configuration file (/tmp/cuzk-batch-test.toml) explicitly preloads only the porep-32g SRS parameters. WinningPoSt uses a different circuit and therefore different SRS parameters. The assistant is testing two things simultaneously:

  1. Does the BatchCollector correctly bypass non-batchable proof types? WinningPoSt is fundamentally different from PoRep — it is a single-circuit proof (not 10 partitions), takes milliseconds rather than minutes, and produces a 192-byte proof rather than 1920 bytes. Batching it alongside PoRep proofs would make no sense. The architecture must recognize this and skip the collector entirely.
  2. Does lazy SRS loading work correctly? Since only porep-32g was preloaded, submitting a WinningPoSt proof will trigger an on-demand load of the WinningPoSt SRS parameters. This must work without deadlocking or corrupting the daemon state. The motivation is thoroughness. The assistant has already validated the core batching path (PoRep batched, PoRep timeout flush, PoRep overflow). But a production system must handle all proof types correctly. WinningPoSt is the most time-sensitive proof type in Filecoin — it must be generated within a 30-second window to avoid losing block rewards. Any delay introduced by the batching infrastructure (even a few hundred milliseconds of queue time) would be catastrophic. The assistant needs to verify that the bypass path is not just present but performant.

The Execution: What the Command Actually Does

The bash command executed in this message is:

echo "=== WinningPoSt test (non-batchable, should bypass BatchCollector) ===" && echo "Start: $(date +%T)" && /home/theuser/curio/extern/cuzk/target/release/cuzk-bench --addr http://127.0.0.1:9821 single -t winning --vanilla /tmp/winning-vanilla.json --registered-proof 3 --miner-id 1000 --randomness 0101010101010101010101010101010101010101010101010101010101010101 2>&1 && echo "End: $(date +%T)"

This invokes the cuzk-bench CLI tool with the single subcommand, targeting the daemon at http://127.0.0.1:9821. The proof type is winning, and the vanilla proof data comes from a pre-generated file at /tmp/winning-vanilla.json. The --registered-proof 3 flag specifies the numeric registered proof type enum value (matching the Go ABI), and --miner-id 1000 along with --randomness provide the required context for the WinningPoSt circuit.

The assistant's expectation is stated explicitly: "should bypass BatchCollector". This is not a guess — it reflects a design decision baked into the Phase 3 architecture. The BatchCollector, implemented in the engine module, classifies proof types as batchable (PoRep, WindowPoSt) or non-batchable (WinningPoSt). Non-batchable proofs are routed directly to the synthesis pipeline without entering the collector's waiting queue. The assistant is testing whether this classification works correctly in the integrated system.

Assumptions and Design Decisions

The message operates on several assumptions that deserve examination:

Assumption 1: The SRS lazy-loading path is functional. The daemon was started with preload = ["porep-32g"], meaning only the 44 GiB PoRep SRS parameters were loaded at startup. The WinningPoSt SRS is a different file of approximately 1.5 GiB. The assistant assumes that submitting a WinningPoSt proof will trigger the SRS manager to load the correct parameters on demand, and that this will complete within a reasonable time (the WinningPoSt proof must complete in under a second to be useful).

Assumption 2: The bypass classification is correct. The assistant assumes that the is_batchable() check in the engine code correctly returns false for WinningPoSt. This is a design-time decision that could have been wrong — if the classification logic had a bug (e.g., checking the wrong field, or using a default-true flag), WinningPoSt proofs could be incorrectly held in the BatchCollector, waiting for a batch partner that would never arrive until the 30-second timeout. For a proof type that must complete in under a second, a 30-second delay would be a critical failure.

Assumption 3: The daemon can handle mixed proof types without state corruption. After three PoRep tests (timeout flush, batch=2, 3-proof overflow), the daemon's internal state — the SRS manager, the GPU worker, the pipeline channels — must be clean. The assistant assumes no resource leaks or stale state from the previous tests.

What Actually Happened

The output shown in the message is truncated (ending with ==...), but the subsequent message (index 745) reveals the result:

Input Knowledge Required

To fully understand this message, one needs knowledge of:

  1. Filecoin proof types: PoRep (Proof-of-Replication) proves a sector is being stored, using 10 parallel circuits per sector. WindowPoSt proves sectors are still present in each 24-hour proving window. WinningPoSt proves a miner won a block election and must be generated within 30 seconds. Each uses different circuits and SRS parameters.
  2. Groth16 proving pipeline: The C2 stage of Filecoin proof generation takes the output of the C1 stage (a circuit-satisfying assignment) and produces a Groth16 zk-SNARK proof. This involves two phases: synthesis (building the R1CS constraint system and witness) and GPU proving (multi-scalar multiplication and number-theoretic transform on the GPU).
  3. The cuzk architecture: The pipeline consists of a daemon process, an SRS manager that loads and caches the ~44 GiB structured reference string, a BatchCollector that accumulates proofs for batched synthesis, a synthesis worker pool (CPU-bound), and a GPU worker (single GPU, processes circuits sequentially).
  4. The testing methodology: The cuzk-bench tool submits proofs to the daemon via HTTP and reports timing breakdowns (queue, SRS load, synthesis, GPU). The batch subcommand submits multiple concurrent proofs and measures throughput.

Output Knowledge Created

This message produced several valuable outputs:

  1. Empirical validation of the bypass path: The WinningPoSt proof completed in 807ms with only 88ms of queue overhead (attributable to HTTP request handling and SRS lazy-load, not batch waiting). This confirms the bypass is working correctly.
  2. Validation of lazy SRS loading: The WinningPoSt SRS was loaded on demand without explicit preloading, completing within the 807ms total. This confirms the SRS manager's lazy-load path is functional and performant.
  3. Confirmation of architectural correctness: All four Phase 3 tests (timeout flush, batch=2, 3-proof overflow, WinningPoSt bypass) passed. The BatchCollector correctly handles all scenarios: empty queue with timeout, full queue with immediate flush, overflow with pipeline overlap, and non-batchable bypass.
  4. Documentation of the Phase 3 completion: The assistant subsequently compiled these results into cuzk-project.md and committed as 353e4c2a, marking Phase 3 as fully validated.

The Thinking Process

The assistant's reasoning in this message reveals a methodical approach to validation. Rather than running a single end-to-end test, the assistant decomposed the verification into four orthogonal scenarios, each testing a different aspect of the BatchCollector's behavior:

Conclusion

Message 744, while appearing to be a simple test command, represents the final validation of a complex distributed proving architecture. The WinningPoSt bypass test confirmed that the BatchCollector correctly classifies proof types, that lazy SRS loading works transparently, and that time-sensitive proofs are not delayed by the batching machinery. With all four Phase 3 tests passing, the cross-sector batching feature was fully validated, achieving a 1.42× throughput improvement for PoRep proofs while maintaining sub-second latency for WinningPoSt. The stage was set for Phase 4, which would tackle compute-level micro-optimizations to further improve performance.