mirror of
https://github.com/saymrwulf/pasta_curves-source.git
synced 2026-09-06 20:20:34 +00:00
Refactor PLONK prover
This commit is contained in:
parent
5f89227cdd
commit
02b5b8442b
4 changed files with 430 additions and 256 deletions
|
|
@ -158,7 +158,7 @@ pub trait Assignment<F: Field> {
|
||||||
/// [`ConstraintSystem`] implementation.
|
/// [`ConstraintSystem`] implementation.
|
||||||
pub trait Circuit<F: Field> {
|
pub trait Circuit<F: Field> {
|
||||||
/// This is a configuration object that stores things like columns.
|
/// This is a configuration object that stores things like columns.
|
||||||
type Config;
|
type Config: Copy;
|
||||||
|
|
||||||
/// The circuit is given an opportunity to describe the exact gate
|
/// The circuit is given an opportunity to describe the exact gate
|
||||||
/// arrangement, column arrangement, etc.
|
/// arrangement, column arrangement, etc.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use super::circuit::{Any, Column};
|
use super::circuit::{Any, Column};
|
||||||
|
|
||||||
mod prover;
|
pub(crate) mod prover;
|
||||||
mod verifier;
|
pub(crate) mod verifier;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct Argument {
|
pub(crate) struct Argument {
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) mod keygen;
|
pub(crate) mod keygen;
|
||||||
mod prover;
|
pub(crate) mod prover;
|
||||||
mod verifier;
|
pub(crate) mod verifier;
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,14 @@ use std::iter;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
circuit::{Advice, Assignment, Circuit, Column, ConstraintSystem, Fixed},
|
circuit::{Advice, Assignment, Circuit, Column, ConstraintSystem, Fixed},
|
||||||
vanishing, ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX, ChallengeY, Error,
|
lookup, permutation, vanishing, ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX,
|
||||||
ProvingKey,
|
ChallengeY, Error, ProvingKey,
|
||||||
};
|
};
|
||||||
use crate::arithmetic::{eval_polynomial, Curve, CurveAffine, FieldExt};
|
use crate::arithmetic::{eval_polynomial, Curve, CurveAffine, FieldExt};
|
||||||
use crate::poly::{
|
use crate::poly::{
|
||||||
commitment::{Blind, Params},
|
commitment::{Blind, Params},
|
||||||
multiopen::{self, ProverQuery},
|
multiopen::{self, ProverQuery},
|
||||||
LagrangeCoeff, Polynomial,
|
Coeff, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial,
|
||||||
};
|
};
|
||||||
use crate::transcript::TranscriptWrite;
|
use crate::transcript::TranscriptWrite;
|
||||||
|
|
||||||
|
|
@ -20,50 +20,13 @@ use crate::transcript::TranscriptWrite;
|
||||||
pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circuit<C::Scalar>>(
|
pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circuit<C::Scalar>>(
|
||||||
params: &Params<C>,
|
params: &Params<C>,
|
||||||
pk: &ProvingKey<C>,
|
pk: &ProvingKey<C>,
|
||||||
circuit: &ConcreteCircuit,
|
circuits: &[ConcreteCircuit],
|
||||||
aux: &[Polynomial<C::Scalar, LagrangeCoeff>],
|
auxs: &[&[Polynomial<C::Scalar, LagrangeCoeff>]],
|
||||||
transcript: &mut T,
|
transcript: &mut T,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if aux.len() != pk.vk.cs.num_aux_columns {
|
for aux in auxs.iter() {
|
||||||
return Err(Error::IncompatibleParams);
|
if aux.len() != pk.vk.cs.num_aux_columns {
|
||||||
}
|
return Err(Error::IncompatibleParams);
|
||||||
|
|
||||||
struct WitnessCollection<F: Field> {
|
|
||||||
advice: Vec<Polynomial<F, LagrangeCoeff>>,
|
|
||||||
_marker: std::marker::PhantomData<F>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F: Field> Assignment<F> for WitnessCollection<F> {
|
|
||||||
fn assign_advice(
|
|
||||||
&mut self,
|
|
||||||
column: Column<Advice>,
|
|
||||||
row: usize,
|
|
||||||
to: impl FnOnce() -> Result<F, Error>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
*self
|
|
||||||
.advice
|
|
||||||
.get_mut(column.index())
|
|
||||||
.and_then(|v| v.get_mut(row))
|
|
||||||
.ok_or(Error::BoundsFailure)? = to()?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assign_fixed(
|
|
||||||
&mut self,
|
|
||||||
_: Column<Fixed>,
|
|
||||||
_: usize,
|
|
||||||
_: impl FnOnce() -> Result<F, Error>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
// We only care about advice columns here
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn copy(&mut self, _: usize, _: usize, _: usize, _: usize, _: usize) -> Result<(), Error> {
|
|
||||||
// We only care about advice columns here
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,115 +34,218 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
|
||||||
let mut meta = ConstraintSystem::default();
|
let mut meta = ConstraintSystem::default();
|
||||||
let config = ConcreteCircuit::configure(&mut meta);
|
let config = ConcreteCircuit::configure(&mut meta);
|
||||||
|
|
||||||
let mut witness = WitnessCollection {
|
struct AuxSingle<C: CurveAffine> {
|
||||||
advice: vec![domain.empty_lagrange(); meta.num_advice_columns],
|
pub aux_values: Vec<Polynomial<C::Scalar, LagrangeCoeff>>,
|
||||||
_marker: std::marker::PhantomData,
|
pub aux_polys: Vec<Polynomial<C::Scalar, Coeff>>,
|
||||||
|
pub aux_cosets: Vec<Polynomial<C::Scalar, ExtendedLagrangeCoeff>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let aux_vec: Result<Vec<_>, _> = auxs
|
||||||
|
.iter()
|
||||||
|
.map(|aux| -> Result<AuxSingle<C>, Error> {
|
||||||
|
let aux_commitments_projective: Vec<_> = aux
|
||||||
|
.iter()
|
||||||
|
.map(|poly| params.commit_lagrange(poly, Blind::default()))
|
||||||
|
.collect();
|
||||||
|
let mut aux_commitments = vec![C::zero(); aux_commitments_projective.len()];
|
||||||
|
C::Projective::batch_to_affine(&aux_commitments_projective, &mut aux_commitments);
|
||||||
|
let aux_commitments = aux_commitments;
|
||||||
|
drop(aux_commitments_projective);
|
||||||
|
metrics::counter!("aux_commitments", aux_commitments.len() as u64);
|
||||||
|
|
||||||
|
for commitment in &aux_commitments {
|
||||||
|
transcript
|
||||||
|
.common_point(*commitment)
|
||||||
|
.map_err(|_| Error::TranscriptError)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let aux_polys: Vec<_> = aux
|
||||||
|
.iter()
|
||||||
|
.map(|poly| {
|
||||||
|
let lagrange_vec = domain.lagrange_from_vec(poly.to_vec());
|
||||||
|
domain.lagrange_to_coeff(lagrange_vec)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let aux_cosets: Vec<_> = meta
|
||||||
|
.aux_queries
|
||||||
|
.iter()
|
||||||
|
.map(|&(column, at)| {
|
||||||
|
let poly = aux_polys[column.index()].clone();
|
||||||
|
domain.coeff_to_extended(poly, at)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(AuxSingle {
|
||||||
|
aux_values: aux.to_vec(),
|
||||||
|
aux_polys,
|
||||||
|
aux_cosets,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let aux_vec = match aux_vec {
|
||||||
|
Ok(aux_vec) => aux_vec,
|
||||||
|
Err(err) => return Err(err),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Synthesize the circuit to obtain the witness and other information.
|
struct AdviceSingle<C: CurveAffine> {
|
||||||
circuit.synthesize(&mut witness, config)?;
|
pub advice_values: Vec<Polynomial<C::Scalar, LagrangeCoeff>>,
|
||||||
|
pub advice_polys: Vec<Polynomial<C::Scalar, Coeff>>,
|
||||||
let witness = witness;
|
pub advice_cosets: Vec<Polynomial<C::Scalar, ExtendedLagrangeCoeff>>,
|
||||||
|
pub advice_blinds: Vec<Blind<C::Scalar>>,
|
||||||
// Compute commitments to aux column polynomials
|
|
||||||
let aux_commitments_projective: Vec<_> = aux
|
|
||||||
.iter()
|
|
||||||
.map(|poly| params.commit_lagrange(poly, Blind::default()))
|
|
||||||
.collect();
|
|
||||||
let mut aux_commitments = vec![C::zero(); aux_commitments_projective.len()];
|
|
||||||
C::Projective::batch_to_affine(&aux_commitments_projective, &mut aux_commitments);
|
|
||||||
let aux_commitments = aux_commitments;
|
|
||||||
drop(aux_commitments_projective);
|
|
||||||
metrics::counter!("aux_commitments", aux_commitments.len() as u64);
|
|
||||||
|
|
||||||
for commitment in &aux_commitments {
|
|
||||||
transcript
|
|
||||||
.common_point(*commitment)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let aux_polys: Vec<_> = aux
|
let advice_vec: Result<Vec<_>, _> = circuits
|
||||||
.iter()
|
.iter()
|
||||||
.map(|poly| {
|
.map(|circuit| -> Result<AdviceSingle<C>, Error> {
|
||||||
let lagrange_vec = domain.lagrange_from_vec(poly.to_vec());
|
struct WitnessCollection<F: Field> {
|
||||||
domain.lagrange_to_coeff(lagrange_vec)
|
pub advice: Vec<Polynomial<F, LagrangeCoeff>>,
|
||||||
|
_marker: std::marker::PhantomData<F>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: Field> Assignment<F> for WitnessCollection<F> {
|
||||||
|
fn assign_advice(
|
||||||
|
&mut self,
|
||||||
|
column: Column<Advice>,
|
||||||
|
row: usize,
|
||||||
|
to: impl FnOnce() -> Result<F, Error>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
*self
|
||||||
|
.advice
|
||||||
|
.get_mut(column.index())
|
||||||
|
.and_then(|v| v.get_mut(row))
|
||||||
|
.ok_or(Error::BoundsFailure)? = to()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assign_fixed(
|
||||||
|
&mut self,
|
||||||
|
_: Column<Fixed>,
|
||||||
|
_: usize,
|
||||||
|
_: impl FnOnce() -> Result<F, Error>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
// We only care about advice columns here
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn copy(
|
||||||
|
&mut self,
|
||||||
|
_: usize,
|
||||||
|
_: usize,
|
||||||
|
_: usize,
|
||||||
|
_: usize,
|
||||||
|
_: usize,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
// We only care about advice columns here
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut witness = WitnessCollection {
|
||||||
|
advice: vec![domain.empty_lagrange(); meta.num_advice_columns],
|
||||||
|
_marker: std::marker::PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Synthesize the circuit to obtain the witness and other information.
|
||||||
|
circuit.synthesize(&mut witness, config)?;
|
||||||
|
|
||||||
|
let witness = witness;
|
||||||
|
|
||||||
|
// Compute commitments to advice column polynomials
|
||||||
|
let advice_blinds: Vec<_> = witness
|
||||||
|
.advice
|
||||||
|
.iter()
|
||||||
|
.map(|_| Blind(C::Scalar::rand()))
|
||||||
|
.collect();
|
||||||
|
let advice_commitments_projective: Vec<_> = witness
|
||||||
|
.advice
|
||||||
|
.iter()
|
||||||
|
.zip(advice_blinds.iter())
|
||||||
|
.map(|(poly, blind)| params.commit_lagrange(poly, *blind))
|
||||||
|
.collect();
|
||||||
|
let mut advice_commitments = vec![C::zero(); advice_commitments_projective.len()];
|
||||||
|
C::Projective::batch_to_affine(&advice_commitments_projective, &mut advice_commitments);
|
||||||
|
let advice_commitments = advice_commitments;
|
||||||
|
drop(advice_commitments_projective);
|
||||||
|
metrics::counter!("advice_commitments", advice_commitments.len() as u64);
|
||||||
|
|
||||||
|
for commitment in &advice_commitments {
|
||||||
|
transcript
|
||||||
|
.write_point(*commitment)
|
||||||
|
.map_err(|_| Error::TranscriptError)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let advice_polys: Vec<_> = witness
|
||||||
|
.advice
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(|poly| domain.lagrange_to_coeff(poly))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let advice_cosets: Vec<_> = meta
|
||||||
|
.advice_queries
|
||||||
|
.iter()
|
||||||
|
.map(|&(column, at)| {
|
||||||
|
let poly = advice_polys[column.index()].clone();
|
||||||
|
domain.coeff_to_extended(poly, at)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(AdviceSingle {
|
||||||
|
advice_values: witness.advice,
|
||||||
|
advice_polys,
|
||||||
|
advice_cosets,
|
||||||
|
advice_blinds,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let aux_cosets: Vec<_> = meta
|
let advice_vec = match advice_vec {
|
||||||
.aux_queries
|
Ok(advice_vec) => advice_vec,
|
||||||
.iter()
|
Err(err) => return Err(err),
|
||||||
.map(|&(column, at)| {
|
};
|
||||||
let poly = aux_polys[column.index()].clone();
|
|
||||||
domain.coeff_to_extended(poly, at)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Compute commitments to advice column polynomials
|
|
||||||
let advice_blinds: Vec<_> = witness
|
|
||||||
.advice
|
|
||||||
.iter()
|
|
||||||
.map(|_| Blind(C::Scalar::rand()))
|
|
||||||
.collect();
|
|
||||||
let advice_commitments_projective: Vec<_> = witness
|
|
||||||
.advice
|
|
||||||
.iter()
|
|
||||||
.zip(advice_blinds.iter())
|
|
||||||
.map(|(poly, blind)| params.commit_lagrange(poly, *blind))
|
|
||||||
.collect();
|
|
||||||
let mut advice_commitments = vec![C::zero(); advice_commitments_projective.len()];
|
|
||||||
C::Projective::batch_to_affine(&advice_commitments_projective, &mut advice_commitments);
|
|
||||||
let advice_commitments = advice_commitments;
|
|
||||||
drop(advice_commitments_projective);
|
|
||||||
metrics::counter!("advice_commitments", advice_commitments.len() as u64);
|
|
||||||
|
|
||||||
for commitment in &advice_commitments {
|
|
||||||
transcript
|
|
||||||
.write_point(*commitment)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let advice_polys: Vec<_> = witness
|
|
||||||
.advice
|
|
||||||
.clone()
|
|
||||||
.into_iter()
|
|
||||||
.map(|poly| domain.lagrange_to_coeff(poly))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let advice_cosets: Vec<_> = meta
|
|
||||||
.advice_queries
|
|
||||||
.iter()
|
|
||||||
.map(|&(column, at)| {
|
|
||||||
let poly = advice_polys[column.index()].clone();
|
|
||||||
domain.coeff_to_extended(poly, at)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Sample theta challenge for keeping lookup columns linearly independent
|
// Sample theta challenge for keeping lookup columns linearly independent
|
||||||
let theta = ChallengeTheta::get(transcript);
|
let theta = ChallengeTheta::get(transcript);
|
||||||
|
|
||||||
// Construct and commit to permuted values for each lookup
|
let lookups_vec: Result<Vec<Vec<_>>, _> = aux_vec
|
||||||
let lookups = pk
|
|
||||||
.vk
|
|
||||||
.cs
|
|
||||||
.lookups
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|lookup| {
|
.zip(advice_vec.iter())
|
||||||
lookup.commit_permuted(
|
.map(
|
||||||
&pk,
|
|(aux, advice)| -> Result<Vec<lookup::prover::Permuted<'_, C>>, Error> {
|
||||||
¶ms,
|
// Construct and commit to permuted values for each lookup
|
||||||
&domain,
|
pk.vk
|
||||||
theta,
|
.cs
|
||||||
&witness.advice,
|
.lookups
|
||||||
&pk.fixed_values,
|
.iter()
|
||||||
&aux,
|
.map(|lookup| {
|
||||||
&advice_cosets,
|
lookup.commit_permuted(
|
||||||
&pk.fixed_cosets,
|
&pk,
|
||||||
&aux_cosets,
|
¶ms,
|
||||||
transcript,
|
&domain,
|
||||||
)
|
theta,
|
||||||
})
|
&advice.advice_values,
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
&pk.fixed_values,
|
||||||
|
&aux.aux_values,
|
||||||
|
&advice.advice_cosets,
|
||||||
|
&pk.fixed_cosets,
|
||||||
|
&aux.aux_cosets,
|
||||||
|
transcript,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let lookups_vec = match lookups_vec {
|
||||||
|
Ok(lookups_vec) => lookups_vec,
|
||||||
|
Err(err) => return Err(err),
|
||||||
|
};
|
||||||
|
|
||||||
// Sample beta challenge
|
// Sample beta challenge
|
||||||
let beta = ChallengeBeta::get(transcript);
|
let beta = ChallengeBeta::get(transcript);
|
||||||
|
|
@ -187,89 +253,166 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
|
||||||
// Sample gamma challenge
|
// Sample gamma challenge
|
||||||
let gamma = ChallengeGamma::get(transcript);
|
let gamma = ChallengeGamma::get(transcript);
|
||||||
|
|
||||||
// Commit to permutations, if any.
|
let permutations_vec: Result<Vec<Vec<_>>, _> = advice_vec
|
||||||
let permutations = pk
|
|
||||||
.vk
|
|
||||||
.cs
|
|
||||||
.permutations
|
|
||||||
.iter()
|
.iter()
|
||||||
.zip(pk.permutations.iter())
|
.map(
|
||||||
.map(|(p, pkey)| p.commit(params, pk, pkey, &witness.advice, beta, gamma, transcript))
|
|advice| -> Result<Vec<permutation::prover::Committed<C>>, Error> {
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
// Commit to permutations, if any.
|
||||||
|
pk.vk
|
||||||
|
.cs
|
||||||
|
.permutations
|
||||||
|
.iter()
|
||||||
|
.zip(pk.permutations.iter())
|
||||||
|
.map(|(p, pkey)| {
|
||||||
|
p.commit(
|
||||||
|
params,
|
||||||
|
pk,
|
||||||
|
pkey,
|
||||||
|
&advice.advice_values,
|
||||||
|
beta,
|
||||||
|
gamma,
|
||||||
|
transcript,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.collect();
|
||||||
|
|
||||||
// Construct and commit to products for each lookup
|
let permutations_vec = match permutations_vec {
|
||||||
let lookups = lookups
|
Ok(permutations_vec) => permutations_vec,
|
||||||
|
Err(err) => return Err(err),
|
||||||
|
};
|
||||||
|
|
||||||
|
let lookups_vec: Result<Vec<Vec<lookup::prover::Committed<'_, C>>>, _> = lookups_vec
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|lookup| lookup.commit_product(&pk, ¶ms, theta, beta, gamma, transcript))
|
.map(|lookups| -> Result<Vec<_>, _> {
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
// Construct and commit to products for each lookup
|
||||||
|
lookups
|
||||||
|
.into_iter()
|
||||||
|
.map(|lookup| lookup.commit_product(&pk, ¶ms, theta, beta, gamma, transcript))
|
||||||
|
.collect::<Result<Vec<_>, _>>()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let lookups_vec = match lookups_vec {
|
||||||
|
Ok(lookups_vec) => lookups_vec,
|
||||||
|
Err(err) => return Err(err),
|
||||||
|
};
|
||||||
|
|
||||||
// Obtain challenge for keeping all separate gates linearly independent
|
// Obtain challenge for keeping all separate gates linearly independent
|
||||||
let y = ChallengeY::get(transcript);
|
let y = ChallengeY::get(transcript);
|
||||||
|
|
||||||
// Evaluate the h(X) polynomial's constraint system expressions for the permutation constraints, if any.
|
let (permutations_vec, permutation_expressions_vec): (Vec<Vec<_>>, Vec<Vec<_>>) =
|
||||||
let (permutations, permutation_expressions): (Vec<_>, Vec<_>) = {
|
permutations_vec
|
||||||
let tmp: Vec<_> = permutations
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(pk.vk.cs.permutations.iter())
|
.zip(advice_vec.iter())
|
||||||
.zip(pk.permutations.iter())
|
.map(|(permutations, advice)| {
|
||||||
.map(|((p, argument), pkey)| {
|
let tmp: Vec<_> = permutations
|
||||||
p.construct(pk, argument, pkey, &advice_cosets, beta, gamma)
|
.into_iter()
|
||||||
|
.zip(pk.vk.cs.permutations.iter())
|
||||||
|
.zip(pk.permutations.iter())
|
||||||
|
.map(|((p, argument), pkey)| {
|
||||||
|
p.construct(pk, argument, pkey, &advice.advice_cosets, beta, gamma)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
tmp.into_iter().unzip()
|
||||||
})
|
})
|
||||||
.collect();
|
.collect::<Vec<(Vec<_>, Vec<_>)>>()
|
||||||
|
|
||||||
tmp.into_iter().unzip()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Evaluate the h(X) polynomial's constraint system expressions for the lookup constraints, if any.
|
|
||||||
let (lookups, lookup_expressions): (Vec<_>, Vec<_>) = {
|
|
||||||
let tmp: Vec<_> = lookups
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|p| p.construct(pk, theta, beta, gamma))
|
.unzip();
|
||||||
.collect();
|
|
||||||
|
|
||||||
tmp.into_iter().unzip()
|
let (lookups_vec, lookup_expressions_vec): (Vec<Vec<_>>, Vec<Vec<_>>) = lookups_vec
|
||||||
};
|
.into_iter()
|
||||||
|
.map(|lookups| {
|
||||||
|
// Evaluate the h(X) polynomial's constraint system expressions for the lookup constraints, if any.
|
||||||
|
let tmp: Vec<_> = lookups
|
||||||
|
.into_iter()
|
||||||
|
.map(|p| p.construct(pk, theta, beta, gamma))
|
||||||
|
.collect();
|
||||||
|
|
||||||
// Evaluate the h(X) polynomial's constraint system expressions for the constraints provided
|
tmp.into_iter().unzip()
|
||||||
let expressions = iter::empty()
|
})
|
||||||
// Custom constraints
|
.collect::<Vec<(Vec<_>, Vec<_>)>>()
|
||||||
.chain(meta.gates.iter().map(|poly| {
|
.into_iter()
|
||||||
poly.evaluate(
|
.unzip();
|
||||||
&|index| pk.fixed_cosets[index].clone(),
|
|
||||||
&|index| advice_cosets[index].clone(),
|
let expressions = advice_vec
|
||||||
&|index| aux_cosets[index].clone(),
|
.iter()
|
||||||
&|a, b| a + &b,
|
.zip(aux_vec.iter())
|
||||||
&|a, b| a * &b,
|
.zip(permutation_expressions_vec.into_iter())
|
||||||
&|a, scalar| a * scalar,
|
.zip(lookup_expressions_vec.into_iter())
|
||||||
)
|
.flat_map(
|
||||||
}))
|
|(((advice, aux), permutation_expressions), lookup_expressions)| {
|
||||||
// Permutation constraints, if any.
|
iter::empty()
|
||||||
.chain(permutation_expressions.into_iter().flatten())
|
// Custom constraints
|
||||||
// Lookup constraints, if any.
|
.chain(meta.gates.iter().map(move |poly| {
|
||||||
.chain(lookup_expressions.into_iter().flatten());
|
poly.evaluate(
|
||||||
|
&|index| pk.fixed_cosets[index].clone(),
|
||||||
|
&|index| advice.advice_cosets[index].clone(),
|
||||||
|
&|index| aux.aux_cosets[index].clone(),
|
||||||
|
&|a, b| a + &b,
|
||||||
|
&|a, b| a * &b,
|
||||||
|
&|a, scalar| a * scalar,
|
||||||
|
)
|
||||||
|
}))
|
||||||
|
// Permutation constraints, if any.
|
||||||
|
.chain(permutation_expressions.into_iter().flatten())
|
||||||
|
// Lookup constraints, if any.
|
||||||
|
.chain(lookup_expressions.into_iter().flatten())
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into_iter();
|
||||||
|
|
||||||
// Construct the vanishing argument
|
// Construct the vanishing argument
|
||||||
let vanishing = vanishing::Argument::construct(params, domain, expressions, y, transcript)?;
|
let vanishing = vanishing::Argument::construct(params, domain, expressions, y, transcript)?;
|
||||||
|
|
||||||
let x = ChallengeX::get(transcript);
|
let x = ChallengeX::get(transcript);
|
||||||
|
|
||||||
// Evaluate polynomials at omega^i x
|
// Compute and hash aux evals for each circuit instance
|
||||||
let advice_evals: Vec<_> = meta
|
for aux in aux_vec.iter() {
|
||||||
.advice_queries
|
// Evaluate polynomials at omega^i x
|
||||||
.iter()
|
let aux_evals: Vec<_> = meta
|
||||||
.map(|&(column, at)| {
|
.aux_queries
|
||||||
eval_polynomial(&advice_polys[column.index()], domain.rotate_omega(*x, at))
|
.iter()
|
||||||
})
|
.map(|&(column, at)| {
|
||||||
.collect();
|
eval_polynomial(&aux.aux_polys[column.index()], domain.rotate_omega(*x, at))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
let aux_evals: Vec<_> = meta
|
// Hash each aux column evaluation
|
||||||
.aux_queries
|
for eval in aux_evals.iter() {
|
||||||
.iter()
|
transcript
|
||||||
.map(|&(column, at)| {
|
.write_scalar(*eval)
|
||||||
eval_polynomial(&aux_polys[column.index()], domain.rotate_omega(*x, at))
|
.map_err(|_| Error::TranscriptError)?;
|
||||||
})
|
}
|
||||||
.collect();
|
}
|
||||||
|
|
||||||
|
// Compute and hash advice evals for each circuit instance
|
||||||
|
for advice in advice_vec.iter() {
|
||||||
|
// Evaluate polynomials at omega^i x
|
||||||
|
let advice_evals: Vec<_> = meta
|
||||||
|
.advice_queries
|
||||||
|
.iter()
|
||||||
|
.map(|&(column, at)| {
|
||||||
|
eval_polynomial(
|
||||||
|
&advice.advice_polys[column.index()],
|
||||||
|
domain.rotate_omega(*x, at),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Hash each advice column evaluation
|
||||||
|
for eval in advice_evals.iter() {
|
||||||
|
transcript
|
||||||
|
.write_scalar(*eval)
|
||||||
|
.map_err(|_| Error::TranscriptError)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute and hash fixed evals (shared across all circuit instances)
|
||||||
let fixed_evals: Vec<_> = meta
|
let fixed_evals: Vec<_> = meta
|
||||||
.fixed_queries
|
.fixed_queries
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -278,12 +421,8 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Hash each column evaluation
|
// Hash each fixed column evaluation
|
||||||
for eval in advice_evals
|
for eval in fixed_evals.iter() {
|
||||||
.iter()
|
|
||||||
.chain(aux_evals.iter())
|
|
||||||
.chain(fixed_evals.iter())
|
|
||||||
{
|
|
||||||
transcript
|
transcript
|
||||||
.write_scalar(*eval)
|
.write_scalar(*eval)
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
.map_err(|_| Error::TranscriptError)?;
|
||||||
|
|
@ -292,63 +431,98 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
|
||||||
let vanishing = vanishing.evaluate(x, transcript)?;
|
let vanishing = vanishing.evaluate(x, transcript)?;
|
||||||
|
|
||||||
// Evaluate the permutations, if any, at omega^i x.
|
// Evaluate the permutations, if any, at omega^i x.
|
||||||
let permutations = permutations
|
let permutations_vec: Result<Vec<Vec<permutation::prover::Evaluated<C>>>, _> = permutations_vec
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(pk.permutations.iter())
|
.map(|permutations| -> Result<Vec<_>, _> {
|
||||||
.map(|(p, pkey)| p.evaluate(pk, pkey, x, transcript))
|
permutations
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.into_iter()
|
||||||
|
.zip(pk.permutations.iter())
|
||||||
|
.map(|(p, pkey)| p.evaluate(pk, pkey, x, transcript))
|
||||||
|
.collect::<Result<Vec<_>, _>>()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let permutations_vec = match permutations_vec {
|
||||||
|
Ok(permutations_vec) => permutations_vec,
|
||||||
|
Err(err) => return Err(err),
|
||||||
|
};
|
||||||
|
|
||||||
// Evaluate the lookups, if any, at omega^i x.
|
// Evaluate the lookups, if any, at omega^i x.
|
||||||
let lookups = lookups
|
let lookups_vec: Result<Vec<Vec<lookup::prover::Evaluated<C>>>, _> = lookups_vec
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|p| p.evaluate(pk, x, transcript))
|
.map(|lookups| -> Result<Vec<_>, _> {
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
lookups
|
||||||
|
.into_iter()
|
||||||
|
.map(|p| p.evaluate(pk, x, transcript))
|
||||||
|
.collect::<Result<Vec<_>, _>>()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
let instances = iter::empty()
|
let lookups_vec = match lookups_vec {
|
||||||
.chain(
|
Ok(lookups_vec) => lookups_vec,
|
||||||
pk.vk
|
Err(err) => return Err(err),
|
||||||
.cs
|
};
|
||||||
.advice_queries
|
|
||||||
.iter()
|
let instances = aux_vec
|
||||||
.map(|&(column, at)| ProverQuery {
|
.iter()
|
||||||
point: domain.rotate_omega(*x, at),
|
.zip(advice_vec.iter())
|
||||||
poly: &advice_polys[column.index()],
|
.zip(permutations_vec.iter())
|
||||||
blind: advice_blinds[column.index()],
|
.zip(lookups_vec.iter())
|
||||||
}),
|
.flat_map(|(((aux, advice), permutations), lookups)| {
|
||||||
)
|
iter::empty()
|
||||||
.chain(
|
.chain(
|
||||||
pk.vk
|
pk.vk
|
||||||
.cs
|
.cs
|
||||||
.aux_queries
|
.aux_queries
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(column, at)| ProverQuery {
|
.map(move |&(column, at)| ProverQuery {
|
||||||
point: domain.rotate_omega(*x, at),
|
point: domain.rotate_omega(*x, at),
|
||||||
poly: &aux_polys[column.index()],
|
poly: &aux.aux_polys[column.index()],
|
||||||
blind: Blind::default(),
|
blind: Blind::default(),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
.chain(
|
||||||
|
pk.vk
|
||||||
|
.cs
|
||||||
|
.advice_queries
|
||||||
|
.iter()
|
||||||
|
.map(move |&(column, at)| ProverQuery {
|
||||||
|
point: domain.rotate_omega(*x, at),
|
||||||
|
poly: &advice.advice_polys[column.index()],
|
||||||
|
blind: advice.advice_blinds[column.index()],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.chain(
|
||||||
|
permutations
|
||||||
|
.iter()
|
||||||
|
.zip(pk.permutations.iter())
|
||||||
|
.map(move |(p, pkey)| p.open(pk, pkey, x))
|
||||||
|
.into_iter()
|
||||||
|
.flatten(),
|
||||||
|
)
|
||||||
|
.chain(
|
||||||
|
lookups
|
||||||
|
.iter()
|
||||||
|
.map(move |p| p.open(pk, x))
|
||||||
|
.into_iter()
|
||||||
|
.flatten(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into_iter()
|
||||||
.chain(
|
.chain(
|
||||||
pk.vk
|
pk.vk
|
||||||
.cs
|
.cs
|
||||||
.fixed_queries
|
.fixed_queries
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(column, at)| ProverQuery {
|
.map(move |&(column, at)| ProverQuery {
|
||||||
point: domain.rotate_omega(*x, at),
|
point: domain.rotate_omega(*x, at),
|
||||||
poly: &pk.fixed_polys[column.index()],
|
poly: &pk.fixed_polys[column.index()],
|
||||||
blind: Blind::default(),
|
blind: Blind::default(),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
// We query the h(X) polynomial at x
|
// We query the h(X) polynomial at x
|
||||||
.chain(vanishing.open(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)
|
multiopen::create_proof(params, transcript, instances).map_err(|_| Error::OpeningError)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue