Provide aux_commitments to verifier and aux_lagrange_polys to prover

This commit is contained in:
therealyingtong 2020-09-18 00:33:42 +08:00 committed by Sean Bowe
parent 0eed821083
commit 0caf1d2087
No known key found for this signature in database
GPG key ID: 95684257D8F8B031
4 changed files with 85 additions and 5 deletions

View file

@ -50,6 +50,7 @@ pub struct Proof<C: CurveAffine> {
permutation_product_inv_evals: Vec<C::Scalar>, permutation_product_inv_evals: Vec<C::Scalar>,
permutation_evals: Vec<Vec<C::Scalar>>, permutation_evals: Vec<Vec<C::Scalar>>,
advice_evals: Vec<C::Scalar>, advice_evals: Vec<C::Scalar>,
aux_evals: Vec<C::Scalar>,
fixed_evals: Vec<C::Scalar>, fixed_evals: Vec<C::Scalar>,
h_evals: Vec<C::Scalar>, h_evals: Vec<C::Scalar>,
f_commitment: C, f_commitment: C,

View file

@ -14,6 +14,10 @@ pub struct FixedWire(pub usize);
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct AdviceWire(pub usize); pub struct AdviceWire(pub usize);
/// This represents a wire which has an externally assigned value
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct AuxWire(pub usize);
/// This trait allows a [`Circuit`] to direct some backend to assign a witness /// This trait allows a [`Circuit`] to direct some backend to assign a witness
/// for a constraint system. /// for a constraint system.
pub trait Assignment<F: Field> { pub trait Assignment<F: Field> {
@ -68,6 +72,8 @@ pub enum Expression<F> {
Fixed(usize), Fixed(usize),
/// This is an advice (witness) wire queried at a certain relative location /// This is an advice (witness) wire queried at a certain relative location
Advice(usize), Advice(usize),
/// This is an auxiliary (external) wire queried at a certain relative location
Aux(usize),
/// This is the sum of two polynomials /// This is the sum of two polynomials
Sum(Box<Expression<F>>, Box<Expression<F>>), Sum(Box<Expression<F>>, Box<Expression<F>>),
/// This is the product of two polynomials /// This is the product of two polynomials
@ -83,6 +89,7 @@ impl<F: Field> Expression<F> {
&self, &self,
fixed_wire: &impl Fn(usize) -> T, fixed_wire: &impl Fn(usize) -> T,
advice_wire: &impl Fn(usize) -> T, advice_wire: &impl Fn(usize) -> T,
aux_wire: &impl Fn(usize) -> T,
sum: &impl Fn(T, T) -> T, sum: &impl Fn(T, T) -> T,
product: &impl Fn(T, T) -> T, product: &impl Fn(T, T) -> T,
scaled: &impl Fn(T, F) -> T, scaled: &impl Fn(T, F) -> T,
@ -90,18 +97,19 @@ impl<F: Field> Expression<F> {
match self { match self {
Expression::Fixed(index) => fixed_wire(*index), Expression::Fixed(index) => fixed_wire(*index),
Expression::Advice(index) => advice_wire(*index), Expression::Advice(index) => advice_wire(*index),
Expression::Aux(index) => aux_wire(*index),
Expression::Sum(a, b) => { Expression::Sum(a, b) => {
let a = a.evaluate(fixed_wire, advice_wire, sum, product, scaled); let a = a.evaluate(fixed_wire, advice_wire, aux_wire, sum, product, scaled);
let b = b.evaluate(fixed_wire, advice_wire, sum, product, scaled); let b = b.evaluate(fixed_wire, advice_wire, aux_wire, sum, product, scaled);
sum(a, b) sum(a, b)
} }
Expression::Product(a, b) => { Expression::Product(a, b) => {
let a = a.evaluate(fixed_wire, advice_wire, sum, product, scaled); let a = a.evaluate(fixed_wire, advice_wire, aux_wire, sum, product, scaled);
let b = b.evaluate(fixed_wire, advice_wire, sum, product, scaled); let b = b.evaluate(fixed_wire, advice_wire, aux_wire, sum, product, scaled);
product(a, b) product(a, b)
} }
Expression::Scaled(a, f) => { Expression::Scaled(a, f) => {
let a = a.evaluate(fixed_wire, advice_wire, sum, product, scaled); let a = a.evaluate(fixed_wire, advice_wire, aux_wire, sum, product, scaled);
scaled(a, *f) scaled(a, *f)
} }
} }
@ -112,6 +120,7 @@ impl<F: Field> Expression<F> {
match self { match self {
Expression::Fixed(_) => 1, Expression::Fixed(_) => 1,
Expression::Advice(_) => 1, Expression::Advice(_) => 1,
Expression::Aux(_) => 1,
Expression::Sum(a, b) => max(a.degree(), b.degree()), Expression::Sum(a, b) => max(a.degree(), b.degree()),
Expression::Product(a, b) => a.degree() + b.degree(), Expression::Product(a, b) => a.degree() + b.degree(),
Expression::Scaled(poly, _) => poly.degree(), Expression::Scaled(poly, _) => poly.degree(),
@ -153,6 +162,7 @@ pub struct ConstraintSystem<F> {
pub(crate) num_advice_wires: usize, pub(crate) num_advice_wires: usize,
pub(crate) gates: Vec<Expression<F>>, pub(crate) gates: Vec<Expression<F>>,
pub(crate) advice_queries: Vec<(AdviceWire, Rotation)>, pub(crate) advice_queries: Vec<(AdviceWire, Rotation)>,
pub(crate) aux_queries: Vec<(AuxWire, Rotation)>,
pub(crate) fixed_queries: Vec<(FixedWire, Rotation)>, pub(crate) fixed_queries: Vec<(FixedWire, Rotation)>,
// Mapping from a witness vector rotation to the index in the point vector. // Mapping from a witness vector rotation to the index in the point vector.
@ -179,6 +189,7 @@ impl<F: Field> Default for ConstraintSystem<F> {
gates: vec![], gates: vec![],
fixed_queries: Vec::new(), fixed_queries: Vec::new(),
advice_queries: Vec::new(), advice_queries: Vec::new(),
aux_queries: Vec::new(),
rotations, rotations,
permutations: Vec::new(), permutations: Vec::new(),
} }

View file

@ -24,6 +24,7 @@ impl<C: CurveAffine> Proof<C> {
params: &Params<C>, params: &Params<C>,
srs: &SRS<C>, srs: &SRS<C>,
circuit: &ConcreteCircuit, circuit: &ConcreteCircuit,
aux_lagrange_polys: Vec<Polynomial<C::Scalar, LagrangeCoeff>>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
struct WitnessCollection<F: Field> { struct WitnessCollection<F: Field> {
advice: Vec<Polynomial<F, LagrangeCoeff>>, advice: Vec<Polynomial<F, LagrangeCoeff>>,
@ -125,6 +126,35 @@ impl<C: CurveAffine> Proof<C> {
}) })
.collect(); .collect();
// Compute commitments to auxiliary wire polynomials
let aux_commitments_projective: Vec<_> = aux_lagrange_polys
.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);
for commitment in &aux_commitments {
hash_point(&mut transcript, commitment)?;
}
let aux_polys: Vec<_> = aux_lagrange_polys
.clone()
.into_iter()
.map(|poly| domain.lagrange_to_coeff(poly))
.collect();
let aux_cosets: Vec<_> = meta
.aux_queries
.iter()
.map(|&(wire, at)| {
let poly = aux_polys[wire.0].clone();
domain.coeff_to_extended(poly, at)
})
.collect();
// Sample x_0 challenge // Sample x_0 challenge
let x_0: C::Scalar = get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128())); let x_0: C::Scalar = get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128()));
@ -253,6 +283,7 @@ impl<C: CurveAffine> Proof<C> {
let evaluation = poly.evaluate( let evaluation = poly.evaluate(
&|index| srs.fixed_cosets[index].clone(), &|index| srs.fixed_cosets[index].clone(),
&|index| advice_cosets[index].clone(), &|index| advice_cosets[index].clone(),
&|index| aux_cosets[index].clone(),
&|a, b| a + &b, &|a, b| a + &b,
&|a, b| a * &b, &|a, b| a * &b,
&|a, scalar| a * scalar, &|a, scalar| a * scalar,
@ -355,6 +386,12 @@ impl<C: CurveAffine> Proof<C> {
.map(|&(wire, at)| eval_polynomial(&advice_polys[wire.0], domain.rotate_omega(x_3, at))) .map(|&(wire, at)| eval_polynomial(&advice_polys[wire.0], domain.rotate_omega(x_3, at)))
.collect(); .collect();
let aux_evals: Vec<_> = meta
.aux_queries
.iter()
.map(|&(wire, at)| eval_polynomial(&aux_polys[wire.0], domain.rotate_omega(x_3, at)))
.collect();
let fixed_evals: Vec<_> = meta let fixed_evals: Vec<_> = meta
.fixed_queries .fixed_queries
.iter() .iter()
@ -396,6 +433,7 @@ impl<C: CurveAffine> Proof<C> {
// Hash each advice evaluation // Hash each advice evaluation
for eval in advice_evals for eval in advice_evals
.iter() .iter()
.chain(aux_evals.iter())
.chain(fixed_evals.iter()) .chain(fixed_evals.iter())
.chain(h_evals.iter()) .chain(h_evals.iter())
.chain(permutation_product_evals.iter()) .chain(permutation_product_evals.iter())
@ -451,6 +489,17 @@ impl<C: CurveAffine> Proof<C> {
); );
} }
for (query_index, &(wire, ref at)) in meta.aux_queries.iter().enumerate() {
let point_index = (*meta.rotations.get(at).unwrap()).0;
accumulate(
point_index,
&aux_polys[wire.0],
Blind::default(),
aux_evals[query_index],
);
}
for (query_index, &(wire, ref at)) in meta.fixed_queries.iter().enumerate() { for (query_index, &(wire, ref at)) in meta.fixed_queries.iter().enumerate() {
let point_index = (*meta.rotations.get(at).unwrap()).0; let point_index = (*meta.rotations.get(at).unwrap()).0;
@ -595,6 +644,7 @@ impl<C: CurveAffine> Proof<C> {
permutation_evals, permutation_evals,
advice_evals, advice_evals,
fixed_evals, fixed_evals,
aux_evals,
h_evals, h_evals,
f_commitment, f_commitment,
q_evals, q_evals,

View file

@ -13,6 +13,7 @@ impl<'a, C: CurveAffine> Proof<C> {
params: &'a Params<C>, params: &'a Params<C>,
srs: &SRS<C>, srs: &SRS<C>,
mut msm: MSM<'a, C>, mut msm: MSM<'a, C>,
aux_commitments: Vec<C>,
) -> Result<Guard<'a, C>, Error> { ) -> Result<Guard<'a, C>, Error> {
// Scale the MSM by a random factor to ensure that if the existing MSM // Scale the MSM by a random factor to ensure that if the existing MSM
// has is_zero() == false then this argument won't be able to interfere // has is_zero() == false then this argument won't be able to interfere
@ -28,6 +29,12 @@ impl<'a, C: CurveAffine> Proof<C> {
.expect("proof cannot contain points at infinity"); .expect("proof cannot contain points at infinity");
} }
// Hash the external auxiliary commitments into the transcript
for commitment in &aux_commitments {
hash_point(&mut transcript, commitment)
.expect("proof cannot contain points at infinity");
}
// Sample x_0 challenge // Sample x_0 challenge
let x_0: C::Scalar = get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128())); let x_0: C::Scalar = get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128()));
@ -59,6 +66,7 @@ impl<'a, C: CurveAffine> Proof<C> {
for eval in self for eval in self
.advice_evals .advice_evals
.iter() .iter()
.chain(self.aux_evals.iter())
.chain(self.fixed_evals.iter()) .chain(self.fixed_evals.iter())
.chain(self.h_evals.iter()) .chain(self.h_evals.iter())
.chain(self.permutation_product_evals.iter()) .chain(self.permutation_product_evals.iter())
@ -80,6 +88,7 @@ impl<'a, C: CurveAffine> Proof<C> {
let evaluation: C::Scalar = poly.evaluate( let evaluation: C::Scalar = poly.evaluate(
&|index| self.fixed_evals[index], &|index| self.fixed_evals[index],
&|index| self.advice_evals[index], &|index| self.advice_evals[index],
&|index| self.aux_evals[index],
&|a, b| a + &b, &|a, b| a + &b,
&|a, b| a * &b, &|a, b| a * &b,
&|a, scalar| a * &scalar, &|a, scalar| a * &scalar,
@ -172,6 +181,15 @@ impl<'a, C: CurveAffine> Proof<C> {
); );
} }
for (query_index, &(wire, ref at)) in srs.cs.aux_queries.iter().enumerate() {
let point_index = (*srs.cs.rotations.get(at).unwrap()).0;
accumulate(
point_index,
aux_commitments[wire.0],
self.aux_evals[query_index],
);
}
for (query_index, &(wire, ref at)) in srs.cs.fixed_queries.iter().enumerate() { for (query_index, &(wire, ref at)) in srs.cs.fixed_queries.iter().enumerate() {
let point_index = (*srs.cs.rotations.get(at).unwrap()).0; let point_index = (*srs.cs.rotations.get(at).unwrap()).0;
accumulate( accumulate(