diff --git a/src/plonk/lookup/prover.rs b/src/plonk/lookup/prover.rs index 82e7921..f13bcdb 100644 --- a/src/plonk/lookup/prover.rs +++ b/src/plonk/lookup/prover.rs @@ -55,11 +55,6 @@ pub(in crate::plonk) struct Constructed { pub(in crate::plonk) struct Evaluated { constructed: Constructed, - product_eval: C::Scalar, - product_inv_eval: C::Scalar, - permuted_input_eval: C::Scalar, - permuted_input_inv_eval: C::Scalar, - permuted_table_eval: C::Scalar, } impl Argument { @@ -465,14 +460,7 @@ impl Constructed { .map_err(|_| Error::TranscriptError)?; } - Ok(Evaluated { - constructed: self, - product_eval, - product_inv_eval, - permuted_input_eval, - permuted_input_inv_eval, - permuted_table_eval, - }) + Ok(Evaluated { constructed: self }) } } @@ -490,35 +478,30 @@ impl Evaluated { point: *x, poly: &self.constructed.product_poly, blind: self.constructed.product_blind, - eval: self.product_eval, })) // Open lookup input commitments at x .chain(Some(ProverQuery { point: *x, poly: &self.constructed.permuted_input_poly, blind: self.constructed.permuted_input_blind, - eval: self.permuted_input_eval, })) // Open lookup table commitments at x .chain(Some(ProverQuery { point: *x, poly: &self.constructed.permuted_table_poly, blind: self.constructed.permuted_table_blind, - eval: self.permuted_table_eval, })) // Open lookup input commitments at x_inv .chain(Some(ProverQuery { point: x_inv, poly: &self.constructed.permuted_input_poly, blind: self.constructed.permuted_input_blind, - eval: self.permuted_input_inv_eval, })) // Open lookup product commitments at x_inv .chain(Some(ProverQuery { point: x_inv, poly: &self.constructed.product_poly, blind: self.constructed.product_blind, - eval: self.product_inv_eval, })) } } diff --git a/src/plonk/permutation/prover.rs b/src/plonk/permutation/prover.rs index 7d5fd7a..5af58e8 100644 --- a/src/plonk/permutation/prover.rs +++ b/src/plonk/permutation/prover.rs @@ -27,9 +27,6 @@ pub(crate) struct Constructed { pub(crate) struct Evaluated { constructed: Constructed, - permutation_product_eval: C::Scalar, - permutation_product_inv_eval: C::Scalar, - permutation_evals: Vec, } impl Argument { @@ -218,20 +215,12 @@ impl super::ProvingKey { .collect() } - fn open<'a>( - &'a self, - evals: &'a [C::Scalar], - x: ChallengeX, - ) -> impl Iterator> + Clone { - self.polys - .iter() - .zip(evals.iter()) - .map(move |(poly, eval)| ProverQuery { - point: *x, - poly, - blind: Blind::default(), - eval: *eval, - }) + fn open<'a>(&'a self, x: ChallengeX) -> impl Iterator> + Clone { + self.polys.iter().map(move |poly| ProverQuery { + point: *x, + poly, + blind: Blind::default(), + }) } } @@ -265,12 +254,7 @@ impl Constructed { .map_err(|_| Error::TranscriptError)?; } - Ok(Evaluated { - constructed: self, - permutation_product_eval, - permutation_product_inv_eval, - permutation_evals, - }) + Ok(Evaluated { constructed: self }) } } @@ -289,15 +273,13 @@ impl Evaluated { point: *x, poly: &self.constructed.permutation_product_poly, blind: self.constructed.permutation_product_blind, - eval: self.permutation_product_eval, })) .chain(Some(ProverQuery { point: x_inv, poly: &self.constructed.permutation_product_poly, blind: self.constructed.permutation_product_blind, - eval: self.permutation_product_inv_eval, })) // Open permutation polynomial commitments at x - .chain(pkey.open(&self.permutation_evals, x)) + .chain(pkey.open(x)) } } diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 365ae55..3f2db38 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -304,53 +304,51 @@ pub fn create_proof, ConcreteCircuit: Circ .map(|p| p.evaluate(pk, x, transcript)) .collect::, _>>()?; - let instances = - iter::empty() - .chain(pk.vk.cs.advice_queries.iter().enumerate().map( - |(query_index, &(column, at))| ProverQuery { + let instances = iter::empty() + .chain( + pk.vk + .cs + .advice_queries + .iter() + .map(|&(column, at)| ProverQuery { point: domain.rotate_omega(*x, at), poly: &advice_polys[column.index()], blind: advice_blinds[column.index()], - eval: advice_evals[query_index], - }, - )) - .chain( - pk.vk - .cs - .aux_queries - .iter() - .enumerate() - .map(|(query_index, &(column, at))| ProverQuery { - point: domain.rotate_omega(*x, at), - poly: &aux_polys[column.index()], - blind: Blind::default(), - eval: aux_evals[query_index], - }), - ) - .chain( - pk.vk - .cs - .fixed_queries - .iter() - .enumerate() - .map(|(query_index, &(column, at))| ProverQuery { - point: domain.rotate_omega(*x, at), - poly: &pk.fixed_polys[column.index()], - blind: Blind::default(), - eval: fixed_evals[query_index], - }), - ) - // We query the h(X) polynomial at x - .chain(vanishing.open(x)) - .chain( - permutations - .iter() - .zip(pk.permutations.iter()) - .map(|(p, pkey)| p.open(pk, pkey, x)) - .into_iter() - .flatten(), - ) - .chain(lookups.iter().map(|p| p.open(pk, x)).into_iter().flatten()); + }), + ) + .chain( + pk.vk + .cs + .aux_queries + .iter() + .map(|&(column, at)| ProverQuery { + point: domain.rotate_omega(*x, at), + poly: &aux_polys[column.index()], + blind: Blind::default(), + }), + ) + .chain( + pk.vk + .cs + .fixed_queries + .iter() + .map(|&(column, at)| ProverQuery { + point: domain.rotate_omega(*x, at), + poly: &pk.fixed_polys[column.index()], + blind: Blind::default(), + }), + ) + // We query the h(X) polynomial at x + .chain(vanishing.open(x)) + .chain( + permutations + .iter() + .zip(pk.permutations.iter()) + .map(|(p, pkey)| p.open(pk, pkey, x)) + .into_iter() + .flatten(), + ) + .chain(lookups.iter().map(|p| p.open(pk, x)).into_iter().flatten()); multiopen::create_proof(params, transcript, instances).map_err(|_| Error::OpeningError) } diff --git a/src/plonk/vanishing/prover.rs b/src/plonk/vanishing/prover.rs index 6f182ac..30f11d1 100644 --- a/src/plonk/vanishing/prover.rs +++ b/src/plonk/vanishing/prover.rs @@ -17,7 +17,6 @@ pub(in crate::plonk) struct Constructed { pub(in crate::plonk) struct Evaluated { constructed: Constructed, - h_evals: Vec, } impl Argument { @@ -85,10 +84,7 @@ impl Constructed { .map_err(|_| Error::TranscriptError)?; } - Ok(Evaluated { - constructed: self, - h_evals, - }) + Ok(Evaluated { constructed: self }) } } @@ -101,12 +97,10 @@ impl Evaluated { .h_pieces .iter() .zip(self.constructed.h_blinds.iter()) - .zip(self.h_evals.iter()) - .map(move |((h_poly, h_blind), h_eval)| ProverQuery { + .map(move |(h_poly, h_blind)| ProverQuery { point: *x, poly: h_poly, blind: *h_blind, - eval: *h_eval, }) } } diff --git a/src/poly/multiopen.rs b/src/poly/multiopen.rs index 4dbb198..a8880e7 100644 --- a/src/poly/multiopen.rs +++ b/src/poly/multiopen.rs @@ -3,7 +3,6 @@ //! //! [halo]: https://eprint.iacr.org/2019/1021 -use ff::Field; use std::collections::{BTreeMap, BTreeSet}; use super::*; @@ -48,8 +47,6 @@ pub struct ProverQuery<'a, C: CurveAffine> { pub poly: &'a Polynomial, /// blinding factor of polynomial pub blind: commitment::Blind, - /// evaluation of polynomial at query point - pub eval: C::Scalar, } /// A polynomial query at a point @@ -63,14 +60,14 @@ pub struct VerifierQuery<'a, C: CurveAffine> { pub eval: C::Scalar, } -struct CommitmentData { +struct CommitmentData { commitment: T, set_index: usize, point_indices: Vec, evals: Vec, } -impl CommitmentData { +impl CommitmentData { fn new(commitment: T) -> Self { CommitmentData { commitment, @@ -83,21 +80,22 @@ impl CommitmentData { trait Query: Sized { type Commitment: PartialEq + Copy; + type Eval: Clone + Default; fn get_point(&self) -> F; - fn get_eval(&self) -> F; + fn get_eval(&self) -> Self::Eval; fn get_commitment(&self) -> Self::Commitment; } fn construct_intermediate_sets>( queries: I, -) -> (Vec>, Vec>) +) -> (Vec>, Vec>) where I: IntoIterator + Clone, { // Construct sets of unique commitments and corresponding information about // their queries. - let mut commitment_map: Vec> = vec![]; + let mut commitment_map: Vec> = vec![]; // Also construct mapping from a unique point to a point_index. This defines // an ordering on the points. @@ -151,7 +149,7 @@ where // Initialise empty evals vec for each unique commitment for commitment_data in commitment_map.iter_mut() { let len = commitment_data.point_indices.len(); - commitment_data.evals = vec![F::zero(); len]; + commitment_data.evals = vec![Q::Eval::default(); len]; } // Populate set_index, evals and points for each commitment using point_idx_sets @@ -203,6 +201,134 @@ where (commitment_map, point_sets) } +#[test] +fn test_roundtrip() { + use super::commitment::{Blind, Params}; + use crate::arithmetic::{eval_polynomial, Curve, FieldExt}; + use crate::pasta::{EqAffine, Fp}; + + const K: u32 = 4; + + let params: Params = Params::new(K); + let domain = EvaluationDomain::new(1, K); + + let mut ax = domain.empty_coeff(); + for (i, a) in ax.iter_mut().enumerate() { + *a = Fp::from(10 + i as u64); + } + + let mut bx = domain.empty_coeff(); + for (i, a) in bx.iter_mut().enumerate() { + *a = Fp::from(100 + i as u64); + } + + let mut cx = domain.empty_coeff(); + for (i, a) in cx.iter_mut().enumerate() { + *a = Fp::from(100 + i as u64); + } + + let blind = Blind(Fp::rand()); + + let a = params.commit(&ax, blind).to_affine(); + let b = params.commit(&bx, blind).to_affine(); + let c = params.commit(&cx, blind).to_affine(); + + let x = Fp::rand(); + let y = Fp::rand(); + let avx = eval_polynomial(&ax, x); + let bvx = eval_polynomial(&bx, x); + let cvy = eval_polynomial(&cx, y); + + let mut transcript = crate::transcript::DummyHashWrite::init(vec![], Field::one()); + create_proof( + ¶ms, + &mut transcript, + std::iter::empty() + .chain(Some(ProverQuery { + point: x, + poly: &ax, + blind, + })) + .chain(Some(ProverQuery { + point: x, + poly: &bx, + blind, + })) + .chain(Some(ProverQuery { + point: y, + poly: &cx, + blind, + })), + ) + .unwrap(); + let proof = transcript.finalize(); + + { + let mut proof = &proof[..]; + let mut transcript = crate::transcript::DummyHashRead::init(&mut proof, Field::one()); + let msm = params.empty_msm(); + + let guard = verify_proof( + ¶ms, + &mut transcript, + std::iter::empty() + .chain(Some(VerifierQuery { + point: x, + commitment: &a, + eval: avx, + })) + .chain(Some(VerifierQuery { + point: x, + commitment: &b, + eval: avx, // NB: wrong! + })) + .chain(Some(VerifierQuery { + point: y, + commitment: &c, + eval: cvy, + })), + msm, + ) + .unwrap(); + + // Should fail. + assert!(!guard.use_challenges().eval()); + } + + { + let mut proof = &proof[..]; + + let mut transcript = crate::transcript::DummyHashRead::init(&mut proof, Field::one()); + let msm = params.empty_msm(); + + let guard = verify_proof( + ¶ms, + &mut transcript, + std::iter::empty() + .chain(Some(VerifierQuery { + point: x, + commitment: &a, + eval: avx, + })) + .chain(Some(VerifierQuery { + point: x, + commitment: &b, + eval: bvx, + })) + .chain(Some(VerifierQuery { + point: y, + commitment: &c, + eval: cvy, + })), + msm, + ) + .unwrap(); + + // Should succeed. + assert!(guard.use_challenges().eval()); + } +} + #[cfg(test)] mod tests { use super::{construct_intermediate_sets, Query}; @@ -216,14 +342,15 @@ mod tests { eval: F, } - impl Query for MyQuery { + impl Query for MyQuery { type Commitment = usize; + type Eval = F; fn get_point(&self) -> F { - self.point + self.point.clone() } - fn get_eval(&self) -> F { - self.eval + fn get_eval(&self) -> Self::Eval { + self.eval.clone() } fn get_commitment(&self) -> Self::Commitment { self.commitment diff --git a/src/poly/multiopen/prover.rs b/src/poly/multiopen/prover.rs index b9f8744..1b9faf4 100644 --- a/src/poly/multiopen/prover.rs +++ b/src/poly/multiopen/prover.rs @@ -7,9 +7,7 @@ use super::{ Query, }; -use crate::arithmetic::{ - eval_polynomial, kate_division, lagrange_interpolate, Curve, CurveAffine, FieldExt, -}; +use crate::arithmetic::{eval_polynomial, kate_division, Curve, CurveAffine, FieldExt}; use crate::transcript::TranscriptWrite; use ff::Field; @@ -43,56 +41,36 @@ where let mut q_polys: Vec>> = vec![None; point_sets.len()]; let mut q_blinds = vec![Blind(C::Scalar::zero()); point_sets.len()]; - // A vec of vecs of evals. The outer vec corresponds to the point set, - // while the inner vec corresponds to the points in a particular set. - let mut q_eval_sets = Vec::with_capacity(point_sets.len()); - for point_set in point_sets.iter() { - q_eval_sets.push(vec![C::Scalar::zero(); point_set.len()]); - } - { - let mut accumulate = |set_idx: usize, - new_poly: &Polynomial, - blind: Blind, - evals: Vec| { - if let Some(poly) = &q_polys[set_idx] { - q_polys[set_idx] = Some(poly.clone() * *x_1 + new_poly); - } else { - q_polys[set_idx] = Some(new_poly.clone()); - } - q_blinds[set_idx] *= *x_1; - q_blinds[set_idx] += blind; - // Each polynomial is evaluated at a set of points. For each set, - // we collapse each polynomial's evals pointwise. - for (eval, set_eval) in evals.iter().zip(q_eval_sets[set_idx].iter_mut()) { - *set_eval *= &(*x_1); - *set_eval += eval; - } - }; + let mut accumulate = + |set_idx: usize, new_poly: &Polynomial, blind: Blind| { + if let Some(poly) = &q_polys[set_idx] { + q_polys[set_idx] = Some(poly.clone() * *x_1 + new_poly); + } else { + q_polys[set_idx] = Some(new_poly.clone()); + } + q_blinds[set_idx] *= *x_1; + q_blinds[set_idx] += blind; + }; for commitment_data in poly_map.into_iter() { accumulate( commitment_data.set_index, // set_idx, commitment_data.commitment.poly, // poly, commitment_data.commitment.blind, // blind, - commitment_data.evals, // evals ); } } let f_poly = point_sets .iter() - .zip(q_eval_sets.iter()) .zip(q_polys.iter()) - .fold(None, |f_poly, ((points, evals), poly)| { - let mut poly = poly.clone().unwrap().values; - // TODO: makes implicit asssumption that poly degree is smaller than interpolation poly degree - for (p, r) in poly.iter_mut().zip(lagrange_interpolate(points, evals)) { - *p -= &r; - } + .fold(None, |f_poly, (points, poly)| { let mut poly = points .iter() - .fold(poly, |poly, point| kate_division(&poly, *point)); + .fold(poly.clone().unwrap().values, |poly, point| { + kate_division(&poly, *point) + }); poly.resize(params.n as usize, C::Scalar::zero()); let poly = Polynomial { values: poly, @@ -153,13 +131,12 @@ impl<'a, C: CurveAffine> PartialEq for PolynomialPointer<'a, C> { impl<'a, C: CurveAffine> Query for ProverQuery<'a, C> { type Commitment = PolynomialPointer<'a, C>; + type Eval = (); fn get_point(&self) -> C::Scalar { self.point } - fn get_eval(&self) -> C::Scalar { - self.eval - } + fn get_eval(&self) -> () {} fn get_commitment(&self) -> Self::Commitment { PolynomialPointer { poly: self.poly, diff --git a/src/poly/multiopen/verifier.rs b/src/poly/multiopen/verifier.rs index d34426a..8ab7734 100644 --- a/src/poly/multiopen/verifier.rs +++ b/src/poly/multiopen/verifier.rs @@ -133,6 +133,7 @@ impl<'a, C> PartialEq for CommitmentPointer<'a, C> { impl<'a, C: CurveAffine> Query for VerifierQuery<'a, C> { type Commitment = CommitmentPointer<'a, C>; + type Eval = C::Scalar; fn get_point(&self) -> C::Scalar { self.point