Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New batch opening #85

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions hyperplonk/src/batching.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
//! Sumcheck based batch opening and verify commitment.
// TODO: refactoring this code to somewhere else
// currently IOP depends on PCS because perm check requires commitment.
// The sumcheck based batch opening therefore cannot stay in the PCS repo --
// which creates a cyclic dependency.

use std::rc::Rc;

use arithmetic::{
bit_decompose, build_eq_x_r, gen_eval_point, DenseMultilinearExtension, VirtualPolynomial,
};
use ark_ec::PairingEngine;
use ark_ff::PrimeField;
use ark_std::{end_timer, log2, start_timer, One, Zero};
use pcs::{
prelude::{
Commitment, MultilinearKzgBatchProof, MultilinearKzgPCS, MultilinearProverParam,
UnivariateProverParam,
},
PolynomialCommitmentScheme,
};
use poly_iop::{
prelude::{IOPProof, SumCheck},
PolyIOP,
};
use transcript::IOPTranscript;

use crate::prelude::HyperPlonkErrors;

pub(crate) struct NewBatchProof<E: PairingEngine> {
/// commitment to tilde g MLE
pub(crate) tilde_g_commit: Commitment<E>,
/// A sum check proof proving tilde g's sum
pub(crate) sum_check_proof: IOPProof<E::Fr>,
}

/// Steps:
/// 1. todo...
pub(crate) fn multi_open_internal<E: PairingEngine>(
uni_prover_param: UnivariateProverParam<E::G1Affine>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is unnecessary anymore.

ml_prover_param: MultilinearProverParam<E>,
polynomials: &[Rc<DenseMultilinearExtension<E::Fr>>],
points: &[Vec<E::Fr>],
transcript: &mut IOPTranscript<E::Fr>,
) -> Result<NewBatchProof<E>, HyperPlonkErrors> {
let open_timer = start_timer!(|| "multi open");

// TODO: sanity checks

let num_var = polynomials[0].num_vars;
let k = polynomials.len();
let ell = log2(k) as usize;

// challenge point t
let t = transcript.get_and_append_challenge_vectors("t".as_ref(), ell)?;

// eq(t, i) for i in [0..k]
let eq_t_i_list = (0..k)
.map(|index| get_eq_t_i(t.as_ref(), index, ell))
.collect::<Vec<_>>();

// \tilde g(i, b) = eq(t, i) * f_i(b)
let mut tilde_g_eval = vec![E::Fr::zero(); 1 << (ell + num_var)];
for (index, f_i) in polynomials.iter().enumerate() {
for &f_i_eval in f_i.iter() {
tilde_g_eval.push(f_i_eval * eq_t_i_list[index])
}
}
let tilde_g = Rc::new(DenseMultilinearExtension::from_evaluations_vec(
num_var + ell,
tilde_g_eval,
));

// commit to tilde g
let tilde_g_commit = MultilinearKzgPCS::commit(&(ml_prover_param, uni_prover_param), &tilde_g)?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to commit.


// \tilde eq is the concat of all points, padded with 0s
let mut tilde_eq_eval = points.iter().flatten().copied().collect::<Vec<E::Fr>>();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is different from tilde_eq_eval in the paper.

tilde_eq_eval.resize(1 << (num_var + ell), E::Fr::zero());
let tilde_eq = Rc::new(DenseMultilinearExtension::from_evaluations_vec(
num_var + ell,
tilde_eq_eval,
));

// built the virtual polynomial for SumCheck
let mut sum_check_vp = VirtualPolynomial::new(num_var + ell);
sum_check_vp.add_mle_list([tilde_g, tilde_eq], E::Fr::one())?;

let proof = <PolyIOP<E::Fr> as SumCheck<E::Fr>>::prove(&sum_check_vp, transcript)?;

end_timer!(open_timer);
Ok(NewBatchProof {
tilde_g_commit,
sum_check_proof: proof,
})
}

// generate an eval which is eq(\vec t, <i>)
fn get_eq_t_i<F: PrimeField>(t: &[F], index: usize, index_len: usize) -> F {
todo!()
}
1 change: 1 addition & 0 deletions hyperplonk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use pcs::prelude::PolynomialCommitmentScheme;
use poly_iop::prelude::PermutationCheck;
use witness::WitnessColumn;

mod batching;
mod custom_gate;
mod errors;
mod mock;
Expand Down
24 changes: 1 addition & 23 deletions pcs/src/multilinear_kzg/srs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// along with the Jellyfish library. If not, see <https://mit-license.org/>.

//! Implementing Structured Reference Strings for multilinear polynomial KZG
use crate::{prelude::PCSError, StructuredReferenceString};
use crate::{multilinear_kzg::util::eq_extension, prelude::PCSError, StructuredReferenceString};
use ark_ec::{msm::FixedBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ff::{Field, PrimeField};
use ark_poly::DenseMultilinearExtension;
Expand Down Expand Up @@ -232,28 +232,6 @@ fn remove_dummy_variable<F: Field>(poly: &[F], pad: usize) -> Result<Vec<F>, PCS
Ok((0..(1 << nv)).map(|x| poly[x << pad]).collect())
}

/// Generate eq(t,x), a product of multilinear polynomials with fixed t.
/// eq(a,b) is takes extensions of a,b in {0,1}^num_vars such that if a and b in
/// {0,1}^num_vars are equal then this polynomial evaluates to 1.
fn eq_extension<F: PrimeField>(t: &[F]) -> Vec<DenseMultilinearExtension<F>> {
let start = start_timer!(|| "eq extension");

let dim = t.len();
let mut result = Vec::new();
for (i, &ti) in t.iter().enumerate().take(dim) {
let mut poly = Vec::with_capacity(1 << dim);
for x in 0..(1 << dim) {
let xi = if x >> i & 1 == 1 { F::one() } else { F::zero() };
let ti_xi = ti * xi;
poly.push(ti_xi + ti_xi - xi - ti + F::one());
}
result.push(DenseMultilinearExtension::from_evaluations_vec(dim, poly));
}

end_timer!(start);
result
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
22 changes: 22 additions & 0 deletions pcs/src/multilinear_kzg/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,28 @@ pub(crate) fn generate_evaluations_single_poly<F: PrimeField>(
Ok(mle_values)
}

/// Generate eq(t,x), a product of multilinear polynomials with fixed t.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a vector of polys? Rather than only a single poly?

/// eq(a,b) is takes extensions of a,b in {0,1}^num_vars such that if a and b in
/// {0,1}^num_vars are equal then this polynomial evaluates to 1.
pub(crate) fn eq_extension<F: PrimeField>(t: &[F]) -> Vec<DenseMultilinearExtension<F>> {
let start = start_timer!(|| "eq extension");

let dim = t.len();
let mut result = Vec::new();
for (i, &ti) in t.iter().enumerate().take(dim) {
let mut poly = Vec::with_capacity(1 << dim);
for x in 0..(1 << dim) {
let xi = if x >> i & 1 == 1 { F::one() } else { F::zero() };
let ti_xi = ti * xi;
poly.push(ti_xi + ti_xi - xi - ti + F::one());
}
result.push(DenseMultilinearExtension::from_evaluations_vec(dim, poly));
}

end_timer!(start);
result
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
2 changes: 1 addition & 1 deletion poly-iop/src/prelude.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub use crate::{
errors::PolyIOPErrors, perm_check::PermutationCheck, prod_check::ProductCheck,
sum_check::SumCheck, utils::*, zero_check::ZeroCheck, PolyIOP,
structs::IOPProof, sum_check::SumCheck, utils::*, zero_check::ZeroCheck, PolyIOP,
};