Skip to content

Commit

Permalink
w circ l function
Browse files Browse the repository at this point in the history
  • Loading branch information
zhenfeizhang committed Jun 29, 2022
1 parent 96ace27 commit 69113cc
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 17 deletions.
17 changes: 3 additions & 14 deletions pcs/src/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,28 +165,17 @@ impl<E: PairingEngine> MultilinearCommitmentScheme<E> for KZGMultilinearPC<E> {
Ok(Proof { proofs })
}

/// On input a polynomial `p` and a point `point`, outputs a proof for the
/// same. This function does not need to take the evaluation value as an
/// input.
///
/// This function takes 2^{num_var +1} number of scalar multiplications over
/// G2:
/// - it proceeds with `num_var` number of rounds,
/// - at round i, we compute an MSM for `2^{num_var - i + 1}` number of G2
/// elements.
/// TODO
fn multi_open(
prover_param: &Self::ProverParam,
polynomials: &[impl MultilinearExtension<E::Fr>],
point: &[E::Fr],
) -> Result<Self::Proof, PCSErrors> {
let open_timer = start_timer!(|| "open");

let poly = merge_polynomials(polynomials);

let proof = Self::open(prover_param, &poly, point)?;

end_timer!(open_timer);
Ok(proof)

todo!()
}

/// Verifies that `value` is the evaluation at `x` of the polynomial
Expand Down
7 changes: 4 additions & 3 deletions pcs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod commit;
mod errors;
mod param;
mod util;

use ark_ec::PairingEngine;
use ark_poly::MultilinearExtension;
Expand Down Expand Up @@ -47,11 +48,11 @@ pub trait MultilinearCommitmentScheme<E: PairingEngine> {
point: &[E::Fr],
) -> Result<Self::Proof, PCSErrors>;

/// On input a polynomial `p` and a point `point`, outputs a proof for the
/// same.
/// On input a list of polynomials and a point `point`, outputs a proof for
/// the same.
fn multi_open(
prover_param: &Self::ProverParam,
polynomial: &[impl MultilinearExtension<E::Fr>],
polynomials: &[impl MultilinearExtension<E::Fr>],
point: &[E::Fr],
) -> Result<Self::Proof, PCSErrors>;

Expand Down
130 changes: 130 additions & 0 deletions pcs/src/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
//! Useful utilities for KZG PCS
use crate::PCSErrors;
use ark_ff::PrimeField;
use ark_poly::{
univariate::DensePolynomial, DenseMultilinearExtension, EvaluationDomain, Evaluations,
MultilinearExtension, Polynomial, Radix2EvaluationDomain,
};
use ark_std::{end_timer, start_timer};

/// Compute W \circ l.
///
/// Given an MLE W, and a list of univariate polynomials l, evaluate W at l.
///
/// Returns an error is l's length does not matches number of variables in W.
pub(crate) fn compute_w_circ_l<F: PrimeField>(
w: &DenseMultilinearExtension<F>,
l: &[DensePolynomial<F>],
) -> Result<DensePolynomial<F>, PCSErrors> {
let timer = start_timer!(|| "compute W \\circ l");

if w.num_vars != l.len() {
return Err(PCSErrors::InvalidParameters(
"l's length does not match num_variables".to_string(),
));
}

let mut res_eval: Vec<F> = vec![];
let uni_degree = l.len() + 1;

let domain = match Radix2EvaluationDomain::<F>::new(uni_degree) {
Some(p) => p,
None => {
return Err(PCSErrors::InvalidParameters(
"failed to build radix 2 domain".to_string(),
))
},
};

for point in domain.elements() {
let l_eval: Vec<F> = l.iter().map(|x| x.evaluate(&point)).collect();
res_eval.push(w.evaluate(l_eval.as_ref()).unwrap())
}
let evaluation = Evaluations::from_vec_and_domain(res_eval, domain);
let res = evaluation.interpolate();

end_timer!(timer);
Ok(res)
}

#[cfg(test)]
mod test {
use super::*;
use ark_bls12_381::Fr;
use ark_poly::UVPolynomial;

#[test]
fn test_w_circ_l() -> Result<(), PCSErrors> {
test_w_circ_l_helper::<Fr>()
}

fn test_w_circ_l_helper<F: PrimeField>() -> Result<(), PCSErrors> {
{
// Example from page 53:
// W = 3x1x2 + 2x2 whose evaluations are
// 0, 0 |-> 0
// 0, 1 |-> 2
// 1, 0 |-> 0
// 1, 1 |-> 5
let w_eval = vec![F::zero(), F::from(2u64), F::zero(), F::from(5u64)];
let w = DenseMultilinearExtension::from_evaluations_vec(2, w_eval);

// l0 = t + 2
// l1 = -2t + 4
let l0 = DensePolynomial::from_coefficients_vec(vec![F::from(2u64), F::one()]);
let l1 = DensePolynomial::from_coefficients_vec(vec![F::from(4u64), -F::from(2u64)]);

// res = -6t^2 - 4t + 32
let res = compute_w_circ_l(&w, [l1, l0].as_ref())?;
let res_rec = DensePolynomial::from_coefficients_vec(vec![
F::from(32u64),
-F::from(4u64),
-F::from(6u64),
]);
assert_eq!(res, res_rec);
}
{
// A random example
// W = x1x2x3 - 2x1x2 + 3x2x3 - 4x1x3 + 5x1 - 6x2 + 7x3
// 0, 0, 0 |-> 0
// 0, 0, 1 |-> 7
// 0, 1, 0 |-> -6
// 0, 1, 1 |-> 4
// 1, 0, 0 |-> 5
// 1, 0, 1 |-> 8
// 1, 1, 0 |-> -3
// 1, 1, 1 |-> 4
let w_eval = vec![
F::zero(),
F::from(7u64),
-F::from(6u64),
F::from(4u64),
F::from(5u64),
F::from(8u64),
-F::from(3u64),
F::from(4u64),
];
let w = DenseMultilinearExtension::from_evaluations_vec(3, w_eval);

// l0 = t + 2
// l1 = 3t - 4
// l2 = -5t + 6
let l0 = DensePolynomial::from_coefficients_vec(vec![F::from(2u64), F::one()]);
let l1 = DensePolynomial::from_coefficients_vec(vec![-F::from(4u64), F::from(3u64)]);
let l2 = DensePolynomial::from_coefficients_vec(vec![F::from(6u64), -F::from(5u64)]);
let res = compute_w_circ_l(&w, [l2, l1, l0].as_ref())?;

// res = -15t^3 - 23t^2 + 130t - 76
let res_rec = DensePolynomial::from_coefficients_vec(vec![
-F::from(76u64),
F::from(130u64),
-F::from(23u64),
-F::from(15u64),
]);

assert_eq!(res, res_rec);
}
Ok(())
}
}

0 comments on commit 69113cc

Please sign in to comment.