halo2/src/plonk/permutation/verifier.rs

156 lines
6.0 KiB
Rust
Raw Normal View History

use ff::Field;
use std::iter;
use super::Proof;
use crate::{
arithmetic::{CurveAffine, FieldExt},
plonk::{ChallengeBeta, ChallengeGamma, ChallengeX, Error, VerifyingKey},
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);
}
for (permutation_evals, p) in self.permutation_evals.iter().zip(vk.cs.permutations.iter()) {
if permutation_evals.len() != p.columns.len() {
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(())
}
pub(in crate::plonk) fn expressions<'a>(
&'a self,
vk: &'a VerifyingKey<C>,
advice_evals: &'a [C::Scalar],
l_0: C::Scalar,
beta: ChallengeBeta<C::Scalar>,
gamma: ChallengeGamma<C::Scalar>,
x: ChallengeX<C::Scalar>,
) -> 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(
move |(((p, permutation_evals), product_eval), product_inv_eval)| {
let mut left = *product_eval;
for (advice_eval, permutation_eval) in p
.columns
.iter()
.map(|&column| {
advice_evals[vk.cs.get_advice_query_index(column, 0)]
})
.zip(permutation_evals.iter())
{
left *= &(advice_eval + &(*beta * permutation_eval) + &gamma);
}
let mut right = *product_inv_eval;
let mut current_delta = *beta * &x;
for advice_eval in p.columns.iter().map(|&column| {
advice_evals[vk.cs.get_advice_query_index(column, 0)]
}) {
right *= &(advice_eval + &current_delta + &gamma);
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()))
}
pub(in crate::plonk) fn queries<'a>(
&'a self,
vk: &'a VerifyingKey<C>,
x: ChallengeX<C::Scalar>,
) -> impl Iterator<Item = VerifierQuery<'a, C>> + Clone {
let x_inv = vk.domain.rotate_omega(*x, Rotation(-1));
iter::empty()
2020-12-01 14:09:50 -08:00
// Open permutation product commitments at x and \omega^{-1} x
.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,
}))
}),
)
// Open permutation commitments for each permutation argument at x
.chain(
(0..vk.permutations.len())
.map(move |outer_idx| {
let inner_len = vk.permutations[outer_idx].commitments.len();
(0..inner_len).map(move |inner_idx| VerifierQuery {
point: *x,
commitment: &vk.permutations[outer_idx].commitments[inner_idx],
eval: self.permutation_evals[outer_idx][inner_idx],
})
})
.flatten(),
)
}
}