From badedc0c994f1ae4fda434ffd679b6f0f0a1fad7 Mon Sep 17 00:00:00 2001 From: Alok Kumar Date: Fri, 20 Dec 2024 05:17:28 +0530 Subject: [PATCH] feat: add trim and commit function --- kzg10/rust_implementation/Cargo.toml | 10 +- kzg10/rust_implementation/src/lib.rs | 171 +++++++++++++++++++++++++-- 2 files changed, 168 insertions(+), 13 deletions(-) diff --git a/kzg10/rust_implementation/Cargo.toml b/kzg10/rust_implementation/Cargo.toml index c1f862c..8c1a15c 100644 --- a/kzg10/rust_implementation/Cargo.toml +++ b/kzg10/rust_implementation/Cargo.toml @@ -4,9 +4,9 @@ version = "0.1.0" edition = "2021" [dependencies] -ark-std = "0.4" -ark-bls12-381 = "0.4" -ark-ec = "0.4" -ark-ff = "0.4" -# ark-poly = { version = "0.3.0", features = ["bls12_381"] } +ark-std = "0.5" +ark-ff = "0.5" +ark-ec = "0.5" +ark-bls12-381 = "0.5" +ark-poly ="0.5.0" rand = "0.8" diff --git a/kzg10/rust_implementation/src/lib.rs b/kzg10/rust_implementation/src/lib.rs index e0af053..6cf1729 100644 --- a/kzg10/rust_implementation/src/lib.rs +++ b/kzg10/rust_implementation/src/lib.rs @@ -1,9 +1,24 @@ -use ark_bls12_381::{Fr, G1Projective as G1, G2Projective as G2}; -use ark_ec::Group; -use ark_ff::{Field, One, UniformRand}; -use ark_std::rand::RngCore; -use ark_std::vec::Vec; +// use ark_bls12_381::{Fr, G1Affine, G1Projective as G1, G2Projective as G2}; +// use ark_ec::Group; +// use ark_ec::{scalar_mul::ScalarMul}; +// use ark_ec::CurveGroup; +// use ark_ff::{Field, One, PrimeField, UniformRand}; +// use ark_poly::univariate::DensePolynomial; +// use ark_std::{rand::RngCore, vec::Vec}; + +use ark_bls12_381::{Fr, G1Affine, G1Projective as G1, G2Projective as G2}; +use ark_ec::CurveGroup; +use ark_ec::AffineRepr; use std::ops::Mul; +use ark_ec::scalar_mul::ScalarMul; +use ark_ff::{Field, One, PrimeField, UniformRand}; +use ark_poly::univariate::DensePolynomial; +use ark_ec::PrimeGroup; +use ark_poly::Polynomial; +use ark_poly::DenseUVPolynomial; +use ark_std::{rand::RngCore, vec::Vec,Zero}; + + pub struct KZG10Commitment { pub debug: bool, @@ -17,6 +32,37 @@ pub struct SetupParams { pub neg_powers_of_h: Vec, } +// Powers Struct +pub struct Powers { + pub powers_of_g: Vec, + pub powers_of_gamma_g: Vec, +} + +// Verification Key struct +pub struct VerifyingKey { + pub g: G1, + pub gamma_g: G1, + pub h: G2, + pub beta_h: G2, +} + +/// A polynomial Commitment +pub struct Commitment(pub G1); + +fn multi_scalar_mul( + bases: &[G1Affine], + scalars: &[::BigInt], +) -> G1 { + assert_eq!(bases.len(), scalars.len(), "Mismatched lengths"); + let mut acc = G1::zero(); + for (base, scalar) in bases.iter().zip(scalars.iter()) { + // Convert from affine to projective and multiply + let point = base.mul_bigint(*scalar); + acc += point; + } + acc +} + impl KZG10Commitment { pub fn new(debug: bool) -> Self { Self { debug } @@ -96,9 +142,118 @@ impl KZG10Commitment { neg_powers_of_h, } } -} + /// Trim function: selects a subset of the setup parameters for a given supported degree + pub fn trim(&self, pp: &SetupParams, supported_degree: usize) -> (Powers, VerifyingKey) { + let mut deg = supported_degree; + if deg == 1 { + deg += 1; + } + + let powers_of_g = pp.powers_of_g[..=deg].to_vec(); + let powers_of_gamma_g = pp.powers_of_gamma_g[..=deg].to_vec(); + + let powers = Powers { + powers_of_g, + powers_of_gamma_g, + }; + + let vk = VerifyingKey { + g: pp.powers_of_g[0], + gamma_g: pp.powers_of_gamma_g[0], + h: pp.h, + beta_h: pp.beta_h, + }; + + (powers, vk) + } + + /// Commit function: commit to a polynomial using the given trimmed powers. + /// + /// # Arguments + /// * `powers` - Powers to use for commitment (from trim) + /// * `polynomial` - The polynomial to commit to + /// * `hiding_bound` - Optional hiding degree + /// * `rng` - RNG for hiding polynomial sampling if needed + /// + /// # Returns + /// A tuple `(Commitment, Option>)` where the second is the random ints used for hiding if hiding_bound is set. + pub fn commit( + &self, + powers: &Powers, + polynomial: &DensePolynomial, + hiding_bound: Option, + rng: &mut R, + ) -> (Commitment, Option>) { + let num_coefficients = polynomial.degree() + 1; + let num_powers = powers.powers_of_g.len(); + assert!( + num_coefficients <= num_powers, + "Too many coefficients: {}, powers: {}", + num_coefficients, + num_powers + ); + + let coeffs = polynomial.coeffs(); + let mut last_non_zero = 0; + for (i, c) in coeffs.iter().enumerate() { + if !c.is_zero() { + last_non_zero = i; + } + } + let trimmed_coeffs = &coeffs[..=last_non_zero]; + let num_leading_zeros = 0; // Since we slice to last_non_zero, no leading zeros at the front + + // Prepare bases and scalars for MSM + let bases: Vec = powers.powers_of_g + [num_leading_zeros..(num_leading_zeros + trimmed_coeffs.len())] + .iter() + .map(|g| g.into_affine()) + .collect(); + + let scalars: Vec<::BigInt> = + trimmed_coeffs.iter().map(|c| c.into_bigint()).collect(); + let mut commitment = multi_scalar_mul(&bases, &scalars); + + // Hiding polynomial if needed + let random_ints = if let Some(hb) = hiding_bound { + // Generate a random polynomial with non-zero degree + let mut rand_coeffs = Vec::new(); + while rand_coeffs.is_empty() || (rand_coeffs.len() - 1 == 0) { + rand_coeffs.clear(); + for _ in 0..(hb + 1) { + rand_coeffs.push(Fr::rand(rng)); + } + } + + let hiding_poly_degree = rand_coeffs.len() - 1; + let gamma_num_powers = powers.powers_of_gamma_g.len(); + assert!(hb != 0, "Hiding bound is zero"); + assert!( + hiding_poly_degree < gamma_num_powers, + "Hiding bound is too large" + ); + + let gamma_bases: Vec = powers.powers_of_gamma_g[..=hiding_poly_degree] + .iter() + .map(|g| g.into_affine()) + .collect(); + + let gamma_scalars: Vec<::BigInt> = + rand_coeffs.iter().map(|c| c.into_bigint()).collect(); + + let random_commitment = multi_scalar_mul(&gamma_bases, &gamma_scalars); + commitment += random_commitment; + + Some(rand_coeffs) + } else { + None + }; + + (Commitment(commitment), random_ints) + } +} #[cfg(test)] mod tests { @@ -111,8 +266,8 @@ mod tests { let kzg = KZG10Commitment::new(false); let params = kzg.setup(10, true, None, None, None, &mut rng); - assert_eq!(params.powers_of_g.len(), 11); // max_degree + 1 + assert_eq!(params.powers_of_g.len(), 11); // max_degree + 1 assert_eq!(params.powers_of_gamma_g.len(), 12); // max_degree + 2 - assert_eq!(params.neg_powers_of_h.len(), 11); // max_degree + 1 + assert_eq!(params.neg_powers_of_h.len(), 11); // max_degree + 1 } }