Skip to content

Commit

Permalink
feat: kzg batch verification (#24)
Browse files Browse the repository at this point in the history
* adding bare changes for batch verification

* adding some comments

* adding more comments

* moving back to sha2

* removing a test which is no longer needed. Removing methods no longer needed

* updates to method visibility, updating tests

* fmt fixes

* clean up

* cleanup, optimization, inline docs

* removing unwanted const

* more docs and cleanup

* formatting

* removing unwanted comments

* cargo fmt and clippy

* adding test for point at infinity

* cleaner errors, cleanup

* adding another test case

* removing unwanted errors

* adding fixes per comments

* adding 4844 spec references

* comment fixes

* formatting, adding index out of bound check, removing print statement

* removing unwanted test, adding test for evaluate_polynomial_in_evaluation_form

* moving test to bottom section

* Update src/polynomial.rs

Co-authored-by: Samuel Laferriere

* Update src/kzg.rs

Co-authored-by: Samuel Laferriere

* Update src/kzg.rs

Co-authored-by: Samuel Laferriere

* Update src/kzg.rs

Co-authored-by: Samuel Laferriere

* Update src/helpers.rs

Co-authored-by: Samuel Laferriere

* updating deps, and toolchain to 1.84

* removing errors test, no longer useful

* adding to_byte_array arg explanation

* fmt fixes

* fmt and clippy fixes

* fixing function names and fmt

* clippy fixes

* Update src/helpers.rs

Co-authored-by: Samuel Laferriere

* changes based on comments and discussion

---------

Co-authored-by: anupsv <[email protected]>
Co-authored-by: Samuel Laferriere
Co-authored-by: Bowen Xue <[email protected]>
  • Loading branch information
3 people authored Jan 11, 2025
1 parent 946a634 commit 4ad14ea
Show file tree
Hide file tree
Showing 12 changed files with 1,328 additions and 647 deletions.
18 changes: 10 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "rust-kzg-bn254"
version = "0.2.1"
edition = "2021"
authors = ["Anup Swamy Veena", "Teddy Knox"]
rust-version = "1.73"
rust-version = "1.81"
description = "This library offers a set of functions for generating and interacting with bn254 KZG commitments and proofs in rust, with the motivation of supporting fraud and validity proof logic in EigenDA rollup integrations."
readme = "README.md"
repository = "https://github.com/Layr-Labs/rust-kzg-bn254"
Expand All @@ -22,21 +22,23 @@ directories = "5.0.1"
hex-literal = "0.4.1"
rand = "0.8.5"
sha2 = "0.10.8"
ureq = "2.9.6"
ureq = "2.12.1"
num-bigint = "0.4"
rayon = "^1.5"
rayon = "1.10"
num-traits = "0.2"
byteorder = "1.4"
byteorder = "1.5"
ark-poly = { version = "0.5.0", features = ["parallel"] }
crossbeam-channel = "0.5"
num_cpus = "1.13.0"
num_cpus = "1.16.0"
sys-info = "0.9"
itertools = "0.13.0"
thiserror = "2.0.10"

[dev-dependencies]
criterion = "0.5"
lazy_static = "1.4"
tracing = { version = "^0.1.34", features = ["log"] }
tracing-subscriber = "0.3.18"
lazy_static = "1.5"
tracing = { version = "0.1.41", features = ["log"] }
tracing-subscriber = "0.3.19"

[[test]]
name = "kzg"
Expand Down
6 changes: 3 additions & 3 deletions benches/bench_kzg_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fn bench_kzg_proof(c: &mut Criterion) {
let index =
rand::thread_rng().gen_range(0..input_poly.len_underlying_blob_field_elements());
b.iter(|| {
kzg.compute_proof_with_roots_of_unity(&input_poly, index.try_into().unwrap())
kzg.compute_proof_with_known_z_fr_index(&input_poly, index.try_into().unwrap())
.unwrap()
});
});
Expand All @@ -37,7 +37,7 @@ fn bench_kzg_proof(c: &mut Criterion) {
let index =
rand::thread_rng().gen_range(0..input_poly.len_underlying_blob_field_elements());
b.iter(|| {
kzg.compute_proof_with_roots_of_unity(&input_poly, index.try_into().unwrap())
kzg.compute_proof_with_known_z_fr_index(&input_poly, index.try_into().unwrap())
.unwrap()
});
});
Expand All @@ -51,7 +51,7 @@ fn bench_kzg_proof(c: &mut Criterion) {
let index =
rand::thread_rng().gen_range(0..input_poly.len_underlying_blob_field_elements());
b.iter(|| {
kzg.compute_proof_with_roots_of_unity(&input_poly, index.try_into().unwrap())
kzg.compute_proof_with_known_z_fr_index(&input_poly, index.try_into().unwrap())
.unwrap()
});
});
Expand Down
12 changes: 6 additions & 6 deletions benches/bench_kzg_verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ fn bench_kzg_verify(c: &mut Criterion) {
rand::thread_rng().gen_range(0..input_poly.len_underlying_blob_field_elements());
let commitment = kzg.commit_eval_form(&input_poly).unwrap();
let proof = kzg
.compute_proof_with_roots_of_unity(&input_poly, index.try_into().unwrap())
.compute_proof_with_known_z_fr_index(&input_poly, index.try_into().unwrap())
.unwrap();
let value_fr = input_poly.get_at_index(index).unwrap();
let value_fr = input_poly.get_evalualtion(index).unwrap();
let z_fr = kzg.get_nth_root_of_unity(index).unwrap();
b.iter(|| kzg.verify_proof(commitment, proof, *value_fr, *z_fr));
});
Expand All @@ -41,9 +41,9 @@ fn bench_kzg_verify(c: &mut Criterion) {
rand::thread_rng().gen_range(0..input_poly.len_underlying_blob_field_elements());
let commitment = kzg.commit_eval_form(&input_poly).unwrap();
let proof = kzg
.compute_proof_with_roots_of_unity(&input_poly, index.try_into().unwrap())
.compute_proof_with_known_z_fr_index(&input_poly, index.try_into().unwrap())
.unwrap();
let value_fr = input_poly.get_at_index(index).unwrap();
let value_fr = input_poly.get_evalualtion(index).unwrap();
let z_fr = kzg.get_nth_root_of_unity(index).unwrap();
b.iter(|| kzg.verify_proof(commitment, proof, *value_fr, *z_fr));
});
Expand All @@ -58,9 +58,9 @@ fn bench_kzg_verify(c: &mut Criterion) {
rand::thread_rng().gen_range(0..input_poly.len_underlying_blob_field_elements());
let commitment = kzg.commit_eval_form(&input_poly).unwrap();
let proof = kzg
.compute_proof_with_roots_of_unity(&input_poly, index.try_into().unwrap())
.compute_proof_with_known_z_fr_index(&input_poly, index.try_into().unwrap())
.unwrap();
let value_fr = input_poly.get_at_index(index).unwrap();
let value_fr = input_poly.get_evalualtion(index).unwrap();
let z_fr = kzg.get_nth_root_of_unity(index).unwrap();
b.iter(|| kzg.verify_proof(commitment, proof, *value_fr, *z_fr));
});
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[toolchain]
channel = '1.75'
channel = '1.81'
profile = 'minimal'
components = ['clippy', 'rustfmt']
targets = ["x86_64-unknown-linux-gnu", "x86_64-pc-windows-gnu", "wasm32-unknown-unknown", "aarch64-apple-darwin"]
17 changes: 14 additions & 3 deletions src/blob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ use crate::{
polynomial::{PolynomialCoeffForm, PolynomialEvalForm},
};

/// A blob which is Eigen DA spec aligned.
/// A blob aligned with the Eigen DA specification.
/// TODO: we should probably move to a transparent repr like
/// <https://docs.rs/alloy-primitives/latest/alloy_primitives/struct.FixedBytes.html>
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Blob {
/// The binary data contained within the blob.
blob_data: Vec<u8>,
}

Expand Down Expand Up @@ -48,12 +49,22 @@ impl Blob {
&self.blob_data
}

/// Returns the length of the data in the blob.
/// Returns the length of the blob data.
///
/// This length reflects the size of the data, including any padding if applied.
///
/// # Returns
///
/// The length of the blob data as a `usize`.
pub fn len(&self) -> usize {
self.blob_data.len()
}

/// Checks if the blob data is empty.
/// Checks whether the blob data is empty.
///
/// # Returns
///
/// `true` if the blob data is empty, `false` otherwise.
pub fn is_empty(&self) -> bool {
self.blob_data.is_empty()
}
Expand Down
14 changes: 14 additions & 0 deletions src/consts.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
pub const BYTES_PER_FIELD_ELEMENT: usize = 32;
pub const SIZE_OF_G1_AFFINE_COMPRESSED: usize = 32; // in bytes
pub const SIZE_OF_G2_AFFINE_COMPRESSED: usize = 64; // in bytes

/// Ref: https://github.com/ethereum/consensus-specs/blob/master/specs/deneb/polynomial-commitments.md#blob
pub const FIAT_SHAMIR_PROTOCOL_DOMAIN: &[u8] = b"EIGENDA_FSBLOBVERIFY_V1_"; // Adapted from 4844

/// Ref: https://github.com/ethereum/consensus-specs/blob/master/specs/deneb/polynomial-commitments.md#blob
pub const RANDOM_CHALLENGE_KZG_BATCH_DOMAIN: &[u8] = b"EIGENDA_RCKZGBATCH___V1_"; // Adapted from 4844

pub const KZG_ENDIANNESS: Endianness = Endianness::Big; // Choose between Big or Little.

#[derive(Debug, Clone, Copy)]
pub enum Endianness {
Big,
Little,
}
104 changes: 52 additions & 52 deletions src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,64 +1,64 @@
use std::{error::Error, fmt};
use thiserror::Error;

#[derive(Clone, Debug, PartialEq)]
pub enum BlobError {
GenericError(String),
}

impl fmt::Display for BlobError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
BlobError::GenericError(ref msg) => write!(f, "generic error: {}", msg),
}
}
}

impl Error for BlobError {}

#[derive(Clone, Debug, PartialEq)]
/// Errors related to Polynomial operations.
///
/// The `PolynomialError` enum encapsulates all possible errors that can occur
/// during operations on the `Polynomial` struct, such as FFT transformations
/// and serialization errors.
#[derive(Clone, Debug, PartialEq, Error)]
pub enum PolynomialError {
SerializationFromStringError,
/// Error related to commitment operations with a descriptive message.
#[error("commitment error: {0}")]
CommitError(String),
GenericError(String),

/// Error related to Fast Fourier Transform (FFT) operations with a descriptive message.
#[error("FFT error: {0}")]
FFTError(String),
IncorrectFormError(String),
}

impl fmt::Display for PolynomialError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
PolynomialError::SerializationFromStringError => {
write!(f, "couldn't load string to fr vector")
},
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)
},
}
}
/// A generic error with a descriptive message.
#[error("generic error: {0}")]
GenericError(String),
}

impl Error for PolynomialError {}

#[derive(Clone, Debug, PartialEq)]
/// Errors related to KZG operations.
///
/// The `KzgError` enum encapsulates all possible errors that can occur during
/// KZG-related operations, including those from `PolynomialError` and `BlobError`.
/// It also includes additional errors specific to KZG operations.
#[derive(Clone, Debug, PartialEq, Error)]
pub enum KzgError {
CommitError(String),
/// Wraps errors originating from Polynomial operations.
#[error("polynomial error: {0}")]
PolynomialError(#[from] PolynomialError),

#[error("MSM error: {0}")]
MsmError(String),

/// Error related to serialization with a descriptive message.
#[error("serialization error: {0}")]
SerializationError(String),
FftError(String),

/// Error related to commitment processes with a descriptive message.
#[error("not on curve error: {0}")]
NotOnCurveError(String),

/// Error indicating an invalid commit operation with a descriptive message.
#[error("commit error: {0}")]
CommitError(String),

/// Error related to Fast Fourier Transform (FFT) operations with a descriptive message.
#[error("FFT error: {0}")]
FFTError(String),

/// A generic error with a descriptive message.
#[error("generic error: {0}")]
GenericError(String),
}

impl fmt::Display for KzgError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
KzgError::CommitError(ref msg) => write!(f, "Commitment error: {}", msg),
KzgError::SerializationError(ref msg) => write!(f, "Serialization error: {}", msg),
KzgError::FftError(ref msg) => write!(f, "FFT error: {}", msg),
KzgError::GenericError(ref msg) => write!(f, "Generic error: {}", msg),
}
}
}
/// Error indicating an invalid denominator scenario, typically in mathematical operations.
#[error("invalid denominator")]
InvalidDenominator,

impl Error for KzgError {}
/// Error indicating an invalid input length scenario, typically in data processing.
#[error("invalid input length")]
InvalidInputLength,
}
Loading

0 comments on commit 4ad14ea

Please sign in to comment.