Use ProverQuery and construct_intermediate_sets() in prover

This commit is contained in:
therealyingtong 2020-10-08 00:13:06 +08:00
parent 9378d0cc70
commit 6cd74999ff
2 changed files with 150 additions and 134 deletions

View file

@ -8,7 +8,8 @@ use crate::arithmetic::{
}; };
use crate::poly::{ use crate::poly::{
commitment::{Blind, Params}, commitment::{Blind, Params},
multiopen, Coeff, LagrangeCoeff, Polynomial, Rotation, multiopen::{self, ProverQuery},
LagrangeCoeff, Polynomial, Rotation,
}; };
use crate::transcript::Hasher; use crate::transcript::Hasher;
@ -457,53 +458,50 @@ impl<C: CurveAffine> Proof<C> {
C::Base::from_bytes(&(transcript_scalar.squeeze()).to_bytes()).unwrap(); C::Base::from_bytes(&(transcript_scalar.squeeze()).to_bytes()).unwrap();
transcript.absorb(transcript_scalar_point); transcript.absorb(transcript_scalar_point);
let mut instances: Vec<( let mut instances: Vec<ProverQuery<C>> = Vec::new();
usize,
Polynomial<C::Scalar, Coeff>,
Blind<C::Scalar>,
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(),
);
for (query_index, &(wire, ref at)) in meta.advice_queries.iter().enumerate() { for (query_index, &(wire, at)) in pk.vk.cs.advice_queries.iter().enumerate() {
let point_index = (*meta.rotations.get(at).unwrap()).0; let point = domain.rotate_omega(x_3, at);
let poly = advice_polys[wire.0].clone();
let blind = advice_blinds[wire.0]; instances.push(ProverQuery {
let eval = advice_evals[query_index]; point,
instances.push((point_index, poly, blind, eval)); 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() { for (query_index, &(wire, at)) in pk.vk.cs.aux_queries.iter().enumerate() {
let point_index = (*meta.rotations.get(at).unwrap()).0; let point = domain.rotate_omega(x_3, at);
let poly = aux_polys[wire.0].clone();
let blind = Blind::default(); instances.push(ProverQuery {
let eval = aux_evals[query_index]; point,
instances.push((point_index, poly, blind, eval)); 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() { for (query_index, &(wire, at)) in pk.vk.cs.fixed_queries.iter().enumerate() {
let point_index = (*meta.rotations.get(at).unwrap()).0; let point = domain.rotate_omega(x_3, at);
let poly = pk.fixed_polys[wire.0].clone();
let blind = Blind::default(); instances.push(ProverQuery {
let eval = fixed_evals[query_index]; point,
instances.push((point_index, poly, blind, eval)); poly: &pk.fixed_polys[wire.0],
blind: Blind::default(),
eval: fixed_evals[query_index],
});
} }
// We query the h(X) polynomial at x_3 // 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.iter().zip(h_blinds.iter()).zip(h_evals.iter())
for ((h_poly, h_blind), h_eval) in h_pieces
.into_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 // Handle permutation arguments, if any exist
@ -514,7 +512,12 @@ impl<C: CurveAffine> Proof<C> {
.zip(permutation_product_blinds.iter()) .zip(permutation_product_blinds.iter())
.zip(permutation_product_evals.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 // Open permutation polynomial commitments at x_3
@ -524,46 +527,48 @@ impl<C: CurveAffine> Proof<C> {
.zip(permutation_evals.iter()) .zip(permutation_evals.iter())
.flat_map(|(polys, evals)| polys.iter().zip(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 // Open permutation product commitments at \omega^{-1} x_3
for ((poly, blind), eval) in permutation_product_polys for ((poly, blind), eval) in permutation_product_polys
.iter() .iter()
.zip(permutation_product_blinds.iter()) .zip(permutation_product_blinds.iter())
.zip(permutation_product_inv_evals.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<C::Scalar> = vec![C::Scalar::zero(); meta.rotations.len()]; if let Ok(multiopening) =
for (&row, &point_index) in meta.rotations.iter() { multiopen::Proof::create(params, &mut transcript, &mut transcript_scalar, instances)
points[point_index.0] = domain.rotate_omega(x_3, row); {
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,
})
} }
} }

View file

@ -1,5 +1,3 @@
use std::marker::PhantomData;
use super::super::{ use super::super::{
commitment::{self, Blind, Params}, commitment::{self, Blind, Params},
Coeff, Error, Polynomial, Coeff, Error, Polynomial,
@ -7,12 +5,13 @@ use super::super::{
use super::{Proof, ProverQuery}; use super::{Proof, ProverQuery};
use crate::arithmetic::{ use crate::arithmetic::{
eval_polynomial, get_challenge_scalar, kate_division, parallelize, Challenge, Curve, eval_polynomial, get_challenge_scalar, interpolate, kate_division, parallelize, Challenge,
CurveAffine, Field, Curve, CurveAffine, Field,
}; };
use crate::plonk::hash_point; use crate::plonk::hash_point;
use crate::transcript::Hasher; use crate::transcript::Hasher;
use std::collections::{BTreeMap, BTreeSet}; use std::collections::{BTreeMap, BTreeSet};
use std::marker::PhantomData;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct CommitmentData<C: CurveAffine> { struct CommitmentData<C: CurveAffine> {
@ -24,88 +23,101 @@ struct CommitmentData<C: CurveAffine> {
impl<C: CurveAffine> Proof<C> { impl<C: CurveAffine> Proof<C> {
/// Create a multi-opening proof /// Create a multi-opening proof
pub fn create<I, HBase: Hasher<C::Base>, HScalar: Hasher<C::Scalar>>( pub fn create<'a, I, HBase: Hasher<C::Base>, HScalar: Hasher<C::Scalar>>(
params: &Params<C>, params: &Params<C>,
transcript: &mut HBase, transcript: &mut HBase,
transcript_scalar: &mut HScalar, transcript_scalar: &mut HScalar,
points: Vec<C::Scalar>, queries: I,
instances: I,
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
I: IntoIterator< I: IntoIterator<Item = ProverQuery<'a, C>> + Clone,
Item = (
usize,
Polynomial<C::Scalar, Coeff>,
Blind<C::Scalar>,
C::Scalar,
),
> + Clone,
{ {
let x_4: C::Scalar = get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128())); let x_4: C::Scalar = get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128()));
// Collapse openings at same points together into single openings using let (poly_map, point_sets) = construct_intermediate_sets::<'a, C, I>(queries);
// x_4 challenge.
let mut q_polys: Vec<Option<Polynomial<C::Scalar, Coeff>>> = 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<C::Scalar, Coeff>, 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;
};
for instance in instances.clone() { // Collapse openings at same point sets together into single openings using
// x_4 challenge.
let mut q_polys: Vec<Option<Polynomial<C::Scalar, Coeff>>> = 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![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<C::Scalar, Coeff>,
blind: Blind<C::Scalar>,
evals: Vec<C::Scalar>| {
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( accumulate(
instance.0, // point_index, commitment_data.set_index, // set_idx,
instance.1, // poly, &poly, // poly,
instance.2, // blind, commitment_data.blind, // blind,
instance.3, // eval commitment_data.evals.to_vec(), // evals
); );
} }
} }
let x_5: C::Scalar = get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128())); 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<C::Scalar>> = 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<Polynomial<C::Scalar, Coeff>> = None; let mut f_poly: Option<Polynomial<C::Scalar, Coeff>> = None;
for (point_index, &point) in points.iter().enumerate() { for (set_idx, point_set) in point_sets.clone().iter().enumerate() {
let mut poly = q_polys[point_index].as_ref().unwrap().clone(); let mut poly = q_polys[set_idx].as_ref().unwrap().clone();
poly[0] -= &q_evals[point_index]; for (coeff_idx, coeff) in r_polys[set_idx].iter().enumerate() {
poly[coeff_idx] -= coeff;
}
// TODO: change kate_division interface? // TODO: change kate_division interface?
let mut poly = kate_division(&poly[..], point); let mut tmp_poly = poly.clone();
poly.push(C::Scalar::zero()); for point in point_set {
let poly = Polynomial { let mut poly = kate_division(&tmp_poly[..], *point);
values: poly, poly.push(C::Scalar::zero());
_marker: PhantomData, tmp_poly = Polynomial {
}; values: poly,
_marker: PhantomData,
};
}
f_poly = f_poly f_poly = f_poly
.map(|mut f_poly| { .map(|mut f_poly| {
parallelize(&mut f_poly, |q, start| { 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 *= &x_5;
*q += a; *q += a;
} }
}); });
f_poly f_poly
}) })
.or_else(|| Some(poly)); .or_else(|| Some(tmp_poly));
} }
let f_poly = f_poly.unwrap(); let f_poly = f_poly.unwrap();
@ -120,11 +132,10 @@ impl<C: CurveAffine> Proof<C> {
let x_6: C::Scalar = let x_6: C::Scalar =
get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128())); 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() { for (set_idx, _) in point_sets.iter().enumerate() {
q_evals[point_index] = q_evals[set_idx] = eval_polynomial(&q_polys[set_idx].as_ref().unwrap(), x_6);
eval_polynomial(&q_polys[point_index].as_ref().unwrap(), x_6);
} }
for eval in q_evals.iter() { for eval in q_evals.iter() {
@ -140,14 +151,14 @@ impl<C: CurveAffine> Proof<C> {
let mut f_blind_dup = f_blind; let mut f_blind_dup = f_blind;
let mut f_poly = f_poly.clone(); 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 *= x_7;
f_blind_dup += q_blinds[point_index]; f_blind_dup += q_blinds[set_idx];
parallelize(&mut f_poly, |f, start| { parallelize(&mut f_poly, |f, start| {
for (f, a) in f for (f, a) in f
.iter_mut() .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 *= &x_7;
*f += a; *f += a;