2020-11-24 16:49:52 -08:00
|
|
|
use ff::Field;
|
|
|
|
use std::iter;
|
|
|
|
|
|
|
|
use super::Proof;
|
|
|
|
use crate::{
|
|
|
|
arithmetic::{CurveAffine, FieldExt},
|
2020-11-25 11:26:31 -08:00
|
|
|
plonk::{ChallengeBeta, ChallengeGamma, ChallengeX, Error, VerifyingKey},
|
2020-11-24 16:49:52 -08:00
|
|
|
poly::{multiopen::VerifierQuery, Rotation},
|
|
|
|
transcript::{Hasher, Transcript},
|
|
|
|
};
|
|
|
|
|
|
|
|
impl<C: CurveAffine> Proof<C> {
|
|
|
|
pub(crate) fn check_lengths(&self, vk: &VerifyingKey<C>) -> Result<(), Error> {
|
|
|
|
if self.permutation_evals.len() != vk.cs.permutations.len() {
|
|
|
|
return Err(Error::IncompatibleParams);
|
|
|
|
}
|
|
|
|
|
2020-11-30 18:09:03 -08:00
|
|
|
for (permutation_evals, p) in self.permutation_evals.iter().zip(vk.cs.permutations.iter()) {
|
|
|
|
if permutation_evals.len() != p.columns.len() {
|
2020-11-24 16:49:52 -08:00
|
|
|
return Err(Error::IncompatibleParams);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.permutation_product_inv_evals.len() != vk.cs.permutations.len() {
|
|
|
|
return Err(Error::IncompatibleParams);
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.permutation_product_evals.len() != vk.cs.permutations.len() {
|
|
|
|
return Err(Error::IncompatibleParams);
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.permutation_product_commitments.len() != vk.cs.permutations.len() {
|
|
|
|
return Err(Error::IncompatibleParams);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn absorb_commitments<HBase: Hasher<C::Base>, HScalar: Hasher<C::Scalar>>(
|
|
|
|
&self,
|
|
|
|
transcript: &mut Transcript<C, HBase, HScalar>,
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
for c in &self.permutation_product_commitments {
|
|
|
|
transcript
|
|
|
|
.absorb_point(c)
|
|
|
|
.map_err(|_| Error::TranscriptError)?;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-12-01 13:14:14 -08:00
|
|
|
pub(in crate::plonk) fn expressions<'a>(
|
2020-11-24 16:49:52 -08:00
|
|
|
&'a self,
|
|
|
|
vk: &'a VerifyingKey<C>,
|
|
|
|
advice_evals: &'a [C::Scalar],
|
|
|
|
l_0: C::Scalar,
|
2020-11-25 11:26:31 -08:00
|
|
|
beta: ChallengeBeta<C::Scalar>,
|
|
|
|
gamma: ChallengeGamma<C::Scalar>,
|
|
|
|
x: ChallengeX<C::Scalar>,
|
2020-11-24 16:49:52 -08:00
|
|
|
) -> impl Iterator<Item = C::Scalar> + 'a {
|
|
|
|
iter::empty()
|
|
|
|
// l_0(X) * (1 - z(X)) = 0
|
|
|
|
.chain(
|
|
|
|
self.permutation_product_evals
|
|
|
|
.iter()
|
|
|
|
.map(move |product_eval| l_0 * &(C::Scalar::one() - product_eval)),
|
|
|
|
)
|
|
|
|
// z(X) \prod (p(X) + \beta s_i(X) + \gamma)
|
|
|
|
// - z(omega^{-1} X) \prod (p(X) + \delta^i \beta X + \gamma)
|
|
|
|
.chain(
|
|
|
|
vk.cs
|
|
|
|
.permutations
|
|
|
|
.iter()
|
|
|
|
.zip(self.permutation_evals.iter())
|
|
|
|
.zip(self.permutation_product_evals.iter())
|
|
|
|
.zip(self.permutation_product_inv_evals.iter())
|
|
|
|
.map(
|
2020-11-30 18:09:03 -08:00
|
|
|
move |(((p, permutation_evals), product_eval), product_inv_eval)| {
|
2020-11-24 16:49:52 -08:00
|
|
|
let mut left = *product_eval;
|
2020-11-30 18:09:03 -08:00
|
|
|
for (advice_eval, permutation_eval) in p
|
|
|
|
.columns
|
2020-11-24 16:49:52 -08:00
|
|
|
.iter()
|
|
|
|
.map(|&column| {
|
|
|
|
advice_evals[vk.cs.get_advice_query_index(column, 0)]
|
|
|
|
})
|
|
|
|
.zip(permutation_evals.iter())
|
|
|
|
{
|
2020-11-25 11:26:31 -08:00
|
|
|
left *= &(advice_eval + &(*beta * permutation_eval) + &gamma);
|
2020-11-24 16:49:52 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
let mut right = *product_inv_eval;
|
2020-11-25 11:26:31 -08:00
|
|
|
let mut current_delta = *beta * &x;
|
2020-11-30 18:09:03 -08:00
|
|
|
for advice_eval in p.columns.iter().map(|&column| {
|
2020-11-24 16:49:52 -08:00
|
|
|
advice_evals[vk.cs.get_advice_query_index(column, 0)]
|
|
|
|
}) {
|
2020-11-25 11:26:31 -08:00
|
|
|
right *= &(advice_eval + ¤t_delta + &gamma);
|
2020-11-24 16:49:52 -08:00
|
|
|
current_delta *= &C::Scalar::DELTA;
|
|
|
|
}
|
|
|
|
|
|
|
|
left - &right
|
|
|
|
},
|
|
|
|
),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn evals(&self) -> impl Iterator<Item = &C::Scalar> {
|
|
|
|
self.permutation_product_evals
|
|
|
|
.iter()
|
|
|
|
.chain(self.permutation_product_inv_evals.iter())
|
|
|
|
.chain(self.permutation_evals.iter().flat_map(|evals| evals.iter()))
|
|
|
|
}
|
|
|
|
|
2020-12-01 13:14:14 -08:00
|
|
|
pub(in crate::plonk) fn queries<'a>(
|
2020-11-24 16:49:52 -08:00
|
|
|
&'a self,
|
|
|
|
vk: &'a VerifyingKey<C>,
|
2020-11-25 11:26:31 -08:00
|
|
|
x: ChallengeX<C::Scalar>,
|
2020-11-24 16:49:52 -08:00
|
|
|
) -> impl Iterator<Item = VerifierQuery<'a, C>> + Clone {
|
2020-11-25 11:26:31 -08:00
|
|
|
let x_inv = vk.domain.rotate_omega(*x, Rotation(-1));
|
2020-11-24 16:49:52 -08:00
|
|
|
|
|
|
|
iter::empty()
|
2020-12-01 14:09:50 -08:00
|
|
|
// Open permutation product commitments at x and \omega^{-1} x
|
2020-11-24 16:49:52 -08:00
|
|
|
.chain(
|
|
|
|
self.permutation_product_commitments
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.zip(self.permutation_product_evals.iter())
|
2020-12-01 14:09:50 -08:00
|
|
|
.zip(self.permutation_product_inv_evals.iter())
|
|
|
|
.flat_map(move |(((idx, _), &eval), &inv_eval)| {
|
|
|
|
iter::empty()
|
|
|
|
.chain(Some(VerifierQuery {
|
|
|
|
point: *x,
|
|
|
|
commitment: &self.permutation_product_commitments[idx],
|
|
|
|
eval,
|
|
|
|
}))
|
|
|
|
.chain(Some(VerifierQuery {
|
|
|
|
point: x_inv,
|
|
|
|
commitment: &self.permutation_product_commitments[idx],
|
|
|
|
eval: inv_eval,
|
|
|
|
}))
|
2020-11-24 16:49:52 -08:00
|
|
|
}),
|
|
|
|
)
|
2020-11-25 11:26:31 -08:00
|
|
|
// Open permutation commitments for each permutation argument at x
|
2020-11-24 16:49:52 -08:00
|
|
|
.chain(
|
2020-11-30 18:09:03 -08:00
|
|
|
(0..vk.permutations.len())
|
2020-11-24 16:49:52 -08:00
|
|
|
.map(move |outer_idx| {
|
2020-11-30 18:09:03 -08:00
|
|
|
let inner_len = vk.permutations[outer_idx].commitments.len();
|
2020-11-24 16:49:52 -08:00
|
|
|
(0..inner_len).map(move |inner_idx| VerifierQuery {
|
2020-11-25 11:26:31 -08:00
|
|
|
point: *x,
|
2020-11-30 18:09:03 -08:00
|
|
|
commitment: &vk.permutations[outer_idx].commitments[inner_idx],
|
2020-11-24 16:49:52 -08:00
|
|
|
eval: self.permutation_evals[outer_idx][inner_idx],
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.flatten(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|