Skip to content

Commit

Permalink
style!: issue15 - cleaner polynomial interface
Browse files Browse the repository at this point in the history
Separate Polynomial into PolynomialEvalForm and PolynomialCoefForm to make library type safe when converting between these.
Eg: fft can only go from coeff->eval, and ifft can only go from eval->coeff
  • Loading branch information
samlaf committed Jan 6, 2025
1 parent 85be357 commit 5d3ec00
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 143 deletions.
16 changes: 10 additions & 6 deletions src/blob.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
errors::BlobError,
helpers,
polynomial::{Polynomial, PolynomialFormat},
polynomial::{PolynomialCoefForm, PolynomialEvalForm},
};

/// A blob which is Eigen DA spec aligned.
Expand Down Expand Up @@ -56,12 +56,16 @@ impl Blob {
self.blob_data.is_empty()
}

/// Converts the blob data to a `Polynomial` if the data is padded.
pub fn to_polynomial(&self, form: PolynomialFormat) -> Result<Polynomial, BlobError> {
/// Convert the blob data to a `PolynomialEvalForm`.
pub fn to_polynomial_eval_form(&self) -> PolynomialEvalForm {
let fr_vec = helpers::to_fr_array(&self.blob_data);
let poly = Polynomial::new(&fr_vec, self.len(), form)
.map_err(|err| BlobError::GenericError(err.to_string()))?;
Ok(poly)
PolynomialEvalForm::new(fr_vec)
}

/// Convert the blob data to a `PolynomialCoefForm`.
pub fn to_polynomial_coeff_form(&self) -> PolynomialCoefForm {
let fr_vec = helpers::to_fr_array(&self.blob_data);
PolynomialCoefForm::new(fr_vec)
}
}

Expand Down
69 changes: 32 additions & 37 deletions src/kzg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
consts::BYTES_PER_FIELD_ELEMENT,
errors::KzgError,
helpers,
polynomial::{Polynomial, PolynomialFormat},
polynomial::{PolynomialCoefForm, PolynomialEvalForm},
traits::ReadPointFromBytes,
};
use ark_bn254::{g1::G1Affine, Bn254, Fr, G1Projective, G2Affine};
Expand Down Expand Up @@ -462,55 +462,58 @@ impl Kzg {
}

/// commit the actual polynomial with the values setup
pub fn commit(&self, polynomial: &Polynomial) -> Result<G1Affine, KzgError> {
pub fn commit_eval_form(&self, polynomial: &PolynomialEvalForm) -> Result<G1Affine, KzgError> {
if polynomial.len() > self.g1.len() {
return Err(KzgError::SerializationError(
"polynomial length is not correct".to_string(),
));
}

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())?
},
};
// When the polynomial is in evaluation form, use the original g1 points
let bases = self.g1[..polynomial.len()].to_vec();

match G1Projective::msm(&bases, &polynomial.to_vec()) {
match G1Projective::msm(&bases, polynomial.evaluations()) {
Ok(res) => Ok(res.into_affine()),
Err(err) => Err(KzgError::CommitError(err.to_string())),
}
}

pub fn blob_to_kzg_commitment(
&self,
blob: &Blob,
form: PolynomialFormat,
) -> Result<G1Affine, KzgError> {
let polynomial = blob
.to_polynomial(form)
.map_err(|err| KzgError::SerializationError(err.to_string()))?;
let commitment = self.commit(&polynomial)?;
Ok(commitment)
/// commit the actual polynomial with the values setup
pub fn commit_coef_form(&self, polynomial: &PolynomialCoefForm) -> Result<G1Affine, KzgError> {
if polynomial.len() > self.g1.len() {
return Err(KzgError::SerializationError(
"polynomial length is not correct".to_string(),
));
}
// When the polynomial is in coefficient form, use inverse FFT on the srs points.
// TODO: is this correct? See https://github.com/Layr-Labs/rust-kzg-bn254/issues/20
let bases = self.g1_ifft(polynomial.len())?;

match G1Projective::msm(&bases, polynomial.coeffs()) {
Ok(res) => Ok(res.into_affine()),
Err(err) => Err(KzgError::CommitError(err.to_string())),
}
}

pub fn blob_to_kzg_commitment(&self, blob: &Blob) -> Result<G1Affine, KzgError> {
let polynomial = blob.to_polynomial_eval_form();
self.commit_eval_form(&polynomial)
}

/// helper function to work with the library and the env of the kzg instance
pub fn compute_kzg_proof_with_roots_of_unity(
&self,
polynomial: &Polynomial,
polynomial: &PolynomialEvalForm,
index: u64,
) -> Result<G1Affine, KzgError> {
self.compute_kzg_proof(polynomial, index, &self.expanded_roots_of_unity)
}

/// function to compute the kzg proof given the values.
/// TODO: do we want a separate function for polynomials in evaluation form?
pub fn compute_kzg_proof(
&self,
polynomial: &Polynomial,
polynomial: &PolynomialEvalForm,
index: u64,
root_of_unities: &[Fr],
) -> Result<G1Affine, KzgError> {
Expand All @@ -526,7 +529,7 @@ impl Kzg {
));
}

let eval_fr = polynomial.to_vec();
let eval_fr = polynomial.evaluations();
let mut poly_shift: Vec<Fr> = Vec::with_capacity(eval_fr.len());
let usized_index = if let Some(x) = index.to_usize() {
x
Expand All @@ -539,7 +542,7 @@ impl Kzg {
let value_fr = eval_fr[usized_index];
let z_fr = root_of_unities[usized_index];

for fr in &eval_fr {
for fr in eval_fr {
poly_shift.push(*fr - value_fr);
}

Expand All @@ -563,16 +566,8 @@ impl Kzg {
}
}

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())?
},
};
// Polynomial is in evaluation form, so use the original g1 points
let bases = self.g1[..polynomial.len()].to_vec();

match G1Projective::msm(&bases, &quotient_poly) {
Ok(res) => Ok(G1Affine::from(res)),
Expand Down
Loading

0 comments on commit 5d3ec00

Please sign in to comment.