#![allow(clippy::too_many_arguments)] #![allow(clippy::type_complexity)] use crate::poseidon_transcript::{AppendToPoseidon, PoseidonTranscript}; use super::dense_mlpoly::DensePolynomial; use super::errors::ProofVerifyError; use super::scalar::Scalar; use super::transcript::ProofTranscript; use super::unipoly::UniPoly; use ark_ff::Zero; use ark_serialize::*; use itertools::izip; #[derive(CanonicalSerialize, CanonicalDeserialize, Debug)] pub struct SumcheckInstanceProof { pub polys: Vec, } impl SumcheckInstanceProof { pub fn new(polys: Vec) -> SumcheckInstanceProof { SumcheckInstanceProof { polys } } pub fn verify( &self, claim: Scalar, num_rounds: usize, degree_bound: usize, transcript: &mut PoseidonTranscript, ) -> Result<(Scalar, Vec), ProofVerifyError> { let mut e = claim; let mut r: Vec = Vec::new(); // verify that there is a univariate polynomial for each round assert_eq!(self.polys.len(), num_rounds); for i in 0..self.polys.len() { let poly = self.polys[i].clone(); // verify degree bound assert_eq!(poly.degree(), degree_bound); // check if G_k(0) + G_k(1) = e assert_eq!(poly.eval_at_zero() + poly.eval_at_one(), e); // append the prover's message to the transcript poly.append_to_poseidon(transcript); //derive the verifier's challenge for the next round let r_i = transcript.challenge_scalar(); r.push(r_i); // evaluate the claimed degree-ell polynomial at r_i e = poly.evaluate(&r_i); } Ok((e, r)) } } // #[derive(CanonicalSerialize, CanonicalDeserialize, Debug)] // pub struct ZKSumcheckInstanceProof { // comm_polys: Vec, // comm_evals: Vec, // proofs: Vec, // } // impl ZKSumcheckInstanceProof { // pub fn new( // comm_polys: Vec, // comm_evals: Vec, // proofs: Vec, // ) -> Self { // ZKSumcheckInstanceProof { // comm_polys, // comm_evals, // proofs, // } // } // pub fn verify( // &self, // comm_claim: &CompressedGroup, // num_rounds: usize, // degree_bound: usize, // gens_1: &MultiCommitGens, // gens_n: &MultiCommitGens, // transcript: &mut Transcript, // ) -> Result<(CompressedGroup, Vec), ProofVerifyError> { // // verify degree bound // assert_eq!(gens_n.n, degree_bound + 1); // // verify that there is a univariate polynomial for each round // assert_eq!(self.comm_polys.len(), num_rounds); // assert_eq!(self.comm_evals.len(), num_rounds); // let mut r: Vec = Vec::new(); // for i in 0..self.comm_polys.len() { // let comm_poly = &self.comm_polys[i]; // // append the prover's polynomial to the transcript // comm_poly.append_to_transcript(b"comm_poly", transcript); // //derive the verifier's challenge for the next round // let r_i = transcript.challenge_scalar(b"challenge_nextround"); // // verify the proof of sum-check and evals // let res = { // let comm_claim_per_round = if i == 0 { // comm_claim // } else { // &self.comm_evals[i - 1] // }; // let mut comm_eval = &self.comm_evals[i]; // // add two claims to transcript // comm_claim_per_round.append_to_transcript(transcript); // comm_eval.append_to_transcript(transcript); // // produce two weights // let w = transcript.challenge_vector(2); // // compute a weighted sum of the RHS // let comm_target = GroupElement::vartime_multiscalar_mul( // w.as_slice(), // iter::once(&comm_claim_per_round) // .chain(iter::once(&comm_eval)) // .map(|pt| GroupElement::decompress(pt).unwrap()) // .collect::>() // .as_slice(), // ) // .compress(); // let a = { // // the vector to use to decommit for sum-check test // let a_sc = { // let mut a = vec![Scalar::one(); degree_bound + 1]; // a[0] += Scalar::one(); // a // }; // // the vector to use to decommit for evaluation // let a_eval = { // let mut a = vec![Scalar::one(); degree_bound + 1]; // for j in 1..a.len() { // a[j] = a[j - 1] * r_i; // } // a // }; // // take weighted sum of the two vectors using w // assert_eq!(a_sc.len(), a_eval.len()); // (0..a_sc.len()) // .map(|i| w[0] * a_sc[i] + w[1] * a_eval[i]) // .collect::>() // }; // self.proofs[i] // .verify( // gens_1, // gens_n, // transcript, // &a, // &self.comm_polys[i], // &comm_target, // ) // .is_ok() // }; // if !res { // return Err(ProofVerifyError::InternalError); // } // r.push(r_i); // } // Ok((self.comm_evals[&self.comm_evals.len() - 1].clone(), r)) // } // } impl SumcheckInstanceProof { pub fn prove_cubic_with_additive_term( claim: &Scalar, num_rounds: usize, poly_tau: &mut DensePolynomial, poly_A: &mut DensePolynomial, poly_B: &mut DensePolynomial, poly_C: &mut DensePolynomial, comb_func: F, transcript: &mut PoseidonTranscript, ) -> (Self, Vec, Vec) where F: Fn(&Scalar, &Scalar, &Scalar, &Scalar) -> Scalar, { let mut e = *claim; let mut r: Vec = Vec::new(); let mut cubic_polys: Vec = Vec::new(); for _j in 0..num_rounds { let mut eval_point_0 = Scalar::zero(); let mut eval_point_2 = Scalar::zero(); let mut eval_point_3 = Scalar::zero(); let len = poly_tau.len() / 2; for i in 0..len { // eval 0: bound_func is A(low) eval_point_0 += comb_func(&poly_tau[i], &poly_A[i], &poly_B[i], &poly_C[i]); // eval 2: bound_func is -A(low) + 2*A(high) let poly_tau_bound_point = poly_tau[len + i] + poly_tau[len + i] - poly_tau[i]; let poly_A_bound_point = poly_A[len + i] + poly_A[len + i] - poly_A[i]; let poly_B_bound_point = poly_B[len + i] + poly_B[len + i] - poly_B[i]; let poly_C_bound_point = poly_C[len + i] + poly_C[len + i] - poly_C[i]; eval_point_2 += comb_func( &poly_tau_bound_point, &poly_A_bound_point, &poly_B_bound_point, &poly_C_bound_point, ); // eval 3: bound_func is -2A(low) + 3A(high); computed incrementally with bound_func applied to eval(2) let poly_tau_bound_point = poly_tau_bound_point + poly_tau[len + i] - poly_tau[i]; let poly_A_bound_point = poly_A_bound_point + poly_A[len + i] - poly_A[i]; let poly_B_bound_point = poly_B_bound_point + poly_B[len + i] - poly_B[i]; let poly_C_bound_point = poly_C_bound_point + poly_C[len + i] - poly_C[i]; eval_point_3 += comb_func( &poly_tau_bound_point, &poly_A_bound_point, &poly_B_bound_point, &poly_C_bound_point, ); } let evals = vec![eval_point_0, e - eval_point_0, eval_point_2, eval_point_3]; let poly = UniPoly::from_evals(&evals); // append the prover's message to the transcript poly.append_to_poseidon(transcript); //derive the verifier's challenge for the next round let r_j = transcript.challenge_scalar(); r.push(r_j); // bound all tables to the verifier's challenege poly_tau.bound_poly_var_top(&r_j); poly_A.bound_poly_var_top(&r_j); poly_B.bound_poly_var_top(&r_j); poly_C.bound_poly_var_top(&r_j); e = poly.evaluate(&r_j); cubic_polys.push(poly); } ( SumcheckInstanceProof::new(cubic_polys), r, vec![poly_tau[0], poly_A[0], poly_B[0], poly_C[0]], ) } pub fn prove_cubic( claim: &Scalar, num_rounds: usize, poly_A: &mut DensePolynomial, poly_B: &mut DensePolynomial, poly_C: &mut DensePolynomial, comb_func: F, transcript: &mut PoseidonTranscript, ) -> (Self, Vec, Vec) where F: Fn(&Scalar, &Scalar, &Scalar) -> Scalar, { let mut e = *claim; let mut r: Vec = Vec::new(); let mut cubic_polys: Vec = Vec::new(); for _j in 0..num_rounds { let mut eval_point_0 = Scalar::zero(); let mut eval_point_2 = Scalar::zero(); let mut eval_point_3 = Scalar::zero(); let len = poly_A.len() / 2; for i in 0..len { // eval 0: bound_func is A(low) eval_point_0 += comb_func(&poly_A[i], &poly_B[i], &poly_C[i]); // eval 2: bound_func is -A(low) + 2*A(high) let poly_A_bound_point = poly_A[len + i] + poly_A[len + i] - poly_A[i]; let poly_B_bound_point = poly_B[len + i] + poly_B[len + i] - poly_B[i]; let poly_C_bound_point = poly_C[len + i] + poly_C[len + i] - poly_C[i]; eval_point_2 += comb_func( &poly_A_bound_point, &poly_B_bound_point, &poly_C_bound_point, ); // eval 3: bound_func is -2A(low) + 3A(high); computed incrementally with bound_func applied to eval(2) let poly_A_bound_point = poly_A_bound_point + poly_A[len + i] - poly_A[i]; let poly_B_bound_point = poly_B_bound_point + poly_B[len + i] - poly_B[i]; let poly_C_bound_point = poly_C_bound_point + poly_C[len + i] - poly_C[i]; eval_point_3 += comb_func( &poly_A_bound_point, &poly_B_bound_point, &poly_C_bound_point, ); } let evals = vec![eval_point_0, e - eval_point_0, eval_point_2, eval_point_3]; let poly = UniPoly::from_evals(&evals); // append the prover's message to the transcript poly.append_to_poseidon(transcript); //derive the verifier's challenge for the next round let r_j = transcript.challenge_scalar(); r.push(r_j); // bound all tables to the verifier's challenege poly_A.bound_poly_var_top(&r_j); poly_B.bound_poly_var_top(&r_j); poly_C.bound_poly_var_top(&r_j); e = poly.evaluate(&r_j); cubic_polys.push(poly); } ( SumcheckInstanceProof::new(cubic_polys), r, vec![poly_A[0], poly_B[0], poly_C[0]], ) } pub fn prove_cubic_batched( claim: &Scalar, num_rounds: usize, poly_vec_par: ( &mut Vec<&mut DensePolynomial>, &mut Vec<&mut DensePolynomial>, &mut DensePolynomial, ), poly_vec_seq: ( &mut Vec<&mut DensePolynomial>, &mut Vec<&mut DensePolynomial>, &mut Vec<&mut DensePolynomial>, ), coeffs: &[Scalar], comb_func: F, transcript: &mut PoseidonTranscript, ) -> ( Self, Vec, (Vec, Vec, Scalar), (Vec, Vec, Vec), ) where F: Fn(&Scalar, &Scalar, &Scalar) -> Scalar, { let (poly_A_vec_par, poly_B_vec_par, poly_C_par) = poly_vec_par; let (poly_A_vec_seq, poly_B_vec_seq, poly_C_vec_seq) = poly_vec_seq; //let (poly_A_vec_seq, poly_B_vec_seq, poly_C_vec_seq) = poly_vec_seq; let mut e = *claim; let mut r: Vec = Vec::new(); let mut cubic_polys: Vec = Vec::new(); for _j in 0..num_rounds { let mut evals: Vec<(Scalar, Scalar, Scalar)> = Vec::new(); for (poly_A, poly_B) in poly_A_vec_par.iter().zip(poly_B_vec_par.iter()) { let mut eval_point_0 = Scalar::zero(); let mut eval_point_2 = Scalar::zero(); let mut eval_point_3 = Scalar::zero(); let len = poly_A.len() / 2; for i in 0..len { // eval 0: bound_func is A(low) eval_point_0 += comb_func(&poly_A[i], &poly_B[i], &poly_C_par[i]); // eval 2: bound_func is -A(low) + 2*A(high) let poly_A_bound_point = poly_A[len + i] + poly_A[len + i] - poly_A[i]; let poly_B_bound_point = poly_B[len + i] + poly_B[len + i] - poly_B[i]; let poly_C_bound_point = poly_C_par[len + i] + poly_C_par[len + i] - poly_C_par[i]; eval_point_2 += comb_func( &poly_A_bound_point, &poly_B_bound_point, &poly_C_bound_point, ); // eval 3: bound_func is -2A(low) + 3A(high); computed incrementally with bound_func applied to eval(2) let poly_A_bound_point = poly_A_bound_point + poly_A[len + i] - poly_A[i]; let poly_B_bound_point = poly_B_bound_point + poly_B[len + i] - poly_B[i]; let poly_C_bound_point = poly_C_bound_point + poly_C_par[len + i] - poly_C_par[i]; eval_point_3 += comb_func( &poly_A_bound_point, &poly_B_bound_point, &poly_C_bound_point, ); } evals.push((eval_point_0, eval_point_2, eval_point_3)); } for (poly_A, poly_B, poly_C) in izip!( poly_A_vec_seq.iter(), poly_B_vec_seq.iter(), poly_C_vec_seq.iter() ) { let mut eval_point_0 = Scalar::zero(); let mut eval_point_2 = Scalar::zero(); let mut eval_point_3 = Scalar::zero(); let len = poly_A.len() / 2; for i in 0..len { // eval 0: bound_func is A(low) eval_point_0 += comb_func(&poly_A[i], &poly_B[i], &poly_C[i]); // eval 2: bound_func is -A(low) + 2*A(high) let poly_A_bound_point = poly_A[len + i] + poly_A[len + i] - poly_A[i]; let poly_B_bound_point = poly_B[len + i] + poly_B[len + i] - poly_B[i]; let poly_C_bound_point = poly_C[len + i] + poly_C[len + i] - poly_C[i]; eval_point_2 += comb_func( &poly_A_bound_point, &poly_B_bound_point, &poly_C_bound_point, ); // eval 3: bound_func is -2A(low) + 3A(high); computed incrementally with bound_func applied to eval(2) let poly_A_bound_point = poly_A_bound_point + poly_A[len + i] - poly_A[i]; let poly_B_bound_point = poly_B_bound_point + poly_B[len + i] - poly_B[i]; let poly_C_bound_point = poly_C_bound_point + poly_C[len + i] - poly_C[i]; eval_point_3 += comb_func( &poly_A_bound_point, &poly_B_bound_point, &poly_C_bound_point, ); } evals.push((eval_point_0, eval_point_2, eval_point_3)); } let evals_combined_0 = (0..evals.len()).map(|i| evals[i].0 * coeffs[i]).sum(); let evals_combined_2 = (0..evals.len()).map(|i| evals[i].1 * coeffs[i]).sum(); let evals_combined_3 = (0..evals.len()).map(|i| evals[i].2 * coeffs[i]).sum(); let evals = vec![ evals_combined_0, e - evals_combined_0, evals_combined_2, evals_combined_3, ]; let poly = UniPoly::from_evals(&evals); // append the prover's message to the transcript poly.append_to_poseidon(transcript); //derive the verifier's challenge for the next round let r_j = transcript.challenge_scalar(); r.push(r_j); // bound all tables to the verifier's challenege for (poly_A, poly_B) in poly_A_vec_par.iter_mut().zip(poly_B_vec_par.iter_mut()) { poly_A.bound_poly_var_top(&r_j); poly_B.bound_poly_var_top(&r_j); } poly_C_par.bound_poly_var_top(&r_j); for (poly_A, poly_B, poly_C) in izip!( poly_A_vec_seq.iter_mut(), poly_B_vec_seq.iter_mut(), poly_C_vec_seq.iter_mut() ) { poly_A.bound_poly_var_top(&r_j); poly_B.bound_poly_var_top(&r_j); poly_C.bound_poly_var_top(&r_j); } e = poly.evaluate(&r_j); cubic_polys.push(poly); } let poly_A_par_final = (0..poly_A_vec_par.len()) .map(|i| poly_A_vec_par[i][0]) .collect(); let poly_B_par_final = (0..poly_B_vec_par.len()) .map(|i| poly_B_vec_par[i][0]) .collect(); let claims_prod = (poly_A_par_final, poly_B_par_final, poly_C_par[0]); let poly_A_seq_final = (0..poly_A_vec_seq.len()) .map(|i| poly_A_vec_seq[i][0]) .collect(); let poly_B_seq_final = (0..poly_B_vec_seq.len()) .map(|i| poly_B_vec_seq[i][0]) .collect(); let poly_C_seq_final = (0..poly_C_vec_seq.len()) .map(|i| poly_C_vec_seq[i][0]) .collect(); let claims_dotp = (poly_A_seq_final, poly_B_seq_final, poly_C_seq_final); ( SumcheckInstanceProof::new(cubic_polys), r, claims_prod, claims_dotp, ) } pub fn prove_quad( claim: &Scalar, num_rounds: usize, poly_A: &mut DensePolynomial, poly_B: &mut DensePolynomial, comb_func: F, transcript: &mut PoseidonTranscript, ) -> (Self, Vec, Vec) where F: Fn(&Scalar, &Scalar) -> Scalar, { let mut e = *claim; let mut r: Vec = Vec::new(); let mut quad_polys: Vec = Vec::new(); for _j in 0..num_rounds { let mut eval_point_0 = Scalar::zero(); let mut eval_point_2 = Scalar::zero(); let len = poly_A.len() / 2; for i in 0..len { // eval 0: bound_func is A(low) eval_point_0 += comb_func(&poly_A[i], &poly_B[i]); // eval 2: bound_func is -A(low) + 2*A(high) let poly_A_bound_point = poly_A[len + i] + poly_A[len + i] - poly_A[i]; let poly_B_bound_point = poly_B[len + i] + poly_B[len + i] - poly_B[i]; eval_point_2 += comb_func(&poly_A_bound_point, &poly_B_bound_point); } let evals = vec![eval_point_0, e - eval_point_0, eval_point_2]; let poly = UniPoly::from_evals(&evals); // append the prover's message to the transcript poly.append_to_poseidon(transcript); //derive the verifier's challenge for the next round let r_j = transcript.challenge_scalar(); r.push(r_j); // bound all tables to the verifier's challenege poly_A.bound_poly_var_top(&r_j); poly_B.bound_poly_var_top(&r_j); e = poly.evaluate(&r_j); quad_polys.push(poly); } ( SumcheckInstanceProof::new(quad_polys), r, vec![poly_A[0], poly_B[0]], ) } } // impl ZKSumcheckInstanceProof { // pub fn prove_quad( // claim: &Scalar, // blind_claim: &Scalar, // num_rounds: usize, // poly_A: &mut DensePolynomial, // poly_B: &mut DensePolynomial, // comb_func: F, // gens_1: &MultiCommitGens, // gens_n: &MultiCommitGens, // transcript: &mut Transcript, // random_tape: &mut RandomTape, // ) -> (Self, Vec, Vec, Scalar) // where // F: Fn(&Scalar, &Scalar) -> Scalar, // { // let (blinds_poly, blinds_evals) = ( // random_tape.random_vector(b"blinds_poly", num_rounds), // random_tape.random_vector(b"blinds_evals", num_rounds), // ); // let mut claim_per_round = *claim; // let mut comm_claim_per_round = claim_per_round.commit(blind_claim, gens_1).compress(); // let mut r: Vec = Vec::new(); // let mut comm_polys: Vec = Vec::new(); // let mut comm_evals: Vec = Vec::new(); // let mut proofs: Vec = Vec::new(); // for j in 0..num_rounds { // let (poly, comm_poly) = { // let mut eval_point_0 = Scalar::zero(); // let mut eval_point_2 = Scalar::zero(); // let len = poly_A.len() / 2; // for i in 0..len { // // eval 0: bound_func is A(low) // eval_point_0 += comb_func(&poly_A[i], &poly_B[i]); // // eval 2: bound_func is -A(low) + 2*A(high) // let poly_A_bound_point = poly_A[len + i] + poly_A[len + i] - poly_A[i]; // let poly_B_bound_point = poly_B[len + i] + poly_B[len + i] - poly_B[i]; // eval_point_2 += comb_func(&poly_A_bound_point, &poly_B_bound_point); // } // let evals = vec![eval_point_0, claim_per_round - eval_point_0, eval_point_2]; // let poly = UniPoly::from_evals(&evals); // let comm_poly = poly.commit(gens_n, &blinds_poly[j]).compress(); // (poly, comm_poly) // }; // // append the prover's message to the transcript // comm_poly.append_to_transcript(b"comm_poly", transcript); // comm_polys.push(comm_poly); // //derive the verifier's challenge for the next round // let r_j = transcript.challenge_scalar(b"challenge_nextround"); // // bound all tables to the verifier's challenege // poly_A.bound_poly_var_top(&r_j); // poly_B.bound_poly_var_top(&r_j); // // produce a proof of sum-check and of evaluation // let (proof, claim_next_round, comm_claim_next_round) = { // let eval = poly.evaluate(&r_j); // let comm_eval = eval.commit(&blinds_evals[j], gens_1).compress(); // // we need to prove the following under homomorphic commitments: // // (1) poly(0) + poly(1) = claim_per_round // // (2) poly(r_j) = eval // // Our technique is to leverage dot product proofs: // // (1) we can prove: = claim_per_round // // (2) we can prove: >() // .as_slice(), // ) // .compress(); // let blind = { // let blind_sc = if j == 0 { // blind_claim // } else { // &blinds_evals[j - 1] // }; // let blind_eval = &blinds_evals[j]; // w[0] * blind_sc + w[1] * blind_eval // }; // assert_eq!(target.commit(&blind, gens_1).compress(), comm_target); // let a = { // // the vector to use to decommit for sum-check test // let a_sc = { // let mut a = vec![Scalar::one(); poly.degree() + 1]; // a[0] += Scalar::one(); // a // }; // // the vector to use to decommit for evaluation // let a_eval = { // let mut a = vec![Scalar::one(); poly.degree() + 1]; // for j in 1..a.len() { // a[j] = a[j - 1] * r_j; // } // a // }; // // take weighted sum of the two vectors using w // assert_eq!(a_sc.len(), a_eval.len()); // (0..a_sc.len()) // .map(|i| w[0] * a_sc[i] + w[1] * a_eval[i]) // .collect::>() // }; // let (proof, _comm_poly, _comm_sc_eval) = DotProductProof::prove( // gens_1, // gens_n, // transcript, // random_tape, // &poly.as_vec(), // &blinds_poly[j], // &a, // &target, // &blind, // ); // (proof, eval, comm_eval) // }; // claim_per_round = claim_next_round; // comm_claim_per_round = comm_claim_next_round; // proofs.push(proof); // r.push(r_j); // comm_evals.push(comm_claim_per_round.clone()); // } // ( // ZKSumcheckInstanceProof::new(comm_polys, comm_evals, proofs), // r, // vec![poly_A[0], poly_B[0]], // blinds_evals[num_rounds - 1], // ) // } // pub fn prove_cubic_with_additive_term( // claim: &Scalar, // blind_claim: &Scalar, // num_rounds: usize, // poly_A: &mut DensePolynomial, // poly_B: &mut DensePolynomial, // poly_C: &mut DensePolynomial, // poly_D: &mut DensePolynomial, // comb_func: F, // gens_1: &MultiCommitGens, // gens_n: &MultiCommitGens, // transcript: &mut Transcript, // random_tape: &mut RandomTape, // ) -> (Self, Vec, Vec, Scalar) // where // F: Fn(&Scalar, &Scalar, &Scalar, &Scalar) -> Scalar, // { // let (blinds_poly, blinds_evals) = ( // random_tape.random_vector(b"blinds_poly", num_rounds), // random_tape.random_vector(b"blinds_evals", num_rounds), // ); // let mut claim_per_round = *claim; // let mut comm_claim_per_round = claim_per_round.commit(blind_claim, gens_1).compress(); // let mut r: Vec = Vec::new(); // let mut comm_polys: Vec = Vec::new(); // let mut comm_evals: Vec = Vec::new(); // let mut proofs: Vec = Vec::new(); // for j in 0..num_rounds { // let (poly, comm_poly) = { // let mut eval_point_0 = Scalar::zero(); // let mut eval_point_2 = Scalar::zero(); // let mut eval_point_3 = Scalar::zero(); // let len = poly_A.len() / 2; // for i in 0..len { // // eval 0: bound_func is A(low) // eval_point_0 += comb_func(&poly_A[i], &poly_B[i], &poly_C[i], &poly_D[i]); // // eval 2: bound_func is -A(low) + 2*A(high) // let poly_A_bound_point = poly_A[len + i] + poly_A[len + i] - poly_A[i]; // let poly_B_bound_point = poly_B[len + i] + poly_B[len + i] - poly_B[i]; // let poly_C_bound_point = poly_C[len + i] + poly_C[len + i] - poly_C[i]; // let poly_D_bound_point = poly_D[len + i] + poly_D[len + i] - poly_D[i]; // eval_point_2 += comb_func( // &poly_A_bound_point, // &poly_B_bound_point, // &poly_C_bound_point, // &poly_D_bound_point, // ); // // eval 3: bound_func is -2A(low) + 3A(high); computed incrementally with bound_func applied to eval(2) // let poly_A_bound_point = poly_A_bound_point + poly_A[len + i] - poly_A[i]; // let poly_B_bound_point = poly_B_bound_point + poly_B[len + i] - poly_B[i]; // let poly_C_bound_point = poly_C_bound_point + poly_C[len + i] - poly_C[i]; // let poly_D_bound_point = poly_D_bound_point + poly_D[len + i] - poly_D[i]; // eval_point_3 += comb_func( // &poly_A_bound_point, // &poly_B_bound_point, // &poly_C_bound_point, // &poly_D_bound_point, // ); // } // let evals = vec![ // eval_point_0, // claim_per_round - eval_point_0, // eval_point_2, // eval_point_3, // ]; // let poly = UniPoly::from_evals(&evals); // let comm_poly = poly.commit(gens_n, &blinds_poly[j]).compress(); // (poly, comm_poly) // }; // // append the prover's message to the transcript // comm_poly.append_to_transcript(b"comm_poly", transcript); // comm_polys.push(comm_poly); // //derive the verifier's challenge for the next round // let r_j = transcript.challenge_scalar(b"challenge_nextround"); // // bound all tables to the verifier's challenege // poly_A.bound_poly_var_top(&r_j); // poly_B.bound_poly_var_top(&r_j); // poly_C.bound_poly_var_top(&r_j); // poly_D.bound_poly_var_top(&r_j); // // produce a proof of sum-check and of evaluation // let (proof, claim_next_round, comm_claim_next_round) = { // let eval = poly.evaluate(&r_j); // let comm_eval = eval.commit(&blinds_evals[j], gens_1).compress(); // // we need to prove the following under homomorphic commitments: // // (1) poly(0) + poly(1) = claim_per_round // // (2) poly(r_j) = eval // // Our technique is to leverage dot product proofs: // // (1) we can prove: = claim_per_round // // (2) we can prove: >() // .as_slice(), // ) // .compress(); // let blind = { // let blind_sc = if j == 0 { // blind_claim // } else { // &blinds_evals[j - 1] // }; // let blind_eval = &blinds_evals[j]; // w[0] * blind_sc + w[1] * blind_eval // }; // let res = target.commit(&blind, gens_1); // assert_eq!(res.compress(), comm_target); // let a = { // // the vector to use to decommit for sum-check test // let a_sc = { // let mut a = vec![Scalar::one(); poly.degree() + 1]; // a[0] += Scalar::one(); // a // }; // // the vector to use to decommit for evaluation // let a_eval = { // let mut a = vec![Scalar::one(); poly.degree() + 1]; // for j in 1..a.len() { // a[j] = a[j - 1] * r_j; // } // a // }; // // take weighted sum of the two vectors using w // assert_eq!(a_sc.len(), a_eval.len()); // (0..a_sc.len()) // .map(|i| w[0] * a_sc[i] + w[1] * a_eval[i]) // .collect::>() // }; // let (proof, _comm_poly, _comm_sc_eval) = DotProductProof::prove( // gens_1, // gens_n, // transcript, // random_tape, // &poly.as_vec(), // &blinds_poly[j], // &a, // &target, // &blind, // ); // (proof, eval, comm_eval) // }; // proofs.push(proof); // claim_per_round = claim_next_round; // comm_claim_per_round = comm_claim_next_round; // r.push(r_j); // comm_evals.push(comm_claim_per_round.clone()); // } // ( // ZKSumcheckInstanceProof::new(comm_polys, comm_evals, proofs), // r, // vec![poly_A[0], poly_B[0], poly_C[0], poly_D[0]], // blinds_evals[num_rounds - 1], // ) // } // }