refactor: decompose composition poly via squared-coset intermediate#515
refactor: decompose composition poly via squared-coset intermediate#515diegokingston wants to merge 7 commits into
Conversation
Factor decompose_and_extend_d2 into decompose_d2 (O(N) pointwise decomposition on squared coset) + iFFT(N,g²) + FFT(2N,g) extension. Mathematically identical to the old path. This factoring exposes the N-point squared-coset representation as an intermediate step, which is the foundation for future eval-form quotient commitment (committing at N points instead of 2N, saving half the composition Merkle tree) once shared/multi-input FRI is available. Changes: - prover: decompose_d2 extracts H₀,H₁ at N squared-coset points - prover: inline extension from squared coset to 2N LDE domain - prover: rename lde_composition_poly_evaluations → composition_poly_evaluations - verifier: factor reconstruct_deep into trace + full variants - fri: add commit_phase_from_evaluations_with_injection (unused, infrastructure for future shared FRI injection) - test: update decomposition test to verify N-point output
|
/bench 3 |
Codex Code Review
No additional concrete security vulnerabilities (unsafe/memory/crypto/VM privilege issues) were evident in this diff. I couldn’t run tests in this environment because |
Benchmark — fib_iterative_8M (median of 3)Table parallelism: 32 (auto = cores / 3)
Commit: 5e9f05b · Baseline: cached · Runner: self-hosted bench |
|
Three pieces of infrastructure added in this PR are dead code with no call sites: |
| .unwrap(); | ||
|
|
||
| let lde_composition_poly_parts_evaluation: Vec<_> = lde_composition_poly_evaluations | ||
| let num_evals = composition_poly_evaluations[0].len(); |
There was a problem hiding this comment.
[Medium — Bug] composition_poly_evaluations[0] panics if the slice is empty. The previous code used flat_map and handled the empty case gracefully. In practice the prover always produces at least one part, but this is an unguarded index. Either add an assertion earlier (assert!(!composition_poly_evaluations.is_empty(), "...")) or write this as composition_poly_evaluations.first().map_or(0, |p| p.len()).
| // After the first fold, inject composition DEEP values if provided. | ||
| if first_fold { | ||
| if let Some(ref inj) = injection { | ||
| debug_assert_eq!( |
There was a problem hiding this comment.
[Low — Security] debug_assert_eq! is compiled out in release builds. If inj.len() != evals.len(), the subsequent zip silently truncates to the shorter length, producing a cryptographically incorrect FRI commitment with no error or diagnostic. This is especially dangerous for crypto code. Please use a hard assert_eq! (or return Err) so the invariant is enforced in all build profiles.
| // Decompose H(x) = H₀(x²) + x·H₁(x²) via O(N) pointwise ops, | ||
| // then extend each part from the N-point squared coset (g²) to the | ||
| // 2N-point LDE domain (g) via iFFT(N) + FFT(2N) per part. | ||
| { |
There was a problem hiding this comment.
[Nit] The inner { ... } block wrapping this branch is unnecessary — there are no temporaries that need early drop or shadowing concerns. Removing it makes the if/else if/else chain visually consistent with the other branches.
| let evaluation_point_sym = | ||
| Self::query_challenge_to_evaluation_point_sym(*iota, domain); | ||
|
|
||
| { |
There was a problem hiding this comment.
[Nit] The braces { ... } wrapping these two push calls have no scoping purpose — there are no temporaries to contain here. Removing them makes the for loop body cleaner.
8-task plan for replacing per-table independent Merkle trees with shared batched trees + shared FRI + eval-form quotient commitment. Expected: ~3x fewer Merkle trees, ~12x fewer FRI instances, 0 composition extension FFTs, ~70% proof size reduction.
Add `commit_main_traces_batched` to `IsStarkProver` that concatenates columns from multiple tables into a single shared Merkle tree, returning the tree, root, and a `BatchedLayout` tracking per-table column ranges.
Add batched proving and verification with shared Merkle trees and FRI: - multi_prove_batched: commits all tables' main, aux, and composition poly evaluations in shared trees, alpha-batches per-table DEEP polys, and runs one shared FRI instance - multi_verify_batched: replays the transcript identically, verifies OOD consistency per table, reconstructs alpha-batched DEEP at query points, and verifies shared FRI + tree openings - TableProofData: add num_composition_parts field and constructor - compute_deep_with_composition_from_evals: variant that takes composition evaluations directly (no Round2 struct needed) - Tests: roundtrip test with CPU/ADD/MUL bus tables (uniform sizing) and all-padding test; both prove and verify successfully
|
/bench 3 |
Factor decompose_and_extend_d2 into decompose_d2 (O(N) pointwise decomposition on squared coset) + iFFT(N,g²) + FFT(2N,g) extension. Mathematically identical to the old path.
This factoring exposes the N-point squared-coset representation as an intermediate step, which is the foundation for future eval-form quotient commitment (committing at N points instead of 2N, saving half the composition Merkle tree) once shared/multi-input FRI is available.
Changes: