Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize: Remove final batching sumcheck #5

Open
sragss opened this issue Jan 17, 2024 · 2 comments
Open

Optimize: Remove final batching sumcheck #5

sragss opened this issue Jan 17, 2024 · 2 comments

Comments

@sragss
Copy link
Collaborator

sragss commented Jan 17, 2024

The final batching sumcheck of Snark::prove is unneeded for us as we only need to support R1CS rather than Relaxed R1CS. This final sumcheck accounts for ~25% of Spartan e2e prover time.

We can cut all of the following:

// We will now reduce a vector of claims of evaluations at different points into claims about them at the same point.
// For example, eval_W =? W(r_y[1..]) and eval_E =? E(r_x) into
// two claims: eval_W_prime =? W(rz) and eval_E_prime =? E(rz)
// We can them combine the two into one: eval_W_prime + gamma * eval_E_prime =? (W + gamma*E)(rz),
// where gamma is a public challenge
// Since commitments to W and E are homomorphic, the verifier can compute a commitment
// to the batched polynomial.
assert!(w_u_vec.len() >= 2);
let (w_vec, u_vec): (Vec<PolyEvalWitness<G>>, Vec<PolyEvalInstance<G>>) =
w_u_vec.into_iter().unzip();
let w_vec_padded = PolyEvalWitness::pad(&w_vec); // pad the polynomials to be of the same size
let u_vec_padded = PolyEvalInstance::pad(&u_vec); // pad the evaluation points
// generate a challenge
let rho = transcript.squeeze(b"r")?;
let num_claims = w_vec_padded.len();
let powers_of_rho = powers::<G>(&rho, num_claims);
let claim_batch_joint = u_vec_padded
.iter()
.zip(powers_of_rho.iter())
.map(|(u, p)| u.e * p)
.sum();
let mut polys_left: Vec<MultilinearPolynomial<G::Scalar>> = w_vec_padded
.iter()
.map(|w| MultilinearPolynomial::new(w.p.clone()))
.collect();
let mut polys_right: Vec<MultilinearPolynomial<G::Scalar>> = u_vec_padded
.iter()
.map(|u| MultilinearPolynomial::new(EqPolynomial::new(u.x.clone()).evals()))
.collect();
let num_rounds_z = u_vec_padded[0].x.len();
let comb_func = |poly_A_comp: &G::Scalar, poly_B_comp: &G::Scalar| -> G::Scalar {
*poly_A_comp * *poly_B_comp
};
let (sc_proof_batch, r_z, claims_batch) = SumcheckProof::prove_quad_batch(
&claim_batch_joint,
num_rounds_z,
&mut polys_left,
&mut polys_right,
&powers_of_rho,
comb_func,
&mut transcript,
)?;
let (claims_batch_left, _): (Vec<G::Scalar>, Vec<G::Scalar>) = claims_batch;
transcript.absorb(b"l", &claims_batch_left.as_slice());
// we now combine evaluation claims at the same point rz into one
let gamma = transcript.squeeze(b"g")?;
let powers_of_gamma: Vec<G::Scalar> = powers::<G>(&gamma, num_claims);
let comm_joint = u_vec_padded
.iter()
.zip(powers_of_gamma.iter())
.map(|(u, g_i)| u.c * *g_i)
.fold(Commitment::<G>::default(), |acc, item| acc + item);
let poly_joint = PolyEvalWitness::weighted_sum(&w_vec_padded, &powers_of_gamma);
let eval_joint = claims_batch_left
.iter()
.zip(powers_of_gamma.iter())
.map(|(e, g_i)| *e * *g_i)
.sum();

  1. Cut above
  2. Modify the final let eval_arg = EE::prove(...) to use eval_W instead.
  3. Verifier checks eval_E is zero
@sragss
Copy link
Collaborator Author

sragss commented Jan 20, 2024

Looks like we can remove w_u_vec and associated expensive cloning as well.

@sragss
Copy link
Collaborator Author

sragss commented Jan 22, 2024

Arasu is handling here: #17

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant