optimizations for prover & verifier#1
Conversation
markosg04
left a comment
There was a problem hiding this comment.
Thanks a lot! Just bunch of nits
| left_vec, // s2 = left_vec | ||
| row_commitments, // v1 = T_vec_prime (row commitments) | ||
| v2, // v2 = v_vec · g_fin | ||
| Some(v_vec.clone()), // v2_scalars available for first-round optimization |
There was a problem hiding this comment.
can we avoid this clone? seems that prover_state is the last thing to consume v_vec
| // The verifier uses O(nu) accumulators derived from per-dimension coordinates. | ||
| // We take the first `nu` coordinates for s1, and the last `nu` coordinates for s2. | ||
| // If there are fewer than `nu` remaining for s2 (when sigma < nu), pad with ones (neutral). | ||
| let s1_coords: Vec<F> = point[..nu].to_vec(); | ||
| let mut s2_coords: Vec<F> = point[nu..(nu + nu).min(point.len())].to_vec(); | ||
| if s2_coords.len() < nu { | ||
| s2_coords.resize_with(nu, F::one); | ||
| } |
There was a problem hiding this comment.
could we use sigma for the remainder? we are requiring square dimensions anyways. It might make the comments here clearer as well
| /// # Parameters | ||
| /// - `v1`: Initial G1 vector | ||
| /// - `v2`: Initial G2 vector | ||
| /// - `v2_scalars`: If v2 = h2 * scalars (first round), pass scalars for MSM+pair optimization |
There was a problem hiding this comment.
| /// - `v2_scalars`: If v2 = h2 * scalars (first round), pass scalars for MSM+pair optimization | |
| /// - `v2_scalars`: Use the scalars in the first round to avoid a multi-pairing by instead performing a (cheaper) MSM + Pairing |
| if let Some(ref sc) = v2_scalars { | ||
| debug_assert_eq!(sc.len(), v2.len(), "v2_scalars must match v2 length"); | ||
| } |
There was a problem hiding this comment.
| if let Some(ref sc) = v2_scalars { | |
| debug_assert_eq!(sc.len(), v2.len(), "v2_scalars must match v2 length"); | |
| } | |
| if let Some(sc) = v2_scalars.as_ref() { | |
| debug_assert_eq!(sc.len(), v2.len(), "v2_scalars must match v2 length"); | |
| } |
ref is older rust and as_ref() is clearer anyways
| // D₂L = ⟨Γ₁', v₂L⟩, D₂R = ⟨Γ₁', v₂R⟩ | ||
| let d2_left = E::multi_pair(g1_prime, v2_l); | ||
| let d2_right = E::multi_pair(g1_prime, v2_r); | ||
| // If v2 was constructed as h2 * scalars (first round), compute MSM(Γ₁', scalars) then one pairing. |
There was a problem hiding this comment.
| // If v2 was constructed as h2 * scalars (first round), compute MSM(Γ₁', scalars) then one pairing. | |
| // In the first round, v2 = h2 * scalars, so we can compute this as the Pairing of MSM(Γ₁', scalars) |
| let d2_left = E::multi_pair(g1_prime, v2_l); | ||
| let d2_right = E::multi_pair(g1_prime, v2_r); | ||
| // If v2 was constructed as h2 * scalars (first round), compute MSM(Γ₁', scalars) then one pairing. | ||
| let (d2_left, d2_right) = if let Some(ref scalars) = self.v2_scalars { |
There was a problem hiding this comment.
let's use as_ref() here as well
| self.v2[i] = self.v2[i] + self.setup.g2_vec[i].scale(&beta_inv); | ||
| } | ||
|
|
||
| // After first combine, v2 is no longer fixed-base; drop scalars to avoid misuse |
There was a problem hiding this comment.
| // After first combine, v2 is no longer fixed-base; drop scalars to avoid misuse | |
| // After first combine, the `v2_scalars` optimization does not apply. |
| // Use accumulated folded scalars | ||
| let s1_final = self.s1_acc; | ||
| let s2_final = self.s2_acc; |
There was a problem hiding this comment.
would it be possible to avoid having both s1/2_final and s1/2_acc ?
| } | ||
| self.s2_tensor.truncate(n2); | ||
| // Update folded scalars in O(1): s1_final *= (α·(1−y_t) + y_t), s2_final *= (α⁻¹·(1−x_t) + x_t) | ||
| // Determine current round index implicitly from remaining rounds (last dimension folds first). |
There was a problem hiding this comment.
question: (last dimension folds first) -> this is because of endian-ness?
PR title
Reduce verifier to O(nu) time and optimize first-round D2 pairings
Summary
Details
DoryVerifierStatenow holdss1_acc,s2_accands1_coords,s2_coords. No tensor folding.verify_evaluation_proofpasses per-dimension coords; if sigma < nu, pad s2 coords with 1.process_roundderives index fromnuand updates accumulators per round.v2_scalarsonly for round 1;compute_first_messageuses MSM+pairing for D2L/D2R when available;apply_first_challengedrops scalars.setup,prove,verifyunchanged.DoryVerifierState::newandDoryProverState::newsignatures changed; all internal call sites updated.cargo test --features backendsidx = nu - 1to match fold order.benches/to quantify improvements.Why this is correct