From 6cd74999ffec403a74195ea1de684bef54a38ed1 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Thu, 8 Oct 2020 00:13:06 +0800 Subject: [PATCH] Use ProverQuery and construct_intermediate_sets() in prover --- src/plonk/prover.rs | 143 ++++++++++++++++++----------------- src/poly/multiopen/prover.rs | 141 ++++++++++++++++++---------------- 2 files changed, 150 insertions(+), 134 deletions(-) diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 90e2c22..3e862d2 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -8,7 +8,8 @@ use crate::arithmetic::{ }; use crate::poly::{ commitment::{Blind, Params}, - multiopen, Coeff, LagrangeCoeff, Polynomial, Rotation, + multiopen::{self, ProverQuery}, + LagrangeCoeff, Polynomial, Rotation, }; use crate::transcript::Hasher; @@ -457,53 +458,50 @@ impl Proof { C::Base::from_bytes(&(transcript_scalar.squeeze()).to_bytes()).unwrap(); transcript.absorb(transcript_scalar_point); - let mut instances: Vec<( - usize, - Polynomial, - Blind, - C::Scalar, - )> = Vec::with_capacity( - meta.advice_queries.len() - + meta.aux_queries.len() - + meta.fixed_queries.len() - + h_pieces.len() - + permutation_product_polys.len() - + permutation_product_polys.len() - + pk.permutation_polys.len(), - ); + let mut instances: Vec> = Vec::new(); - for (query_index, &(wire, ref at)) in meta.advice_queries.iter().enumerate() { - let point_index = (*meta.rotations.get(at).unwrap()).0; - let poly = advice_polys[wire.0].clone(); - let blind = advice_blinds[wire.0]; - let eval = advice_evals[query_index]; - instances.push((point_index, poly, blind, eval)); + for (query_index, &(wire, at)) in pk.vk.cs.advice_queries.iter().enumerate() { + let point = domain.rotate_omega(x_3, at); + + instances.push(ProverQuery { + point, + poly: &advice_polys[wire.0], + blind: advice_blinds[wire.0], + eval: advice_evals[query_index], + }); } - for (query_index, &(wire, ref at)) in meta.aux_queries.iter().enumerate() { - let point_index = (*meta.rotations.get(at).unwrap()).0; - let poly = aux_polys[wire.0].clone(); - let blind = Blind::default(); - let eval = aux_evals[query_index]; - instances.push((point_index, poly, blind, eval)); + for (query_index, &(wire, at)) in pk.vk.cs.aux_queries.iter().enumerate() { + let point = domain.rotate_omega(x_3, at); + + instances.push(ProverQuery { + point, + poly: &aux_polys[wire.0], + blind: Blind::default(), + eval: aux_evals[query_index], + }); } - for (query_index, &(wire, ref at)) in meta.fixed_queries.iter().enumerate() { - let point_index = (*meta.rotations.get(at).unwrap()).0; - let poly = pk.fixed_polys[wire.0].clone(); - let blind = Blind::default(); - let eval = fixed_evals[query_index]; - instances.push((point_index, poly, blind, eval)); + for (query_index, &(wire, at)) in pk.vk.cs.fixed_queries.iter().enumerate() { + let point = domain.rotate_omega(x_3, at); + + instances.push(ProverQuery { + point, + poly: &pk.fixed_polys[wire.0], + blind: Blind::default(), + eval: fixed_evals[query_index], + }); } // We query the h(X) polynomial at x_3 - let current_index = (*meta.rotations.get(&Rotation::default()).unwrap()).0; - for ((h_poly, h_blind), h_eval) in h_pieces - .into_iter() - .zip(h_blinds.iter()) - .zip(h_evals.iter()) + for ((h_poly, h_blind), h_eval) in h_pieces.iter().zip(h_blinds.iter()).zip(h_evals.iter()) { - instances.push((current_index, h_poly.clone(), *h_blind, *h_eval)); + instances.push(ProverQuery { + point: x_3, + poly: h_poly, + blind: *h_blind, + eval: *h_eval, + }); } // Handle permutation arguments, if any exist @@ -514,7 +512,12 @@ impl Proof { .zip(permutation_product_blinds.iter()) .zip(permutation_product_evals.iter()) { - instances.push((current_index, poly.clone(), *blind, *eval)); + instances.push(ProverQuery { + point: x_3, + poly: poly, + blind: *blind, + eval: *eval, + }); } // Open permutation polynomial commitments at x_3 @@ -524,46 +527,48 @@ impl Proof { .zip(permutation_evals.iter()) .flat_map(|(polys, evals)| polys.iter().zip(evals.iter())) { - instances.push((current_index, poly.clone(), Blind::default(), *eval)); + instances.push(ProverQuery { + point: x_3, + poly: poly, + blind: Blind::default(), + eval: *eval, + }); } - let current_index = (*pk.vk.cs.rotations.get(&Rotation(-1)).unwrap()).0; + let x_3_inv = domain.rotate_omega(x_3, Rotation(-1)); // Open permutation product commitments at \omega^{-1} x_3 for ((poly, blind), eval) in permutation_product_polys .iter() .zip(permutation_product_blinds.iter()) .zip(permutation_product_inv_evals.iter()) { - instances.push((current_index, poly.clone(), *blind, *eval)); + instances.push(ProverQuery { + point: x_3_inv, + poly: poly, + blind: *blind, + eval: *eval, + }); } } - let mut points: Vec = vec![C::Scalar::zero(); meta.rotations.len()]; - for (&row, &point_index) in meta.rotations.iter() { - points[point_index.0] = domain.rotate_omega(x_3, row); + if let Ok(multiopening) = + multiopen::Proof::create(params, &mut transcript, &mut transcript_scalar, instances) + { + Ok(Proof { + advice_commitments, + h_commitments, + permutation_product_commitments, + permutation_product_evals, + permutation_product_inv_evals, + permutation_evals, + advice_evals, + fixed_evals, + aux_evals, + h_evals, + multiopening, + }) + } else { + Err(Error::OpeningError) } - - let multiopening = multiopen::Proof::create( - params, - &mut transcript, - &mut transcript_scalar, - points, - instances, - ) - .unwrap(); - - Ok(Proof { - advice_commitments, - h_commitments, - permutation_product_commitments, - permutation_product_evals, - permutation_product_inv_evals, - permutation_evals, - advice_evals, - fixed_evals, - aux_evals, - h_evals, - multiopening, - }) } } diff --git a/src/poly/multiopen/prover.rs b/src/poly/multiopen/prover.rs index 803a727..42060dc 100644 --- a/src/poly/multiopen/prover.rs +++ b/src/poly/multiopen/prover.rs @@ -1,5 +1,3 @@ -use std::marker::PhantomData; - use super::super::{ commitment::{self, Blind, Params}, Coeff, Error, Polynomial, @@ -7,12 +5,13 @@ use super::super::{ use super::{Proof, ProverQuery}; use crate::arithmetic::{ - eval_polynomial, get_challenge_scalar, kate_division, parallelize, Challenge, Curve, - CurveAffine, Field, + eval_polynomial, get_challenge_scalar, interpolate, kate_division, parallelize, Challenge, + Curve, CurveAffine, Field, }; use crate::plonk::hash_point; use crate::transcript::Hasher; use std::collections::{BTreeMap, BTreeSet}; +use std::marker::PhantomData; #[derive(Debug, Clone)] struct CommitmentData { @@ -24,88 +23,101 @@ struct CommitmentData { impl Proof { /// Create a multi-opening proof - pub fn create, HScalar: Hasher>( + pub fn create<'a, I, HBase: Hasher, HScalar: Hasher>( params: &Params, transcript: &mut HBase, transcript_scalar: &mut HScalar, - points: Vec, - instances: I, + queries: I, ) -> Result where - I: IntoIterator< - Item = ( - usize, - Polynomial, - Blind, - C::Scalar, - ), - > + Clone, + I: IntoIterator> + Clone, { let x_4: C::Scalar = get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128())); - // Collapse openings at same points together into single openings using - // x_4 challenge. - let mut q_polys: Vec>> = vec![None; points.len()]; - let mut q_blinds = vec![Blind(C::Scalar::zero()); points.len()]; - let mut q_evals: Vec<_> = vec![C::Scalar::zero(); points.len()]; - { - let mut accumulate = - |point_index: usize, new_poly: Polynomial, blind, eval| { - q_polys[point_index] - .as_mut() - .map(|poly| { - parallelize(poly, |q, start| { - for (q, a) in q.iter_mut().zip(new_poly[start..].iter()) { - *q *= &x_4; - *q += a; - } - }); - }) - .or_else(|| { - q_polys[point_index] = Some(new_poly.clone()); - Some(()) - }); - q_blinds[point_index] *= x_4; - q_blinds[point_index] += blind; - q_evals[point_index] *= &x_4; - q_evals[point_index] += &eval; - }; + let (poly_map, point_sets) = construct_intermediate_sets::<'a, C, I>(queries); - for instance in instances.clone() { + // Collapse openings at same point sets together into single openings using + // x_4 challenge. + let mut q_polys: Vec>> = vec![None; point_sets.len()]; + let mut q_blinds = vec![Blind(C::Scalar::zero()); point_sets.len()]; + let mut q_eval_sets: Vec> = vec![Vec::new(); point_sets.len()]; + for (set_idx, point_set) in point_sets.iter().enumerate() { + q_eval_sets[set_idx] = vec![C::Scalar::zero(); point_set.len()]; + } + + { + let mut accumulate = |set_idx: usize, + new_poly: &Polynomial, + blind: Blind, + evals: Vec| { + q_polys[set_idx] + .as_mut() + .map(|poly| { + parallelize(poly, |q, start| { + for (q, a) in q.iter_mut().zip(new_poly[start..].iter()) { + *q *= &x_4; + *q += a; + } + }); + }) + .or_else(|| { + q_polys[set_idx] = Some(new_poly.clone()); + Some(()) + }); + q_blinds[set_idx] *= x_4; + q_blinds[set_idx] += blind; + for (eval_idx, &eval) in evals.iter().enumerate() { + q_eval_sets[set_idx][eval_idx] *= &x_4; + q_eval_sets[set_idx][eval_idx] += &eval; + } + }; + + for (poly, commitment_data) in poly_map { accumulate( - instance.0, // point_index, - instance.1, // poly, - instance.2, // blind, - instance.3, // eval + commitment_data.set_index, // set_idx, + &poly, // poly, + commitment_data.blind, // blind, + commitment_data.evals.to_vec(), // evals ); } } let x_5: C::Scalar = get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128())); + // Interpolate polynomial for evaluations at each set + let mut r_polys: Vec> = Vec::with_capacity(point_sets.len()); + for (points, evals) in point_sets.iter().zip(q_eval_sets.iter()) { + r_polys.push(interpolate(points.clone(), evals.clone())); + } + let mut f_poly: Option> = None; - for (point_index, &point) in points.iter().enumerate() { - let mut poly = q_polys[point_index].as_ref().unwrap().clone(); - poly[0] -= &q_evals[point_index]; + for (set_idx, point_set) in point_sets.clone().iter().enumerate() { + let mut poly = q_polys[set_idx].as_ref().unwrap().clone(); + for (coeff_idx, coeff) in r_polys[set_idx].iter().enumerate() { + poly[coeff_idx] -= coeff; + } // TODO: change kate_division interface? - let mut poly = kate_division(&poly[..], point); - poly.push(C::Scalar::zero()); - let poly = Polynomial { - values: poly, - _marker: PhantomData, - }; + let mut tmp_poly = poly.clone(); + for point in point_set { + let mut poly = kate_division(&tmp_poly[..], *point); + poly.push(C::Scalar::zero()); + tmp_poly = Polynomial { + values: poly, + _marker: PhantomData, + }; + } f_poly = f_poly .map(|mut f_poly| { parallelize(&mut f_poly, |q, start| { - for (q, a) in q.iter_mut().zip(poly[start..].iter()) { + for (q, a) in q.iter_mut().zip(tmp_poly[start..].iter()) { *q *= &x_5; *q += a; } }); f_poly }) - .or_else(|| Some(poly)); + .or_else(|| Some(tmp_poly)); } let f_poly = f_poly.unwrap(); @@ -120,11 +132,10 @@ impl Proof { let x_6: C::Scalar = get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128())); - let mut q_evals = vec![C::Scalar::zero(); points.len()]; + let mut q_evals = vec![C::Scalar::zero(); point_sets.len()]; - for (point_index, _) in points.iter().enumerate() { - q_evals[point_index] = - eval_polynomial(&q_polys[point_index].as_ref().unwrap(), x_6); + for (set_idx, _) in point_sets.iter().enumerate() { + q_evals[set_idx] = eval_polynomial(&q_polys[set_idx].as_ref().unwrap(), x_6); } for eval in q_evals.iter() { @@ -140,14 +151,14 @@ impl Proof { let mut f_blind_dup = f_blind; let mut f_poly = f_poly.clone(); - for (point_index, _) in points.iter().enumerate() { + for (set_idx, _) in point_sets.iter().enumerate() { f_blind_dup *= x_7; - f_blind_dup += q_blinds[point_index]; + f_blind_dup += q_blinds[set_idx]; parallelize(&mut f_poly, |f, start| { for (f, a) in f .iter_mut() - .zip(q_polys[point_index].as_ref().unwrap()[start..].iter()) + .zip(q_polys[set_idx].as_ref().unwrap()[start..].iter()) { *f *= &x_7; *f += a;