2020-12-01 01:11:47 -08:00
|
|
|
|
use std::iter;
|
2020-11-30 22:53:20 -08:00
|
|
|
|
|
2021-02-10 06:57:08 -08:00
|
|
|
|
use super::super::circuit::Expression;
|
2020-12-23 12:03:31 -08:00
|
|
|
|
use super::Argument;
|
2020-12-01 01:11:47 -08:00
|
|
|
|
use crate::{
|
2021-02-10 03:36:25 -08:00
|
|
|
|
arithmetic::{CurveAffine, FieldExt},
|
2020-12-01 01:11:47 -08:00
|
|
|
|
plonk::{ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX, Error, VerifyingKey},
|
|
|
|
|
poly::{multiopen::VerifierQuery, Rotation},
|
2020-12-23 12:03:31 -08:00
|
|
|
|
transcript::TranscriptRead,
|
2020-12-01 01:11:47 -08:00
|
|
|
|
};
|
|
|
|
|
use ff::Field;
|
|
|
|
|
|
2020-12-23 12:03:31 -08:00
|
|
|
|
pub struct PermutationCommitments<C: CurveAffine> {
|
|
|
|
|
permuted_input_commitment: C,
|
|
|
|
|
permuted_table_commitment: C,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct Committed<C: CurveAffine> {
|
2021-01-13 14:44:37 -08:00
|
|
|
|
permuted: PermutationCommitments<C>,
|
2020-12-23 12:03:31 -08:00
|
|
|
|
product_commitment: C,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct Evaluated<C: CurveAffine> {
|
|
|
|
|
committed: Committed<C>,
|
|
|
|
|
product_eval: C::Scalar,
|
|
|
|
|
product_inv_eval: C::Scalar,
|
|
|
|
|
permuted_input_eval: C::Scalar,
|
|
|
|
|
permuted_input_inv_eval: C::Scalar,
|
|
|
|
|
permuted_table_eval: C::Scalar,
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-10 03:36:25 -08:00
|
|
|
|
impl<F: FieldExt> Argument<F> {
|
2021-01-13 14:47:35 -08:00
|
|
|
|
pub(in crate::plonk) fn read_permuted_commitments<C: CurveAffine, T: TranscriptRead<C>>(
|
2020-12-01 01:11:47 -08:00
|
|
|
|
&self,
|
2020-12-23 12:03:31 -08:00
|
|
|
|
transcript: &mut T,
|
|
|
|
|
) -> Result<PermutationCommitments<C>, Error> {
|
|
|
|
|
let permuted_input_commitment = transcript
|
|
|
|
|
.read_point()
|
|
|
|
|
.map_err(|_| Error::TranscriptError)?;
|
|
|
|
|
let permuted_table_commitment = transcript
|
|
|
|
|
.read_point()
|
2020-12-01 01:11:47 -08:00
|
|
|
|
.map_err(|_| Error::TranscriptError)?;
|
2020-12-23 12:03:31 -08:00
|
|
|
|
|
|
|
|
|
Ok(PermutationCommitments {
|
|
|
|
|
permuted_input_commitment,
|
|
|
|
|
permuted_table_commitment,
|
|
|
|
|
})
|
2020-12-01 01:11:47 -08:00
|
|
|
|
}
|
2020-12-23 12:03:31 -08:00
|
|
|
|
}
|
2020-12-01 01:11:47 -08:00
|
|
|
|
|
2020-12-23 12:03:31 -08:00
|
|
|
|
impl<C: CurveAffine> PermutationCommitments<C> {
|
2021-01-13 14:47:35 -08:00
|
|
|
|
pub(in crate::plonk) fn read_product_commitment<T: TranscriptRead<C>>(
|
2020-12-23 12:03:31 -08:00
|
|
|
|
self,
|
|
|
|
|
transcript: &mut T,
|
|
|
|
|
) -> Result<Committed<C>, Error> {
|
|
|
|
|
let product_commitment = transcript
|
|
|
|
|
.read_point()
|
|
|
|
|
.map_err(|_| Error::TranscriptError)?;
|
|
|
|
|
|
|
|
|
|
Ok(Committed {
|
2021-01-13 14:44:37 -08:00
|
|
|
|
permuted: self,
|
2020-12-23 12:03:31 -08:00
|
|
|
|
product_commitment,
|
|
|
|
|
})
|
2020-12-01 01:11:47 -08:00
|
|
|
|
}
|
2020-12-23 12:03:31 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<C: CurveAffine> Committed<C> {
|
2020-12-23 15:20:27 -08:00
|
|
|
|
pub(crate) fn evaluate<T: TranscriptRead<C>>(
|
2020-12-23 12:03:31 -08:00
|
|
|
|
self,
|
|
|
|
|
transcript: &mut T,
|
|
|
|
|
) -> Result<Evaluated<C>, Error> {
|
|
|
|
|
let product_eval = transcript
|
|
|
|
|
.read_scalar()
|
|
|
|
|
.map_err(|_| Error::TranscriptError)?;
|
|
|
|
|
let product_inv_eval = transcript
|
|
|
|
|
.read_scalar()
|
|
|
|
|
.map_err(|_| Error::TranscriptError)?;
|
|
|
|
|
let permuted_input_eval = transcript
|
|
|
|
|
.read_scalar()
|
|
|
|
|
.map_err(|_| Error::TranscriptError)?;
|
|
|
|
|
let permuted_input_inv_eval = transcript
|
|
|
|
|
.read_scalar()
|
|
|
|
|
.map_err(|_| Error::TranscriptError)?;
|
|
|
|
|
let permuted_table_eval = transcript
|
|
|
|
|
.read_scalar()
|
|
|
|
|
.map_err(|_| Error::TranscriptError)?;
|
2020-12-01 01:11:47 -08:00
|
|
|
|
|
2020-12-23 12:03:31 -08:00
|
|
|
|
Ok(Evaluated {
|
|
|
|
|
committed: self,
|
|
|
|
|
product_eval,
|
|
|
|
|
product_inv_eval,
|
|
|
|
|
permuted_input_eval,
|
|
|
|
|
permuted_input_inv_eval,
|
|
|
|
|
permuted_table_eval,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<C: CurveAffine> Evaluated<C> {
|
2020-12-01 01:11:47 -08:00
|
|
|
|
pub(in crate::plonk) fn expressions<'a>(
|
|
|
|
|
&'a self,
|
|
|
|
|
l_0: C::Scalar,
|
2021-02-10 03:36:25 -08:00
|
|
|
|
argument: &'a Argument<C::Scalar>,
|
2020-12-23 12:03:31 -08:00
|
|
|
|
theta: ChallengeTheta<C>,
|
|
|
|
|
beta: ChallengeBeta<C>,
|
|
|
|
|
gamma: ChallengeGamma<C>,
|
2020-12-01 01:11:47 -08:00
|
|
|
|
advice_evals: &[C::Scalar],
|
|
|
|
|
fixed_evals: &[C::Scalar],
|
2021-02-14 09:30:36 -08:00
|
|
|
|
instance_evals: &[C::Scalar],
|
2020-12-01 01:11:47 -08:00
|
|
|
|
) -> impl Iterator<Item = C::Scalar> + 'a {
|
|
|
|
|
let product_expression = || {
|
|
|
|
|
// z'(X) (a'(X) + \beta) (s'(X) + \gamma)
|
2020-12-05 14:58:48 -08:00
|
|
|
|
// - z'(\omega^{-1} X) (\theta^{m-1} a_0(X) + ... + a_{m-1}(X) + \beta) (\theta^{m-1} s_0(X) + ... + s_{m-1}(X) + \gamma)
|
2020-12-01 01:11:47 -08:00
|
|
|
|
let left = self.product_eval
|
2021-01-05 16:00:27 -08:00
|
|
|
|
* &(self.permuted_input_eval + &*beta)
|
|
|
|
|
* &(self.permuted_table_eval + &*gamma);
|
2020-12-01 01:11:47 -08:00
|
|
|
|
|
2021-02-11 18:24:55 -08:00
|
|
|
|
let compress_expressions = |expressions: &[Expression<C::Scalar>]| {
|
|
|
|
|
expressions
|
2020-12-03 17:18:28 -08:00
|
|
|
|
.iter()
|
2021-02-11 18:24:55 -08:00
|
|
|
|
.map(|expression| {
|
|
|
|
|
expression.evaluate(
|
2021-02-13 02:36:29 -08:00
|
|
|
|
&|scalar| scalar,
|
2021-02-10 06:57:08 -08:00
|
|
|
|
&|index| fixed_evals[index],
|
|
|
|
|
&|index| advice_evals[index],
|
|
|
|
|
&|index| instance_evals[index],
|
|
|
|
|
&|a, b| a + &b,
|
|
|
|
|
&|a, b| a * &b,
|
2021-02-18 15:50:01 -08:00
|
|
|
|
&|a, scalar| a * &scalar,
|
2021-02-10 06:57:08 -08:00
|
|
|
|
)
|
2020-12-03 17:18:28 -08:00
|
|
|
|
})
|
2021-01-05 16:00:27 -08:00
|
|
|
|
.fold(C::Scalar::zero(), |acc, eval| acc * &*theta + &eval)
|
2020-12-03 17:18:28 -08:00
|
|
|
|
};
|
|
|
|
|
let right = self.product_inv_eval
|
2021-02-11 18:24:55 -08:00
|
|
|
|
* &(compress_expressions(&argument.input_expressions) + &*beta)
|
|
|
|
|
* &(compress_expressions(&argument.table_expressions) + &*gamma);
|
2020-12-01 01:11:47 -08:00
|
|
|
|
|
|
|
|
|
left - &right
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::iter::empty()
|
|
|
|
|
.chain(
|
|
|
|
|
// l_0(X) * (1 - z'(X)) = 0
|
|
|
|
|
Some(l_0 * &(C::Scalar::one() - &self.product_eval)),
|
|
|
|
|
)
|
|
|
|
|
.chain(
|
|
|
|
|
// z'(X) (a'(X) + \beta) (s'(X) + \gamma)
|
2020-12-05 14:58:48 -08:00
|
|
|
|
// - z'(\omega^{-1} X) (\theta^{m-1} a_0(X) + ... + a_{m-1}(X) + \beta) (\theta^{m-1} s_0(X) + ... + s_{m-1}(X) + \gamma)
|
2020-12-01 01:11:47 -08:00
|
|
|
|
Some(product_expression()),
|
|
|
|
|
)
|
|
|
|
|
.chain(Some(
|
2020-12-02 20:39:44 -08:00
|
|
|
|
// l_0(X) * (a'(X) - s'(X)) = 0
|
2020-12-01 01:11:47 -08:00
|
|
|
|
l_0 * &(self.permuted_input_eval - &self.permuted_table_eval),
|
|
|
|
|
))
|
|
|
|
|
.chain(Some(
|
2020-12-02 20:39:44 -08:00
|
|
|
|
// (a′(X)−s′(X))⋅(a′(X)−a′(\omega{-1} X)) = 0
|
2020-12-01 01:11:47 -08:00
|
|
|
|
(self.permuted_input_eval - &self.permuted_table_eval)
|
|
|
|
|
* &(self.permuted_input_eval - &self.permuted_input_inv_eval),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(in crate::plonk) fn queries<'a>(
|
|
|
|
|
&'a self,
|
|
|
|
|
vk: &'a VerifyingKey<C>,
|
2020-12-23 12:03:31 -08:00
|
|
|
|
x: ChallengeX<C>,
|
2020-12-01 01:11:47 -08:00
|
|
|
|
) -> impl Iterator<Item = VerifierQuery<'a, C>> + Clone {
|
|
|
|
|
let x_inv = vk.domain.rotate_omega(*x, Rotation(-1));
|
|
|
|
|
|
|
|
|
|
iter::empty()
|
|
|
|
|
// Open lookup product commitments at x
|
|
|
|
|
.chain(Some(VerifierQuery {
|
|
|
|
|
point: *x,
|
2020-12-23 12:03:31 -08:00
|
|
|
|
commitment: &self.committed.product_commitment,
|
2020-12-01 01:11:47 -08:00
|
|
|
|
eval: self.product_eval,
|
|
|
|
|
}))
|
|
|
|
|
// Open lookup input commitments at x
|
|
|
|
|
.chain(Some(VerifierQuery {
|
|
|
|
|
point: *x,
|
2021-01-13 14:44:37 -08:00
|
|
|
|
commitment: &self.committed.permuted.permuted_input_commitment,
|
2020-12-01 01:11:47 -08:00
|
|
|
|
eval: self.permuted_input_eval,
|
|
|
|
|
}))
|
|
|
|
|
// Open lookup table commitments at x
|
|
|
|
|
.chain(Some(VerifierQuery {
|
|
|
|
|
point: *x,
|
2021-01-13 14:44:37 -08:00
|
|
|
|
commitment: &self.committed.permuted.permuted_table_commitment,
|
2020-12-01 01:11:47 -08:00
|
|
|
|
eval: self.permuted_table_eval,
|
|
|
|
|
}))
|
|
|
|
|
// Open lookup input commitments at \omega^{-1} x
|
|
|
|
|
.chain(Some(VerifierQuery {
|
|
|
|
|
point: x_inv,
|
2021-01-13 14:44:37 -08:00
|
|
|
|
commitment: &self.committed.permuted.permuted_input_commitment,
|
2020-12-01 01:11:47 -08:00
|
|
|
|
eval: self.permuted_input_inv_eval,
|
|
|
|
|
}))
|
|
|
|
|
// Open lookup product commitments at \omega^{-1} x
|
|
|
|
|
.chain(Some(VerifierQuery {
|
|
|
|
|
point: x_inv,
|
2020-12-23 12:03:31 -08:00
|
|
|
|
commitment: &self.committed.product_commitment,
|
2020-12-01 01:11:47 -08:00
|
|
|
|
eval: self.product_inv_eval,
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
}
|