use midnight_proofs::{
circuit::Layouter,
plonk::{ConstraintSystem, Error},
poly::CommitmentLabel,
};
use crate::{
field::AssignedNative,
verifier::{
kzg::VerifierQuery, transcript_gadget::TranscriptGadget, utils::AssignedBoundedScalar,
SelfEmulation,
},
};
#[derive(Clone, Debug)]
pub(crate) struct Committed<S: SelfEmulation> {
permutation_product_commitments: Vec<S::AssignedPoint>,
}
#[derive(Clone, Debug)]
pub(crate) struct EvaluatedSet<S: SelfEmulation> {
pub(crate) permutation_product_eval: AssignedNative<S::F>,
pub(crate) permutation_product_next_eval: AssignedNative<S::F>,
pub(crate) permutation_product_last_eval: Option<AssignedNative<S::F>>,
}
#[derive(Clone, Debug)]
pub(crate) struct CommonEvaluated<S: SelfEmulation> {
pub(crate) permutation_evals: Vec<AssignedNative<S::F>>,
}
#[derive(Clone, Debug)]
pub(crate) struct Evaluated<S: SelfEmulation> {
coms: Committed<S>,
pub(crate) sets: Vec<EvaluatedSet<S>>,
}
pub(crate) fn read_product_commitments<S: SelfEmulation>(
layouter: &mut impl Layouter<S::F>,
transcript_gadget: &mut TranscriptGadget<S>,
cs: &ConstraintSystem<S::F>,
) -> Result<Committed<S>, Error> {
let chunk_len = cs.degree() - 2;
let permutation_product_commitments = cs
.permutation()
.get_columns()
.chunks(chunk_len)
.map(|_| transcript_gadget.read_point(layouter))
.collect::<Result<Vec<_>, _>>()?;
Ok(Committed {
permutation_product_commitments,
})
}
pub(crate) fn evaluate_permutation_common<S: SelfEmulation>(
layouter: &mut impl Layouter<S::F>,
transcript_gadget: &mut TranscriptGadget<S>,
nb_perm_commitments: usize,
) -> Result<CommonEvaluated<S>, Error> {
let permutation_evals = (0..nb_perm_commitments)
.map(|_| transcript_gadget.read_scalar(layouter))
.collect::<Result<Vec<_>, _>>()?;
Ok(CommonEvaluated { permutation_evals })
}
impl<S: SelfEmulation> Committed<S> {
pub(crate) fn evaluate(
self,
layouter: &mut impl Layouter<S::F>,
transcript_gadget: &mut TranscriptGadget<S>,
) -> Result<Evaluated<S>, Error> {
let mut sets = vec![];
let mut iter = self.permutation_product_commitments.iter();
while iter.next().is_some() {
let permutation_product_eval = transcript_gadget.read_scalar(layouter)?;
let permutation_product_next_eval = transcript_gadget.read_scalar(layouter)?;
let permutation_product_last_eval = if iter.len() > 0 {
Some(transcript_gadget.read_scalar(layouter)?)
} else {
None
};
sets.push(EvaluatedSet {
permutation_product_eval,
permutation_product_next_eval,
permutation_product_last_eval,
});
}
Ok(Evaluated { coms: self, sets })
}
}
impl<S: SelfEmulation> Evaluated<S> {
pub(crate) fn queries(
&self,
one: &AssignedBoundedScalar<S::F>, x: &AssignedNative<S::F>, x_next: &AssignedNative<S::F>, x_last: &AssignedNative<S::F>, ) -> Vec<VerifierQuery<S>> {
let mut queries = vec![];
for (i, set) in self.sets.iter().enumerate() {
queries.push(VerifierQuery::new(
one,
x,
CommitmentLabel::NoLabel,
&self.coms.permutation_product_commitments[i],
&set.permutation_product_eval,
));
queries.push(VerifierQuery::new(
one,
x_next,
CommitmentLabel::NoLabel,
&self.coms.permutation_product_commitments[i],
&set.permutation_product_next_eval,
));
}
for (i, set) in self.sets.iter().enumerate().rev().skip(1) {
queries.push(VerifierQuery::new(
one,
x_last,
CommitmentLabel::NoLabel,
&self.coms.permutation_product_commitments[i],
set.permutation_product_last_eval.as_ref().unwrap(),
));
}
queries
}
}
impl<S: SelfEmulation> CommonEvaluated<S> {
pub(crate) fn queries(
&self,
commitment_names: &[String],
one: &AssignedBoundedScalar<S::F>, x: &AssignedNative<S::F>, ) -> Vec<VerifierQuery<S>> {
assert_eq!(commitment_names.len(), self.permutation_evals.len());
commitment_names
.iter()
.enumerate()
.zip(self.permutation_evals.iter())
.map(|((i, com_name), eval)| {
VerifierQuery::new_fixed(one, x, CommitmentLabel::Permutation(i), com_name, eval)
})
.collect()
}
}