mirror of
https://github.com/saymrwulf/pasta_curves-source.git
synced 2026-09-06 20:20:34 +00:00
Use ProverQuery and construct_intermediate_sets() in prover
This commit is contained in:
parent
9378d0cc70
commit
6cd74999ff
2 changed files with 150 additions and 134 deletions
|
|
@ -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,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue