Feat/batched fri per epoch#768
Draft
diegokingston wants to merge 29 commits into
Draft
Conversation
Round 1 now commits all tables' main-split LDE matrices into ONE mixed-height MixedMmcs and absorbs a single root (before the shared LogUp challenges), replacing the per-table main-root absorption. Single-table roots are byte- identical to the old per-table row-pair tree, so single-table proofs are unchanged; only multi-table transcripts change, so multi-table prove->verify tests are #[ignore]'d until the verifier is updated (Scope B Task 7). The MMCS is built transiently for the root (Task 5 will thread it into round 4 and drop the per-table trees).
Absorb ONE mixed-height MMCS root over every aux-carrying table's LDE into the shared transcript (after Phase B LogUp challenges, before forking), replacing the per-fork per-table aux root absorptions. Mirrors the main-trace batched commit. Transient MMCS (root only); Round 4 still opens per-table aux trees. Single-table roundtrips byte-identical (131 passed / 17 ignored).
Drop the per-table transcript forks. multi_prove now runs one linear transcript: bus contributions bind, then per-table beta (sequential), then round 2 composition built in parallel and committed as ONE mixed-height MMCS root, then round 3 (z, OOD) and round 4 (FRI) per table sequentially with PER-TABLE z. prove_rounds_2_to_4 is inlined and removed. Round 4 is still per-table (per-table FRI + per-table StarkProof/MultiProof) — the single batched FRI and shard proof format are the next step. Multi-table verify stays gated to the verifier task; single-table roundtrips remain byte-identical (131 passed / 17 ignored, clippy clean) because for one table the linear transcript equals the old fork and the single-matrix composition MMCS root equals the per-table composition root.
Sample a single z for the whole epoch instead of one per table, against the tallest table's domain. Since every shorter table's LDE and trace domain is a subgroup of the tallest's, z out-of-domain for the tallest is out-of-domain for all. Cleaner and simpler to mirror in the verifier; byte-identical for a single table (131 passed / 17 ignored, clippy clean).
Add the unified-shard proof types: BatchedMultiProof (shared main/aux/composition MMCS roots + one batched FRI + per-query MixedOpenings + per-table OOD data), BatchedQueryOpening (one shared auth path per phase per query), BatchedTableData. Make MixedOpening serde-serializable. Additive/pub — compiles clean, no behavior change yet; the prover (multi_prove_batched) and verifier wire these next.
Compute every table's round-3 OOD and absorb it before starting round 4, instead of interleaving round 3/4 per table. Creates the shared 'after rounds 1-3' boundary the batched path will reuse, and is required for the batched round 4 (one FRI over all tables needs all OOD bound first). Reference MultiProof path unchanged in behavior; single-table byte-identical (131/0/17).
Extract rounds 1-3 into prove_rounds_1_to_3 (returns round1s/round2s/round3s, shared z, and the three KEPT MMCS trees + per-table lde heights). multi_prove (reference MultiProof path) reuses it unchanged. New multi_prove_batched runs the batched round 4: gamma (one shared DEEP challenge) -> per-table DEEP codewords (bit-reversed) -> absorb height histogram -> alpha -> combine_by_height -> batched_commit_phase (fold-and-inject FRI) -> grinding -> query indices vs the tallest domain -> per-query open_batch on main/aux/composition MMCS (one shared path each) + per-preprocessed-table precomputed openings -> BatchedMultiProof. Reuses Scope-A fri::batched primitives. Reference path byte-identical (131/0/17, clippy clean). No verifier yet, so no batched roundtrip. Also: module-level allow(private_interfaces) — surfacing the rounds-1-3 bundle through a pub trait method trips the lint across the whole internal trait; the round types are never nameable across the crate boundary.
Mirror multi_prove_batched: one linear transcript, one shared OOD point z, and one fold-and-inject FRI over the height-combined per-table DEEP codewords, with all tables opened per query from the three shared mixed-height MMCS trees. - batched_multi_verify + batched_synthetic_table_proof (reuses step_2 and reconstruct_deep_composition_poly_evaluation per table via a lightweight synthetic StarkProof carrying only the OOD/public fields those read). - Transcript replay: precomputed roots -> batched main root -> LogUp challenges -> batched aux root -> bus contribs -> per-table betas -> batched composition root -> shared z (tallest domain) -> per-table OOD -> gamma -> derive_batched_fri_challenges (histogram, alpha, betas, iotas). - MMCS verify_batch per phase with AIR-intrinsic width binding: main-split width = trace_columns - num_aux - num_precomputed (trace_layout().0 is a logical figure for step-packed AIRs, not the physical column count). - Fold-and-inject query check inverts batched_commit_phase exactly: initial fold of the tallest (uncommitted) layer, then per layer inject the tables entering at that height (beta^2 * combined[h]) before verifying/folding. Converts all 17 Task-7-gated multi-table tests to the batched path (multi_prove_batched_ram + batched_multi_verify); 148 pass, 0 ignored.
11 tamper tests + 1 valid-anchor over a bus-balanced 3-table padding epoch, exercising every batched_multi_verify path: main/aux/composition MMCS auth, MMCS width binding, fold-and-inject terminal + layer-root + layer-sym checks, composition-OOD (step 2), query-count guard, grinding nonce, bus balance. 160 stark lib tests pass; new file clippy-clean.
…c path Point the public prove/verify at the batched STARK path so the existing server benchmarks measure it (prove/verify time + proof size), and to restore multi-table correctness — the linear-transcript refactor left the reference multi_prove -> multi_verify broken for multi-table (verifier still forked). - VmProof.proof: MultiProof -> BatchedMultiProof (serde-compatible; external consumers deserialize opaquely). - prove(): Prover::multi_prove -> multi_prove_batched. - verify_with_options(): batched_multi_verify + per_table.len() + batched COMMIT-bus-balance replay (replay_transcript_phase_a_batched: precomputed roots + single main_root + shared LogUp z/alpha). - test_utils: multi_prove_batched_ram. Minimal prove/verify test helpers + lt_bus completeness helper switched to batched (validated: the 4 lt_bus completeness tests, which FAIL on the reference path, PASS on batched). Scope: exploratory prototype for measurement. Continuation (continuation.rs) stays on the reference path — its cross-epoch L2G binding reads PER-TABLE main roots that the unified shard replaces with one MMCS root (a real design question, deferred). Reference multi_prove/multi_verify kept alive for it.
Switch two positive multi-table roundtrips to the batched path as end-to-end validation of the default MMCS prover/verifier: - lt_bus completeness (LT sender/receiver): 4 tests that FAIL on the reference path now pass on batched. - bitwise honest (true preprocessed table via with_preprocessed + hardcoded commitment): exercises precomputed-root check + precomputed openings + DEEP base = precomputed ++ main-split — the preprocessed path the real VM uses. Together with the stark-crate roundtrip/soundness/mixed-height/different-blowup coverage, every constituent path of the monolithic batched prove/verify is validated locally (full 14-table ELF run needs the server toolchain).
Collaborator
Author
|
/bench |
Resolves conflicts from #748 (feat(cuda): keep LDE and Merkle trees resident on the GPU) and #726 (profiling markers), which both landed on main after this branch forked. Conflicts: - crypto/stark/src/prover.rs: both sides heavily rewrote `multi_prove`. #748 restructured rounds 1-4 into a peak-VRAM-bounded chunked loop (`peak_chunks` + per-table `prove_rounds_2_to_4`) with resident-GPU paths; this branch replaced the same region with the batched unified-shard path (linear transcript, batched composition MMCS, single FRI). A line merge Frankensteined the two, so `prover.rs` is taken from this branch wholesale: the batched rewrite subsumes the chunked per-table structure, and GPU residency for the batched path is deferred to T9 (GPU batched MMCS + FRI). This drops #748's in- `multi_prove` GPU-residency ONLY; its cuda-gated changes to other files (gpu_lde, math-cuda, trace) remain from the auto-merge. - prover/src/lib.rs: kept this branch's `multi_prove_batched` / `batched_multi_verify` calls and folded in main's orthogonal `instruments::span("proving")` and `profile_markers::step_marker`. Verified (non-cuda): `cargo check` clean on stark + lambda-vm-prover; 17 batched stark tests, serialized multi-table roundtrip, 18 lt_bus real-VM-table tests, and the honest-bitwise preprocessed path all pass. NOTE: cuda-build integration between the batched path and #748's resident-GPU API is deferred (T9); non-cuda is the benchmarked config.
Collaborator
Author
|
/bench |
Resolve conflicts from main's #764 (single-source constraints) refactor: - verifier.rs: keep the batched imports (BatchedMultiProof, BatchedTableData); drop PackingShifts. #764 changed TransitionEvaluationContext::new_verifier from 6 args to 4 (removed periodic_values + packing_shifts, now handled internally). The batched verify path reuses the same shared per-table transition helper, so this applies to both verify paths. - air_tests.rs: accept main's deletion of test_multi_prove_different_airs. The test predates this PR (the PR only ported it to the batched API); #764 removed it together with its bit_flags example dependency. No bit_flags references remain. - prover.rs: drop the now-dead IntoParallelRefIterator import (this PR had already removed its last .par_iter() call but left the import). Validated: cargo check clean (no warnings); stark lib suite 192/192 pass, including the batched soundness suite and logup_all_packing_variants.
Merging main surfaced breaks in code my default-feature validation never compiled: - disk-spill: `prove_rounds_1_to_3` takes `air_trace_pairs: &mut Vec<_>`, but two disk-spill call sites reborrowed it as `&mut air_trace_pairs` (a `&mut &mut Vec`, needing a `mut` binding). `par_try_for_each_mut` takes `&mut [T]`, so pass `air_trace_pairs` directly (implicit reborrow). - cuda: main changed `try_build_comp_poly_tree_gpu` to return `(host_tree, dev_tree)` and `try_inv_denoms_dev_with_stream` to take a 4th `bound_stream` arg; the auto-merge kept main's signatures but the PR's callers. Map the GPU tuple to just the host tree (this batched path doesn't use the device tree) and pass `lde_trace.bound_stream()` to match main. - Lint: `cargo fmt` (much of the branch was never formatted). Verified: cargo check clean on default, `disk-spill`, `cuda`, and `cuda,disk-spill`; workspace `cargo fmt --check` clean.
…tinuation)
Root cause: the merge combined the PR's shared-transcript multi_prove
(prover) with main's per-table-forking multi_verify (verifier). Main evolved
BOTH sides of the non-batched path to fork an independent transcript per table
(idx separator + aux root + table_contribution, per-table z); the PR kept the
older shared-transcript multi_prove and added the batched path as the new
default. The auto-merge took the PR's prover but main's verifier — no textual
conflict flagged it — so their Fiat-Shamir transcripts diverge and grinding
fails ("Grinding factor not satisfied" -> verify_rounds_2_to_4). Only
continuation uses the non-batched pair (monolithic uses batched; the stark
multi-table tests were migrated to batched; single-table soundness tests skip
the num_tables>1 fork), so only continuation broke.
Fix: restore main's per-table non-batched multi_prove so the prover matches
main's verifier that continuation was validated against. Ports main's
multi_prove + its prove_rounds_2_to_4 + free fns plan_table_chunks /
estimate_table_vram_bytes; all build on the SAME low-level primitives
(commit_main_trace, Round1/2/3, round_2/3/4_*) which are byte-identical
between main and the merged tree. The batched path (multi_prove_batched +
prove_rounds_1_to_3) is untouched. Restore the IntoParallelRefIterator import
(main's multi_prove uses par_iter) and drop the now-dead RoundsOneToThree
twiddle_caches field.
Validated: 26/26 continuation tests (incl. tamper-rejection soundness
negatives), 192/192 stark lib tests (batched path intact), clean build on
default/disk-spill/cuda, fmt clean.
…mination) Conflict: crypto/stark/src/fri/mod.rs — union the two new module decls (this PR's `pub mod mmcs;` + #729's `pub(crate) mod terminal;`). Semantic: #729 replaced StarkProof.fri_last_value with fri_final_poly_coeffs (early-termination). Auto-merge reconciled it everywhere except the batched verifier's synthetic placeholder proof (batched_synthetic_table_proof), where fri_last_value: zero() -> fri_final_poly_coeffs: Vec::new(). The two FRI representations now coexist cleanly: non-batched StarkProof uses #729's early-termination coeffs; BatchedMultiProof keeps its own unified fri_last_value. Because main's non-batched multi_prove was ported verbatim, #729's changes to it applied cleanly through this merge. Validated: stark lib 211/211, continuation 25/25 (25: #789 removed the flaky privacy byte-scan test), clean build on default/disk-spill/cuda, fmt clean.
Collaborator
Author
|
/bench |
CI Lint runs `cargo clippy --workspace --all-targets -- -D warnings`; a newer clippy (1.94) flags `.clone()` on Copy `FieldElement` at batched.rs:316 and mmcs.rs:398/688. Drop the redundant clones. Verified: workspace clippy clean (-D warnings), fmt clean.
Factor multi_prove_batched's Round 4 into a reusable batched_round_4() so the upcoming continuation epoch driver can share it for the VM-table lane. Also drop round2s (dead after the DEEP codeword loop) and deep_inputs (dead after combine_by_height) before the FRI-commit + query-opening phases to lower the batched peak. Behavior-preserving: 211 stark-lib tests pass.
…iver STEP A: commit_aux_trace (CPU mirror of commit_main_trace) for the standalone L2G aux lane. STEP B: multi_prove_batched_epoch weaves two lanes through one transcript: absorb L2G main root first, prove_rounds_1_to_3 over the VM tables, fork at the seam to prove the L2G lane via prove_rounds_2_to_4, then batched_round_4 for the VM tables. Returns (BatchedMultiProof, StarkProof).
STEP C: split batched_multi_verify into batched_verify_rounds_1_to_3 (-> VmMidState) + batched_verify_round_4, behavior-preserving (batched_multi_verify calls both in sequence). 211 stark-lib tests unchanged. STEP D: batched_verify_epoch mirrors multi_prove_batched_epoch's transcript order (L2G main root first, VM rounds 1-3, fork for L2G at the seam, then VM round 4).
…-root fix STEP E + wiring: EpochProof now carries vm_proof (BatchedMultiProof) + l2g_proof (StarkProof); prove_epoch/verify_epoch use multi_prove_batched_epoch / batched_verify_epoch with the batched COMMIT-bus balance. verify_round_4 folds L2G's table_contribution into the VM target. Fix: the expected COMMIT-bus balance now absorbs the standalone L2G main root FIRST (new Option<&Commitment> param on compute_expected_commit_bus_balance_batched / replay_transcript_phase_a_batched), mirroring multi_prove_batched_epoch's transcript order. Without it the sampled LogUp (z,alpha) diverged and epochs that commit non-empty output failed to verify (empty output masked it).
- Add AuxCommitTuple<E> alias for commit_aux_trace return (type_complexity) - Gate now-test-only replay_transcript_phase_a / compute_expected_commit_bus_balance under #[cfg(test)] (dead_code in lib target) - fmt reflow of batched_verify_epoch call site
Collaborator
Author
|
/bench |
prove_rounds_1_to_3's air_trace_pairs is &mut Vec, so &air_trace_pairs in the debug-checks-gated run_debug_checks call was a needless &&mut Vec. Pass it directly (coerces to &[AirTracePair]). Only the CI clippy pass with --features lambda-vm-prover/debug-checks compiles this line, so the default-feature lint was green. multi_prove's owned-Vec call site (3199) keeps its required &.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.