Skip to content

Commit

Permalink
feat: add pcs::univariate::{hyrax,ipa}
Browse files Browse the repository at this point in the history
  • Loading branch information
han0110 committed Oct 21, 2023
1 parent 1014eba commit ca985fc
Show file tree
Hide file tree
Showing 13 changed files with 985 additions and 204 deletions.
10 changes: 5 additions & 5 deletions plonkish_backend/src/pcs/multilinear.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ mod kzg;
mod zeromorph;

pub use brakedown::{
MultilinearBrakedown, MultilinearBrakedownCommitment, MultilinearBrakedownParams,
MultilinearBrakedown, MultilinearBrakedownCommitment, MultilinearBrakedownParam,
};
pub use gemini::Gemini;
pub use hyrax::{MultilinearHyrax, MultilinearHyraxCommitment, MultilinearHyraxParams};
pub use ipa::{MultilinearIpa, MultilinearIpaCommitment, MultilinearIpaParams};
pub use hyrax::{MultilinearHyrax, MultilinearHyraxCommitment, MultilinearHyraxParam};
pub use ipa::{MultilinearIpa, MultilinearIpaCommitment, MultilinearIpaParam};
pub use kzg::{
MultilinearKzg, MultilinearKzgCommitment, MultilinearKzgParams, MultilinearKzgProverParams,
MultilinearKzgVerifierParams,
MultilinearKzg, MultilinearKzgCommitment, MultilinearKzgParam, MultilinearKzgProverParam,
MultilinearKzgVerifierParam,
};
pub use zeromorph::{Zeromorph, ZeromorphKzgProverParam, ZeromorphKzgVerifierParam};

Expand Down
14 changes: 7 additions & 7 deletions plonkish_backend/src/pcs/multilinear/brakedown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ impl<F: PrimeField, H: Hash, S: BrakedownSpec> Clone for MultilinearBrakedown<F,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MultilinearBrakedownParams<F: PrimeField> {
pub struct MultilinearBrakedownParam<F: PrimeField> {
num_vars: usize,
num_rows: usize,
brakedown: Brakedown<F>,
}

impl<F: PrimeField> MultilinearBrakedownParams<F> {
impl<F: PrimeField> MultilinearBrakedownParam<F> {
pub fn num_vars(&self) -> usize {
self.num_vars
}
Expand Down Expand Up @@ -92,9 +92,9 @@ where
H: Hash,
S: BrakedownSpec,
{
type Param = MultilinearBrakedownParams<F>;
type ProverParam = MultilinearBrakedownParams<F>;
type VerifierParam = MultilinearBrakedownParams<F>;
type Param = MultilinearBrakedownParam<F>;
type ProverParam = MultilinearBrakedownParam<F>;
type VerifierParam = MultilinearBrakedownParam<F>;
type Polynomial = MultilinearPolynomial<F>;
type Commitment = MultilinearBrakedownCommitment<F, H>;
type CommitmentChunk = Output<H>;
Expand All @@ -103,7 +103,7 @@ where
assert!(poly_size.is_power_of_two());
let num_vars = poly_size.ilog2() as usize;
let brakedown = Brakedown::new_multilinear::<S>(num_vars, 20.min((1 << num_vars) - 1), rng);
Ok(MultilinearBrakedownParams {
Ok(MultilinearBrakedownParam {
num_vars,
num_rows: (1 << num_vars) / brakedown.row_len(),
brakedown,
Expand All @@ -120,7 +120,7 @@ where
Ok((param.clone(), param.clone()))
} else {
Err(Error::InvalidPcsParam(
"Can't trim MultilinearBrakedownParams into different poly_size".to_string(),
"Can't trim MultilinearBrakedownParam into different poly_size".to_string(),
))
}
}
Expand Down
16 changes: 5 additions & 11 deletions plonkish_backend/src/pcs/multilinear/gemini.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use crate::{
pcs::{
multilinear::additive,
univariate::{UnivariateKzg, UnivariateKzgCommitment},
univariate::{err_too_large_deree, UnivariateKzg, UnivariateKzgCommitment},
Evaluation, Point, PolynomialCommitmentScheme,
},
poly::{
Expand Down Expand Up @@ -54,11 +54,8 @@ where

fn commit(pp: &Self::ProverParam, poly: &Self::Polynomial) -> Result<Self::Commitment, Error> {
if pp.degree() + 1 < poly.evals().len() {
return Err(Error::InvalidPcsParam(format!(
"Too large degree of poly to commit (param supports degree up to {} but got {})",
pp.degree(),
poly.evals().len()
)));
let got = poly.evals().len() - 1;
return Err(err_too_large_deree("commit", pp.degree(), got));
}

Ok(UnivariateKzg::commit_monomial(pp, poly.evals()))
Expand All @@ -84,11 +81,8 @@ where
) -> Result<(), Error> {
let num_vars = point.len();
if pp.degree() + 1 < poly.evals().len() {
return Err(Error::InvalidPcsParam(format!(
"Too large degree of poly to open (param supports degree up to {} but got {})",
pp.degree(),
poly.evals().len()
)));
let got = poly.evals().len() - 1;
return Err(err_too_large_deree("open", pp.degree(), got));
}

if cfg!(feature = "sanity-check") {
Expand Down
29 changes: 13 additions & 16 deletions plonkish_backend/src/pcs/multilinear/hyrax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
pcs::{
multilinear::{
additive, err_too_many_variates,
ipa::{MultilinearIpa, MultilinearIpaCommitment, MultilinearIpaParams},
ipa::{MultilinearIpa, MultilinearIpaCommitment, MultilinearIpaParam},
validate_input,
},
Additive, Evaluation, Point, PolynomialCommitmentScheme,
Expand All @@ -16,22 +16,21 @@ use crate::{
},
Error,
};

use rand::RngCore;
use std::{borrow::Cow, iter, marker::PhantomData};

#[derive(Clone, Debug)]
pub struct MultilinearHyrax<C: CurveAffine>(PhantomData<C>);

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MultilinearHyraxParams<C: CurveAffine> {
pub struct MultilinearHyraxParam<C: CurveAffine> {
num_vars: usize,
batch_num_vars: usize,
row_num_vars: usize,
ipa: MultilinearIpaParams<C>,
ipa: MultilinearIpaParam<C>,
}

impl<C: CurveAffine> MultilinearHyraxParams<C> {
impl<C: CurveAffine> MultilinearHyraxParam<C> {
pub fn num_vars(&self) -> usize {
self.num_vars
}
Expand Down Expand Up @@ -108,9 +107,9 @@ where
C: CurveAffine + Serialize + DeserializeOwned,
C::ScalarExt: Serialize + DeserializeOwned,
{
type Param = MultilinearHyraxParams<C>;
type ProverParam = MultilinearHyraxParams<C>;
type VerifierParam = MultilinearHyraxParams<C>;
type Param = MultilinearHyraxParam<C>;
type ProverParam = MultilinearHyraxParam<C>;
type VerifierParam = MultilinearHyraxParam<C>;
type Polynomial = MultilinearPolynomial<C::Scalar>;
type Commitment = MultilinearHyraxCommitment<C>;
type CommitmentChunk = C;
Expand Down Expand Up @@ -171,8 +170,8 @@ where
let comm = {
let mut comm = vec![C::CurveExt::identity(); pp.num_chunks()];
parallelize(&mut comm, |(comm, start)| {
for (comm, start) in comm.iter_mut().zip((start * row_len..).step_by(row_len)) {
*comm = variable_base_msm(&scalars[start..start + row_len], pp.g());
for (comm, offset) in comm.iter_mut().zip((start * row_len..).step_by(row_len)) {
*comm = variable_base_msm(&scalars[offset..offset + row_len], pp.g());
}
});
batch_projective_to_affine(&comm)
Expand All @@ -198,8 +197,8 @@ where
let comms = {
let mut comms = vec![C::CurveExt::identity(); scalars.len()];
parallelize(&mut comms, |(comms, start)| {
for (comm, scalars) in comms.iter_mut().zip(&scalars[start..]) {
*comm = variable_base_msm(*scalars, pp.g());
for (comm, row) in comms.iter_mut().zip(&scalars[start..]) {
*comm = variable_base_msm(*row, pp.g());
}
});
batch_projective_to_affine(&comms)
Expand Down Expand Up @@ -268,14 +267,13 @@ where
num_polys: usize,
transcript: &mut impl TranscriptRead<Self::CommitmentChunk, C::Scalar>,
) -> Result<Vec<Self::Commitment>, Error> {
let comms = iter::repeat_with(|| {
iter::repeat_with(|| {
transcript
.read_commitments(vp.num_chunks())
.map(MultilinearHyraxCommitment)
})
.take(num_polys)
.try_collect()?;
Ok(comms)
.collect()
}

fn verify(
Expand All @@ -297,7 +295,6 @@ where
variable_base_msm(&scalars, &comm.0).into()
})
};

MultilinearIpa::verify(&vp.ipa, &comm, &lo.to_vec(), eval, transcript)
}

Expand Down
126 changes: 16 additions & 110 deletions plonkish_backend/src/pcs/multilinear/ipa.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,34 @@
use crate::{
pcs::{
multilinear::{additive, err_too_many_variates, validate_input},
univariate::ipa::{prove_bulletproof_reduction, verify_bulletproof_reduction},
Additive, Evaluation, Point, PolynomialCommitmentScheme,
},
poly::multilinear::MultilinearPolynomial,
util::{
arithmetic::{
batch_projective_to_affine, inner_product, variable_base_msm, Curve, CurveAffine,
CurveExt, Field, Group,
batch_projective_to_affine, variable_base_msm, Curve, CurveAffine, CurveExt, Group,
},
chain,
parallel::parallelize,
transcript::{TranscriptRead, TranscriptWrite},
Deserialize, DeserializeOwned, Itertools, Serialize,
Deserialize, DeserializeOwned, Either, Itertools, Serialize,
},
Error,
};
use halo2_curves::group::ff::BatchInvert;
use rand::RngCore;
use std::{iter, marker::PhantomData, slice};
use std::{marker::PhantomData, slice};

#[derive(Clone, Debug)]
pub struct MultilinearIpa<C: CurveAffine>(PhantomData<C>);

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MultilinearIpaParams<C: CurveAffine> {
pub struct MultilinearIpaParam<C: CurveAffine> {
num_vars: usize,
g: Vec<C>,
h: C,
}

impl<C: CurveAffine> MultilinearIpaParams<C> {
impl<C: CurveAffine> MultilinearIpaParam<C> {
pub fn num_vars(&self) -> usize {
self.num_vars
}
Expand Down Expand Up @@ -87,9 +85,9 @@ where
C: CurveAffine + Serialize + DeserializeOwned,
C::ScalarExt: Serialize + DeserializeOwned,
{
type Param = MultilinearIpaParams<C>;
type ProverParam = MultilinearIpaParams<C>;
type VerifierParam = MultilinearIpaParams<C>;
type Param = MultilinearIpaParam<C>;
type ProverParam = MultilinearIpaParam<C>;
type VerifierParam = MultilinearIpaParam<C>;
type Polynomial = MultilinearPolynomial<C::Scalar>;
type Commitment = MultilinearIpaCommitment<C>;
type CommitmentChunk = C;
Expand Down Expand Up @@ -173,56 +171,10 @@ where
assert_eq!(poly.evaluate(point), *eval);
}

let xi_0 = transcript.squeeze_challenge();
let h_prime = (pp.h * xi_0).to_affine();

let mut bases = pp.g().to_vec();
let mut coeffs = poly.evals().to_vec();
let mut zs = MultilinearPolynomial::eq_xy(point).into_evals();

for i in 0..pp.num_vars() {
let mid = 1 << (pp.num_vars() - i - 1);

let (bases_l, bases_r) = bases.split_at(mid);
let (coeffs_l, coeffs_r) = coeffs.split_at(mid);
let (zs_l, zs_r) = zs.split_at(mid);
let (c_l, c_r) = (inner_product(coeffs_r, zs_l), inner_product(coeffs_l, zs_r));
let l_i = variable_base_msm(chain![coeffs_r, [&c_l]], chain![bases_l, [&h_prime]]);
let r_i = variable_base_msm(chain![coeffs_l, [&c_r]], chain![bases_r, [&h_prime]]);
transcript.write_commitment(&l_i.to_affine())?;
transcript.write_commitment(&r_i.to_affine())?;

let xi_i = transcript.squeeze_challenge();
let xi_i_inv = xi_i.invert().unwrap();

let (bases_l, bases_r) = bases.split_at_mut(mid);
let (coeffs_l, coeffs_r) = coeffs.split_at_mut(mid);
let (zs_l, zs_r) = zs.split_at_mut(mid);
parallelize(bases_l, |(bases_l, start)| {
let mut tmp = Vec::with_capacity(bases_l.len());
for (lhs, rhs) in bases_l.iter().zip(bases_r[start..].iter()) {
tmp.push(lhs.to_curve() + *rhs * xi_i);
}
C::Curve::batch_normalize(&tmp, bases_l);
});
parallelize(coeffs_l, |(coeffs_l, start)| {
for (lhs, rhs) in coeffs_l.iter_mut().zip(coeffs_r[start..].iter()) {
*lhs += xi_i_inv * rhs;
}
});
parallelize(zs_l, |(zs_l, start)| {
for (lhs, rhs) in zs_l.iter_mut().zip(zs_r[start..].iter()) {
*lhs += xi_i * rhs;
}
});
bases.truncate(mid);
coeffs.truncate(mid);
zs.truncate(mid);
}

transcript.write_field_element(&coeffs[0])?;

Ok(())
let bases = pp.g();
let coeffs = poly.evals();
let zs = MultilinearPolynomial::eq_xy(point).into_evals();
prove_bulletproof_reduction(bases, pp.h(), coeffs, zs, transcript)
}

fn batch_open<'a>(
Expand Down Expand Up @@ -258,35 +210,9 @@ where
eval: &C::Scalar,
transcript: &mut impl TranscriptRead<C, C::Scalar>,
) -> Result<(), Error> {
validate_input("verify", vp.num_vars(), [], [point])?;

let xi_0 = transcript.squeeze_challenge();

let (ls, rs, xis) = iter::repeat_with(|| {
Ok((
transcript.read_commitment()?,
transcript.read_commitment()?,
transcript.squeeze_challenge(),
))
})
.take(vp.num_vars())
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.multiunzip::<(Vec<_>, Vec<_>, Vec<_>)>();
let neg_c = -transcript.read_field_element()?;

let xi_invs = {
let mut xi_invs = xis.clone();
xi_invs.batch_invert();
xi_invs
};
let neg_c_h = MultilinearPolynomial::new(h_coeffs(neg_c, &xis));
let u = &(xi_0 * (neg_c_h.evaluate(point) + eval));
let scalars = chain![&xi_invs, &xis, neg_c_h.evals(), [u]];
let bases = chain![&ls, &rs, vp.g(), [vp.h()]];
bool::from((variable_base_msm(scalars, bases) + comm.0).is_identity())
.then_some(())
.ok_or_else(|| Error::InvalidPcsOpen("Invalid multilinear IPA open".to_string()))
let bases = vp.g();
let point = Either::Right(point.as_slice());
verify_bulletproof_reduction(bases, vp.h(), comm, point, eval, transcript)
}

fn batch_verify<'a>(
Expand All @@ -301,26 +227,6 @@ where
}
}

fn h_coeffs<F: Field>(scalar: F, xi: &[F]) -> Vec<F> {
assert!(!xi.is_empty());

let mut coeffs = vec![F::ZERO; 1 << xi.len()];
coeffs[0] = scalar;

for (len, xi) in xi.iter().rev().enumerate().map(|(i, xi)| (1 << i, xi)) {
let (left, right) = coeffs.split_at_mut(len);
let right = &mut right[0..len];
right.copy_from_slice(left);
parallelize(right, |(right, _)| {
for coeff in right {
*coeff *= xi;
}
});
}

coeffs
}

#[cfg(test)]
mod test {
use crate::{
Expand Down
Loading

0 comments on commit ca985fc

Please sign in to comment.