refactoring building block PIOPs (#71)
@@ -680,7 +680,7 @@ &zero_check_aux_info,
&mut transcript, )?; - let zero_check_point = &zero_check_sub_claim.sum_check_sub_claim.point; + let zero_check_point = &zero_check_sub_claim.point; // check zero check subclaim let f_eval = eval_f(@@ -718,10 +718,9 @@
let perm_check_point = &perm_check_sub_claim .product_check_sub_claim .zero_check_sub_claim - .sum_check_sub_claim .point; - let alpha = perm_check_sub_claim.product_check_sub_claim.challenge; + let alpha = perm_check_sub_claim.product_check_sub_claim.alpha; let (beta, gamma) = perm_check_sub_claim.challenges; // check perm check subclaim:
@@ -4,7 +4,8 @@ use ark_poly::{DenseMultilinearExtension, MultilinearExtension};
use ark_std::test_rng; use pcs::{prelude::KZGMultilinearPCS, PolynomialCommitmentScheme}; use poly_iop::prelude::{ - identity_permutation_mle, PermutationCheck, PolyIOP, PolyIOPErrors, SumCheck, ZeroCheck, + identity_permutation_mle, PermutationCheck, PolyIOP, PolyIOPErrors, ProductCheck, SumCheck, + ZeroCheck, }; use std::{marker::PhantomData, rc::Rc, time::Instant};@@ -14,6 +15,8 @@ fn main() -> Result<(), PolyIOPErrors> {
bench_permutation_check()?; println!("\n\n"); bench_sum_check()?; + println!("\n\n"); + bench_prod_check()?; println!("\n\n"); bench_zero_check() }@@ -113,11 +116,10 @@ {
let start = Instant::now(); let mut transcript = <PolyIOP<Fr> as ZeroCheck<Fr>>::init_transcript(); transcript.append_message(b"testing", b"initializing transcript for testing")?; - let subclaim = - <PolyIOP<Fr> as ZeroCheck<Fr>>::verify(&proof, &poly_info, &mut transcript)? - .sum_check_sub_claim; + let zero_subclaim = + <PolyIOP<Fr> as ZeroCheck<Fr>>::verify(&proof, &poly_info, &mut transcript)?; assert!( - poly.evaluate(&subclaim.point)? == subclaim.expected_evaluation, + poly.evaluate(&zero_subclaim.point)? == zero_subclaim.expected_evaluation, "wrong subclaim" ); println!(@@ -204,3 +206,72 @@ }
Ok(()) } + +fn bench_prod_check() -> Result<(), PolyIOPErrors> { + let mut rng = test_rng(); + + for nv in 4..20 { + let srs = KZG::gen_srs_for_testing(&mut rng, nv + 1)?; + let (pcs_param, _) = KZG::trim(&srs, nv + 1, Some(nv + 1))?; + + let repetition = if nv < 10 { + 100 + } else if nv < 20 { + 50 + } else { + 10 + }; + + let f: DenseMultilinearExtension<Fr> = DenseMultilinearExtension::rand(nv, &mut rng); + let mut g = f.clone(); + g.evaluations.reverse(); + let f = Rc::new(f); + let g = Rc::new(g); + + let proof = { + let start = Instant::now(); + let mut transcript = <PolyIOP<Fr> as ProductCheck<Bls12_381, KZG>>::init_transcript(); + transcript.append_message(b"testing", b"initializing transcript for testing")?; + + let (proof, _prod_x) = <PolyIOP<Fr> as ProductCheck<Bls12_381, KZG>>::prove( + &pcs_param, + &f, + &g, + &mut transcript, + )?; + + println!( + "product check proving time for {} variables: {} ns", + nv, + start.elapsed().as_nanos() / repetition as u128 + ); + proof + }; + + { + let poly_info = VPAuxInfo { + max_degree: 2, + num_variables: nv, + phantom: PhantomData::default(), + }; + + let start = Instant::now(); + let mut transcript = <PolyIOP<Fr> as ProductCheck<Bls12_381, KZG>>::init_transcript(); + transcript.append_message(b"testing", b"initializing transcript for testing")?; + let _perm_check_sum_claim = <PolyIOP<Fr> as ProductCheck<Bls12_381, KZG>>::verify( + &proof, + &poly_info, + &mut transcript, + )?; + println!( + "product check verification time for {} variables: {} ns", + nv, + start.elapsed().as_nanos() / repetition as u128 + ); + } + + println!("===================================="); + } + + Ok(()) +}
@@ -27,7 +27,10 @@ }
pub mod util; -/// A PermutationCheck is derived from ZeroCheck. +/// A PermutationCheck w.r.t. `(f, g, perm)` +/// proves that g is a permutation of f under +/// permutation `perm` +/// It is derived from ProductCheck. /// /// A Permutation Check IOP takes the following steps: ///@@ -58,7 +61,7 @@ /// - permutation s_perm(x)
/// Outputs: /// - a permutation check proof proving that g is a permutation of f under /// s_perm - /// - the Q(x) polynomial build during product check + /// - the product polynomial build during product check /// /// Cost: O(N) fn prove(@@ -78,53 +81,18 @@ transcript: &mut Self::Transcript,
) -> Result<Self::PermutationCheckSubClaim, PolyIOPErrors>; } -/// A PermutationCheck is derived from ZeroCheck. -/// -/// A Permutation Check IOP takes the following steps: -/// -/// Inputs: -/// - f(x) -/// - g(x) -/// - permutation s_perm(x) -/// -/// Steps: -/// 1. `generate_challenge` from current transcript (generate beta, gamma) -/// 2. `compute_product` to build `prod(x)` etc. from f, g and s_perm -/// 3. push a commitment of `prod(x)` to the transcript (done by the snark -/// caller) -/// 4. `update_challenge` with the updated transcript (generate alpha) -/// 5. `prove` to generate the proof impl<E, PCS> PermutationCheck<E, PCS> for PolyIOP<E::Fr> where E: PairingEngine, PCS: PolynomialCommitmentScheme<E, Polynomial = Rc<DenseMultilinearExtension<E::Fr>>>, { - /// A Permutation SubClaim is indeed a ZeroCheck SubClaim that consists of - /// - the SubClaim from the SumCheck - /// - the initial challenge r which is used to build eq(x, r) type PermutationCheckSubClaim = PermutationCheckSubClaim<E, PCS, Self>; type PermutationProof = Self::ProductCheckProof; - /// Initialize the system with a transcript - /// - /// This function is optional -- in the case where a PermutationCheck is - /// an building block for a more complex protocol, the transcript - /// may be initialized by this complex protocol, and passed to the - /// PermutationCheck prover/verifier. fn init_transcript() -> Self::Transcript { IOPTranscript::<E::Fr>::new(b"Initializing PermutationCheck transcript") } - /// Inputs: - /// - f(x) - /// - g(x) - /// - permutation s_perm(x) - /// Outputs: - /// - a permutation check proof proving that g is a permutation of f under - /// s_perm - /// - the Q(x) polynomial build during product check - /// - /// Cost: O(N) fn prove( pcs_param: &PCS::ProverParam, fx: &Self::MultilinearExtension,@@ -151,11 +119,11 @@ let gamma = transcript.get_and_append_challenge(b"gamma")?;
let (numerator, denominator) = computer_num_and_denom(&beta, &gamma, fx, gx, s_perm)?; // invoke product check on numerator and denominator - let (proof, poly) = + let (proof, prod_poly) = <Self as ProductCheck<E, PCS>>::prove(pcs_param, &numerator, &denominator, transcript)?; end_timer!(start); - Ok((proof, poly)) + Ok((proof, prod_poly)) } /// Verify that an MLE g(x) is a permutation of an@@ -184,18 +152,15 @@ }
#[cfg(test)] mod test { - use super::{util::build_prod_partial_eval, PermutationCheck}; + use super::PermutationCheck; use crate::{ errors::PolyIOPErrors, - perm_check::util::computer_num_and_denom, prelude::{identity_permutation_mle, random_permutation_mle}, - utils::bit_decompose, PolyIOP, }; - use arithmetic::{VPAuxInfo, VirtualPolynomial}; + use arithmetic::VPAuxInfo; use ark_bls12_381::Bls12_381; use ark_ec::PairingEngine; - use ark_ff::{One, Zero}; use ark_poly::{DenseMultilinearExtension, MultilinearExtension}; use ark_std::test_rng; use pcs::{prelude::KZGMultilinearPCS, PolynomialCommitmentScheme};@@ -223,7 +188,7 @@
// prover let mut transcript = <PolyIOP<E::Fr> as PermutationCheck<E, PCS>>::init_transcript(); transcript.append_message(b"testing", b"initializing transcript for testing")?; - let (proof, q_x) = <PolyIOP<E::Fr> as PermutationCheck<E, PCS>>::prove( + let (proof, prod_x) = <PolyIOP<E::Fr> as PermutationCheck<E, PCS>>::prove( pcs_param, fx, gx,@@ -234,76 +199,21 @@
// verifier let mut transcript = <PolyIOP<E::Fr> as PermutationCheck<E, PCS>>::init_transcript(); transcript.append_message(b"testing", b"initializing transcript for testing")?; - let perm_check_sum_claim = <PolyIOP<E::Fr> as PermutationCheck<E, PCS>>::verify( + let perm_check_sub_claim = <PolyIOP<E::Fr> as PermutationCheck<E, PCS>>::verify( &proof, &poly_info, &mut transcript, )?; - let prod_partial_evals = build_prod_partial_eval(&q_x)?; - let prod_0x = prod_partial_evals[0].clone(); - let prod_1x = prod_partial_evals[1].clone(); - let prod_x0 = prod_partial_evals[2].clone(); - let prod_x1 = prod_partial_evals[3].clone(); - - let (numerator, denominator) = computer_num_and_denom( - &perm_check_sum_claim.challenges.0, - &perm_check_sum_claim.challenges.1, - fx, - gx, - &s_perm, - )?; - - // compute (g(x) + beta * s_perm(x) + gamma) * prod(0, x) * alpha - // which is prods[6] * prod[1] * alpha - let mut q_x = VirtualPolynomial::new_from_mle(&denominator, E::Fr::one()); - q_x.mul_by_mle( - prod_0x, - perm_check_sum_claim.product_check_sub_claim.challenge, - )?; - - // (g(x) + beta * s_perm(x) + gamma) * prod(0, x) * alpha - // - (f(x) + beta * s_id(x) + gamma) * alpha - q_x.add_mle_list( - [numerator], - -perm_check_sum_claim.product_check_sub_claim.challenge, - )?; - - // Q(x) := prod(1,x) - prod(x, 0) * prod(x, 1) - // + alpha * ( - // (g(x) + beta * s_perm(x) + gamma) * prod(0, x) - // - (f(x) + beta * s_id(x) + gamma)) - q_x.add_mle_list([prod_x0, prod_x1], -E::Fr::one())?; - q_x.add_mle_list([prod_1x], E::Fr::one())?; - - if q_x - .evaluate( - &perm_check_sum_claim - .product_check_sub_claim - .zero_check_sub_claim - .sum_check_sub_claim - .point, - ) + // check product subclaim + if prod_x + .evaluate(&perm_check_sub_claim.product_check_sub_claim.final_query.0) .unwrap() - != perm_check_sum_claim - .product_check_sub_claim - .zero_check_sub_claim - .sum_check_sub_claim - .expected_evaluation + != perm_check_sub_claim.product_check_sub_claim.final_query.1 { return Err(PolyIOPErrors::InvalidVerifier("wrong subclaim".to_string())); }; - // test q_x is a 0 over boolean hypercube - for i in 0..1 << nv { - let bit_sequence = bit_decompose(i, nv); - let eval: Vec<E::Fr> = bit_sequence - .iter() - .map(|x| E::Fr::from(*x as u64)) - .collect(); - let res = q_x.evaluate(&eval).unwrap(); - if !res.is_zero() {} - } Ok(()) }
@@ -6,60 +6,6 @@ use ark_poly::DenseMultilinearExtension;
use ark_std::{end_timer, rand::RngCore, start_timer}; use std::rc::Rc; -/// Returns the evaluations of three MLEs: -/// - prod(0,x) -/// - numerator -/// - denominator -/// -/// where -/// - `prod(0,x) := prod(0, x1, …, xn)` which is the MLE over the -/// evaluations of the following polynomial on the boolean hypercube {0,1}^n: -/// -/// (f(x) + \beta s_id(x) + \gamma)/(g(x) + \beta s_perm(x) + \gamma) -/// -/// where -/// - beta and gamma are challenges -/// - f(x), g(x), s_id(x), s_perm(x) are mle-s -/// -/// - numerator is the MLE for `f(x) + \beta s_id(x) + \gamma` -/// - denominator is the MLE for `g(x) + \beta s_perm(x) + \gamma` -/// -/// The caller needs to check num_vars matches in f/g/s_id/s_perm -/// Cost: linear in N. -#[cfg(test)] -#[allow(clippy::type_complexity)] -pub(super) fn compute_prod_0<F: PrimeField>( - beta: &F, - gamma: &F, - fx: &DenseMultilinearExtension<F>, - gx: &DenseMultilinearExtension<F>, - s_perm: &DenseMultilinearExtension<F>, -) -> Result<(Vec<F>, Vec<F>, Vec<F>), PolyIOPErrors> { - let start = start_timer!(|| "compute prod(1,x)"); - - let num_vars = fx.num_vars; - let mut prod_0x_evals = vec![]; - let mut numerator_evals = vec![]; - let mut denominator_evals = vec![]; - - // TODO: remove this line after replacing `s_perm` with `s`. - let s_id = identity_permutation_mle::<F>(num_vars); - - for (&fi, (&gi, (&s_id_i, &s_perm_i))) in - fx.iter().zip(gx.iter().zip(s_id.iter().zip(s_perm.iter()))) - { - let numerator = fi + *beta * s_id_i + gamma; - let denominator = gi + *beta * s_perm_i + gamma; - - prod_0x_evals.push(numerator / denominator); - numerator_evals.push(numerator); - denominator_evals.push(denominator); - } - - end_timer!(start); - Ok((prod_0x_evals, numerator_evals, denominator_evals)) -} - /// Returns the evaluations of two MLEs: /// - numerator /// - denominator@@ -139,118 +85,3 @@ Rc::new(DenseMultilinearExtension::from_evaluations_vec(
num_vars, s_perm_vec, )) } - -/// Helper function of the IOP. -/// -/// Input: -/// - prod(x) -/// -/// Output: the following 4 polynomials -/// - prod(0, x) -/// - prod(1, x) -/// - prod(x, 0) -/// - prod(x, 1) -#[cfg(test)] -pub(super) fn build_prod_partial_eval<F: PrimeField>( - prod_x: &Rc<DenseMultilinearExtension<F>>, -) -> Result<[Rc<DenseMultilinearExtension<F>>; 4], PolyIOPErrors> { - let start = start_timer!(|| "build prod polynomial"); - - let prod_x_eval = &prod_x.evaluations; - let num_vars = prod_x.num_vars - 1; - - // prod(0, x) - let prod_0_x = Rc::new(DenseMultilinearExtension::from_evaluations_slice( - num_vars, - &prod_x_eval[0..1 << num_vars], - )); - // prod(1, x) - let prod_1_x = Rc::new(DenseMultilinearExtension::from_evaluations_slice( - num_vars, - &prod_x_eval[1 << num_vars..1 << (num_vars + 1)], - )); - - // =================================== - // prod(x, 0) and prod(x, 1) - // =================================== - // - // now we compute eval_x0 and eval_x1 - // eval_0x will be the odd coefficients of eval - // and eval_1x will be the even coefficients of eval - let mut eval_x0 = vec![]; - let mut eval_x1 = vec![]; - for (x, &prod_x) in prod_x_eval.iter().enumerate() { - if x & 1 == 0 { - eval_x0.push(prod_x); - } else { - eval_x1.push(prod_x); - } - } - let prod_x_0 = Rc::new(DenseMultilinearExtension::from_evaluations_vec( - num_vars, eval_x0, - )); - let prod_x_1 = Rc::new(DenseMultilinearExtension::from_evaluations_vec( - num_vars, eval_x1, - )); - - end_timer!(start); - - Ok([prod_0_x, prod_1_x, prod_x_0, prod_x_1]) -} - -#[cfg(test)] -mod test { - use super::*; - use crate::utils::bit_decompose; - use ark_bls12_381::Fr; - use ark_ff::UniformRand; - use ark_poly::MultilinearExtension; - use ark_std::test_rng; - - #[test] - fn test_compute_prod_0() -> Result<(), PolyIOPErrors> { - let mut rng = test_rng(); - - for num_vars in 2..6 { - let f = DenseMultilinearExtension::rand(num_vars, &mut rng); - let g = DenseMultilinearExtension::rand(num_vars, &mut rng); - - let s_id = identity_permutation_mle::<Fr>(num_vars); - let s_perm = random_permutation_mle(num_vars, &mut rng); - - let beta = Fr::rand(&mut rng); - let gamma = Fr::rand(&mut rng); - - let (prod_0, numerator, denominator) = compute_prod_0(&beta, &gamma, &f, &g, &s_perm)?; - let prod_0 = DenseMultilinearExtension::from_evaluations_vec(num_vars, prod_0); - let numerator = DenseMultilinearExtension::from_evaluations_vec(num_vars, numerator); - let denominator = - DenseMultilinearExtension::from_evaluations_vec(num_vars, denominator); - - for i in 0..1 << num_vars { - let r: Vec<Fr> = bit_decompose(i, num_vars) - .iter() - .map(|&x| Fr::from(x)) - .collect(); - - let prod_0_eval = prod_0.evaluate(&r).unwrap(); - let numerator_eval = numerator.evaluate(&r).unwrap(); - let denominator_eval = denominator.evaluate(&r).unwrap(); - - let f_eval = f.evaluate(&r).unwrap(); - let g_eval = g.evaluate(&r).unwrap(); - let s_id_eval = s_id.evaluate(&r).unwrap(); - let s_perm_eval = s_perm.evaluate(&r).unwrap(); - - let numerator_eval_rec = f_eval + beta * s_id_eval + gamma; - let denominator_eval_rec = g_eval + beta * s_perm_eval + gamma; - let prod_0_eval_rec = numerator_eval_rec / denominator_eval_rec; - - assert_eq!(numerator_eval, numerator_eval_rec); - assert_eq!(denominator_eval, denominator_eval_rec); - assert_eq!(prod_0_eval, prod_0_eval_rec); - } - } - Ok(()) - } -}
@@ -86,12 +86,10 @@ }
/// A product check subclaim consists of /// - A zero check IOP subclaim for -/// `Q(x) = prod(1, x) - prod(x, 0) * prod(x, 1) + challenge * (f(x) - prod(0, -/// x) * g(x))` is 0, consists of the following: -/// - the SubClaim from the SumCheck -/// - the initial challenge r which is used to build eq(x, r) in ZeroCheck -/// - The challenge `challenge` -/// - A final query for `prod(1, ..., 1, 0) = claimed_product`. +/// `Q(x) = prod(1, x) - prod(x, 0) * prod(x, 1) + alpha * (f(x) - prod(0, +/// x) * g(x)) = 0` +/// - The random challenge `alpha` +/// - A final query for `prod(1, ..., 1, 0) = 1`. // Note that this final query is in fact a constant that // is independent from the proof. So we should avoid // (de)serialize it.@@ -103,8 +101,8 @@ // final query which consists of
// - the vector `(1, ..., 1, 0)` (needs to be reversed because Arkwork's MLE uses big-endian // format for points) // The expected final query evaluation is 1 - final_query: (Vec<F>, F), - pub challenge: F, + pub final_query: (Vec<F>, F), + pub alpha: F, } /// A product check proof consists of@@ -195,7 +193,7 @@
Ok(ProductCheckSubClaim { zero_check_sub_claim, final_query: (final_query, final_eval), - challenge: alpha, + alpha, }) } }@@ -240,11 +238,11 @@ max_degree: 2,
num_variables: f.num_vars, phantom: PhantomData::default(), }; - let subclaim = + let prod_subclaim = <PolyIOP<E::Fr> as ProductCheck<E, PCS>>::verify(&proof, &aux_info, &mut transcript)?; assert_eq!( - prod_x.evaluate(&subclaim.final_query.0).unwrap(), - subclaim.final_query.1, + prod_x.evaluate(&prod_subclaim.final_query.0).unwrap(), + prod_subclaim.final_query.1, "different product" );
@@ -131,7 +131,6 @@ type MultilinearExtension = Rc<DenseMultilinearExtension<F>>;
type SumCheckSubClaim = SumCheckSubClaim<F>; type Transcript = IOPTranscript<F>; - /// Extract sum from the proof fn extract_sum(proof: &Self::SumCheckProof) -> F { let start = start_timer!(|| "extract sum"); let res = proof.proofs[0].evaluations[0] + proof.proofs[0].evaluations[1];@@ -139,12 +138,6 @@ end_timer!(start);
res } - /// Initialize the system with a transcript - /// - /// This function is optional -- in the case where a SumCheck is - /// an building block for a more complex protocol, the transcript - /// may be initialized by this complex protocol, and passed to the - /// SumCheck prover/verifier. fn init_transcript() -> Self::Transcript { let start = start_timer!(|| "init transcript"); let res = IOPTranscript::<F>::new(b"Initializing SumCheck transcript");@@ -152,9 +145,6 @@ end_timer!(start);
res } - /// Generate proof of the sum of polynomial over {0,1}^`num_vars` - /// - /// The polynomial is represented in the form of a VirtualPolynomial. fn prove( poly: &Self::VirtualPolynomial, transcript: &mut Self::Transcript,@@ -185,7 +175,6 @@ proofs: prover_msgs,
}) } - /// Verify the claimed sum using the proof fn verify( claimed_sum: F, proof: &Self::SumCheckProof,
@@ -9,20 +9,23 @@ use ark_poly::MultilinearExtension;
use ark_std::{end_timer, start_timer}; use transcript::IOPTranscript; -/// A zero check IOP subclaim for \hat f(x) is 0, consists of the following: -/// - the SubClaim from the SumCheck -/// - the initial challenge r which is used to build eq(x, r) in ZeroCheck -#[derive(Clone, Debug, Default, PartialEq)] -pub struct ZeroCheckSubClaim<F: PrimeField, SC: SumCheck<F>> { - // the SubClaim from the SumCheck - pub sum_check_sub_claim: SC::SumCheckSubClaim, +/// A zero check IOP subclaim for `f(x)` consists of the following: +/// - the initial challenge vector r which is used to build eq(x, r) in +/// SumCheck +/// - the random vector `v` to be evaluated +/// - the claimed evaluation of `f(v)` +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct ZeroCheckSubClaim<F: PrimeField> { + // the evaluation point + pub point: Vec<F>, /// the expected evaluation pub expected_evaluation: F, // the initial challenge r which is used to build eq(x, r) pub init_challenge: Vec<F>, } -/// A ZeroCheck is derived from SumCheck. +/// A ZeroCheck for `f(x)` proves that `f(x) = 0` for all `x \in {0,1}^num_vars` +/// It is derived from SumCheck. pub trait ZeroCheck<F: PrimeField>: SumCheck<F> { type ZeroCheckSubClaim: Clone + Debug + Default + PartialEq; type ZeroCheckProof: Clone + Debug + Default + PartialEq;@@ -51,31 +54,13 @@ ) -> Result<Self::ZeroCheckSubClaim, PolyIOPErrors>;
} impl<F: PrimeField> ZeroCheck<F> for PolyIOP<F> { - /// A ZeroCheck SubClaim consists of - /// - the SubClaim from the SumCheck - /// - the initial challenge r which is used to build eq(x, r) - type ZeroCheckSubClaim = ZeroCheckSubClaim<F, Self>; - /// A ZeroCheckProof is a SumCheckProof + type ZeroCheckSubClaim = ZeroCheckSubClaim<F>; type ZeroCheckProof = Self::SumCheckProof; - /// Initialize the system with a transcript - /// - /// This function is optional -- in the case where a ZeroCheck is - /// an building block for a more complex protocol, the transcript - /// may be initialized by this complex protocol, and passed to the - /// ZeroCheck prover/verifier. fn init_transcript() -> Self::Transcript { IOPTranscript::<F>::new(b"Initializing ZeroCheck transcript") } - /// Initialize the prover to argue for the sum of polynomial f(x) over - /// {0,1}^`num_vars` is zero. - /// - /// f(x) is zero if \hat f(x) := f(x) * eq(x,r) is also a zero polynomial - /// for a random r sampled from transcript. - /// - /// This function will build the \hat f(x) and then invoke the sumcheck - /// protocol to generate a proof for which the sum of \hat f(x) is zero fn prove( poly: &Self::VirtualPolynomial, transcript: &mut Self::Transcript,@@ -91,15 +76,6 @@ end_timer!(start);
res } - /// Verify that the polynomial's sum is zero using the proof. - /// Return a Self::Subclaim that consists of the - /// - /// - a Subclaim that the sum is zero - /// - the initial challenge `r` that is used to build `eq(x, r)` - /// - /// This function will check that \hat f(x)'s sum is zero. It does not check - /// `\hat f(x)` is build correctly. The caller needs to makes sure that - /// `\hat f(x) = f(x) * eq(x, r)` fn verify( proof: &Self::ZeroCheckProof, fx_aux_info: &Self::VPAuxInfo,@@ -122,20 +98,20 @@
// hat_fx's max degree is increased by eq(x, r).degree() which is 1 let mut hat_fx_aux_info = fx_aux_info.clone(); hat_fx_aux_info.max_degree += 1; - let subclaim = + let sum_subclaim = <Self as SumCheck<F>>::verify(F::zero(), proof, &hat_fx_aux_info, transcript)?; - // expected_eval = sumcheck.expect_eval/eq(x, r) - // where x = sum_check_sub_claim.point + // expected_eval = sumcheck.expect_eval/eq(v, r) + // where v = sum_check_sub_claim.point let eq_x_r = build_eq_x_r(&r)?; - let expected_evaluation = subclaim.expected_evaluation - / eq_x_r.evaluate(&subclaim.point).ok_or_else(|| { + let expected_evaluation = sum_subclaim.expected_evaluation + / eq_x_r.evaluate(&sum_subclaim.point).ok_or_else(|| { PolyIOPErrors::InvalidParameters("evaluation dimension does not match".to_string()) })?; end_timer!(start); Ok(ZeroCheckSubClaim { - sum_check_sub_claim: subclaim, + point: sum_subclaim.point, expected_evaluation, init_challenge: r, })@@ -170,11 +146,10 @@
let poly_info = poly.aux_info.clone(); let mut transcript = <PolyIOP<Fr> as ZeroCheck<Fr>>::init_transcript(); transcript.append_message(b"testing", b"initializing transcript for testing")?; - let subclaim = - <PolyIOP<Fr> as ZeroCheck<Fr>>::verify(&proof, &poly_info, &mut transcript)? - .sum_check_sub_claim; + let zero_subclaim = + <PolyIOP<Fr> as ZeroCheck<Fr>>::verify(&proof, &poly_info, &mut transcript)?; assert!( - poly.evaluate(&subclaim.point)? == subclaim.expected_evaluation, + poly.evaluate(&zero_subclaim.point)? == zero_subclaim.expected_evaluation, "wrong subclaim" ); }