mirror of https://github.com/zcash/halo2.git
commit
a05f48be8f
|
@ -20,6 +20,7 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) {
|
|||
// Initialize the polynomial commitment parameters
|
||||
let params: Params<EqAffine> = Params::new(k);
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct PLONKConfig {
|
||||
a: Column<Advice>,
|
||||
b: Column<Advice>,
|
||||
|
@ -43,6 +44,7 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) {
|
|||
fn copy(&mut self, a: Variable, b: Variable) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct MyCircuit<F: FieldExt> {
|
||||
a: Option<F>,
|
||||
k: u32,
|
||||
|
@ -241,7 +243,7 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) {
|
|||
|
||||
// Create a proof
|
||||
let mut transcript = DummyHashWrite::init(vec![], Fq::one());
|
||||
create_proof(¶ms, &pk, &circuit, &[], &mut transcript)
|
||||
create_proof(¶ms, &pk, &[circuit], &[], &mut transcript)
|
||||
.expect("proof generation should not fail")
|
||||
});
|
||||
});
|
||||
|
@ -253,7 +255,7 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) {
|
|||
|
||||
// Create a proof
|
||||
let mut transcript = DummyHashWrite::init(vec![], Fq::one());
|
||||
create_proof(¶ms, &pk, &circuit, &[], &mut transcript)
|
||||
create_proof(¶ms, &pk, &[circuit], &[], &mut transcript)
|
||||
.expect("proof generation should not fail");
|
||||
let proof = transcript.finalize();
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ use std::marker::PhantomData;
|
|||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Variable(Column<Advice>, usize);
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct PLONKConfig {
|
||||
a: Column<Advice>,
|
||||
b: Column<Advice>,
|
||||
|
@ -43,6 +44,7 @@ trait StandardCS<FF: FieldExt> {
|
|||
F: FnOnce() -> Result<FF, Error>;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct MyCircuit<F: FieldExt> {
|
||||
a: Option<F>,
|
||||
k: u32,
|
||||
|
@ -278,7 +280,7 @@ fn main() {
|
|||
|
||||
// Create a proof
|
||||
let mut transcript = DummyHashWrite::init(vec![], Fq::one());
|
||||
create_proof(¶ms, &pk, &circuit, &[pubinputs], &mut transcript)
|
||||
create_proof(¶ms, &pk, &[circuit], &[&[pubinputs]], &mut transcript)
|
||||
.expect("proof generation should not fail");
|
||||
let proof: Vec<u8> = transcript.finalize();
|
||||
|
||||
|
@ -288,7 +290,14 @@ fn main() {
|
|||
let pubinput_slice = &[pubinput];
|
||||
let msm = params.empty_msm();
|
||||
let mut transcript = DummyHashRead::init(&proof[..], Fq::one());
|
||||
let guard = verify_proof(¶ms, pk.get_vk(), msm, pubinput_slice, &mut transcript).unwrap();
|
||||
let guard = verify_proof(
|
||||
¶ms,
|
||||
pk.get_vk(),
|
||||
msm,
|
||||
&[pubinput_slice],
|
||||
&mut transcript,
|
||||
)
|
||||
.unwrap();
|
||||
let msm = guard.clone().use_challenges();
|
||||
assert!(msm.eval());
|
||||
|
||||
|
|
|
@ -62,12 +62,14 @@ pub enum VerifyFailure {
|
|||
/// };
|
||||
/// const K: u32 = 5;
|
||||
///
|
||||
/// #[derive(Copy, Clone)]
|
||||
/// struct MyConfig {
|
||||
/// a: Column<Advice>,
|
||||
/// b: Column<Advice>,
|
||||
/// c: Column<Advice>,
|
||||
/// }
|
||||
///
|
||||
/// #[derive(Clone)]
|
||||
/// struct MyCircuit {
|
||||
/// a: Option<u64>,
|
||||
/// b: Option<u64>,
|
||||
|
|
26
src/plonk.rs
26
src/plonk.rs
|
@ -164,6 +164,7 @@ fn test_proving() {
|
|||
// Initialize the polynomial commitment parameters
|
||||
let params: Params<EqAffine> = Params::new(K);
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct PLONKConfig {
|
||||
a: Column<Advice>,
|
||||
b: Column<Advice>,
|
||||
|
@ -197,6 +198,7 @@ fn test_proving() {
|
|||
fn lookup_table(&mut self, values: &[Vec<FF>]) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct MyCircuit<F: FieldExt> {
|
||||
a: Option<F>,
|
||||
lookup_tables: Vec<Vec<F>>,
|
||||
|
@ -507,18 +509,25 @@ fn test_proving() {
|
|||
create_proof(
|
||||
¶ms,
|
||||
&pk,
|
||||
&circuit,
|
||||
&[pubinputs.clone()],
|
||||
&[circuit.clone(), circuit.clone()],
|
||||
&[&[pubinputs.clone()], &[pubinputs.clone()]],
|
||||
&mut transcript,
|
||||
)
|
||||
.expect("proof generation should not fail");
|
||||
let proof: Vec<u8> = transcript.finalize();
|
||||
|
||||
let pubinput_slice = &[pubinput];
|
||||
let pubinput_slice_copy = &[pubinput];
|
||||
let msm = params.empty_msm();
|
||||
let mut transcript = DummyHashRead::init(&proof[..], Fq::one());
|
||||
let guard =
|
||||
verify_proof(¶ms, pk.get_vk(), msm, pubinput_slice, &mut transcript).unwrap();
|
||||
let guard = verify_proof(
|
||||
¶ms,
|
||||
pk.get_vk(),
|
||||
msm,
|
||||
&[pubinput_slice, pubinput_slice_copy],
|
||||
&mut transcript,
|
||||
)
|
||||
.unwrap();
|
||||
{
|
||||
let msm = guard.clone().use_challenges();
|
||||
assert!(msm.eval());
|
||||
|
@ -535,7 +544,14 @@ fn test_proving() {
|
|||
pk.get_vk().write(&mut vk_buffer).unwrap();
|
||||
let vk = VerifyingKey::<EqAffine>::read::<_, MyCircuit<Fp>>(&mut &vk_buffer[..], ¶ms)
|
||||
.unwrap();
|
||||
let guard = verify_proof(¶ms, &vk, msm, pubinput_slice, &mut transcript).unwrap();
|
||||
let guard = verify_proof(
|
||||
¶ms,
|
||||
&vk,
|
||||
msm,
|
||||
&[pubinput_slice, pubinput_slice_copy],
|
||||
&mut transcript,
|
||||
)
|
||||
.unwrap();
|
||||
{
|
||||
let msm = guard.clone().use_challenges();
|
||||
assert!(msm.eval());
|
||||
|
|
|
@ -158,7 +158,7 @@ pub trait Assignment<F: Field> {
|
|||
/// [`ConstraintSystem`] implementation.
|
||||
pub trait Circuit<F: Field> {
|
||||
/// This is a configuration object that stores things like columns.
|
||||
type Config;
|
||||
type Config: Copy;
|
||||
|
||||
/// The circuit is given an opportunity to describe the exact gate
|
||||
/// arrangement, column arrangement, etc.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::circuit::{Any, Column};
|
||||
|
||||
mod prover;
|
||||
mod verifier;
|
||||
pub(crate) mod prover;
|
||||
pub(crate) mod verifier;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct Argument {
|
||||
|
|
|
@ -7,8 +7,8 @@ use crate::{
|
|||
};
|
||||
|
||||
pub(crate) mod keygen;
|
||||
mod prover;
|
||||
mod verifier;
|
||||
pub(crate) mod prover;
|
||||
pub(crate) mod verifier;
|
||||
|
||||
use std::io;
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@ use std::iter;
|
|||
|
||||
use super::{
|
||||
circuit::{Advice, Assignment, Circuit, Column, ConstraintSystem, Fixed},
|
||||
vanishing, ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX, ChallengeY, Error,
|
||||
ProvingKey,
|
||||
lookup, permutation, vanishing, ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX,
|
||||
ChallengeY, Error, ProvingKey,
|
||||
};
|
||||
use crate::arithmetic::{eval_polynomial, Curve, CurveAffine, FieldExt};
|
||||
use crate::poly::{
|
||||
commitment::{Blind, Params},
|
||||
multiopen::{self, ProverQuery},
|
||||
LagrangeCoeff, Polynomial,
|
||||
Coeff, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial,
|
||||
};
|
||||
use crate::transcript::TranscriptWrite;
|
||||
|
||||
|
@ -20,50 +20,13 @@ use crate::transcript::TranscriptWrite;
|
|||
pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circuit<C::Scalar>>(
|
||||
params: &Params<C>,
|
||||
pk: &ProvingKey<C>,
|
||||
circuit: &ConcreteCircuit,
|
||||
aux: &[Polynomial<C::Scalar, LagrangeCoeff>],
|
||||
circuits: &[ConcreteCircuit],
|
||||
auxs: &[&[Polynomial<C::Scalar, LagrangeCoeff>]],
|
||||
transcript: &mut T,
|
||||
) -> Result<(), Error> {
|
||||
if aux.len() != pk.vk.cs.num_aux_columns {
|
||||
return Err(Error::IncompatibleParams);
|
||||
}
|
||||
|
||||
struct WitnessCollection<F: Field> {
|
||||
advice: Vec<Polynomial<F, LagrangeCoeff>>,
|
||||
_marker: std::marker::PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F: Field> Assignment<F> for WitnessCollection<F> {
|
||||
fn assign_advice(
|
||||
&mut self,
|
||||
column: Column<Advice>,
|
||||
row: usize,
|
||||
to: impl FnOnce() -> Result<F, Error>,
|
||||
) -> Result<(), Error> {
|
||||
*self
|
||||
.advice
|
||||
.get_mut(column.index())
|
||||
.and_then(|v| v.get_mut(row))
|
||||
.ok_or(Error::BoundsFailure)? = to()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn assign_fixed(
|
||||
&mut self,
|
||||
_: Column<Fixed>,
|
||||
_: usize,
|
||||
_: impl FnOnce() -> Result<F, Error>,
|
||||
) -> Result<(), Error> {
|
||||
// We only care about advice columns here
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn copy(&mut self, _: usize, _: usize, _: usize, _: usize, _: usize) -> Result<(), Error> {
|
||||
// We only care about advice columns here
|
||||
|
||||
Ok(())
|
||||
for aux in auxs.iter() {
|
||||
if aux.len() != pk.vk.cs.num_aux_columns {
|
||||
return Err(Error::IncompatibleParams);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,113 +34,199 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
|
|||
let mut meta = ConstraintSystem::default();
|
||||
let config = ConcreteCircuit::configure(&mut meta);
|
||||
|
||||
let mut witness = WitnessCollection {
|
||||
advice: vec![domain.empty_lagrange(); meta.num_advice_columns],
|
||||
_marker: std::marker::PhantomData,
|
||||
};
|
||||
|
||||
// Synthesize the circuit to obtain the witness and other information.
|
||||
circuit.synthesize(&mut witness, config)?;
|
||||
|
||||
let witness = witness;
|
||||
|
||||
// Compute commitments to aux column polynomials
|
||||
let aux_commitments_projective: Vec<_> = aux
|
||||
.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);
|
||||
metrics::counter!("aux_commitments", aux_commitments.len() as u64);
|
||||
|
||||
for commitment in &aux_commitments {
|
||||
transcript
|
||||
.common_point(*commitment)
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
struct AuxSingle<'a, C: CurveAffine> {
|
||||
pub aux_values: &'a [Polynomial<C::Scalar, LagrangeCoeff>],
|
||||
pub aux_polys: Vec<Polynomial<C::Scalar, Coeff>>,
|
||||
pub aux_cosets: Vec<Polynomial<C::Scalar, ExtendedLagrangeCoeff>>,
|
||||
}
|
||||
|
||||
let aux_polys: Vec<_> = aux
|
||||
let aux: Vec<AuxSingle<C>> = auxs
|
||||
.iter()
|
||||
.map(|poly| {
|
||||
let lagrange_vec = domain.lagrange_from_vec(poly.to_vec());
|
||||
domain.lagrange_to_coeff(lagrange_vec)
|
||||
.map(|aux| -> Result<AuxSingle<C>, Error> {
|
||||
let aux_commitments_projective: Vec<_> = aux
|
||||
.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);
|
||||
metrics::counter!("aux_commitments", aux_commitments.len() as u64);
|
||||
|
||||
for commitment in &aux_commitments {
|
||||
transcript
|
||||
.common_point(*commitment)
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
}
|
||||
|
||||
let aux_polys: Vec<_> = aux
|
||||
.iter()
|
||||
.map(|poly| {
|
||||
let lagrange_vec = domain.lagrange_from_vec(poly.to_vec());
|
||||
domain.lagrange_to_coeff(lagrange_vec)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let aux_cosets: Vec<_> = meta
|
||||
.aux_queries
|
||||
.iter()
|
||||
.map(|&(column, at)| {
|
||||
let poly = aux_polys[column.index()].clone();
|
||||
domain.coeff_to_extended(poly, at)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(AuxSingle {
|
||||
aux_values: *aux,
|
||||
aux_polys,
|
||||
aux_cosets,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let aux_cosets: Vec<_> = meta
|
||||
.aux_queries
|
||||
.iter()
|
||||
.map(|&(column, at)| {
|
||||
let poly = aux_polys[column.index()].clone();
|
||||
domain.coeff_to_extended(poly, at)
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Compute commitments to advice column polynomials
|
||||
let advice_blinds: Vec<_> = witness
|
||||
.advice
|
||||
.iter()
|
||||
.map(|_| Blind(C::Scalar::rand()))
|
||||
.collect();
|
||||
let advice_commitments_projective: Vec<_> = witness
|
||||
.advice
|
||||
.iter()
|
||||
.zip(advice_blinds.iter())
|
||||
.map(|(poly, blind)| params.commit_lagrange(poly, *blind))
|
||||
.collect();
|
||||
let mut advice_commitments = vec![C::zero(); advice_commitments_projective.len()];
|
||||
C::Projective::batch_to_affine(&advice_commitments_projective, &mut advice_commitments);
|
||||
let advice_commitments = advice_commitments;
|
||||
drop(advice_commitments_projective);
|
||||
metrics::counter!("advice_commitments", advice_commitments.len() as u64);
|
||||
|
||||
for commitment in &advice_commitments {
|
||||
transcript
|
||||
.write_point(*commitment)
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
struct AdviceSingle<C: CurveAffine> {
|
||||
pub advice_values: Vec<Polynomial<C::Scalar, LagrangeCoeff>>,
|
||||
pub advice_polys: Vec<Polynomial<C::Scalar, Coeff>>,
|
||||
pub advice_cosets: Vec<Polynomial<C::Scalar, ExtendedLagrangeCoeff>>,
|
||||
pub advice_blinds: Vec<Blind<C::Scalar>>,
|
||||
}
|
||||
|
||||
let advice_polys: Vec<_> = witness
|
||||
.advice
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|poly| domain.lagrange_to_coeff(poly))
|
||||
.collect();
|
||||
|
||||
let advice_cosets: Vec<_> = meta
|
||||
.advice_queries
|
||||
let advice: Vec<AdviceSingle<C>> = circuits
|
||||
.iter()
|
||||
.map(|&(column, at)| {
|
||||
let poly = advice_polys[column.index()].clone();
|
||||
domain.coeff_to_extended(poly, at)
|
||||
.map(|circuit| -> Result<AdviceSingle<C>, Error> {
|
||||
struct WitnessCollection<F: Field> {
|
||||
pub advice: Vec<Polynomial<F, LagrangeCoeff>>,
|
||||
_marker: std::marker::PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F: Field> Assignment<F> for WitnessCollection<F> {
|
||||
fn assign_advice(
|
||||
&mut self,
|
||||
column: Column<Advice>,
|
||||
row: usize,
|
||||
to: impl FnOnce() -> Result<F, Error>,
|
||||
) -> Result<(), Error> {
|
||||
*self
|
||||
.advice
|
||||
.get_mut(column.index())
|
||||
.and_then(|v| v.get_mut(row))
|
||||
.ok_or(Error::BoundsFailure)? = to()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn assign_fixed(
|
||||
&mut self,
|
||||
_: Column<Fixed>,
|
||||
_: usize,
|
||||
_: impl FnOnce() -> Result<F, Error>,
|
||||
) -> Result<(), Error> {
|
||||
// We only care about advice columns here
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn copy(
|
||||
&mut self,
|
||||
_: usize,
|
||||
_: usize,
|
||||
_: usize,
|
||||
_: usize,
|
||||
_: usize,
|
||||
) -> Result<(), Error> {
|
||||
// We only care about advice columns here
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
let mut witness = WitnessCollection {
|
||||
advice: vec![domain.empty_lagrange(); meta.num_advice_columns],
|
||||
_marker: std::marker::PhantomData,
|
||||
};
|
||||
|
||||
// Synthesize the circuit to obtain the witness and other information.
|
||||
circuit.synthesize(&mut witness, config)?;
|
||||
|
||||
let witness = witness;
|
||||
|
||||
// Compute commitments to advice column polynomials
|
||||
let advice_blinds: Vec<_> = witness
|
||||
.advice
|
||||
.iter()
|
||||
.map(|_| Blind(C::Scalar::rand()))
|
||||
.collect();
|
||||
let advice_commitments_projective: Vec<_> = witness
|
||||
.advice
|
||||
.iter()
|
||||
.zip(advice_blinds.iter())
|
||||
.map(|(poly, blind)| params.commit_lagrange(poly, *blind))
|
||||
.collect();
|
||||
let mut advice_commitments = vec![C::zero(); advice_commitments_projective.len()];
|
||||
C::Projective::batch_to_affine(&advice_commitments_projective, &mut advice_commitments);
|
||||
let advice_commitments = advice_commitments;
|
||||
drop(advice_commitments_projective);
|
||||
metrics::counter!("advice_commitments", advice_commitments.len() as u64);
|
||||
|
||||
for commitment in &advice_commitments {
|
||||
transcript
|
||||
.write_point(*commitment)
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
}
|
||||
|
||||
let advice_polys: Vec<_> = witness
|
||||
.advice
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|poly| domain.lagrange_to_coeff(poly))
|
||||
.collect();
|
||||
|
||||
let advice_cosets: Vec<_> = meta
|
||||
.advice_queries
|
||||
.iter()
|
||||
.map(|&(column, at)| {
|
||||
let poly = advice_polys[column.index()].clone();
|
||||
domain.coeff_to_extended(poly, at)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(AdviceSingle {
|
||||
advice_values: witness.advice,
|
||||
advice_polys,
|
||||
advice_cosets,
|
||||
advice_blinds,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// Sample theta challenge for keeping lookup columns linearly independent
|
||||
let theta = ChallengeTheta::get(transcript);
|
||||
|
||||
// Construct and commit to permuted values for each lookup
|
||||
let lookups = pk
|
||||
.vk
|
||||
.cs
|
||||
.lookups
|
||||
let lookups: Vec<Vec<lookup::prover::Permuted<'_, C>>> = aux
|
||||
.iter()
|
||||
.map(|lookup| {
|
||||
lookup.commit_permuted(
|
||||
&pk,
|
||||
¶ms,
|
||||
&domain,
|
||||
theta,
|
||||
&witness.advice,
|
||||
&pk.fixed_values,
|
||||
&aux,
|
||||
&advice_cosets,
|
||||
&pk.fixed_cosets,
|
||||
&aux_cosets,
|
||||
transcript,
|
||||
)
|
||||
.zip(advice.iter())
|
||||
.map(|(aux, advice)| -> Result<Vec<_>, Error> {
|
||||
// Construct and commit to permuted values for each lookup
|
||||
pk.vk
|
||||
.cs
|
||||
.lookups
|
||||
.iter()
|
||||
.map(|lookup| {
|
||||
lookup.commit_permuted(
|
||||
&pk,
|
||||
¶ms,
|
||||
&domain,
|
||||
theta,
|
||||
&advice.advice_values,
|
||||
&pk.fixed_values,
|
||||
&aux.aux_values,
|
||||
&advice.advice_cosets,
|
||||
&pk.fixed_cosets,
|
||||
&aux.aux_cosets,
|
||||
transcript,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
|
@ -187,89 +236,148 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
|
|||
// Sample gamma challenge
|
||||
let gamma = ChallengeGamma::get(transcript);
|
||||
|
||||
// Commit to permutations, if any.
|
||||
let permutations = pk
|
||||
.vk
|
||||
.cs
|
||||
.permutations
|
||||
let permutations: Vec<Vec<permutation::prover::Committed<C>>> = advice
|
||||
.iter()
|
||||
.zip(pk.permutations.iter())
|
||||
.map(|(p, pkey)| p.commit(params, pk, pkey, &witness.advice, beta, gamma, transcript))
|
||||
.map(|advice| -> Result<Vec<_>, Error> {
|
||||
// Commit to permutations, if any.
|
||||
pk.vk
|
||||
.cs
|
||||
.permutations
|
||||
.iter()
|
||||
.zip(pk.permutations.iter())
|
||||
.map(|(p, pkey)| {
|
||||
p.commit(
|
||||
params,
|
||||
pk,
|
||||
pkey,
|
||||
&advice.advice_values,
|
||||
beta,
|
||||
gamma,
|
||||
transcript,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// Construct and commit to products for each lookup
|
||||
let lookups = lookups
|
||||
let lookups: Vec<Vec<lookup::prover::Committed<'_, C>>> = lookups
|
||||
.into_iter()
|
||||
.map(|lookup| lookup.commit_product(&pk, ¶ms, theta, beta, gamma, transcript))
|
||||
.map(|lookups| -> Result<Vec<_>, _> {
|
||||
// Construct and commit to products for each lookup
|
||||
lookups
|
||||
.into_iter()
|
||||
.map(|lookup| lookup.commit_product(&pk, ¶ms, theta, beta, gamma, transcript))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// Obtain challenge for keeping all separate gates linearly independent
|
||||
let y = ChallengeY::get(transcript);
|
||||
|
||||
// Evaluate the h(X) polynomial's constraint system expressions for the permutation constraints, if any.
|
||||
let (permutations, permutation_expressions): (Vec<_>, Vec<_>) = {
|
||||
let tmp: Vec<_> = permutations
|
||||
.into_iter()
|
||||
.zip(pk.vk.cs.permutations.iter())
|
||||
.zip(pk.permutations.iter())
|
||||
.map(|((p, argument), pkey)| {
|
||||
p.construct(pk, argument, pkey, &advice_cosets, beta, gamma)
|
||||
})
|
||||
.collect();
|
||||
let (permutations, permutation_expressions): (Vec<Vec<_>>, Vec<Vec<_>>) = permutations
|
||||
.into_iter()
|
||||
.zip(advice.iter())
|
||||
.map(|(permutations, advice)| {
|
||||
// Evaluate the h(X) polynomial's constraint system expressions for the permutation constraints, if any.
|
||||
let tmp: Vec<_> = permutations
|
||||
.into_iter()
|
||||
.zip(pk.vk.cs.permutations.iter())
|
||||
.zip(pk.permutations.iter())
|
||||
.map(|((p, argument), pkey)| {
|
||||
p.construct(pk, argument, pkey, &advice.advice_cosets, beta, gamma)
|
||||
})
|
||||
.collect();
|
||||
|
||||
tmp.into_iter().unzip()
|
||||
};
|
||||
tmp.into_iter().unzip()
|
||||
})
|
||||
.unzip();
|
||||
|
||||
// Evaluate the h(X) polynomial's constraint system expressions for the lookup constraints, if any.
|
||||
let (lookups, lookup_expressions): (Vec<_>, Vec<_>) = {
|
||||
let tmp: Vec<_> = lookups
|
||||
.into_iter()
|
||||
.map(|p| p.construct(pk, theta, beta, gamma))
|
||||
.collect();
|
||||
let (lookups, lookup_expressions): (Vec<Vec<_>>, Vec<Vec<_>>) = lookups
|
||||
.into_iter()
|
||||
.map(|lookups| {
|
||||
// Evaluate the h(X) polynomial's constraint system expressions for the lookup constraints, if any.
|
||||
let tmp: Vec<_> = lookups
|
||||
.into_iter()
|
||||
.map(|p| p.construct(pk, theta, beta, gamma))
|
||||
.collect();
|
||||
|
||||
tmp.into_iter().unzip()
|
||||
};
|
||||
tmp.into_iter().unzip()
|
||||
})
|
||||
.unzip();
|
||||
|
||||
// Evaluate the h(X) polynomial's constraint system expressions for the constraints provided
|
||||
let expressions = iter::empty()
|
||||
// Custom constraints
|
||||
.chain(meta.gates.iter().map(|poly| {
|
||||
poly.evaluate(
|
||||
&|index| pk.fixed_cosets[index].clone(),
|
||||
&|index| advice_cosets[index].clone(),
|
||||
&|index| aux_cosets[index].clone(),
|
||||
&|a, b| a + &b,
|
||||
&|a, b| a * &b,
|
||||
&|a, scalar| a * scalar,
|
||||
)
|
||||
}))
|
||||
// Permutation constraints, if any.
|
||||
.chain(permutation_expressions.into_iter().flatten())
|
||||
// Lookup constraints, if any.
|
||||
.chain(lookup_expressions.into_iter().flatten());
|
||||
let expressions = advice
|
||||
.iter()
|
||||
.zip(aux.iter())
|
||||
.zip(permutation_expressions.into_iter())
|
||||
.zip(lookup_expressions.into_iter())
|
||||
.flat_map(
|
||||
|(((advice, aux), permutation_expressions), lookup_expressions)| {
|
||||
iter::empty()
|
||||
// Custom constraints
|
||||
.chain(meta.gates.iter().map(move |poly| {
|
||||
poly.evaluate(
|
||||
&|index| pk.fixed_cosets[index].clone(),
|
||||
&|index| advice.advice_cosets[index].clone(),
|
||||
&|index| aux.aux_cosets[index].clone(),
|
||||
&|a, b| a + &b,
|
||||
&|a, b| a * &b,
|
||||
&|a, scalar| a * scalar,
|
||||
)
|
||||
}))
|
||||
// Permutation constraints, if any.
|
||||
.chain(permutation_expressions.into_iter().flatten())
|
||||
// Lookup constraints, if any.
|
||||
.chain(lookup_expressions.into_iter().flatten())
|
||||
},
|
||||
);
|
||||
|
||||
// Construct the vanishing argument
|
||||
let vanishing = vanishing::Argument::construct(params, domain, expressions, y, transcript)?;
|
||||
|
||||
let x = ChallengeX::get(transcript);
|
||||
|
||||
// Evaluate polynomials at omega^i x
|
||||
let advice_evals: Vec<_> = meta
|
||||
.advice_queries
|
||||
.iter()
|
||||
.map(|&(column, at)| {
|
||||
eval_polynomial(&advice_polys[column.index()], domain.rotate_omega(*x, at))
|
||||
})
|
||||
.collect();
|
||||
// Compute and hash aux evals for each circuit instance
|
||||
for aux in aux.iter() {
|
||||
// Evaluate polynomials at omega^i x
|
||||
let aux_evals: Vec<_> = meta
|
||||
.aux_queries
|
||||
.iter()
|
||||
.map(|&(column, at)| {
|
||||
eval_polynomial(&aux.aux_polys[column.index()], domain.rotate_omega(*x, at))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let aux_evals: Vec<_> = meta
|
||||
.aux_queries
|
||||
.iter()
|
||||
.map(|&(column, at)| {
|
||||
eval_polynomial(&aux_polys[column.index()], domain.rotate_omega(*x, at))
|
||||
})
|
||||
.collect();
|
||||
// Hash each aux column evaluation
|
||||
for eval in aux_evals.iter() {
|
||||
transcript
|
||||
.write_scalar(*eval)
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute and hash advice evals for each circuit instance
|
||||
for advice in advice.iter() {
|
||||
// Evaluate polynomials at omega^i x
|
||||
let advice_evals: Vec<_> = meta
|
||||
.advice_queries
|
||||
.iter()
|
||||
.map(|&(column, at)| {
|
||||
eval_polynomial(
|
||||
&advice.advice_polys[column.index()],
|
||||
domain.rotate_omega(*x, at),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Hash each advice column evaluation
|
||||
for eval in advice_evals.iter() {
|
||||
transcript
|
||||
.write_scalar(*eval)
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute and hash fixed evals (shared across all circuit instances)
|
||||
let fixed_evals: Vec<_> = meta
|
||||
.fixed_queries
|
||||
.iter()
|
||||
|
@ -278,12 +386,8 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
|
|||
})
|
||||
.collect();
|
||||
|
||||
// Hash each column evaluation
|
||||
for eval in advice_evals
|
||||
.iter()
|
||||
.chain(aux_evals.iter())
|
||||
.chain(fixed_evals.iter())
|
||||
{
|
||||
// Hash each fixed column evaluation
|
||||
for eval in fixed_evals.iter() {
|
||||
transcript
|
||||
.write_scalar(*eval)
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
|
@ -292,41 +396,66 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
|
|||
let vanishing = vanishing.evaluate(x, transcript)?;
|
||||
|
||||
// Evaluate the permutations, if any, at omega^i x.
|
||||
let permutations = permutations
|
||||
let permutations: Vec<Vec<permutation::prover::Evaluated<C>>> = permutations
|
||||
.into_iter()
|
||||
.zip(pk.permutations.iter())
|
||||
.map(|(p, pkey)| p.evaluate(pk, pkey, x, transcript))
|
||||
.map(|permutations| -> Result<Vec<_>, _> {
|
||||
permutations
|
||||
.into_iter()
|
||||
.zip(pk.permutations.iter())
|
||||
.map(|(p, pkey)| p.evaluate(pk, pkey, x, transcript))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// Evaluate the lookups, if any, at omega^i x.
|
||||
let lookups = lookups
|
||||
let lookups: Vec<Vec<lookup::prover::Evaluated<C>>> = lookups
|
||||
.into_iter()
|
||||
.map(|p| p.evaluate(pk, x, transcript))
|
||||
.map(|lookups| -> Result<Vec<_>, _> {
|
||||
lookups
|
||||
.into_iter()
|
||||
.map(|p| p.evaluate(pk, x, transcript))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let instances = iter::empty()
|
||||
.chain(
|
||||
pk.vk
|
||||
.cs
|
||||
.advice_queries
|
||||
.iter()
|
||||
.map(|&(column, at)| ProverQuery {
|
||||
point: domain.rotate_omega(*x, at),
|
||||
poly: &advice_polys[column.index()],
|
||||
blind: advice_blinds[column.index()],
|
||||
}),
|
||||
)
|
||||
.chain(
|
||||
pk.vk
|
||||
.cs
|
||||
.aux_queries
|
||||
.iter()
|
||||
.map(|&(column, at)| ProverQuery {
|
||||
point: domain.rotate_omega(*x, at),
|
||||
poly: &aux_polys[column.index()],
|
||||
blind: Blind::default(),
|
||||
}),
|
||||
)
|
||||
let instances = aux
|
||||
.iter()
|
||||
.zip(advice.iter())
|
||||
.zip(permutations.iter())
|
||||
.zip(lookups.iter())
|
||||
.flat_map(|(((aux, advice), permutations), lookups)| {
|
||||
iter::empty()
|
||||
.chain(
|
||||
pk.vk
|
||||
.cs
|
||||
.aux_queries
|
||||
.iter()
|
||||
.map(move |&(column, at)| ProverQuery {
|
||||
point: domain.rotate_omega(*x, at),
|
||||
poly: &aux.aux_polys[column.index()],
|
||||
blind: Blind::default(),
|
||||
}),
|
||||
)
|
||||
.chain(
|
||||
pk.vk
|
||||
.cs
|
||||
.advice_queries
|
||||
.iter()
|
||||
.map(move |&(column, at)| ProverQuery {
|
||||
point: domain.rotate_omega(*x, at),
|
||||
poly: &advice.advice_polys[column.index()],
|
||||
blind: advice.advice_blinds[column.index()],
|
||||
}),
|
||||
)
|
||||
.chain(
|
||||
permutations
|
||||
.iter()
|
||||
.zip(pk.permutations.iter())
|
||||
.flat_map(move |(p, pkey)| p.open(pk, pkey, x))
|
||||
.into_iter(),
|
||||
)
|
||||
.chain(lookups.iter().flat_map(move |p| p.open(pk, x)).into_iter())
|
||||
})
|
||||
.chain(
|
||||
pk.vk
|
||||
.cs
|
||||
|
@ -339,16 +468,7 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
|
|||
}),
|
||||
)
|
||||
// We query the h(X) polynomial at x
|
||||
.chain(vanishing.open(x))
|
||||
.chain(
|
||||
permutations
|
||||
.iter()
|
||||
.zip(pk.permutations.iter())
|
||||
.map(|(p, pkey)| p.open(pk, pkey, x))
|
||||
.into_iter()
|
||||
.flatten(),
|
||||
)
|
||||
.chain(lookups.iter().map(|p| p.open(pk, x)).into_iter().flatten());
|
||||
.chain(vanishing.open(x));
|
||||
|
||||
multiopen::create_proof(params, transcript, instances).map_err(|_| Error::OpeningError)
|
||||
}
|
||||
|
|
|
@ -17,34 +17,46 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
|||
params: &'a Params<C>,
|
||||
vk: &VerifyingKey<C>,
|
||||
msm: MSM<'a, C>,
|
||||
aux_commitments: &[C],
|
||||
aux_commitments: &[&[C]],
|
||||
transcript: &mut T,
|
||||
) -> Result<Guard<'a, C>, Error> {
|
||||
// Check that aux_commitments matches the expected number of aux columns
|
||||
if aux_commitments.len() != vk.cs.num_aux_columns {
|
||||
return Err(Error::IncompatibleParams);
|
||||
for aux_commitments in aux_commitments.iter() {
|
||||
if aux_commitments.len() != vk.cs.num_aux_columns {
|
||||
return Err(Error::IncompatibleParams);
|
||||
}
|
||||
}
|
||||
|
||||
// Hash the aux (external) commitments into the transcript
|
||||
for commitment in aux_commitments {
|
||||
transcript
|
||||
.common_point(*commitment)
|
||||
.map_err(|_| Error::TranscriptError)?
|
||||
let num_proofs = aux_commitments.len();
|
||||
|
||||
for aux_commitments in aux_commitments.iter() {
|
||||
// Hash the aux (external) commitments into the transcript
|
||||
for commitment in *aux_commitments {
|
||||
transcript
|
||||
.common_point(*commitment)
|
||||
.map_err(|_| Error::TranscriptError)?
|
||||
}
|
||||
}
|
||||
|
||||
// Hash the prover's advice commitments into the transcript
|
||||
let advice_commitments =
|
||||
read_n_points(transcript, vk.cs.num_advice_columns).map_err(|_| Error::TranscriptError)?;
|
||||
let advice_commitments = (0..num_proofs)
|
||||
.map(|_| -> Result<Vec<_>, _> {
|
||||
// Hash the prover's advice commitments into the transcript
|
||||
read_n_points(transcript, vk.cs.num_advice_columns).map_err(|_| Error::TranscriptError)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// Sample theta challenge for keeping lookup columns linearly independent
|
||||
let theta = ChallengeTheta::get(transcript);
|
||||
|
||||
// Hash each lookup permuted commitment
|
||||
let lookups = vk
|
||||
.cs
|
||||
.lookups
|
||||
.iter()
|
||||
.map(|argument| argument.read_permuted_commitments(transcript))
|
||||
let lookups_permuted = (0..num_proofs)
|
||||
.map(|_| -> Result<Vec<_>, _> {
|
||||
// Hash each lookup permuted commitment
|
||||
vk.cs
|
||||
.lookups
|
||||
.iter()
|
||||
.map(|argument| argument.read_permuted_commitments(transcript))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// Sample beta challenge
|
||||
|
@ -53,18 +65,26 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
|||
// Sample gamma challenge
|
||||
let gamma = ChallengeGamma::get(transcript);
|
||||
|
||||
// Hash each permutation product commitment
|
||||
let permutations = vk
|
||||
.cs
|
||||
.permutations
|
||||
.iter()
|
||||
.map(|argument| argument.read_product_commitment(transcript))
|
||||
let permutations_committed = (0..num_proofs)
|
||||
.map(|_| -> Result<Vec<_>, _> {
|
||||
// Hash each permutation product commitment
|
||||
vk.cs
|
||||
.permutations
|
||||
.iter()
|
||||
.map(|argument| argument.read_product_commitment(transcript))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// Hash each lookup product commitment
|
||||
let lookups = lookups
|
||||
let lookups_committed = lookups_permuted
|
||||
.into_iter()
|
||||
.map(|lookup| lookup.read_product_commitment(transcript))
|
||||
.map(|lookups| {
|
||||
// Hash each lookup product commitment
|
||||
lookups
|
||||
.into_iter()
|
||||
.map(|lookup| lookup.read_product_commitment(transcript))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// Sample y challenge, which keeps the gates linearly independent.
|
||||
|
@ -76,24 +96,43 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
|||
// satisfied with high probability.
|
||||
let x = ChallengeX::get(transcript);
|
||||
|
||||
let advice_evals = read_n_scalars(transcript, vk.cs.advice_queries.len())
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
let aux_evals =
|
||||
read_n_scalars(transcript, vk.cs.aux_queries.len()).map_err(|_| Error::TranscriptError)?;
|
||||
let aux_evals = (0..num_proofs)
|
||||
.map(|_| -> Result<Vec<_>, _> {
|
||||
read_n_scalars(transcript, vk.cs.aux_queries.len()).map_err(|_| Error::TranscriptError)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let advice_evals = (0..num_proofs)
|
||||
.map(|_| -> Result<Vec<_>, _> {
|
||||
read_n_scalars(transcript, vk.cs.advice_queries.len())
|
||||
.map_err(|_| Error::TranscriptError)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let fixed_evals = read_n_scalars(transcript, vk.cs.fixed_queries.len())
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
|
||||
let vanishing = vanishing.evaluate(transcript)?;
|
||||
|
||||
let permutations = permutations
|
||||
let permutations_evaluated = permutations_committed
|
||||
.into_iter()
|
||||
.zip(vk.permutations.iter())
|
||||
.map(|(permutation, vkey)| permutation.evaluate(vkey, transcript))
|
||||
.map(|permutations| -> Result<Vec<_>, _> {
|
||||
permutations
|
||||
.into_iter()
|
||||
.zip(vk.permutations.iter())
|
||||
.map(|(permutation, vkey)| permutation.evaluate(vkey, transcript))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let lookups = lookups
|
||||
let lookups_evaluated = lookups_committed
|
||||
.into_iter()
|
||||
.map(|lookup| lookup.evaluate(transcript))
|
||||
.map(|lookups| -> Result<Vec<_>, _> {
|
||||
lookups
|
||||
.into_iter()
|
||||
.map(|lookup| lookup.evaluate(transcript))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// This check ensures the circuit is satisfied so long as the polynomial
|
||||
|
@ -109,74 +148,101 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
|||
* &vk.domain.get_barycentric_weight(); // l_0(x)
|
||||
|
||||
// Compute the expected value of h(x)
|
||||
let expressions = std::iter::empty()
|
||||
// Evaluate the circuit using the custom gates provided
|
||||
.chain(vk.cs.gates.iter().map(|poly| {
|
||||
poly.evaluate(
|
||||
&|index| fixed_evals[index],
|
||||
&|index| advice_evals[index],
|
||||
&|index| aux_evals[index],
|
||||
&|a, b| a + &b,
|
||||
&|a, b| a * &b,
|
||||
&|a, scalar| a * &scalar,
|
||||
)
|
||||
}))
|
||||
.chain(
|
||||
permutations
|
||||
.iter()
|
||||
.zip(vk.cs.permutations.iter())
|
||||
.map(|(p, argument)| {
|
||||
p.expressions(vk, argument, &advice_evals, l_0, beta, gamma, x)
|
||||
})
|
||||
.into_iter()
|
||||
.flatten(),
|
||||
)
|
||||
.chain(
|
||||
lookups
|
||||
.iter()
|
||||
.zip(vk.cs.lookups.iter())
|
||||
.map(|(p, argument)| {
|
||||
p.expressions(
|
||||
vk,
|
||||
l_0,
|
||||
argument,
|
||||
theta,
|
||||
beta,
|
||||
gamma,
|
||||
&advice_evals,
|
||||
&fixed_evals,
|
||||
&aux_evals,
|
||||
let expressions = advice_evals
|
||||
.iter()
|
||||
.zip(aux_evals.iter())
|
||||
.zip(permutations_evaluated.iter())
|
||||
.zip(lookups_evaluated.iter())
|
||||
.flat_map(|(((advice_evals, aux_evals), permutations), lookups)| {
|
||||
let fixed_evals = fixed_evals.clone();
|
||||
let fixed_evals_copy = fixed_evals.clone();
|
||||
|
||||
std::iter::empty()
|
||||
// Evaluate the circuit using the custom gates provided
|
||||
.chain(vk.cs.gates.iter().map(move |poly| {
|
||||
poly.evaluate(
|
||||
&|index| fixed_evals[index],
|
||||
&|index| advice_evals[index],
|
||||
&|index| aux_evals[index],
|
||||
&|a, b| a + &b,
|
||||
&|a, b| a * &b,
|
||||
&|a, scalar| a * &scalar,
|
||||
)
|
||||
})
|
||||
.into_iter()
|
||||
.flatten(),
|
||||
);
|
||||
}))
|
||||
.chain(
|
||||
permutations
|
||||
.iter()
|
||||
.zip(vk.cs.permutations.iter())
|
||||
.flat_map(move |(p, argument)| {
|
||||
p.expressions(vk, argument, &advice_evals, l_0, beta, gamma, x)
|
||||
})
|
||||
.into_iter(),
|
||||
)
|
||||
.chain(
|
||||
lookups
|
||||
.iter()
|
||||
.zip(vk.cs.lookups.iter())
|
||||
.flat_map(move |(p, argument)| {
|
||||
p.expressions(
|
||||
vk,
|
||||
l_0,
|
||||
argument,
|
||||
theta,
|
||||
beta,
|
||||
gamma,
|
||||
&advice_evals,
|
||||
&fixed_evals_copy,
|
||||
&aux_evals,
|
||||
)
|
||||
})
|
||||
.into_iter(),
|
||||
)
|
||||
});
|
||||
|
||||
vanishing.verify(expressions, y, xn)?;
|
||||
}
|
||||
|
||||
let queries = iter::empty()
|
||||
.chain(
|
||||
vk.cs
|
||||
.advice_queries
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(query_index, &(column, at))| VerifierQuery {
|
||||
point: vk.domain.rotate_omega(*x, at),
|
||||
commitment: &advice_commitments[column.index()],
|
||||
eval: advice_evals[query_index],
|
||||
}),
|
||||
)
|
||||
.chain(
|
||||
vk.cs
|
||||
.aux_queries
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(query_index, &(column, at))| VerifierQuery {
|
||||
point: vk.domain.rotate_omega(*x, at),
|
||||
commitment: &aux_commitments[column.index()],
|
||||
eval: aux_evals[query_index],
|
||||
}),
|
||||
let queries = aux_commitments
|
||||
.iter()
|
||||
.zip(aux_evals.iter())
|
||||
.zip(advice_commitments.iter())
|
||||
.zip(advice_evals.iter())
|
||||
.zip(permutations_evaluated.iter())
|
||||
.zip(lookups_evaluated.iter())
|
||||
.flat_map(
|
||||
|(
|
||||
((((aux_commitments, aux_evals), advice_commitments), advice_evals), permutations),
|
||||
lookups,
|
||||
)| {
|
||||
iter::empty()
|
||||
.chain(vk.cs.aux_queries.iter().enumerate().map(
|
||||
move |(query_index, &(column, at))| VerifierQuery {
|
||||
point: vk.domain.rotate_omega(*x, at),
|
||||
commitment: &aux_commitments[column.index()],
|
||||
eval: aux_evals[query_index],
|
||||
},
|
||||
))
|
||||
.chain(vk.cs.advice_queries.iter().enumerate().map(
|
||||
move |(query_index, &(column, at))| VerifierQuery {
|
||||
point: vk.domain.rotate_omega(*x, at),
|
||||
commitment: &advice_commitments[column.index()],
|
||||
eval: advice_evals[query_index],
|
||||
},
|
||||
))
|
||||
.chain(
|
||||
permutations
|
||||
.iter()
|
||||
.zip(vk.permutations.iter())
|
||||
.flat_map(move |(p, vkey)| p.queries(vk, vkey, x))
|
||||
.into_iter(),
|
||||
)
|
||||
.chain(
|
||||
lookups
|
||||
.iter()
|
||||
.flat_map(move |p| p.queries(vk, x))
|
||||
.into_iter(),
|
||||
)
|
||||
},
|
||||
)
|
||||
.chain(
|
||||
vk.cs
|
||||
|
@ -189,22 +255,7 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
|||
eval: fixed_evals[query_index],
|
||||
}),
|
||||
)
|
||||
.chain(vanishing.queries(x))
|
||||
.chain(
|
||||
permutations
|
||||
.iter()
|
||||
.zip(vk.permutations.iter())
|
||||
.map(|(p, vkey)| p.queries(vk, vkey, x))
|
||||
.into_iter()
|
||||
.flatten(),
|
||||
)
|
||||
.chain(
|
||||
lookups
|
||||
.iter()
|
||||
.map(|p| p.queries(vk, x))
|
||||
.into_iter()
|
||||
.flatten(),
|
||||
);
|
||||
.chain(vanishing.queries(x));
|
||||
|
||||
// We are now convinced the circuit is satisfied so long as the
|
||||
// polynomial commitments open to the correct values.
|
||||
|
|
Loading…
Reference in New Issue