2021-03-03 09:52:24 -08:00
|
|
|
use std::iter;
|
|
|
|
|
2021-02-26 16:12:38 -08:00
|
|
|
use ff::Field;
|
2021-02-22 11:02:53 -08:00
|
|
|
use group::Curve;
|
|
|
|
|
2020-12-23 12:03:31 -08:00
|
|
|
use super::Argument;
|
2020-12-02 07:16:37 -08:00
|
|
|
use crate::{
|
2021-03-03 09:52:24 -08:00
|
|
|
arithmetic::{eval_polynomial, CurveAffine, FieldExt},
|
2021-02-26 16:12:38 -08:00
|
|
|
plonk::{ChallengeX, ChallengeY, Error},
|
2020-12-02 07:16:37 -08:00
|
|
|
poly::{
|
|
|
|
commitment::{Blind, Params},
|
|
|
|
multiopen::ProverQuery,
|
|
|
|
Coeff, EvaluationDomain, ExtendedLagrangeCoeff, Polynomial,
|
|
|
|
},
|
2021-04-30 18:28:50 -07:00
|
|
|
transcript::{EncodedChallenge, TranscriptWrite},
|
2020-12-02 07:16:37 -08:00
|
|
|
};
|
|
|
|
|
2021-03-03 09:52:24 -08:00
|
|
|
pub(in crate::plonk) struct Committed<C: CurveAffine> {
|
|
|
|
random_poly: Polynomial<C::Scalar, Coeff>,
|
|
|
|
random_blind: Blind<C::Scalar>,
|
|
|
|
}
|
|
|
|
|
2020-12-02 07:16:37 -08:00
|
|
|
pub(in crate::plonk) struct Constructed<C: CurveAffine> {
|
|
|
|
h_pieces: Vec<Polynomial<C::Scalar, Coeff>>,
|
|
|
|
h_blinds: Vec<Blind<C::Scalar>>,
|
2021-07-13 15:19:44 -07:00
|
|
|
committed: Committed<C>,
|
2020-12-02 07:16:37 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
pub(in crate::plonk) struct Evaluated<C: CurveAffine> {
|
2021-02-26 16:12:38 -08:00
|
|
|
h_poly: Polynomial<C::Scalar, Coeff>,
|
|
|
|
h_blind: Blind<C::Scalar>,
|
2021-07-13 15:19:44 -07:00
|
|
|
committed: Committed<C>,
|
2020-12-02 07:16:37 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<C: CurveAffine> Argument<C> {
|
2021-03-03 09:52:24 -08:00
|
|
|
pub(in crate::plonk) fn commit<E: EncodedChallenge<C>, T: TranscriptWrite<C, E>>(
|
|
|
|
params: &Params<C>,
|
|
|
|
domain: &EvaluationDomain<C::Scalar>,
|
|
|
|
transcript: &mut T,
|
|
|
|
) -> Result<Committed<C>, Error> {
|
|
|
|
// Sample a random polynomial of degree n - 1
|
|
|
|
let mut random_poly = domain.empty_coeff();
|
|
|
|
for coeff in random_poly.iter_mut() {
|
|
|
|
*coeff = C::Scalar::rand();
|
|
|
|
}
|
|
|
|
// Sample a random blinding factor
|
|
|
|
let random_blind = Blind(C::Scalar::rand());
|
|
|
|
|
|
|
|
// Commit
|
|
|
|
let c = params.commit(&random_poly, random_blind).to_affine();
|
|
|
|
transcript
|
|
|
|
.write_point(c)
|
|
|
|
.map_err(|_| Error::TranscriptError)?;
|
|
|
|
|
|
|
|
Ok(Committed {
|
|
|
|
random_poly,
|
|
|
|
random_blind,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<C: CurveAffine> Committed<C> {
|
2021-05-07 07:21:54 -07:00
|
|
|
pub(in crate::plonk) fn construct<E: EncodedChallenge<C>, T: TranscriptWrite<C, E>>(
|
2021-03-03 09:52:24 -08:00
|
|
|
self,
|
2020-12-02 07:16:37 -08:00
|
|
|
params: &Params<C>,
|
|
|
|
domain: &EvaluationDomain<C::Scalar>,
|
|
|
|
expressions: impl Iterator<Item = Polynomial<C::Scalar, ExtendedLagrangeCoeff>>,
|
2020-12-23 12:03:31 -08:00
|
|
|
y: ChallengeY<C>,
|
|
|
|
transcript: &mut T,
|
2020-12-02 07:16:37 -08:00
|
|
|
) -> Result<Constructed<C>, Error> {
|
|
|
|
// Evaluate the h(X) polynomial's constraint system expressions for the constraints provided
|
|
|
|
let h_poly = expressions.fold(domain.empty_extended(), |h_poly, v| h_poly * *y + &v);
|
|
|
|
|
|
|
|
// Divide by t(X) = X^{params.n} - 1.
|
|
|
|
let h_poly = domain.divide_by_vanishing_poly(h_poly);
|
|
|
|
|
|
|
|
// Obtain final h(X) polynomial
|
|
|
|
let h_poly = domain.extended_to_coeff(h_poly);
|
|
|
|
|
|
|
|
// Split h(X) up into pieces
|
|
|
|
let h_pieces = h_poly
|
|
|
|
.chunks_exact(params.n as usize)
|
|
|
|
.map(|v| domain.coeff_from_vec(v.to_vec()))
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
drop(h_poly);
|
|
|
|
let h_blinds: Vec<_> = h_pieces.iter().map(|_| Blind(C::Scalar::rand())).collect();
|
|
|
|
|
|
|
|
// Compute commitments to each h(X) piece
|
|
|
|
let h_commitments_projective: Vec<_> = h_pieces
|
|
|
|
.iter()
|
|
|
|
.zip(h_blinds.iter())
|
2021-06-21 10:19:15 -07:00
|
|
|
.map(|(h_piece, blind)| params.commit(h_piece, *blind))
|
2020-12-02 07:16:37 -08:00
|
|
|
.collect();
|
2021-02-22 10:39:14 -08:00
|
|
|
let mut h_commitments = vec![C::identity(); h_commitments_projective.len()];
|
|
|
|
C::Curve::batch_normalize(&h_commitments_projective, &mut h_commitments);
|
2020-12-02 07:16:37 -08:00
|
|
|
let h_commitments = h_commitments;
|
|
|
|
|
|
|
|
// Hash each h(X) piece
|
|
|
|
for c in h_commitments.iter() {
|
|
|
|
transcript
|
2020-12-23 12:03:31 -08:00
|
|
|
.write_point(*c)
|
2020-12-02 07:16:37 -08:00
|
|
|
.map_err(|_| Error::TranscriptError)?;
|
|
|
|
}
|
|
|
|
|
2021-03-03 09:52:24 -08:00
|
|
|
Ok(Constructed {
|
|
|
|
h_pieces,
|
|
|
|
h_blinds,
|
2021-07-13 15:19:44 -07:00
|
|
|
committed: self,
|
2021-03-03 09:52:24 -08:00
|
|
|
})
|
2020-12-02 07:16:37 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<C: CurveAffine> Constructed<C> {
|
2021-03-03 09:52:24 -08:00
|
|
|
pub(in crate::plonk) fn evaluate<E: EncodedChallenge<C>, T: TranscriptWrite<C, E>>(
|
2020-12-02 07:16:37 -08:00
|
|
|
self,
|
2021-03-03 09:52:24 -08:00
|
|
|
x: ChallengeX<C>,
|
2021-02-26 16:12:38 -08:00
|
|
|
xn: C::Scalar,
|
|
|
|
domain: &EvaluationDomain<C::Scalar>,
|
2021-03-03 09:52:24 -08:00
|
|
|
transcript: &mut T,
|
|
|
|
) -> Result<Evaluated<C>, Error> {
|
2021-02-26 16:12:38 -08:00
|
|
|
let h_poly = self
|
2020-12-02 07:16:37 -08:00
|
|
|
.h_pieces
|
|
|
|
.iter()
|
2021-02-26 16:12:38 -08:00
|
|
|
.rev()
|
|
|
|
.fold(domain.empty_coeff(), |acc, eval| acc * xn + eval);
|
2020-12-02 07:16:37 -08:00
|
|
|
|
2021-02-26 16:12:38 -08:00
|
|
|
let h_blind = self
|
|
|
|
.h_blinds
|
|
|
|
.iter()
|
|
|
|
.rev()
|
|
|
|
.fold(Blind(C::Scalar::zero()), |acc, eval| {
|
|
|
|
acc * Blind(xn) + *eval
|
|
|
|
});
|
2020-12-02 07:16:37 -08:00
|
|
|
|
2021-07-13 15:19:44 -07:00
|
|
|
let random_eval = eval_polynomial(&self.committed.random_poly, *x);
|
2021-03-03 09:52:24 -08:00
|
|
|
transcript
|
|
|
|
.write_scalar(random_eval)
|
|
|
|
.map_err(|_| Error::TranscriptError)?;
|
|
|
|
|
|
|
|
Ok(Evaluated {
|
|
|
|
h_poly,
|
|
|
|
h_blind,
|
2021-07-13 15:19:44 -07:00
|
|
|
committed: self.committed,
|
2021-03-03 09:52:24 -08:00
|
|
|
})
|
2020-12-02 07:16:37 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<C: CurveAffine> Evaluated<C> {
|
2021-01-14 05:16:56 -08:00
|
|
|
pub(in crate::plonk) fn open(
|
|
|
|
&self,
|
2020-12-23 12:03:31 -08:00
|
|
|
x: ChallengeX<C>,
|
2021-01-14 05:16:56 -08:00
|
|
|
) -> impl Iterator<Item = ProverQuery<'_, C>> + Clone {
|
2021-03-03 09:52:24 -08:00
|
|
|
iter::empty()
|
|
|
|
.chain(Some(ProverQuery {
|
|
|
|
point: *x,
|
|
|
|
poly: &self.h_poly,
|
|
|
|
blind: self.h_blind,
|
|
|
|
}))
|
|
|
|
.chain(Some(ProverQuery {
|
|
|
|
point: *x,
|
2021-07-13 15:19:44 -07:00
|
|
|
poly: &self.committed.random_poly,
|
|
|
|
blind: self.committed.random_blind,
|
2021-03-03 09:52:24 -08:00
|
|
|
}))
|
2020-12-02 07:16:37 -08:00
|
|
|
}
|
|
|
|
}
|