Skip to content

Commit

Permalink
add enum to polynomial specifying what form it's in, use that to info…
Browse files Browse the repository at this point in the history
…rm what SRS to use when commiting and computing proofs for a polynomial
  • Loading branch information
afkbyte committed May 31, 2024
1 parent 10beec1 commit b26c934
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 65 deletions.
10 changes: 7 additions & 3 deletions src/blob.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use crate::{errors::BlobError, helpers, polynomial::Polynomial};
use crate::{
errors::BlobError,
helpers,
polynomial::{Polynomial, PolynomialFormat},
};

/// A blob which is Eigen DA spec aligned.
#[derive(Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -100,12 +104,12 @@ impl Blob {
}

/// Converts the blob data to a `Polynomial` if the data is padded.
pub fn to_polynomial(&self) -> Result<Polynomial, BlobError> {
pub fn to_polynomial(&self, form: PolynomialFormat) -> Result<Polynomial, BlobError> {
if !self.is_padded {
Err(BlobError::NotPaddedError)
} else {
let fr_vec = helpers::to_fr_array(&self.blob_data);
let poly = Polynomial::new(&fr_vec, self.length_after_padding)
let poly = Polynomial::new(&fr_vec, self.length_after_padding, form)
.map_err(|err| BlobError::GenericError(err.to_string()))?;
Ok(poly)
}
Expand Down
13 changes: 13 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub enum PolynomialError {
CommitError(String),
GenericError(String),
FFTError(String),
IncorrectFormError(String),
}

impl fmt::Display for PolynomialError {
Expand All @@ -36,6 +37,9 @@ impl fmt::Display for PolynomialError {
PolynomialError::CommitError(ref msg) => write!(f, "Commitment error: {}", msg),
PolynomialError::FFTError(ref msg) => write!(f, "FFT error: {}", msg),
PolynomialError::GenericError(ref msg) => write!(f, "generic error: {}", msg),
PolynomialError::IncorrectFormError(ref msg) => {
write!(f, "Incorrect form error: {}", msg)
},
}
}
}
Expand Down Expand Up @@ -94,6 +98,15 @@ mod tests {
assert_eq!(format!("{}", error), format!("FFT error: {}", msg));
}

fn test_polynomial_error_incorrect_form() {
let msg = String::from("test incorrect form error");
let error = PolynomialError::IncorrectFormError(msg.clone());
assert_eq!(
format!("{}", error),
format!("Incorrect form error: {}", msg)
);
}

#[test]
fn test_polynomial_error_equality() {
let error1 = PolynomialError::SerializationFromStringError;
Expand Down
58 changes: 28 additions & 30 deletions src/kzg.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use crate::{
blob::Blob, consts::BYTES_PER_FIELD_ELEMENT, errors::KzgError, helpers, polynomial::Polynomial,
blob::Blob,
consts::BYTES_PER_FIELD_ELEMENT,
errors::KzgError,
helpers,
polynomial::{Polynomial, PolynomialFormat},
traits::ReadPointFromBytes,
};
use ark_bn254::{g1::G1Affine, Bn254, Fr, G1Projective, G2Affine};
Expand Down Expand Up @@ -384,11 +388,7 @@ impl Kzg {
}

/// commit the actual polynomial with the values setup
pub fn commit(
&self,
polynomial: &Polynomial,
is_data_polynomial_evaluations: bool,
) -> Result<G1Affine, KzgError> {
pub fn commit(&self, polynomial: &Polynomial) -> Result<G1Affine, KzgError> {
if polynomial.len() > self.g1.len() {
return Err(KzgError::SerializationError(
"polynomial length is not correct".to_string(),
Expand All @@ -401,14 +401,16 @@ impl Kzg {
.build()
.map_err(|err| KzgError::CommitError(err.to_string()))?;

// Perform the multi-exponentiation
config.install(|| {
let bases = if is_data_polynomial_evaluations {
// if the blob data is polynomial evaluations then we use the original g1 points
self.g1[..polynomial.len()].to_vec()
} else {
// Use inverse FFT if not
self.g1_ifft(polynomial.len())?
let bases = match polynomial.get_form() {
PolynomialFormat::InEvaluationForm => {
// If the polynomial is in evaluation form, use the original g1 points
self.g1[..polynomial.len()].to_vec()
},
PolynomialFormat::InCoefficientForm => {
// If the polynomial is in coefficient form, use inverse FFT
self.g1_ifft(polynomial.len())?
},
};

match G1Projective::msm(&bases, &polynomial.to_vec()) {
Expand All @@ -421,12 +423,12 @@ impl Kzg {
pub fn blob_to_kzg_commitment(
&self,
blob: &Blob,
is_blob_ifft: bool,
form: PolynomialFormat,
) -> Result<G1Affine, KzgError> {
let polynomial = blob
.to_polynomial()
.to_polynomial(form)
.map_err(|err| KzgError::SerializationError(err.to_string()))?;
let commitment = self.commit(&polynomial, is_blob_ifft)?;
let commitment = self.commit(&polynomial)?;
Ok(commitment)
}

Expand All @@ -435,14 +437,8 @@ impl Kzg {
&self,
polynomial: &Polynomial,
index: u64,
is_data_polynomial_evaluations: bool,
) -> Result<G1Affine, KzgError> {
self.compute_kzg_proof(
polynomial,
index,
&self.expanded_roots_of_unity,
is_data_polynomial_evaluations,
)
self.compute_kzg_proof(polynomial, index, &self.expanded_roots_of_unity)
}

/// function to compute the kzg proof given the values.
Expand All @@ -451,7 +447,6 @@ impl Kzg {
polynomial: &Polynomial,
index: u64,
root_of_unities: &Vec<Fr>,
is_data_polynomial_evaluations: bool,
) -> Result<G1Affine, KzgError> {
if !self.params.completed_setup {
return Err(KzgError::GenericError(
Expand Down Expand Up @@ -502,12 +497,15 @@ impl Kzg {
}
}

let bases = if is_data_polynomial_evaluations {
// if the blob data is polynomial evaluations then we use the original g1 points
self.g1[..polynomial.len()].to_vec()
} else {
// Use inverse FFT if not
self.g1_ifft(polynomial.len())?
let bases = match polynomial.get_form() {
PolynomialFormat::InEvaluationForm => {
// If the polynomial is in evaluation form, use the original g1 points
self.g1[..polynomial.len()].to_vec()
},
PolynomialFormat::InCoefficientForm => {
// If the polynomial is in coefficient form, use inverse FFT
self.g1_ifft(polynomial.len())?
},
};

match G1Projective::msm(&bases, &quotient_poly) {
Expand Down
39 changes: 38 additions & 1 deletion src/polynomial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,27 @@ use ark_bn254::Fr;
use ark_poly::{EvaluationDomain, GeneralEvaluationDomain};
use ark_std::Zero;

#[derive(Clone, Debug, PartialEq, Copy)]
pub enum PolynomialFormat {
InCoefficientForm,
InEvaluationForm,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Polynomial {
elements: Vec<Fr>,
length_of_padded_blob: usize,
length_of_padded_blob_as_fr_vector: usize,
form: PolynomialFormat,
}

impl Polynomial {
/// Constructs a new `Polynomial` with a given vector of `Fr` elements.
pub fn new(elements: &Vec<Fr>, length_of_padded_blob: usize) -> Result<Self, PolynomialError> {
pub fn new(
elements: &Vec<Fr>,
length_of_padded_blob: usize,
form: PolynomialFormat,
) -> Result<Self, PolynomialError> {
if elements.is_empty() {
return Err(PolynomialError::GenericError(
"elements are empty".to_string(),
Expand All @@ -30,13 +41,19 @@ impl Polynomial {
elements: padded_input_fr,
length_of_padded_blob,
length_of_padded_blob_as_fr_vector: elements.len(),
form,
})
}

pub fn get_length_of_padded_blob_as_fr_vector(&self) -> usize {
self.length_of_padded_blob_as_fr_vector
}

/// Returns the form of the polynomial.
pub fn get_form(&self) -> PolynomialFormat {
self.form
}

/// Returns the number of elements in the polynomial.
pub fn len(&self) -> usize {
self.elements.len()
Expand All @@ -61,6 +78,26 @@ impl Polynomial {
self.elements.clone()
}

/// Helper function to transform the polynomial to the given form.
pub fn transform_to_form(&mut self, form: PolynomialFormat) -> Result<(), PolynomialError> {
if self.form == form {
return Err(PolynomialError::IncorrectFormError(
"Polynomial is already in the given form".to_string(),
));
}

match form {
PolynomialFormat::InCoefficientForm => {
// Transform from evaluation form to coefficient form using IFFT
self.fft_on_elements(true)
},
PolynomialFormat::InEvaluationForm => {
// Transform from coefficient form to evaluation form using FFT
self.fft_on_elements(false)
},
}
}

/// Performs an fft or ifft on the polynomial's elements
pub fn fft_on_elements(&mut self, inverse: bool) -> Result<(), PolynomialError> {
let fft_result = Self::fft(&self.to_vec(), inverse);
Expand Down
49 changes: 29 additions & 20 deletions tests/kzg_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@
mod tests {
use ark_bn254::{Fr, G1Affine, G2Affine};
use lazy_static::lazy_static;
use rust_kzg_bn254::{blob::Blob, errors::KzgError, helpers, kzg::Kzg, polynomial::Polynomial};
use rust_kzg_bn254::{
blob::Blob,
errors::KzgError,
helpers,
kzg::Kzg,
polynomial::{Polynomial, PolynomialFormat},
};
use std::{
env,
fs::File,
Expand Down Expand Up @@ -53,8 +59,8 @@ mod tests {
poly.push(Fr::one());
}

let polynomial = Polynomial::new(&poly, 2).unwrap();
let result = KZG_3000.commit(&polynomial, false);
let polynomial = Polynomial::new(&poly, 2, PolynomialFormat::InCoefficientForm).unwrap();
let result = KZG_3000.commit(&polynomial);
assert_eq!(
result,
Err(KzgError::SerializationError(
Expand Down Expand Up @@ -170,7 +176,9 @@ mod tests {
.calculate_roots_of_unity(input.get_length_after_padding().try_into().unwrap())
.unwrap();

let polynomial_input = input.to_polynomial().unwrap();
let polynomial_input = input
.to_polynomial(PolynomialFormat::InCoefficientForm)
.unwrap();
let expanded_roots_of_unity_vec_1: Vec<&Fr> = (0..polynomial_input.len())
.map(|i| kzg_clone1.get_nth_root_of_unity(i).unwrap())
.collect();
Expand Down Expand Up @@ -216,19 +224,17 @@ mod tests {
println!("generating blob of length is {}", blob_length);

let input = Blob::from_bytes_and_pad(&random_blob);
let input_poly = input.to_polynomial().unwrap();
let input_poly = input
.to_polynomial(PolynomialFormat::InCoefficientForm)
.unwrap();
kzg.data_setup_custom(1, input.len().try_into().unwrap())
.unwrap();

let index = rand::thread_rng()
.gen_range(0..input_poly.get_length_of_padded_blob_as_fr_vector());
let commitment = kzg.commit(&input_poly.clone(), false).unwrap();
let commitment = kzg.commit(&input_poly.clone()).unwrap();
let proof = kzg
.compute_kzg_proof_with_roots_of_unity(
&input_poly,
index.try_into().unwrap(),
false,
)
.compute_kzg_proof_with_roots_of_unity(&input_poly, index.try_into().unwrap())
.unwrap();
let value_fr = input_poly.get_at_index(index).unwrap();
let z_fr = kzg.get_nth_root_of_unity(index).unwrap();
Expand Down Expand Up @@ -260,7 +266,9 @@ mod tests {
let mut kzg = KZG_INSTANCE.clone();

let input = Blob::from_bytes_and_pad(GETTYSBURG_ADDRESS_BYTES);
let input_poly = input.to_polynomial().unwrap();
let input_poly = input
.to_polynomial(PolynomialFormat::InCoefficientForm)
.unwrap();

for index in 0..input_poly.len() - 1 {
kzg.data_setup_custom(4, input.len().try_into().unwrap())
Expand All @@ -273,13 +281,9 @@ mod tests {
break;
}
}
let commitment = kzg.commit(&input_poly.clone(), false).unwrap();
let commitment = kzg.commit(&input_poly.clone()).unwrap();
let proof = kzg
.compute_kzg_proof_with_roots_of_unity(
&input_poly,
index.try_into().unwrap(),
false,
)
.compute_kzg_proof_with_roots_of_unity(&input_poly, index.try_into().unwrap())
.unwrap();
let value_fr = input_poly.get_at_index(index).unwrap();
let z_fr = kzg.get_nth_root_of_unity(index).unwrap();
Expand Down Expand Up @@ -453,11 +457,16 @@ mod tests {
let hard_coded_x = Fq::from_str(the_strings_str[1]).expect("should be fine");
let hard_coded_y = Fq::from_str(the_strings_str[2]).expect("should be fine");
let gnark_proof = G1Affine::new(hard_coded_x, hard_coded_y);
let poly = Polynomial::new(&padded_input_fr_elements, 30).unwrap();
let poly = Polynomial::new(
&padded_input_fr_elements,
30,
PolynomialFormat::InCoefficientForm,
)
.unwrap();
kzg.data_setup_custom(4, poly.len().try_into().unwrap())
.unwrap();
let result = kzg
.compute_kzg_proof(&poly, index, &roots_of_unities, false)
.compute_kzg_proof(&poly, index, &roots_of_unities)
.unwrap();
assert_eq!(gnark_proof, result)
}
Expand Down
Loading

0 comments on commit b26c934

Please sign in to comment.