pasta_curves-source/src/plonk/lookup/verifier.rs
Jack Grigg f49e1e6177 Fix breakage of trait resolution in Rust 1.49.0
Previously, `ChallengeScalar` could use the operator traits defined on
the `F: Field` type it wrapped, due to its `impl Deref<Target = F>`.
This was technically ambiguous, and Rust 1.49.0 makes that ambiguity an
error.

We could fix this by adding operator impls with `ChallengeScalar` on the
RHS, but that would conflict with zcash/halo2#111. Instead we manually
dereference every challenge scalar when used in an arithmetic operation.
2021-01-06 00:48:29 +00:00

149 lines
5.5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use std::iter;
use super::super::circuit::{Any, Column};
use super::{Argument, Proof};
use crate::{
arithmetic::CurveAffine,
plonk::{ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX, Error, VerifyingKey},
poly::{multiopen::VerifierQuery, Rotation},
transcript::{Hasher, Transcript},
};
use ff::Field;
impl<C: CurveAffine> Proof<C> {
pub(in crate::plonk) fn absorb_permuted_commitments<
HBase: Hasher<C::Base>,
HScalar: Hasher<C::Scalar>,
>(
&self,
transcript: &mut Transcript<C, HBase, HScalar>,
) -> Result<(), Error> {
transcript
.absorb_point(&self.permuted_input_commitment)
.map_err(|_| Error::TranscriptError)?;
transcript
.absorb_point(&self.permuted_table_commitment)
.map_err(|_| Error::TranscriptError)
}
pub(in crate::plonk) fn absorb_product_commitment<
HBase: Hasher<C::Base>,
HScalar: Hasher<C::Scalar>,
>(
&self,
transcript: &mut Transcript<C, HBase, HScalar>,
) -> Result<(), Error> {
transcript
.absorb_point(&self.product_commitment)
.map_err(|_| Error::TranscriptError)
}
pub(in crate::plonk) fn expressions<'a>(
&'a self,
vk: &'a VerifyingKey<C>,
l_0: C::Scalar,
argument: &'a Argument,
theta: ChallengeTheta<C::Scalar>,
beta: ChallengeBeta<C::Scalar>,
gamma: ChallengeGamma<C::Scalar>,
advice_evals: &[C::Scalar],
fixed_evals: &[C::Scalar],
aux_evals: &[C::Scalar],
) -> impl Iterator<Item = C::Scalar> + 'a {
let product_expression = || {
// z'(X) (a'(X) + \beta) (s'(X) + \gamma)
// - 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)
let left = self.product_eval
* &(self.permuted_input_eval + &*beta)
* &(self.permuted_table_eval + &*gamma);
let compress_columns = |columns: &[Column<Any>]| {
columns
.iter()
.map(|column| {
let index = vk.cs.get_any_query_index(*column, 0);
match column.column_type() {
Any::Advice => advice_evals[index],
Any::Fixed => fixed_evals[index],
Any::Aux => aux_evals[index],
}
})
.fold(C::Scalar::zero(), |acc, eval| acc * &*theta + &eval)
};
let right = self.product_inv_eval
* &(compress_columns(&argument.input_columns) + &*beta)
* &(compress_columns(&argument.table_columns) + &*gamma);
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)
// - 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)
Some(product_expression()),
)
.chain(Some(
// l_0(X) * (a'(X) - s'(X)) = 0
l_0 * &(self.permuted_input_eval - &self.permuted_table_eval),
))
.chain(Some(
// (a(X)s(X))⋅(a(X)a(\omega{-1} X)) = 0
(self.permuted_input_eval - &self.permuted_table_eval)
* &(self.permuted_input_eval - &self.permuted_input_inv_eval),
))
}
pub(in crate::plonk) fn evals(&self) -> impl Iterator<Item = &C::Scalar> {
iter::empty()
.chain(Some(&self.product_eval))
.chain(Some(&self.product_inv_eval))
.chain(Some(&self.permuted_input_eval))
.chain(Some(&self.permuted_input_inv_eval))
.chain(Some(&self.permuted_table_eval))
}
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()
// Open lookup product commitments at x
.chain(Some(VerifierQuery {
point: *x,
commitment: &self.product_commitment,
eval: self.product_eval,
}))
// Open lookup input commitments at x
.chain(Some(VerifierQuery {
point: *x,
commitment: &self.permuted_input_commitment,
eval: self.permuted_input_eval,
}))
// Open lookup table commitments at x
.chain(Some(VerifierQuery {
point: *x,
commitment: &self.permuted_table_commitment,
eval: self.permuted_table_eval,
}))
// Open lookup input commitments at \omega^{-1} x
.chain(Some(VerifierQuery {
point: x_inv,
commitment: &self.permuted_input_commitment,
eval: self.permuted_input_inv_eval,
}))
// Open lookup product commitments at \omega^{-1} x
.chain(Some(VerifierQuery {
point: x_inv,
commitment: &self.product_commitment,
eval: self.product_inv_eval,
}))
}
}