diff --git a/hyperplonk/src/lib.rs b/hyperplonk/src/lib.rs index d7669ab..6bed05e 100644 --- a/hyperplonk/src/lib.rs +++ b/hyperplonk/src/lib.rs @@ -680,7 +680,7 @@ where &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 @@ where 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: diff --git a/poly-iop/benches/bench.rs b/poly-iop/benches/bench.rs index 0e9a332..0fa2c61 100644 --- a/poly-iop/benches/bench.rs +++ b/poly-iop/benches/bench.rs @@ -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}; @@ -15,6 +16,8 @@ fn main() -> Result<(), PolyIOPErrors> { println!("\n\n"); bench_sum_check()?; println!("\n\n"); + bench_prod_check()?; + println!("\n\n"); bench_zero_check() } @@ -113,11 +116,10 @@ fn bench_zero_check() -> Result<(), PolyIOPErrors> { let start = Instant::now(); let mut transcript = as ZeroCheck>::init_transcript(); transcript.append_message(b"testing", b"initializing transcript for testing")?; - let subclaim = - as ZeroCheck>::verify(&proof, &poly_info, &mut transcript)? - .sum_check_sub_claim; + let zero_subclaim = + as ZeroCheck>::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 @@ fn bench_permutation_check() -> Result<(), PolyIOPErrors> { 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 = 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 = as ProductCheck>::init_transcript(); + transcript.append_message(b"testing", b"initializing transcript for testing")?; + + let (proof, _prod_x) = as ProductCheck>::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 = as ProductCheck>::init_transcript(); + transcript.append_message(b"testing", b"initializing transcript for testing")?; + let _perm_check_sum_claim = as ProductCheck>::verify( + &proof, + &poly_info, + &mut transcript, + )?; + println!( + "product check verification time for {} variables: {} ns", + nv, + start.elapsed().as_nanos() / repetition as u128 + ); + } + + println!("===================================="); + } + + Ok(()) +} diff --git a/poly-iop/src/perm_check/mod.rs b/poly-iop/src/perm_check/mod.rs index b250294..190a1e7 100644 --- a/poly-iop/src/perm_check/mod.rs +++ b/poly-iop/src/perm_check/mod.rs @@ -27,7 +27,10 @@ where 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 @@ where /// 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 @@ where ) -> Result; } -/// 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 PermutationCheck for PolyIOP where E: PairingEngine, PCS: PolynomialCommitmentScheme>>, { - /// 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; 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::::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 @@ where 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) = >::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 @@ where #[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 @@ mod test { // prover let mut transcript = as PermutationCheck>::init_transcript(); transcript.append_message(b"testing", b"initializing transcript for testing")?; - let (proof, q_x) = as PermutationCheck>::prove( + let (proof, prod_x) = as PermutationCheck>::prove( pcs_param, fx, gx, @@ -234,76 +199,21 @@ mod test { // verifier let mut transcript = as PermutationCheck>::init_transcript(); transcript.append_message(b"testing", b"initializing transcript for testing")?; - let perm_check_sum_claim = as PermutationCheck>::verify( + let perm_check_sub_claim = as PermutationCheck>::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 = bit_sequence - .iter() - .map(|x| E::Fr::from(*x as u64)) - .collect(); - let res = q_x.evaluate(&eval).unwrap(); - if !res.is_zero() {} - } Ok(()) } diff --git a/poly-iop/src/perm_check/util.rs b/poly-iop/src/perm_check/util.rs index 35ccc65..cec0f4d 100644 --- a/poly-iop/src/perm_check/util.rs +++ b/poly-iop/src/perm_check/util.rs @@ -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( - beta: &F, - gamma: &F, - fx: &DenseMultilinearExtension, - gx: &DenseMultilinearExtension, - s_perm: &DenseMultilinearExtension, -) -> Result<(Vec, Vec, Vec), 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::(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 @@ pub fn random_permutation_mle( 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( - prod_x: &Rc>, -) -> Result<[Rc>; 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::(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 = 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(()) - } -} diff --git a/poly-iop/src/prod_check/mod.rs b/poly-iop/src/prod_check/mod.rs index 8d9952e..c94d69f 100644 --- a/poly-iop/src/prod_check/mod.rs +++ b/poly-iop/src/prod_check/mod.rs @@ -86,12 +86,10 @@ where /// 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 @@ pub struct ProductCheckSubClaim> { // - 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), - pub challenge: F, + pub final_query: (Vec, F), + pub alpha: F, } /// A product check proof consists of @@ -195,7 +193,7 @@ where Ok(ProductCheckSubClaim { zero_check_sub_claim, final_query: (final_query, final_eval), - challenge: alpha, + alpha, }) } } @@ -240,11 +238,11 @@ mod test { num_variables: f.num_vars, phantom: PhantomData::default(), }; - let subclaim = + let prod_subclaim = as ProductCheck>::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" ); diff --git a/poly-iop/src/sum_check/mod.rs b/poly-iop/src/sum_check/mod.rs index f164b7e..db15d60 100644 --- a/poly-iop/src/sum_check/mod.rs +++ b/poly-iop/src/sum_check/mod.rs @@ -131,7 +131,6 @@ impl SumCheck for PolyIOP { type SumCheckSubClaim = SumCheckSubClaim; type Transcript = IOPTranscript; - /// 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 @@ impl SumCheck for PolyIOP { 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::::new(b"Initializing SumCheck transcript"); @@ -152,9 +145,6 @@ impl SumCheck for PolyIOP { 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 @@ impl SumCheck for PolyIOP { }) } - /// Verify the claimed sum using the proof fn verify( claimed_sum: F, proof: &Self::SumCheckProof, diff --git a/poly-iop/src/zero_check/mod.rs b/poly-iop/src/zero_check/mod.rs index a6eaa0a..0538c86 100644 --- a/poly-iop/src/zero_check/mod.rs +++ b/poly-iop/src/zero_check/mod.rs @@ -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> { - // 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 { + // the evaluation point + pub point: Vec, /// the expected evaluation pub expected_evaluation: F, // the initial challenge r which is used to build eq(x, r) pub init_challenge: Vec, } -/// 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: SumCheck { type ZeroCheckSubClaim: Clone + Debug + Default + PartialEq; type ZeroCheckProof: Clone + Debug + Default + PartialEq; @@ -51,31 +54,13 @@ pub trait ZeroCheck: SumCheck { } impl ZeroCheck for PolyIOP { - /// 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; - /// A ZeroCheckProof is a SumCheckProof + type ZeroCheckSubClaim = ZeroCheckSubClaim; 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::::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 @@ impl ZeroCheck for PolyIOP { 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 @@ impl ZeroCheck for PolyIOP { // 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 = >::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 @@ mod test { let poly_info = poly.aux_info.clone(); let mut transcript = as ZeroCheck>::init_transcript(); transcript.append_message(b"testing", b"initializing transcript for testing")?; - let subclaim = - as ZeroCheck>::verify(&proof, &poly_info, &mut transcript)? - .sum_check_sub_claim; + let zero_subclaim = + as ZeroCheck>::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" ); }