Skip to content

Commit

Permalink
feat: Add 2 alternative implementations of 'UVKZGPCS::commit' function
Browse files Browse the repository at this point in the history
  • Loading branch information
storojs72 committed Dec 22, 2023
1 parent cca3e63 commit e6beebc
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 6 deletions.
51 changes: 51 additions & 0 deletions src/provider/non_hiding_kzg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,57 @@ impl<E: MultiMillerLoop> UVKZGPCS<E>
where
E::G1: DlogGroup<PreprocessedGroupElement = E::G1Affine, Scalar = E::Fr>,
{
pub fn commit_offset(
prover_param: impl Borrow<KZGProverKey<E>>,
poly: &UVKZGPoly<E::Fr>,
offset: usize,
) -> Result<UVKZGCommitment<E>, NovaError> {
let prover_param = prover_param.borrow();

if poly.degree() > prover_param.powers_of_g.len() {
return Err(NovaError::PCSError(PCSError::LengthError));
}

let scalars = poly.coeffs.as_slice();
let bases = prover_param.powers_of_g.as_slice();

// We can avoid some scalar multiplications if 'scalars' contains a lot of leading zeroes using
// offset, that points where non-zero scalars start.
let C = <E::G1 as DlogGroup>::vartime_multiscalar_mul(
&scalars[(offset)..],
&bases[(offset)..scalars.len()],
);

Ok(UVKZGCommitment(C.to_affine()))
}

#[allow(dead_code)]
pub fn commit_filtered(
prover_param: impl Borrow<KZGProverKey<E>>,
poly: &UVKZGPoly<E::Fr>,
) -> Result<UVKZGCommitment<E>, NovaError> {
let prover_param = prover_param.borrow();

if poly.degree() > prover_param.powers_of_g.len() {
return Err(NovaError::PCSError(PCSError::LengthError));
}

// We use following filter to optimise MSM for cases where scalars contain a lot of zeroes
let initial_bases = &prover_param.powers_of_g.as_slice()[..poly.coeffs.len()].to_vec();
let mut scalars = vec![];
let mut bases = vec![];
for (index, scalar) in poly.coeffs.iter().enumerate() {
if !scalar.is_zero_vartime() {
scalars.push(*scalar);
bases.push(initial_bases[index]);
}
}

let C = <E::G1 as DlogGroup>::vartime_multiscalar_mul(&scalars, &bases);

Ok(UVKZGCommitment(C.to_affine()))
}

/// Generate a commitment for a polynomial
/// Note that the scheme is not hidding
pub fn commit(
Expand Down
65 changes: 59 additions & 6 deletions src/provider/non_hiding_zeromorph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,10 @@ where

// Compute the batched, lifted-degree quotient `\hat{q}`
// qq_hat = ∑_{i=0}^{num_vars-1} y^i * X^(2^num_vars - d_k - 1) * q_i(x)
let q_hat = batched_lifted_degree_quotient(y, &quotients_polys);
let (q_hat, offset) = batched_lifted_degree_quotient(y, &quotients_polys);

// Compute and absorb the commitment C_q = [\hat{q}]
let q_hat_comm = UVKZGPCS::commit(&pp.commit_pp, &q_hat)?;
let q_hat_comm = UVKZGPCS::commit_offset(&pp.commit_pp, &q_hat, offset)?;
transcript.absorb(b"q_hat", &q_hat_comm);

// Get challenges x and z
Expand Down Expand Up @@ -367,7 +368,7 @@ fn quotients<F: PrimeField>(poly: &MultilinearPolynomial<F>, point: &[F]) -> (Ve
fn batched_lifted_degree_quotient<F: PrimeField>(
y: F,
quotients_polys: &[UVKZGPoly<F>],
) -> UVKZGPoly<F> {
) -> (UVKZGPoly<F>, usize) {
let num_vars = quotients_polys.len();

let powers_of_y = (0..num_vars)
Expand All @@ -378,6 +379,7 @@ fn batched_lifted_degree_quotient<F: PrimeField>(
})
.collect::<Vec<F>>();

let mut offset = 0;
#[allow(clippy::disallowed_methods)]
let q_hat = powers_of_y
.iter()
Expand All @@ -386,7 +388,7 @@ fn batched_lifted_degree_quotient<F: PrimeField>(
.fold(
vec![F::ZERO; 1 << num_vars],
|mut q_hat, (idx, (power_of_y, q))| {
let offset = q_hat.len() - (1 << idx);
offset = q_hat.len() - (1 << idx);
q_hat[offset..]
.par_iter_mut()
.zip(q)
Expand All @@ -396,7 +398,10 @@ fn batched_lifted_degree_quotient<F: PrimeField>(
q_hat
},
);
UVKZGPoly::new(q_hat)

assert_eq!(offset, q_hat.len() / 2);

(UVKZGPoly::new(q_hat), offset)
}

/// Computes some key terms necessary for computing the partially evaluated univariate ZM polynomial
Expand Down Expand Up @@ -526,6 +531,7 @@ mod test {
use rand_core::SeedableRng;

use super::quotients;
use crate::provider::non_hiding_kzg::UVKZGPCS;
use crate::{
provider::{
keccak::Keccak256Transcript,
Expand All @@ -538,6 +544,7 @@ mod test {
},
spartan::polys::multilinear::MultilinearPolynomial,
traits::{Engine as NovaEngine, Group, TranscriptEngineTrait, TranscriptReprTrait},
NovaError,
};

fn commit_open_verify_with<E: MultiMillerLoop, NE: NovaEngine<GE = E::G1, Scalar = E::Fr>>()
Expand Down Expand Up @@ -696,7 +703,10 @@ mod test {
});

// Compare the computed and expected batched quotients
assert_eq!(batched_quotient, UVKZGPoly::new(batched_quotient_expected));
assert_eq!(
batched_quotient.0,
UVKZGPoly::new(batched_quotient_expected)
);
}

#[test]
Expand Down Expand Up @@ -801,4 +811,47 @@ mod test {
assert_eq!(zeta_x_scalars[k], scalar);
}
}

fn test_various_uvkzpcs_commit_template<E>() -> Result<(), NovaError>
where
E: MultiMillerLoop,
E::G1: DlogGroup<PreprocessedGroupElement = E::G1Affine, Scalar = E::Fr>,
E::Fr: PrimeFieldBits,
{
let degree = 10;
let num_vars_multilinear = 3;

let mut rng = &mut thread_rng();
let multilinear_poly = MultilinearPolynomial::<E::Fr>::random(num_vars_multilinear, &mut rng);

let mut random_points = vec![];
for _ in 0..num_vars_multilinear {
random_points.push(E::Fr::random(&mut rng));
}

let (quotients, _remainder) = quotients(&multilinear_poly, random_points.as_slice());
let quotients_polys = quotients
.into_iter()
.map(UVKZGPoly::new)
.collect::<Vec<_>>();

let (q_hat, offset) = batched_lifted_degree_quotient(E::Fr::random(&mut rng), &quotients_polys);

let pp = UniversalKZGParam::<E>::gen_srs_for_testing(&mut rng, degree);
let (ck, _vk) = pp.trim(degree);

let commitment_expected = UVKZGPCS::commit(&ck, &q_hat)?;
let commitment_actual_1 = UVKZGPCS::commit_filtered(&ck, &q_hat)?;
let commitment_actual_2 = UVKZGPCS::commit_offset(&ck, &q_hat, offset)?;

assert_eq!(commitment_expected.0, commitment_actual_1.0);
assert_eq!(commitment_expected.0, commitment_actual_2.0);

Ok(())
}

#[test]
fn test_various_uvkzpcs_commit() {
test_various_uvkzpcs_commit_template::<halo2curves::bn256::Bn256>().expect("test failed for Bn256");
}
}

0 comments on commit e6beebc

Please sign in to comment.