From bbbaa8e6ceb312b6b2affd4c4b018a512a4299b6 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 25 Jan 2023 13:51:18 +0100 Subject: [PATCH 01/22] Start to use bytes48 type --- bindings/rust/src/bindings.rs | 23 ++++++++-- bindings/rust/src/lib.rs | 83 +++++++++++++++++++++++++++-------- src/c_kzg_4844.c | 28 ++++++------ src/c_kzg_4844.h | 14 +++--- 4 files changed, 106 insertions(+), 42 deletions(-) diff --git a/bindings/rust/src/bindings.rs b/bindings/rust/src/bindings.rs index 54e2c231e..c4f33bb69 100644 --- a/bindings/rust/src/bindings.rs +++ b/bindings/rust/src/bindings.rs @@ -30,11 +30,13 @@ struct blst_fr { struct blst_fp { l: [limb_t; 6usize], } + #[repr(C)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] struct blst_fp2 { fp: [blst_fp; 2usize], } + #[repr(C)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] struct blst_fp6 { @@ -90,6 +92,19 @@ impl Deref for Bytes32 { } } +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Bytes48 { + bytes: [u8; 48], +} + +impl Deref for Bytes48 { + type Target = [u8; 48]; + fn deref(&self) -> &Self::Target { + &self.bytes + } +} + #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct Blob { @@ -207,9 +222,9 @@ extern "C" { pub fn verify_aggregate_kzg_proof( out: *mut bool, blobs: *const Blob, - expected_kzg_commitments: *const KZGCommitment, + expected_commitments: *const Bytes48, n: usize, - kzg_aggregated_proof: *const KZGProof, + aggregated_proof: *const Bytes48, s: *const KZGSettings, ) -> C_KZG_RET; @@ -221,10 +236,10 @@ extern "C" { pub fn verify_kzg_proof( out: *mut bool, - polynomial_kzg: *const KZGCommitment, + commitment: *const Bytes48, z: *const Bytes32, y: *const Bytes32, - kzg_proof: *const KZGProof, + proof: *const Bytes48, s: *const KZGSettings, ) -> C_KZG_RET; } diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 8dff1057a..902841065 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -19,6 +19,8 @@ const NUM_G2_POINTS: usize = 65; #[derive(Debug)] pub enum Error { + /// The Bytes48 is invalid. + InvalidBytes48(String), /// The KZG proof is invalid. InvalidKzgProof(String), /// The KZG commitment is invalid. @@ -105,6 +107,33 @@ impl Drop for KZGSettings { } } +impl Bytes48 { + pub fn from_bytes(bytes: &[u8]) -> Result { + if bytes.len() != 48 { + return Err(Error::InvalidBytes48(format!( + "Invalid byte length. Expected {} got {}", + 48, + bytes.len(), + ))); + } + let mut new_bytes = [0; 48]; + new_bytes.copy_from_slice(bytes); + Ok(Self { bytes: new_bytes }) + } + + pub fn to_proof(self) -> Result { + let mut proof_bytes = [0; BYTES_PER_PROOF]; + proof_bytes.copy_from_slice(&self.bytes); + Ok(KZGProof { bytes: proof_bytes }) + } + + pub fn to_commitment(self) -> Result { + let mut commitment_bytes = [0; BYTES_PER_COMMITMENT]; + commitment_bytes.copy_from_slice(&self.bytes); + Ok(KZGCommitment { bytes: commitment_bytes }) + } +} + impl KZGProof { pub fn from_bytes(bytes: &[u8]) -> Result { if bytes.len() != BYTES_PER_PROOF { @@ -123,6 +152,12 @@ impl KZGProof { self.bytes } + pub fn to_bytes48(&self) -> Bytes48 { + let mut bytes = [0; 48]; + bytes.copy_from_slice(&self.bytes); + Bytes48 { bytes } + } + pub fn as_hex_string(&self) -> String { hex::encode(self.to_bytes()) } @@ -150,14 +185,14 @@ impl KZGProof { pub fn verify_aggregate_kzg_proof( &self, blobs: &[Blob], - expected_kzg_commitments: &[KZGCommitment], + expected_commitments: &[Bytes48], kzg_settings: &KZGSettings, ) -> Result { - if blobs.len() != expected_kzg_commitments.len() { + if blobs.len() != expected_commitments.len() { return Err(Error::MismatchLength(format!( "There are {} blobs and {} commitments", blobs.len(), - expected_kzg_commitments.len() + expected_commitments.len() ))); } let mut verified: MaybeUninit = MaybeUninit::uninit(); @@ -165,9 +200,9 @@ impl KZGProof { let res = verify_aggregate_kzg_proof( verified.as_mut_ptr(), blobs.as_ptr(), - expected_kzg_commitments.as_ptr(), + expected_commitments.as_ptr(), blobs.len(), - self, + &self.to_bytes48(), kzg_settings, ); if let C_KZG_RET::C_KZG_OK = res { @@ -180,7 +215,7 @@ impl KZGProof { pub fn verify_kzg_proof( &self, - kzg_commitment: KZGCommitment, + commitment: Bytes48, z: Bytes32, y: Bytes32, kzg_settings: &KZGSettings, @@ -189,10 +224,10 @@ impl KZGProof { unsafe { let res = verify_kzg_proof( verified.as_mut_ptr(), - &kzg_commitment, + &commitment, &z, &y, - self, + &self.to_bytes48(), kzg_settings, ); if let C_KZG_RET::C_KZG_OK = res { @@ -222,6 +257,12 @@ impl KZGCommitment { self.bytes } + pub fn to_bytes48(&self) -> Bytes48 { + let mut bytes = [0; 48]; + bytes.copy_from_slice(&self.bytes); + Bytes48 { bytes } + } + pub fn as_hex_string(&self) -> String { hex::encode(self.to_bytes()) } @@ -263,6 +304,12 @@ impl From<[u8; 32]> for Bytes32 { } } +impl From<[u8; 48]> for Bytes48 { + fn from(value: [u8; 48]) -> Self { + Self { bytes: value } + } +} + #[cfg(test)] mod tests { use super::*; @@ -289,22 +336,23 @@ mod tests { .map(|_| generate_random_blob(&mut rng)) .collect(); - let kzg_commitments: Vec = blobs + let commitments: Vec = blobs .clone() .into_iter() .map(|blob| KZGCommitment::blob_to_kzg_commitment(blob, &kzg_settings)) + .map(|commitment| commitment.to_bytes48()) .collect(); let kzg_proof = KZGProof::compute_aggregate_kzg_proof(&blobs, &kzg_settings).unwrap(); assert!(kzg_proof - .verify_aggregate_kzg_proof(&blobs, &kzg_commitments, &kzg_settings) + .verify_aggregate_kzg_proof(&blobs, &commitments, &kzg_settings) .unwrap()); blobs.pop(); let error = kzg_proof - .verify_aggregate_kzg_proof(&blobs, &kzg_commitments, &kzg_settings) + .verify_aggregate_kzg_proof(&blobs, &commitments, &kzg_settings) .unwrap_err(); assert!(matches!(error, Error::MismatchLength(_))); @@ -312,7 +360,7 @@ mod tests { blobs.push(incorrect_blob); assert!(!kzg_proof - .verify_aggregate_kzg_proof(&blobs, &kzg_commitments, &kzg_settings) + .verify_aggregate_kzg_proof(&blobs, &commitments, &kzg_settings) .unwrap()); } @@ -341,7 +389,7 @@ mod tests { for test in tests.iter() { let expected_proof = test.get("Proof").unwrap().as_str().unwrap(); - let expected_kzg_commitments = test + let expected_commitments = test .get("Commitments") .unwrap() .as_array() @@ -372,7 +420,7 @@ mod tests { let commitment = KZGCommitment::blob_to_kzg_commitment(blob, &kzg_settings); assert_eq!( commitment.as_hex_string().as_str(), - expected_kzg_commitments[i] + expected_commitments[i] ); } } @@ -394,9 +442,8 @@ mod tests { let proof = test.get("Proof").unwrap().as_str().unwrap(); let kzg_proof = KZGProof::from_bytes(&hex::decode(proof).unwrap()).unwrap(); - let commitment = test.get("Commitment").unwrap().as_str().unwrap(); - let kzg_commitment = - KZGCommitment::from_bytes(&hex::decode(commitment).unwrap()).unwrap(); + let commitment_hex = test.get("Commitment").unwrap().as_str().unwrap(); + let commitment = Bytes48::from_bytes(&hex::decode(commitment_hex).unwrap()).unwrap(); let z = test.get("InputPoint").unwrap().as_str().unwrap(); let mut z_bytes = [0; BYTES_PER_FIELD_ELEMENT]; @@ -408,7 +455,7 @@ mod tests { assert!(kzg_proof .verify_kzg_proof( - kzg_commitment, + commitment, z_bytes.into(), y_bytes.into(), &kzg_settings diff --git a/src/c_kzg_4844.c b/src/c_kzg_4844.c index 4319958cc..abd8e7b12 100644 --- a/src/c_kzg_4844.c +++ b/src/c_kzg_4844.c @@ -510,8 +510,8 @@ static C_KZG_RET bytes_to_g1(g1_t* out, const uint8_t bytes[48]) { * @param[out] out A 32-byte array to store the serialized field element * @param[in] in The field element to be serialized */ -static void bytes_from_bls_field(uint8_t out[32], const fr_t *in) { - blst_scalar_from_fr((blst_scalar*)out, in); +static void bytes_from_bls_field(Bytes32 *out, const fr_t *in) { + blst_scalar_from_fr((blst_scalar*)out->bytes, in); } /** @@ -716,7 +716,7 @@ static C_KZG_RET compute_challenges(fr_t *eval_challenge_out, fr_t *r_powers_out /* Copy polynomials */ for (i = 0; i < n; i++) for (j = 0; j < FIELD_ELEMENTS_PER_BLOB; j++) - bytes_from_bls_field(&bytes[ni + BYTES_PER_FIELD_ELEMENT * (i * FIELD_ELEMENTS_PER_BLOB + j)], &polys[i].evals[j]); + bytes_from_bls_field((Bytes32 *)&bytes[ni + BYTES_PER_FIELD_ELEMENT * (i * FIELD_ELEMENTS_PER_BLOB + j)], &polys[i].evals[j]); /* Copy commitments */ for (i = 0; i < n; i++) @@ -973,25 +973,25 @@ static C_KZG_RET verify_kzg_proof_impl(bool *out, const g1_t *commitment, const * @retval C_KZG_BADARGS Invalid inputs */ C_KZG_RET verify_kzg_proof(bool *out, - const KZGCommitment *commitment, + const Bytes48 *commitment, const Bytes32 *z, const Bytes32 *y, - const KZGProof *kzg_proof, + const Bytes48 *proof, const KZGSettings *s) { C_KZG_RET ret; - fr_t frz, fry; - g1_t g1commitment, g1proof; + fr_t z_fr, y_fr; + g1_t commitment_g1, proof_g1; - ret = bytes_to_g1(&g1commitment, commitment->bytes); + ret = bytes_to_g1(&commitment_g1, commitment->bytes); if (ret != C_KZG_OK) return ret; - ret = bytes_to_bls_field(&frz, z); + ret = bytes_to_bls_field(&z_fr, z); if (ret != C_KZG_OK) return ret; - ret = bytes_to_bls_field(&fry, y); + ret = bytes_to_bls_field(&y_fr, y); if (ret != C_KZG_OK) return ret; - ret = bytes_to_g1(&g1proof, kzg_proof->bytes); + ret = bytes_to_g1(&proof_g1, proof->bytes); if (ret != C_KZG_OK) return ret; - return verify_kzg_proof_impl(out, &g1commitment, &frz, &fry, &g1proof, s); + return verify_kzg_proof_impl(out, &commitment_g1, &z_fr, &y_fr, &proof_g1, s); } /** @@ -1231,9 +1231,9 @@ C_KZG_RET compute_aggregate_kzg_proof(KZGProof *out, */ C_KZG_RET verify_aggregate_kzg_proof(bool *out, const Blob *blobs, - const KZGCommitment *expected_kzg_commitments, + const Bytes48 *expected_kzg_commitments, size_t n, - const KZGProof *kzg_aggregated_proof, + const Bytes48 *kzg_aggregated_proof, const KZGSettings *s) { C_KZG_RET ret; g1_t* commitments = NULL; diff --git a/src/c_kzg_4844.h b/src/c_kzg_4844.h index 270ee6784..7c6200c02 100644 --- a/src/c_kzg_4844.h +++ b/src/c_kzg_4844.h @@ -45,10 +45,12 @@ typedef blst_p2 g2_t; /**< Internal G2 group element type */ typedef blst_fr fr_t; /**< Internal Fr field element type */ typedef struct { uint8_t bytes[32]; } Bytes32; -typedef struct { uint8_t bytes[BYTES_PER_COMMITMENT]; } KZGCommitment; -typedef struct { uint8_t bytes[BYTES_PER_PROOF]; } KZGProof; +typedef struct { uint8_t bytes[48]; } Bytes48; typedef struct { uint8_t bytes[BYTES_PER_BLOB]; } Blob; +typedef Bytes48 KZGCommitment; +typedef Bytes48 KZGProof; + /** * The common return type for all routines in which something can go wrong. */ @@ -101,9 +103,9 @@ C_KZG_RET compute_aggregate_kzg_proof(KZGProof *out, C_KZG_RET verify_aggregate_kzg_proof(bool *out, const Blob *blobs, - const KZGCommitment *expected_kzg_commitments, + const Bytes48 *expected_commitments, size_t n, - const KZGProof *kzg_aggregated_proof, + const Bytes48 *aggregated_proof, const KZGSettings *s); C_KZG_RET blob_to_kzg_commitment(KZGCommitment *out, @@ -111,10 +113,10 @@ C_KZG_RET blob_to_kzg_commitment(KZGCommitment *out, const KZGSettings *s); C_KZG_RET verify_kzg_proof(bool *out, - const KZGCommitment *polynomial_kzg, + const Bytes48 *commitment, const Bytes32 *z, const Bytes32 *y, - const KZGProof *kzg_proof, + const Bytes48 *proof, const KZGSettings *s); C_KZG_RET compute_kzg_proof(KZGProof *out, From 9ecf0a1355a3494ddfbb83be14a917dbdf98a3d6 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 25 Jan 2023 14:06:38 +0100 Subject: [PATCH 02/22] Update java bindings --- bindings/java/c_kzg_4844_jni.c | 8 ++++---- .../java/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bindings/java/c_kzg_4844_jni.c b/bindings/java/c_kzg_4844_jni.c index 9c3bb54d2..802cf5504 100644 --- a/bindings/java/c_kzg_4844_jni.c +++ b/bindings/java/c_kzg_4844_jni.c @@ -186,8 +186,8 @@ JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyAggregateKzg return 0; } - KZGProof *proof_native = (KZGProof *)(*env)->GetByteArrayElements(env, proof, NULL); - KZGCommitment *commitments_native = (KZGCommitment *)(*env)->GetByteArrayElements(env, commitments, NULL); + Bytes48 *proof_native = (Bytes48 *)(*env)->GetByteArrayElements(env, proof, NULL); + Bytes48 *commitments_native = (Bytes48 *)(*env)->GetByteArrayElements(env, commitments, NULL); jbyte *blobs_native = (*env)->GetByteArrayElements(env, blobs, NULL); bool out; @@ -247,8 +247,8 @@ JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyKzgProof(JNI return 0; } - KZGCommitment *commitment_native = (KZGCommitment *)(*env)->GetByteArrayElements(env, commitment, NULL); - KZGProof *proof_native = (KZGProof *)(*env)->GetByteArrayElements(env, proof, NULL); + Bytes48 *commitment_native = (Bytes48 *)(*env)->GetByteArrayElements(env, commitment, NULL); + Bytes48 *proof_native = (Bytes48 *)(*env)->GetByteArrayElements(env, proof, NULL); Bytes32 *z_native = (Bytes32 *)(*env)->GetByteArrayElements(env, z, NULL); Bytes32 *y_native = (Bytes32 *)(*env)->GetByteArrayElements(env, y, NULL); diff --git a/bindings/java/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java b/bindings/java/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java index c2d8a20a1..48378f747 100644 --- a/bindings/java/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java +++ b/bindings/java/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java @@ -133,8 +133,8 @@ public static native void loadTrustedSetup(byte[] g1, long g1Count, byte[] g2, * @return true if the proof is valid and false otherwise * @throws CKZGException if there is a crypto error */ - public static native boolean verifyAggregateKzgProof(byte[] blobs, byte[] commitments, long count, - byte[] proof); + public static native boolean verifyAggregateKzgProof(byte[] blobs, byte[] expected_commitments, long count, + byte[] aggregated_proof); /** * Calculates commitment for a given blob @@ -155,6 +155,6 @@ public static native boolean verifyAggregateKzgProof(byte[] blobs, byte[] commit * @return true if the proof is valid and false otherwise * @throws CKZGException if there is a crypto error */ - public static native boolean verifyKzgProof(byte[] commitment, byte[] z, byte[] y, byte[] proof); + public static native boolean verifyKzgProof(byte[] expected_commitment, byte[] z, byte[] y, byte[] proof); } From 8d846518d3e0ea30ee2304db6a2e3c771ca1e8c5 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 25 Jan 2023 14:29:51 +0100 Subject: [PATCH 03/22] Update variable names --- bindings/java/c_kzg_4844_jni.c | 30 +++++++++++------------ bindings/rust/src/bindings.rs | 12 ++++----- bindings/rust/src/lib.rs | 20 +++++++-------- src/c_kzg_4844.c | 45 +++++++++++++++++----------------- src/c_kzg_4844.h | 16 ++++++------ 5 files changed, 61 insertions(+), 62 deletions(-) diff --git a/bindings/java/c_kzg_4844_jni.c b/bindings/java/c_kzg_4844_jni.c index 802cf5504..49312aacf 100644 --- a/bindings/java/c_kzg_4844_jni.c +++ b/bindings/java/c_kzg_4844_jni.c @@ -160,7 +160,7 @@ JNIEXPORT jbyteArray JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_computeAggregate return proof; } -JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyAggregateKzgProof(JNIEnv *env, jclass thisCls, jbyteArray blobs, jbyteArray commitments, jlong count, jbyteArray proof) +JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyAggregateKzgProof(JNIEnv *env, jclass thisCls, jbyteArray blobs, jbyteArray expected_commitments_bytes, jlong count, jbyteArray proof_bytes) { if (settings == NULL) { @@ -178,7 +178,7 @@ JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyAggregateKzg return 0; } - size_t commitments_size = (size_t)(*env)->GetArrayLength(env, commitments); + size_t commitments_size = (size_t)(*env)->GetArrayLength(env, expected_commitments_bytes); size_t expected_commitments_size = BYTES_PER_COMMITMENT * count_native; if (commitments_size != expected_commitments_size) { @@ -186,15 +186,15 @@ JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyAggregateKzg return 0; } - Bytes48 *proof_native = (Bytes48 *)(*env)->GetByteArrayElements(env, proof, NULL); - Bytes48 *commitments_native = (Bytes48 *)(*env)->GetByteArrayElements(env, commitments, NULL); + Bytes48 *proof_native = (Bytes48 *)(*env)->GetByteArrayElements(env, proof_bytes, NULL); + Bytes48 *commitments_native = (Bytes48 *)(*env)->GetByteArrayElements(env, expected_commitments_bytes, NULL); jbyte *blobs_native = (*env)->GetByteArrayElements(env, blobs, NULL); bool out; C_KZG_RET ret = verify_aggregate_kzg_proof(&out, (const Blob *)blobs_native, commitments_native, count_native, proof_native, settings); - (*env)->ReleaseByteArrayElements(env, proof, (jbyte *)proof_native, JNI_ABORT); - (*env)->ReleaseByteArrayElements(env, commitments, (jbyte *)commitments_native, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, proof_bytes, (jbyte *)proof_native, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, expected_commitments_bytes, (jbyte *)commitments_native, JNI_ABORT); (*env)->ReleaseByteArrayElements(env, blobs, blobs_native, JNI_ABORT); if (ret != C_KZG_OK) @@ -239,7 +239,7 @@ JNIEXPORT jbyteArray JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_blobToKzgCommitm return commitment; } -JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyKzgProof(JNIEnv *env, jclass thisCls, jbyteArray commitment, jbyteArray z, jbyteArray y, jbyteArray proof) +JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyKzgProof(JNIEnv *env, jclass thisCls, jbyteArray expected_commitment_bytes, jbyteArray z_bytes, jbyteArray y_bytes, jbyteArray proof_bytes) { if (settings == NULL) { @@ -247,18 +247,18 @@ JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyKzgProof(JNI return 0; } - Bytes48 *commitment_native = (Bytes48 *)(*env)->GetByteArrayElements(env, commitment, NULL); - Bytes48 *proof_native = (Bytes48 *)(*env)->GetByteArrayElements(env, proof, NULL); - Bytes32 *z_native = (Bytes32 *)(*env)->GetByteArrayElements(env, z, NULL); - Bytes32 *y_native = (Bytes32 *)(*env)->GetByteArrayElements(env, y, NULL); + Bytes48 *commitment_native = (Bytes48 *)(*env)->GetByteArrayElements(env, expected_commitment_bytes, NULL); + Bytes48 *proof_native = (Bytes48 *)(*env)->GetByteArrayElements(env, proof_bytes, NULL); + Bytes32 *z_native = (Bytes32 *)(*env)->GetByteArrayElements(env, z_bytes, NULL); + Bytes32 *y_native = (Bytes32 *)(*env)->GetByteArrayElements(env, y_bytes, NULL); bool out; C_KZG_RET ret = verify_kzg_proof(&out, commitment_native, z_native, y_native, proof_native, settings); - (*env)->ReleaseByteArrayElements(env, commitment, (jbyte *)commitment_native, JNI_ABORT); - (*env)->ReleaseByteArrayElements(env, z, (jbyte *)z_native, JNI_ABORT); - (*env)->ReleaseByteArrayElements(env, y, (jbyte *)y_native, JNI_ABORT); - (*env)->ReleaseByteArrayElements(env, proof, (jbyte *)proof_native, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, expected_commitment_bytes, (jbyte *)commitment_native, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, z_bytes, (jbyte *)z_native, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, y_bytes, (jbyte *)y_native, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, proof_bytes, (jbyte *)proof_native, JNI_ABORT); if (ret != C_KZG_OK) { diff --git a/bindings/rust/src/bindings.rs b/bindings/rust/src/bindings.rs index c4f33bb69..c9b488e36 100644 --- a/bindings/rust/src/bindings.rs +++ b/bindings/rust/src/bindings.rs @@ -222,9 +222,9 @@ extern "C" { pub fn verify_aggregate_kzg_proof( out: *mut bool, blobs: *const Blob, - expected_commitments: *const Bytes48, + commitments_bytes: *const Bytes48, n: usize, - aggregated_proof: *const Bytes48, + aggregated_proof_bytes: *const Bytes48, s: *const KZGSettings, ) -> C_KZG_RET; @@ -236,10 +236,10 @@ extern "C" { pub fn verify_kzg_proof( out: *mut bool, - commitment: *const Bytes48, - z: *const Bytes32, - y: *const Bytes32, - proof: *const Bytes48, + commitment_bytes: *const Bytes48, + z_bytes: *const Bytes32, + y_bytes: *const Bytes32, + proof_bytes: *const Bytes48, s: *const KZGSettings, ) -> C_KZG_RET; } diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 902841065..3d9c9c798 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -185,14 +185,14 @@ impl KZGProof { pub fn verify_aggregate_kzg_proof( &self, blobs: &[Blob], - expected_commitments: &[Bytes48], + commitments_bytes: &[Bytes48], kzg_settings: &KZGSettings, ) -> Result { - if blobs.len() != expected_commitments.len() { + if blobs.len() != commitments_bytes.len() { return Err(Error::MismatchLength(format!( "There are {} blobs and {} commitments", blobs.len(), - expected_commitments.len() + commitments_bytes.len() ))); } let mut verified: MaybeUninit = MaybeUninit::uninit(); @@ -200,7 +200,7 @@ impl KZGProof { let res = verify_aggregate_kzg_proof( verified.as_mut_ptr(), blobs.as_ptr(), - expected_commitments.as_ptr(), + commitments_bytes.as_ptr(), blobs.len(), &self.to_bytes48(), kzg_settings, @@ -215,18 +215,18 @@ impl KZGProof { pub fn verify_kzg_proof( &self, - commitment: Bytes48, - z: Bytes32, - y: Bytes32, + commitment_bytes: Bytes48, + z_bytes: Bytes32, + y_bytes: Bytes32, kzg_settings: &KZGSettings, ) -> Result { let mut verified: MaybeUninit = MaybeUninit::uninit(); unsafe { let res = verify_kzg_proof( verified.as_mut_ptr(), - &commitment, - &z, - &y, + &commitment_bytes, + &z_bytes, + &y_bytes, &self.to_bytes48(), kzg_settings, ); diff --git a/src/c_kzg_4844.c b/src/c_kzg_4844.c index abd8e7b12..98cc75c12 100644 --- a/src/c_kzg_4844.c +++ b/src/c_kzg_4844.c @@ -482,8 +482,8 @@ static int log2_pow2(uint32_t n) { * @param[out] out A 48-byte array to store the serialized G1 element * @param[in] in The G1 element to be serialized */ -static void bytes_from_g1(uint8_t out[48], const g1_t *in) { - blst_p1_compress(out, in); +static void bytes_from_g1(Bytes48 *out, const g1_t *in) { + blst_p1_compress(out->bytes, in); } @@ -495,9 +495,9 @@ static void bytes_from_g1(uint8_t out[48], const g1_t *in) { * @retval C_KZG_OK Deserialization successful * @retval C_KZG_BADARGS Input bytes were not a valid G1 element */ -static C_KZG_RET bytes_to_g1(g1_t* out, const uint8_t bytes[48]) { +static C_KZG_RET bytes_to_g1(g1_t* out, const Bytes48 *in) { blst_p1_affine tmp; - if (blst_p1_uncompress(&tmp, bytes) != BLST_SUCCESS) + if (blst_p1_uncompress(&tmp, in->bytes) != BLST_SUCCESS) return C_KZG_BADARGS; blst_p1_from_affine(out, &tmp); return C_KZG_OK; @@ -720,7 +720,7 @@ static C_KZG_RET compute_challenges(fr_t *eval_challenge_out, fr_t *r_powers_out /* Copy commitments */ for (i = 0; i < n; i++) - bytes_from_g1(&bytes[np + i * 48], &comms[i]); + bytes_from_g1((Bytes48 *)&bytes[np + i * 48], &comms[i]); /* Now let's create challenges! */ uint8_t hashed_data[32] = {0}; @@ -920,7 +920,6 @@ static C_KZG_RET evaluate_polynomial_in_evaluation_form(fr_t *out, const Polynom // KZG Functions /////////////////////////////////////////////////////////////////////////////// - /** * Compute a KZG commitment from a polynomial. * @@ -952,7 +951,7 @@ C_KZG_RET blob_to_kzg_commitment(KZGCommitment *out, const Blob *blob, const KZG if (ret != C_KZG_OK) return ret; ret = poly_to_kzg_commitment(&commitment, &p, s); if (ret != C_KZG_OK) return ret; - bytes_from_g1((uint8_t *)(out), &commitment); + bytes_from_g1(out, &commitment); return C_KZG_OK; } @@ -973,22 +972,22 @@ static C_KZG_RET verify_kzg_proof_impl(bool *out, const g1_t *commitment, const * @retval C_KZG_BADARGS Invalid inputs */ C_KZG_RET verify_kzg_proof(bool *out, - const Bytes48 *commitment, - const Bytes32 *z, - const Bytes32 *y, - const Bytes48 *proof, + const Bytes48 *commitment_bytes, + const Bytes32 *z_bytes, + const Bytes32 *y_bytes, + const Bytes48 *proof_bytes, const KZGSettings *s) { C_KZG_RET ret; fr_t z_fr, y_fr; g1_t commitment_g1, proof_g1; - ret = bytes_to_g1(&commitment_g1, commitment->bytes); + ret = bytes_to_g1(&commitment_g1, commitment_bytes); if (ret != C_KZG_OK) return ret; - ret = bytes_to_bls_field(&z_fr, z); + ret = bytes_to_bls_field(&z_fr, z_bytes); if (ret != C_KZG_OK) return ret; - ret = bytes_to_bls_field(&y_fr, y); + ret = bytes_to_bls_field(&y_fr, y_bytes); if (ret != C_KZG_OK) return ret; - ret = bytes_to_g1(&proof_g1, proof->bytes); + ret = bytes_to_g1(&proof_g1, proof_bytes); if (ret != C_KZG_OK) return ret; return verify_kzg_proof_impl(out, &commitment_g1, &z_fr, &y_fr, &proof_g1, s); @@ -1034,14 +1033,14 @@ C_KZG_RET compute_kzg_proof_impl(KZGProof *out, const Polynomial *polynomial, co * @retval C_KZG_OK All is well * @retval C_KZG_MALLOC Memory allocation failed */ -C_KZG_RET compute_kzg_proof(KZGProof *out, const Blob *blob, const Bytes32 *z, const KZGSettings *s) { +C_KZG_RET compute_kzg_proof(KZGProof *out, const Blob *blob, const Bytes32 *z_bytes, const KZGSettings *s) { C_KZG_RET ret; Polynomial polynomial; fr_t frz; ret = blob_to_polynomial(&polynomial, blob); if (ret != C_KZG_OK) goto out; - ret = bytes_to_bls_field(&frz, z); + ret = bytes_to_bls_field(&frz, z_bytes); if (ret != C_KZG_OK) goto out; ret = compute_kzg_proof_impl(out, &polynomial, &frz, s); if (ret != C_KZG_OK) goto out; @@ -1118,7 +1117,7 @@ C_KZG_RET compute_kzg_proof_impl(KZGProof *out, const Polynomial *polynomial, co ret = g1_lincomb(&out_g1, s->g1_values, (const fr_t *)(&q.evals), FIELD_ELEMENTS_PER_BLOB); if (ret != C_KZG_OK) goto out; - bytes_from_g1(out->bytes, &out_g1); + bytes_from_g1(out, &out_g1); out: free(inverses_in); @@ -1231,16 +1230,16 @@ C_KZG_RET compute_aggregate_kzg_proof(KZGProof *out, */ C_KZG_RET verify_aggregate_kzg_proof(bool *out, const Blob *blobs, - const Bytes48 *expected_kzg_commitments, + const Bytes48 *commitments_bytes, size_t n, - const Bytes48 *kzg_aggregated_proof, + const Bytes48 *aggregated_proof_bytes, const KZGSettings *s) { C_KZG_RET ret; g1_t* commitments = NULL; Polynomial* polys = NULL; g1_t proof; - ret = bytes_to_g1(&proof, kzg_aggregated_proof->bytes); + ret = bytes_to_g1(&proof, aggregated_proof_bytes); if (ret != C_KZG_OK) goto out; commitments = calloc(n, sizeof(g1_t)); @@ -1256,7 +1255,7 @@ C_KZG_RET verify_aggregate_kzg_proof(bool *out, } for (size_t i = 0; i < n; i++) { - ret = bytes_to_g1(&commitments[i], expected_kzg_commitments[i].bytes); + ret = bytes_to_g1(&commitments[i], &commitments_bytes[i]); if (ret != C_KZG_OK) goto out; ret = blob_to_polynomial(&polys[i], &blobs[i]); if (ret != C_KZG_OK) goto out; @@ -1496,7 +1495,7 @@ C_KZG_RET load_trusted_setup(KZGSettings *out, const uint8_t *g1_bytes, size_t n if (ret != C_KZG_OK) goto out_error; for (i = 0; i < n1; i++) { - ret = bytes_to_g1(&g1_projective[i], &g1_bytes[48 * i]); + ret = bytes_to_g1(&g1_projective[i], (Bytes48 *)&g1_bytes[48 * i]); if (ret != C_KZG_OK) goto out_error; } diff --git a/src/c_kzg_4844.h b/src/c_kzg_4844.h index 7c6200c02..422fe258e 100644 --- a/src/c_kzg_4844.h +++ b/src/c_kzg_4844.h @@ -103,9 +103,9 @@ C_KZG_RET compute_aggregate_kzg_proof(KZGProof *out, C_KZG_RET verify_aggregate_kzg_proof(bool *out, const Blob *blobs, - const Bytes48 *expected_commitments, + const Bytes48 *commitments_bytes, size_t n, - const Bytes48 *aggregated_proof, + const Bytes48 *aggregated_proof_bytes, const KZGSettings *s); C_KZG_RET blob_to_kzg_commitment(KZGCommitment *out, @@ -113,15 +113,15 @@ C_KZG_RET blob_to_kzg_commitment(KZGCommitment *out, const KZGSettings *s); C_KZG_RET verify_kzg_proof(bool *out, - const Bytes48 *commitment, - const Bytes32 *z, - const Bytes32 *y, - const Bytes48 *proof, + const Bytes48 *commitment_bytes, + const Bytes32 *z_bytes, + const Bytes32 *y_bytes, + const Bytes48 *proof_bytes, const KZGSettings *s); C_KZG_RET compute_kzg_proof(KZGProof *out, - const Blob *p, - const Bytes32 *z, + const Blob *blobs, + const Bytes32 *z_bytes, const KZGSettings *s); #ifdef __cplusplus From c7c4852f531f8de909d6aa8af581ac2fd317a24b Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 25 Jan 2023 14:35:12 +0100 Subject: [PATCH 04/22] Update csharp bindings --- bindings/csharp/Ckzg.Bindings/Ckzg.cs | 4 ++-- bindings/csharp/ckzg.c | 8 ++++---- bindings/csharp/ckzg.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/bindings/csharp/Ckzg.Bindings/Ckzg.cs b/bindings/csharp/Ckzg.Bindings/Ckzg.cs index e7eab67a6..851158936 100644 --- a/bindings/csharp/Ckzg.Bindings/Ckzg.cs +++ b/bindings/csharp/Ckzg.Bindings/Ckzg.cs @@ -53,7 +53,7 @@ static Ckzg() => AssemblyLoadContext.Default.ResolvingUnmanagedDll += (assembly, /// Trusted setup settings /// Returns error code or 0 if the proof is correct [DllImport("ckzg", EntryPoint = "verify_aggregate_kzg_proof_wrap", CallingConvention = CallingConvention.Cdecl)] - public unsafe static extern int VerifyAggregatedKzgProof(byte* blobs, byte* commitments, int count, byte* proof, IntPtr ts); + public unsafe static extern int VerifyAggregatedKzgProof(byte* blobs, byte* commitments_bytes, int count, byte* aggregated_proof_bytes, IntPtr ts); /// /// Verify the proof by point evaluation for the given commitment @@ -65,7 +65,7 @@ static Ckzg() => AssemblyLoadContext.Default.ResolvingUnmanagedDll += (assembly, /// Trusted setup settings /// Returns error code or 0 if the proof is correct [DllImport("ckzg", EntryPoint = "verify_kzg_proof_wrap", CallingConvention = CallingConvention.Cdecl)] - public unsafe static extern int VerifyKzgProof(byte* commitment, byte* z, byte* y, byte* proof, IntPtr ts); + public unsafe static extern int VerifyKzgProof(byte* commitment_bytes, byte* z_bytes, byte* y_bytes, byte* proof_bytes, IntPtr ts); /// /// Load trusted setup settings from file diff --git a/bindings/csharp/ckzg.c b/bindings/csharp/ckzg.c index af5968cdc..a29773395 100644 --- a/bindings/csharp/ckzg.c +++ b/bindings/csharp/ckzg.c @@ -24,17 +24,17 @@ void free_trusted_setup_wrap(KZGSettings *s) { free(s); } -int verify_aggregate_kzg_proof_wrap(const Blob *blobs, const KZGCommitment *commitments, size_t n, const KZGProof *proof, const KZGSettings *s) { +int verify_aggregate_kzg_proof_wrap(const Blob *blobs, const Bytes48 *commitments_bytes, size_t n, const Bytes48 *aggregated_proof_bytes, const KZGSettings *s) { bool b; - C_KZG_RET ret = verify_aggregate_kzg_proof(&b, blobs, commitments, n, proof, s); + C_KZG_RET ret = verify_aggregate_kzg_proof(&b, blobs, commitments_bytes, n, aggregated_proof_bytes, s); if (ret != C_KZG_OK) return -1; return b ? 0 : 1; } -int verify_kzg_proof_wrap(const KZGCommitment *c, const Bytes32 *z, const Bytes32 *y, const KZGProof *p, KZGSettings *s) { +int verify_kzg_proof_wrap(const Bytes48 *commitment_bytes, const Bytes32 *z_bytes, const Bytes32 *y_bytes, const Bytes48 *proof_bytes, KZGSettings *s) { bool out; - if (verify_kzg_proof(&out, c, z, y, p, s) != C_KZG_OK) + if (verify_kzg_proof(&out, commitment_bytes, z_bytes, y_bytes, proof_bytes, s) != C_KZG_OK) return -2; return out ? 0 : 1; diff --git a/bindings/csharp/ckzg.h b/bindings/csharp/ckzg.h index c27f61db4..9a5e5d99b 100644 --- a/bindings/csharp/ckzg.h +++ b/bindings/csharp/ckzg.h @@ -15,8 +15,8 @@ DLLEXPORT void free_trusted_setup_wrap(KZGSettings *s); DLLEXPORT C_KZG_RET blob_to_kzg_commitment(KZGCommitment *out, const Blob *blob, const KZGSettings *s); -DLLEXPORT int verify_aggregate_kzg_proof_wrap(const Blob blobs[], const KZGCommitment *commitments, size_t n, const KZGProof *proof, const KZGSettings *s); +DLLEXPORT int verify_aggregate_kzg_proof_wrap(const Blob blobs[], const Bytes48 *commitments_bytes, size_t n, const Bytes48 *aggregated_proof_bytes, const KZGSettings *s); DLLEXPORT C_KZG_RET compute_aggregate_kzg_proof(KZGProof *out, const Blob blobs[], size_t n, const KZGSettings *s); -DLLEXPORT int verify_kzg_proof_wrap(const KZGCommitment *c, const Bytes32 *z, const Bytes32 *y, const KZGProof *p, KZGSettings *s); +DLLEXPORT int verify_kzg_proof_wrap(const Bytes48 *commitment_bytes, const Bytes32 *z_bytes, const Bytes32 *y_bytes, const Bytes48 *proof_bytes, KZGSettings *s); From 1681d54811d50b8c3380e807d78e2248d193fde7 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 25 Jan 2023 14:47:42 +0100 Subject: [PATCH 05/22] Update node.js bindings --- bindings/node.js/kzg.cxx | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/bindings/node.js/kzg.cxx b/bindings/node.js/kzg.cxx index 020fd5ce2..b11eb520b 100644 --- a/bindings/node.js/kzg.cxx +++ b/bindings/node.js/kzg.cxx @@ -197,7 +197,7 @@ Napi::Value ComputeAggregateKzgProof(const Napi::CallbackInfo& info) { return napi_typed_array_from_bytes((uint8_t *)(&proof), BYTES_PER_PROOF, env); } -// verifyAggregateKzgProof: (blobs: Blob[], expectedKzgCommitments: KZGCommitment[], kzgAggregatedProof: KZGProof, setupHandle: SetupHandle) => boolean; +// verifyAggregateKzgProof: (blobs: Blob[], commitmentsBytes: Bytes48[], aggregatedProof: Bytes48, setupHandle: SetupHandle) => boolean; Napi::Value VerifyAggregateKzgProof(const Napi::CallbackInfo& info) { auto env = info.Env(); @@ -221,7 +221,7 @@ Napi::Value VerifyAggregateKzgProof(const Napi::CallbackInfo& info) { return env.Null(); }; - auto commitments = (KZGCommitment*)calloc(blobs_count, sizeof(KZGCommitment)); + auto commitments = (Bytes48*)calloc(blobs_count, sizeof(Bytes48)); if (commitments == NULL) { free(blobs); Napi::Error::New(env, "Error while allocating memory for commitments").ThrowAsJavaScriptException(); @@ -248,7 +248,7 @@ Napi::Value VerifyAggregateKzgProof(const Napi::CallbackInfo& info) { blobs, commitments, blobs_count, - (KZGProof *)proof_bytes, + (Bytes48 *)proof_bytes, kzg_settings ); @@ -266,7 +266,7 @@ Napi::Value VerifyAggregateKzgProof(const Napi::CallbackInfo& info) { return Napi::Boolean::New(env, verification_result); } -// verifyKzgProof: (polynomialKzg: KZGCommitment, z: Bytes32, y: Bytes32, kzgProof: KZGProof, setupHandle: SetupHandle) => boolean; +// verifyKzgProof: (commitmentBytes: Bytes48, zBytes: Bytes32, yBytes: Bytes32, proofBytes: Bytes48, setupHandle: SetupHandle) => boolean; Napi::Value VerifyKzgProof(const Napi::CallbackInfo& info) { auto env = info.Env(); @@ -276,10 +276,10 @@ Napi::Value VerifyKzgProof(const Napi::CallbackInfo& info) { return throw_invalid_arguments_count(expected_argument_count, argument_count, env); } - auto polynomial_kzg = extract_byte_array_from_param(info, 0, "polynomialKzg"); - auto z = extract_byte_array_from_param(info, 1, "z"); - auto y = extract_byte_array_from_param(info, 2, "y"); - auto kzg_proof = extract_byte_array_from_param(info, 3, "kzgProof"); + auto commitment_bytes = extract_byte_array_from_param(info, 0, "commitmentBytes"); + auto z_bytes = extract_byte_array_from_param(info, 1, "zBytes"); + auto y_bytes = extract_byte_array_from_param(info, 2, "yBytes"); + auto proof_bytes = extract_byte_array_from_param(info, 3, "proofBytes"); auto kzg_settings = info[4].As>().Data(); if (env.IsExceptionPending()) { @@ -289,10 +289,10 @@ Napi::Value VerifyKzgProof(const Napi::CallbackInfo& info) { bool out; C_KZG_RET ret = verify_kzg_proof( &out, - (KZGCommitment *)polynomial_kzg, - (Bytes32 *)z, - (Bytes32 *)y, - (KZGProof *)kzg_proof, + (Bytes48 *)commitment_bytes, + (Bytes32 *)z_bytes, + (Bytes32 *)y_bytes, + (Bytes48 *)proof_bytes, kzg_settings ); From db0015468686535171f05b1f3e4700b62afaf720 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 25 Jan 2023 14:50:30 +0100 Subject: [PATCH 06/22] Update python bindings --- bindings/python/ckzg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/python/ckzg.c b/bindings/python/ckzg.c index bfc2cf79e..8b975aaab 100644 --- a/bindings/python/ckzg.c +++ b/bindings/python/ckzg.c @@ -106,8 +106,8 @@ static PyObject* verify_aggregate_kzg_proof_wrap(PyObject *self, PyObject *args) return PyErr_Format(PyExc_ValueError, "expected same number of commitments as polynomials"); const Blob* blobs = (Blob *)PyBytes_AsString(b); - const KZGProof *proof = (KZGProof *)PyBytes_AsString(p); - const KZGCommitment *commitments = (KZGCommitment *)PyBytes_AsString(c); + const Bytes48 *proof_bytes = (Bytes48 *)PyBytes_AsString(p); + const Bytes48 *commitments_bytes = (Bytes48 *)PyBytes_AsString(c); bool out; if (verify_aggregate_kzg_proof(&out, From 5f66d270521c2fd8aa86e8cfdffa1858f58e397c Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 25 Jan 2023 16:58:46 +0100 Subject: [PATCH 07/22] Fix mistake in python bindings --- bindings/python/ckzg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/ckzg.c b/bindings/python/ckzg.c index 8b975aaab..45e2d6dbd 100644 --- a/bindings/python/ckzg.c +++ b/bindings/python/ckzg.c @@ -111,7 +111,7 @@ static PyObject* verify_aggregate_kzg_proof_wrap(PyObject *self, PyObject *args) bool out; if (verify_aggregate_kzg_proof(&out, - blobs, commitments, n, proof, + blobs, commitments_bytes, n, proof_bytes, PyCapsule_GetPointer(s, "KZGSettings")) != C_KZG_OK) { return PyErr_Format(PyExc_RuntimeError, "verify_aggregate_kzg_proof failed"); } From a38d78cf4fed65e5ea9c6269f38b383e8b8ff751 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 25 Jan 2023 23:00:53 +0100 Subject: [PATCH 08/22] Add new functions --- src/c_kzg_4844.c | 66 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/src/c_kzg_4844.c b/src/c_kzg_4844.c index 98cc75c12..25e684d47 100644 --- a/src/c_kzg_4844.c +++ b/src/c_kzg_4844.c @@ -486,7 +486,6 @@ static void bytes_from_g1(Bytes48 *out, const g1_t *in) { blst_p1_compress(out->bytes, in); } - /** * Deserialize bytes into a G1 group element. * @@ -495,15 +494,14 @@ static void bytes_from_g1(Bytes48 *out, const g1_t *in) { * @retval C_KZG_OK Deserialization successful * @retval C_KZG_BADARGS Input bytes were not a valid G1 element */ -static C_KZG_RET bytes_to_g1(g1_t* out, const Bytes48 *in) { +static C_KZG_RET bytes_to_g1(g1_t* out, const Bytes48 *b) { blst_p1_affine tmp; - if (blst_p1_uncompress(&tmp, in->bytes) != BLST_SUCCESS) + if (blst_p1_uncompress(&tmp, b->bytes) != BLST_SUCCESS) return C_KZG_BADARGS; blst_p1_from_affine(out, &tmp); return C_KZG_OK; } - /** * Serialize a BLS field element into bytes. * @@ -664,6 +662,58 @@ static C_KZG_RET bytes_to_bls_field(fr_t *out, const Bytes32 *b) { return C_KZG_OK; } +/** + * Perform BLS validation required by the types KZGProof and KZGCommitment. + * + * @param[in] b The proof/commitment bytes + */ +static C_KZG_RET validate_kzg_g1(const Bytes48 *b) { + blst_p1_affine tmp; + if (blst_p1_uncompress(&tmp, b->bytes) != BLST_SUCCESS) + return C_KZG_BADARGS; + return C_KZG_OK; +} + +/** + * Convert untrusted bytes into a trusted and validated KZGCommitment. + * + * @param[out] out The output commitment + * @param[in] in The commitment bytes + * @retval C_KZG_OK Deserialization successful + * @retval C_KZG_BADARGS Invalid input bytes + */ +static C_KZG_RET bytes_to_kzg_commitment(g1_t *out, const Bytes48 *b) { + C_KZG_RET ret; + + ret = validate_kzg_g1(b); + if (ret != C_KZG_OK) goto out; + ret = bytes_to_g1(out, b); + if (ret != C_KZG_OK) goto out; + +out: + return ret; +} + +/** + * Convert untrusted bytes into a trusted and validated KZGProof. + * + * @param[out] out The output proof + * @param[in] in The proof bytes + * @retval C_KZG_OK Deserialization successful + * @retval C_KZG_BADARGS Invalid input bytes + */ +static C_KZG_RET bytes_to_kzg_proof(g1_t *out, const Bytes48 *b) { + C_KZG_RET ret; + + ret = validate_kzg_g1(b); + if (ret != C_KZG_OK) goto out; + ret = bytes_to_g1(out, b); + if (ret != C_KZG_OK) goto out; + +out: + return ret; +} + /** * Deserialize a Blob (array of bytes) into a Polynomial (array of field elements). * @@ -981,13 +1031,13 @@ C_KZG_RET verify_kzg_proof(bool *out, fr_t z_fr, y_fr; g1_t commitment_g1, proof_g1; - ret = bytes_to_g1(&commitment_g1, commitment_bytes); + ret = bytes_to_kzg_commitment(&commitment_g1, commitment_bytes); if (ret != C_KZG_OK) return ret; ret = bytes_to_bls_field(&z_fr, z_bytes); if (ret != C_KZG_OK) return ret; ret = bytes_to_bls_field(&y_fr, y_bytes); if (ret != C_KZG_OK) return ret; - ret = bytes_to_g1(&proof_g1, proof_bytes); + ret = bytes_to_kzg_proof(&proof_g1, proof_bytes); if (ret != C_KZG_OK) return ret; return verify_kzg_proof_impl(out, &commitment_g1, &z_fr, &y_fr, &proof_g1, s); @@ -1239,7 +1289,7 @@ C_KZG_RET verify_aggregate_kzg_proof(bool *out, Polynomial* polys = NULL; g1_t proof; - ret = bytes_to_g1(&proof, aggregated_proof_bytes); + ret = bytes_to_kzg_proof(&proof, aggregated_proof_bytes); if (ret != C_KZG_OK) goto out; commitments = calloc(n, sizeof(g1_t)); @@ -1255,7 +1305,7 @@ C_KZG_RET verify_aggregate_kzg_proof(bool *out, } for (size_t i = 0; i < n; i++) { - ret = bytes_to_g1(&commitments[i], &commitments_bytes[i]); + ret = bytes_to_kzg_commitment(&commitments[i], &commitments_bytes[i]); if (ret != C_KZG_OK) goto out; ret = blob_to_polynomial(&polys[i], &blobs[i]); if (ret != C_KZG_OK) goto out; From ad893eb03013e53eeb2b0c47695461d9824d8692 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 25 Jan 2023 23:03:26 +0100 Subject: [PATCH 09/22] Fix nit in java bindings --- bindings/java/c_kzg_4844_jni.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bindings/java/c_kzg_4844_jni.c b/bindings/java/c_kzg_4844_jni.c index 49312aacf..833182bfa 100644 --- a/bindings/java/c_kzg_4844_jni.c +++ b/bindings/java/c_kzg_4844_jni.c @@ -160,7 +160,7 @@ JNIEXPORT jbyteArray JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_computeAggregate return proof; } -JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyAggregateKzgProof(JNIEnv *env, jclass thisCls, jbyteArray blobs, jbyteArray expected_commitments_bytes, jlong count, jbyteArray proof_bytes) +JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyAggregateKzgProof(JNIEnv *env, jclass thisCls, jbyteArray blobs, jbyteArray commitments_bytes, jlong count, jbyteArray proof_bytes) { if (settings == NULL) { @@ -178,7 +178,7 @@ JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyAggregateKzg return 0; } - size_t commitments_size = (size_t)(*env)->GetArrayLength(env, expected_commitments_bytes); + size_t commitments_size = (size_t)(*env)->GetArrayLength(env, commitments_bytes); size_t expected_commitments_size = BYTES_PER_COMMITMENT * count_native; if (commitments_size != expected_commitments_size) { @@ -187,14 +187,14 @@ JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyAggregateKzg } Bytes48 *proof_native = (Bytes48 *)(*env)->GetByteArrayElements(env, proof_bytes, NULL); - Bytes48 *commitments_native = (Bytes48 *)(*env)->GetByteArrayElements(env, expected_commitments_bytes, NULL); + Bytes48 *commitments_native = (Bytes48 *)(*env)->GetByteArrayElements(env, commitments_bytes, NULL); jbyte *blobs_native = (*env)->GetByteArrayElements(env, blobs, NULL); bool out; C_KZG_RET ret = verify_aggregate_kzg_proof(&out, (const Blob *)blobs_native, commitments_native, count_native, proof_native, settings); (*env)->ReleaseByteArrayElements(env, proof_bytes, (jbyte *)proof_native, JNI_ABORT); - (*env)->ReleaseByteArrayElements(env, expected_commitments_bytes, (jbyte *)commitments_native, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, commitments_bytes, (jbyte *)commitments_native, JNI_ABORT); (*env)->ReleaseByteArrayElements(env, blobs, blobs_native, JNI_ABORT); if (ret != C_KZG_OK) From 607375953a7d31ea4d10331a8a81388164c6655d Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 25 Jan 2023 23:08:06 +0100 Subject: [PATCH 10/22] Update variable names in java bindings --- .../java/ethereum/ckzg4844/CKZG4844JNI.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/bindings/java/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java b/bindings/java/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java index 48378f747..077c5967e 100644 --- a/bindings/java/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java +++ b/bindings/java/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java @@ -126,15 +126,15 @@ public static native void loadTrustedSetup(byte[] g1, long g1Count, byte[] g2, /** * Verify aggregated proof and commitments for the given blobs * - * @param blobs blobs as flattened bytes - * @param commitments commitments as flattened bytes - * @param count the count of the blobs (should be same as the count of the commitments) - * @param proof the proof that needs verifying + * @param blobs blobs as flattened bytes + * @param commitments_bytes commitments as flattened bytes + * @param count the count of the blobs (should be same as the count of the commitments) + * @param proof_bytes the proof that needs verifying * @return true if the proof is valid and false otherwise * @throws CKZGException if there is a crypto error */ - public static native boolean verifyAggregateKzgProof(byte[] blobs, byte[] expected_commitments, long count, - byte[] aggregated_proof); + public static native boolean verifyAggregateKzgProof(byte[] blobs, byte[] commitments_bytes, long count, + byte[] aggregated_proof_bytes); /** * Calculates commitment for a given blob @@ -148,13 +148,14 @@ public static native boolean verifyAggregateKzgProof(byte[] blobs, byte[] expect /** * Verify the proof by point evaluation for the given commitment * - * @param commitment commitment bytes - * @param z Z - * @param y Y - * @param proof the proof that needs verifying + * @param commitment_bytes commitment bytes + * @param z_bytes Z + * @param y_bytes Y + * @param proof_bytes the proof that needs verifying * @return true if the proof is valid and false otherwise * @throws CKZGException if there is a crypto error */ - public static native boolean verifyKzgProof(byte[] expected_commitment, byte[] z, byte[] y, byte[] proof); + public static native boolean verifyKzgProof(byte[] expected_commitment_bytes, byte[] z_bytes, byte[] y_bytes, + byte[] proof_bytes); } From c99519708b3cdb0ec784aea067a2ea5fb36a7424 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 25 Jan 2023 23:27:27 +0100 Subject: [PATCH 11/22] Compare to point at infinity --- src/c_kzg_4844.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/c_kzg_4844.c b/src/c_kzg_4844.c index 25e684d47..b3c4d522d 100644 --- a/src/c_kzg_4844.c +++ b/src/c_kzg_4844.c @@ -37,7 +37,17 @@ typedef struct { fr_t evals[FIELD_ELEMENTS_PER_BLOB]; } Polynomial; // Constants /////////////////////////////////////////////////////////////////////////////// -/** The G1 identity/infinity. */ +/** Serialized form of the point at infinity on the G1 group. */ +static const Bytes48 G1_POINT_AT_INFINITY = { + 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/** Deserialized form of the G1 identity/infinity point. */ static const g1_t g1_identity = {{0L, 0L, 0L, 0L, 0L, 0L}, {0L, 0L, 0L, 0L, 0L, 0L}, {0L, 0L, 0L, 0L, 0L, 0L}}; /** The G1 generator. */ @@ -669,8 +679,12 @@ static C_KZG_RET bytes_to_bls_field(fr_t *out, const Bytes32 *b) { */ static C_KZG_RET validate_kzg_g1(const Bytes48 *b) { blst_p1_affine tmp; + + if (memcmp(G1_POINT_AT_INFINITY.bytes, b->bytes, sizeof(Bytes48)) != 0) + return C_KZG_OK; if (blst_p1_uncompress(&tmp, b->bytes) != BLST_SUCCESS) return C_KZG_BADARGS; + return C_KZG_OK; } From 893a191a79bcec6a978b9ba1f231b4565e260f02 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 25 Jan 2023 23:30:04 +0100 Subject: [PATCH 12/22] Update bytes_to_bls_field doc --- src/c_kzg_4844.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/c_kzg_4844.c b/src/c_kzg_4844.c index b3c4d522d..81e5d6d42 100644 --- a/src/c_kzg_4844.c +++ b/src/c_kzg_4844.c @@ -657,7 +657,7 @@ static void hash_to_bls_field(fr_t *out, const Bytes32 *b) { } /** - * Deserialize bytes into a BLS field element. + * Convert untrusted bytes to a trusted and validated BLS scalar field element. * * @param[out] out The field element to store the deserialized data * @param[in] bytes A 32-byte array containing the serialized field element From 9e315743fb8afef8e539df296d15e60327d5888f Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 25 Jan 2023 23:41:32 +0100 Subject: [PATCH 13/22] Add todo --- src/c_kzg_4844.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/c_kzg_4844.c b/src/c_kzg_4844.c index 81e5d6d42..1b2ff24c6 100644 --- a/src/c_kzg_4844.c +++ b/src/c_kzg_4844.c @@ -680,10 +680,10 @@ static C_KZG_RET bytes_to_bls_field(fr_t *out, const Bytes32 *b) { static C_KZG_RET validate_kzg_g1(const Bytes48 *b) { blst_p1_affine tmp; - if (memcmp(G1_POINT_AT_INFINITY.bytes, b->bytes, sizeof(Bytes48)) != 0) + if (memcmp(G1_POINT_AT_INFINITY.bytes, b->bytes, sizeof(b)) != 0) return C_KZG_OK; - if (blst_p1_uncompress(&tmp, b->bytes) != BLST_SUCCESS) - return C_KZG_BADARGS; + + // TODO: validate the point. return C_KZG_OK; } From adacc35d1bf83ca61e42bb1cf2072a1be3af24e4 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Thu, 26 Jan 2023 11:26:52 +0100 Subject: [PATCH 14/22] Do key validation --- src/c_kzg_4844.c | 72 +++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/src/c_kzg_4844.c b/src/c_kzg_4844.c index 1b2ff24c6..23f81eaf5 100644 --- a/src/c_kzg_4844.c +++ b/src/c_kzg_4844.c @@ -48,10 +48,10 @@ static const Bytes48 G1_POINT_AT_INFINITY = { }; /** Deserialized form of the G1 identity/infinity point. */ -static const g1_t g1_identity = {{0L, 0L, 0L, 0L, 0L, 0L}, {0L, 0L, 0L, 0L, 0L, 0L}, {0L, 0L, 0L, 0L, 0L, 0L}}; +static const g1_t G1_IDENTITY = {{0L, 0L, 0L, 0L, 0L, 0L}, {0L, 0L, 0L, 0L, 0L, 0L}, {0L, 0L, 0L, 0L, 0L, 0L}}; /** The G1 generator. */ -static const g1_t g1_generator = {{ +static const g1_t G1_GENERATOR = {{ 0x5cb38790fd530c16L, 0x7817fc679976fff5L, 0x154f95c7143ba1c1L, 0xf0ae6acdf3d0e747L, 0xedce6ecc21dbf440L, 0x120177419e0bfb75L }, @@ -66,7 +66,7 @@ static const g1_t g1_generator = {{ }; /** The G2 generator. */ -static const g2_t g2_generator = {{{{ +static const g2_t G2_GENERATOR = {{{{ 0xf5f28fa202940a10L, 0xb3f5fb2687b4961aL, 0xa1a893b53e2ae580L, 0x9894999d1a3caee9L, 0x6f67b7631863366bL, 0x058191924350bcd7L }, @@ -118,7 +118,7 @@ static const g2_t g2_generator = {{{{ * to create the roots of unity below. There are a lot of primitive roots: * https://crypto.stanford.edu/pbc/notes/numbertheory/gen.html */ -static const uint64_t scale2_root_of_unity[][4] = { +static const uint64_t SCALE2_ROOT_OF_UNITY[][4] = { {0x0000000000000001L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L}, {0xffffffff00000000L, 0x53bda402fffe5bfeL, 0x3339d80809a1d805L, 0x73eda753299d7d48L}, {0x0001000000000000L, 0xec03000276030000L, 0x8d51ccce760304d0L, 0x0000000000000000L}, @@ -377,7 +377,7 @@ static void g1_mul(g1_t *out, const g1_t *a, const fr_t *b) { int i = sizeof(blst_scalar); while (i && !s.b[i - 1]) --i; if (i == 0) { - *out = g1_identity; + *out = G1_IDENTITY; } else if (i == 1 && s.b[0] == 1) { *out = *a; } else { @@ -675,15 +675,33 @@ static C_KZG_RET bytes_to_bls_field(fr_t *out, const Bytes32 *b) { /** * Perform BLS validation required by the types KZGProof and KZGCommitment. * + * @param[out] out The output g1 point * @param[in] b The proof/commitment bytes + * @retval C_KZG_OK Deserialization successful + * @retval C_KZG_BADARGS Invalid input bytes */ -static C_KZG_RET validate_kzg_g1(const Bytes48 *b) { - blst_p1_affine tmp; +static C_KZG_RET validate_kzg_g1(g1_t *out, const Bytes48 *b) { + blst_p1 p1; + blst_p1_affine p1_affine; + /* Fast check without needing to uncompress */ if (memcmp(G1_POINT_AT_INFINITY.bytes, b->bytes, sizeof(b)) != 0) return C_KZG_OK; - // TODO: validate the point. + /* Convert the bytes to a p1 point */ + if (blst_p1_uncompress(&p1_affine, b->bytes) != BLST_SUCCESS) + return C_KZG_BADARGS; + blst_p1_from_affine(&p1, &p1_affine); + + /* Duplicate check, just in case */ + if (blst_p1_is_inf(&p1)) + return C_KZG_OK; + + /* Key validation */ + if (!blst_p1_on_curve(&p1)) + return C_KZG_BADARGS; + if (!blst_p1_in_g1(&p1)) + return C_KZG_BADARGS; return C_KZG_OK; } @@ -692,40 +710,24 @@ static C_KZG_RET validate_kzg_g1(const Bytes48 *b) { * Convert untrusted bytes into a trusted and validated KZGCommitment. * * @param[out] out The output commitment - * @param[in] in The commitment bytes + * @param[in] b The commitment bytes * @retval C_KZG_OK Deserialization successful * @retval C_KZG_BADARGS Invalid input bytes */ static C_KZG_RET bytes_to_kzg_commitment(g1_t *out, const Bytes48 *b) { - C_KZG_RET ret; - - ret = validate_kzg_g1(b); - if (ret != C_KZG_OK) goto out; - ret = bytes_to_g1(out, b); - if (ret != C_KZG_OK) goto out; - -out: - return ret; + return validate_kzg_g1(out, b); } /** * Convert untrusted bytes into a trusted and validated KZGProof. * * @param[out] out The output proof - * @param[in] in The proof bytes + * @param[in] b The proof bytes * @retval C_KZG_OK Deserialization successful * @retval C_KZG_BADARGS Invalid input bytes */ static C_KZG_RET bytes_to_kzg_proof(g1_t *out, const Bytes48 *b) { - C_KZG_RET ret; - - ret = validate_kzg_g1(b); - if (ret != C_KZG_OK) goto out; - ret = bytes_to_g1(out, b); - if (ret != C_KZG_OK) goto out; - -out: - return ret; + return validate_kzg_g1(out, b); } /** @@ -772,7 +774,7 @@ static C_KZG_RET compute_challenges(fr_t *eval_challenge_out, fr_t *r_powers_out uint8_t* bytes = calloc(nb, sizeof(uint8_t)); if (bytes == NULL) return C_KZG_MALLOC; - /* Copy domain seperator */ + /* Copy domain separator */ memcpy(bytes, FIAT_SHAMIR_PROTOCOL_DOMAIN, 16); bytes_of_uint64(&bytes[16], FIELD_ELEMENTS_PER_BLOB); bytes_of_uint64(&bytes[16 + 8], n); @@ -844,7 +846,7 @@ static C_KZG_RET g1_lincomb(g1_t *out, const g1_t *p, const fr_t *coeffs, const if (len < 8) { // Direct approach g1_t tmp; - *out = g1_identity; + *out = G1_IDENTITY; for (uint64_t i = 0; i < len; i++) { g1_mul(&tmp, &p[i], &coeffs[i]); blst_p1_add_or_double(out, out, &tmp); @@ -1074,12 +1076,12 @@ static C_KZG_RET verify_kzg_proof_impl(bool *out, const g1_t *commitment, const const g1_t *proof, const KZGSettings *ks) { g2_t x_g2, s_minus_x; g1_t y_g1, commitment_minus_y; - g2_mul(&x_g2, &g2_generator, z); + g2_mul(&x_g2, &G2_GENERATOR, z); g2_sub(&s_minus_x, &ks->g2_values[1], &x_g2); - g1_mul(&y_g1, &g1_generator, y); + g1_mul(&y_g1, &G1_GENERATOR, y); g1_sub(&commitment_minus_y, commitment, &y_g1); - *out = pairings_verify(&commitment_minus_y, &g2_generator, proof, &s_minus_x); + *out = pairings_verify(&commitment_minus_y, &G2_GENERATOR, proof, &s_minus_x); return C_KZG_OK; } @@ -1468,8 +1470,8 @@ static C_KZG_RET new_fft_settings(FFTSettings *fs, unsigned int max_scale) { fs->reverse_roots_of_unity = NULL; fs->roots_of_unity = NULL; - CHECK((max_scale < sizeof scale2_root_of_unity / sizeof scale2_root_of_unity[0])); - blst_fr_from_uint64(&root_of_unity, scale2_root_of_unity[max_scale]); + CHECK((max_scale < sizeof SCALE2_ROOT_OF_UNITY / sizeof SCALE2_ROOT_OF_UNITY[0])); + blst_fr_from_uint64(&root_of_unity, SCALE2_ROOT_OF_UNITY[max_scale]); // Allocate space for the roots of unity ret = new_fr_array(&fs->expanded_roots_of_unity, fs->max_width + 1); From f830261701bcbea0d541930dbd13d274433d74b5 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Thu, 26 Jan 2023 11:29:41 +0100 Subject: [PATCH 15/22] Remove bytes_to_g1 --- src/c_kzg_4844.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/c_kzg_4844.c b/src/c_kzg_4844.c index 23f81eaf5..f0f702e21 100644 --- a/src/c_kzg_4844.c +++ b/src/c_kzg_4844.c @@ -496,22 +496,6 @@ static void bytes_from_g1(Bytes48 *out, const g1_t *in) { blst_p1_compress(out->bytes, in); } -/** - * Deserialize bytes into a G1 group element. - * - * @param[out] out The G1 element to store the deserialized data - * @param[in] bytes A 48-byte array containing the serialized G1 element - * @retval C_KZG_OK Deserialization successful - * @retval C_KZG_BADARGS Input bytes were not a valid G1 element - */ -static C_KZG_RET bytes_to_g1(g1_t* out, const Bytes48 *b) { - blst_p1_affine tmp; - if (blst_p1_uncompress(&tmp, b->bytes) != BLST_SUCCESS) - return C_KZG_BADARGS; - blst_p1_from_affine(out, &tmp); - return C_KZG_OK; -} - /** * Serialize a BLS field element into bytes. * @@ -1561,7 +1545,7 @@ C_KZG_RET load_trusted_setup(KZGSettings *out, const uint8_t *g1_bytes, size_t n if (ret != C_KZG_OK) goto out_error; for (i = 0; i < n1; i++) { - ret = bytes_to_g1(&g1_projective[i], (Bytes48 *)&g1_bytes[48 * i]); + ret = validate_kzg_g1(&g1_projective[i], (Bytes48 *)&g1_bytes[48 * i]); if (ret != C_KZG_OK) goto out_error; } From 57125e4888da2bea3d07b14a3dc1d91b25783b13 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Thu, 26 Jan 2023 11:45:16 +0100 Subject: [PATCH 16/22] Fix bug & add remark --- src/c_kzg_4844.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/c_kzg_4844.c b/src/c_kzg_4844.c index f0f702e21..0bc5fdabe 100644 --- a/src/c_kzg_4844.c +++ b/src/c_kzg_4844.c @@ -663,28 +663,30 @@ static C_KZG_RET bytes_to_bls_field(fr_t *out, const Bytes32 *b) { * @param[in] b The proof/commitment bytes * @retval C_KZG_OK Deserialization successful * @retval C_KZG_BADARGS Invalid input bytes + * + * @remark This function deviates from the spec because it returns (via an + * output argument) the g1 point. This way is more efficient (faster) but + * the function name is a bit misleading. */ static C_KZG_RET validate_kzg_g1(g1_t *out, const Bytes48 *b) { - blst_p1 p1; - blst_p1_affine p1_affine; - /* Fast check without needing to uncompress */ if (memcmp(G1_POINT_AT_INFINITY.bytes, b->bytes, sizeof(b)) != 0) return C_KZG_OK; /* Convert the bytes to a p1 point */ + blst_p1_affine p1_affine; if (blst_p1_uncompress(&p1_affine, b->bytes) != BLST_SUCCESS) return C_KZG_BADARGS; - blst_p1_from_affine(&p1, &p1_affine); + blst_p1_from_affine(out, &p1_affine); /* Duplicate check, just in case */ - if (blst_p1_is_inf(&p1)) + if (blst_p1_is_inf(out)) return C_KZG_OK; /* Key validation */ - if (!blst_p1_on_curve(&p1)) + if (!blst_p1_on_curve(out)) return C_KZG_BADARGS; - if (!blst_p1_in_g1(&p1)) + if (!blst_p1_in_g1(out)) return C_KZG_BADARGS; return C_KZG_OK; From 16a9f9119d5d5bb6e5b8420e686d55c2b33db70e Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Thu, 26 Jan 2023 12:04:25 +0100 Subject: [PATCH 17/22] Fix memcmp mistake --- src/c_kzg_4844.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/c_kzg_4844.c b/src/c_kzg_4844.c index 0bc5fdabe..a30098bfd 100644 --- a/src/c_kzg_4844.c +++ b/src/c_kzg_4844.c @@ -670,7 +670,7 @@ static C_KZG_RET bytes_to_bls_field(fr_t *out, const Bytes32 *b) { */ static C_KZG_RET validate_kzg_g1(g1_t *out, const Bytes48 *b) { /* Fast check without needing to uncompress */ - if (memcmp(G1_POINT_AT_INFINITY.bytes, b->bytes, sizeof(b)) != 0) + if (memcmp(G1_POINT_AT_INFINITY.bytes, b->bytes, sizeof(b)) == 0) return C_KZG_OK; /* Convert the bytes to a p1 point */ From c076e2f43c12ebca2a6b124861c3d8c9c6514e8d Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Thu, 26 Jan 2023 12:10:55 +0100 Subject: [PATCH 18/22] Fix nit in nodejs bindings --- bindings/node.js/kzg.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/node.js/kzg.cxx b/bindings/node.js/kzg.cxx index b11eb520b..04180db9e 100644 --- a/bindings/node.js/kzg.cxx +++ b/bindings/node.js/kzg.cxx @@ -197,7 +197,7 @@ Napi::Value ComputeAggregateKzgProof(const Napi::CallbackInfo& info) { return napi_typed_array_from_bytes((uint8_t *)(&proof), BYTES_PER_PROOF, env); } -// verifyAggregateKzgProof: (blobs: Blob[], commitmentsBytes: Bytes48[], aggregatedProof: Bytes48, setupHandle: SetupHandle) => boolean; +// verifyAggregateKzgProof: (blobs: Blob[], commitmentsBytes: Bytes48[], aggregatedProofBytes: Bytes48, setupHandle: SetupHandle) => boolean; Napi::Value VerifyAggregateKzgProof(const Napi::CallbackInfo& info) { auto env = info.Env(); From 2f6f608205ba87a28dbc73ff7859e9ea06103ffb Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Thu, 26 Jan 2023 12:12:26 +0100 Subject: [PATCH 19/22] Fix another nit --- bindings/java/c_kzg_4844_jni.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bindings/java/c_kzg_4844_jni.c b/bindings/java/c_kzg_4844_jni.c index 833182bfa..e9ba40839 100644 --- a/bindings/java/c_kzg_4844_jni.c +++ b/bindings/java/c_kzg_4844_jni.c @@ -239,7 +239,7 @@ JNIEXPORT jbyteArray JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_blobToKzgCommitm return commitment; } -JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyKzgProof(JNIEnv *env, jclass thisCls, jbyteArray expected_commitment_bytes, jbyteArray z_bytes, jbyteArray y_bytes, jbyteArray proof_bytes) +JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyKzgProof(JNIEnv *env, jclass thisCls, jbyteArray commitment_bytes, jbyteArray z_bytes, jbyteArray y_bytes, jbyteArray proof_bytes) { if (settings == NULL) { @@ -247,7 +247,7 @@ JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyKzgProof(JNI return 0; } - Bytes48 *commitment_native = (Bytes48 *)(*env)->GetByteArrayElements(env, expected_commitment_bytes, NULL); + Bytes48 *commitment_native = (Bytes48 *)(*env)->GetByteArrayElements(env, commitment_bytes, NULL); Bytes48 *proof_native = (Bytes48 *)(*env)->GetByteArrayElements(env, proof_bytes, NULL); Bytes32 *z_native = (Bytes32 *)(*env)->GetByteArrayElements(env, z_bytes, NULL); Bytes32 *y_native = (Bytes32 *)(*env)->GetByteArrayElements(env, y_bytes, NULL); @@ -255,7 +255,7 @@ JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyKzgProof(JNI bool out; C_KZG_RET ret = verify_kzg_proof(&out, commitment_native, z_native, y_native, proof_native, settings); - (*env)->ReleaseByteArrayElements(env, expected_commitment_bytes, (jbyte *)commitment_native, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, commitment_bytes, (jbyte *)commitment_native, JNI_ABORT); (*env)->ReleaseByteArrayElements(env, z_bytes, (jbyte *)z_native, JNI_ABORT); (*env)->ReleaseByteArrayElements(env, y_bytes, (jbyte *)y_native, JNI_ABORT); (*env)->ReleaseByteArrayElements(env, proof_bytes, (jbyte *)proof_native, JNI_ABORT); From 5a0a466e541663540c60a544e321b51189c668b0 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Thu, 26 Jan 2023 12:19:42 +0100 Subject: [PATCH 20/22] Update nodejs parameter names --- .../java/ethereum/ckzg4844/CKZG4844JNI.java | 2 +- bindings/node.js/kzg.ts | 37 ++++++++++--------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/bindings/java/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java b/bindings/java/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java index 077c5967e..2eb233758 100644 --- a/bindings/java/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java +++ b/bindings/java/src/main/java/ethereum/ckzg4844/CKZG4844JNI.java @@ -155,7 +155,7 @@ public static native boolean verifyAggregateKzgProof(byte[] blobs, byte[] commit * @return true if the proof is valid and false otherwise * @throws CKZGException if there is a crypto error */ - public static native boolean verifyKzgProof(byte[] expected_commitment_bytes, byte[] z_bytes, byte[] y_bytes, + public static native boolean verifyKzgProof(byte[] commitment_bytes, byte[] z_bytes, byte[] y_bytes, byte[] proof_bytes); } diff --git a/bindings/node.js/kzg.ts b/bindings/node.js/kzg.ts index 45b9567c7..34b095c4f 100644 --- a/bindings/node.js/kzg.ts +++ b/bindings/node.js/kzg.ts @@ -6,6 +6,7 @@ const kzg: KZG = require("./kzg.node"); const fs = require("fs"); export type Bytes32 = Uint8Array; // 32 bytes +export type Bytes48 = Uint8Array; // 48 bytes export type KZGProof = Uint8Array; // 48 bytes export type KZGCommitment = Uint8Array; // 48 bytes export type Blob = Uint8Array; // 4096 * 32 bytes @@ -30,16 +31,16 @@ type KZG = { verifyAggregateKzgProof: ( blobs: Blob[], - expectedKzgCommitments: KZGCommitment[], - kzgAggregatedProof: KZGProof, + commitmentsBytes: Bytes48[], + aggregatedProofBytes: Bytes48, setupHandle: SetupHandle, ) => boolean; verifyKzgProof: ( - polynomialKzg: KZGCommitment, - z: Bytes32, - y: Bytes32, - kzgProof: KZGProof, + commitmentBytes: Bytes48, + zBytes: Bytes32, + yBytes: Bytes32, + proofBytes: Bytes48, setupHandle: SetupHandle, ) => boolean; }; @@ -114,29 +115,29 @@ export function computeAggregateKzgProof(blobs: Blob[]): KZGProof { } export function verifyKzgProof( - polynomialKzg: KZGCommitment, - z: Bytes32, - y: Bytes32, - kzgProof: KZGProof, + commitmentBytes: Bytes48, + zBytes: Bytes32, + yBytes: Bytes32, + proofBytes: Bytes48, ): boolean { return kzg.verifyKzgProof( - polynomialKzg, - z, - y, - kzgProof, + commitmentBytes, + zBytes, + yBytes, + proofBytes, requireSetupHandle(), ); } export function verifyAggregateKzgProof( blobs: Blob[], - expectedKzgCommitments: KZGCommitment[], - kzgAggregatedProof: KZGProof, + commitmentsBytes: Bytes48[], + proofBytes: Bytes48, ): boolean { return kzg.verifyAggregateKzgProof( blobs, - expectedKzgCommitments, - kzgAggregatedProof, + commitmentsBytes, + proofBytes, requireSetupHandle(), ); } From 70855e2f42d0b496fd6b63c225ffd500e5b5654d Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Thu, 26 Jan 2023 13:41:56 +0100 Subject: [PATCH 21/22] Remove to_proof() and to_commitment() --- bindings/rust/src/lib.rs | 69 ++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 38 deletions(-) diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 3d9c9c798..8f3bd8a4c 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -19,8 +19,8 @@ const NUM_G2_POINTS: usize = 65; #[derive(Debug)] pub enum Error { - /// The Bytes48 is invalid. - InvalidBytes48(String), + /// Wrong number of bytes. + InvalidBytesLength(String), /// The KZG proof is invalid. InvalidKzgProof(String), /// The KZG commitment is invalid. @@ -107,10 +107,25 @@ impl Drop for KZGSettings { } } +impl Bytes32 { + pub fn from_bytes(bytes: &[u8]) -> Result { + if bytes.len() != 32 { + return Err(Error::InvalidBytesLength(format!( + "Invalid byte length. Expected {} got {}", + 32, + bytes.len(), + ))); + } + let mut new_bytes = [0; 32]; + new_bytes.copy_from_slice(bytes); + Ok(Self { bytes: new_bytes }) + } +} + impl Bytes48 { pub fn from_bytes(bytes: &[u8]) -> Result { if bytes.len() != 48 { - return Err(Error::InvalidBytes48(format!( + return Err(Error::InvalidBytesLength(format!( "Invalid byte length. Expected {} got {}", 48, bytes.len(), @@ -120,18 +135,6 @@ impl Bytes48 { new_bytes.copy_from_slice(bytes); Ok(Self { bytes: new_bytes }) } - - pub fn to_proof(self) -> Result { - let mut proof_bytes = [0; BYTES_PER_PROOF]; - proof_bytes.copy_from_slice(&self.bytes); - Ok(KZGProof { bytes: proof_bytes }) - } - - pub fn to_commitment(self) -> Result { - let mut commitment_bytes = [0; BYTES_PER_COMMITMENT]; - commitment_bytes.copy_from_slice(&self.bytes); - Ok(KZGCommitment { bytes: commitment_bytes }) - } } impl KZGProof { @@ -148,18 +151,14 @@ impl KZGProof { Ok(Self { bytes: proof_bytes }) } - pub fn to_bytes(&self) -> [u8; BYTES_PER_G1_POINT] { - self.bytes - } - - pub fn to_bytes48(&self) -> Bytes48 { + pub fn to_bytes(&self) -> Bytes48 { let mut bytes = [0; 48]; bytes.copy_from_slice(&self.bytes); Bytes48 { bytes } } pub fn as_hex_string(&self) -> String { - hex::encode(self.to_bytes()) + hex::encode(self.bytes) } pub fn compute_aggregate_kzg_proof( @@ -202,7 +201,7 @@ impl KZGProof { blobs.as_ptr(), commitments_bytes.as_ptr(), blobs.len(), - &self.to_bytes48(), + &self.to_bytes(), kzg_settings, ); if let C_KZG_RET::C_KZG_OK = res { @@ -227,7 +226,7 @@ impl KZGProof { &commitment_bytes, &z_bytes, &y_bytes, - &self.to_bytes48(), + &self.to_bytes(), kzg_settings, ); if let C_KZG_RET::C_KZG_OK = res { @@ -253,18 +252,14 @@ impl KZGCommitment { Ok(Self { bytes: commitment }) } - pub fn to_bytes(&self) -> [u8; BYTES_PER_G1_POINT] { - self.bytes - } - - pub fn to_bytes48(&self) -> Bytes48 { + pub fn to_bytes(&self) -> Bytes48 { let mut bytes = [0; 48]; bytes.copy_from_slice(&self.bytes); Bytes48 { bytes } } pub fn as_hex_string(&self) -> String { - hex::encode(self.to_bytes()) + hex::encode(self.bytes) } pub fn blob_to_kzg_commitment(blob: Blob, kzg_settings: &KZGSettings) -> Self { @@ -340,7 +335,7 @@ mod tests { .clone() .into_iter() .map(|blob| KZGCommitment::blob_to_kzg_commitment(blob, &kzg_settings)) - .map(|commitment| commitment.to_bytes48()) + .map(|commitment| commitment.to_bytes()) .collect(); let kzg_proof = KZGProof::compute_aggregate_kzg_proof(&blobs, &kzg_settings).unwrap(); @@ -445,19 +440,17 @@ mod tests { let commitment_hex = test.get("Commitment").unwrap().as_str().unwrap(); let commitment = Bytes48::from_bytes(&hex::decode(commitment_hex).unwrap()).unwrap(); - let z = test.get("InputPoint").unwrap().as_str().unwrap(); - let mut z_bytes = [0; BYTES_PER_FIELD_ELEMENT]; - z_bytes.copy_from_slice(&hex::decode(z).unwrap()); + let z_hex = test.get("InputPoint").unwrap().as_str().unwrap(); + let z_bytes = Bytes32::from_bytes(&hex::decode(z_hex).unwrap()).unwrap(); - let y = test.get("ClaimedValue").unwrap().as_str().unwrap(); - let mut y_bytes = [0; BYTES_PER_FIELD_ELEMENT]; - y_bytes.copy_from_slice(&hex::decode(y).unwrap()); + let y_hex = test.get("ClaimedValue").unwrap().as_str().unwrap(); + let y_bytes = Bytes32::from_bytes(&hex::decode(y_hex).unwrap()).unwrap(); assert!(kzg_proof .verify_kzg_proof( commitment, - z_bytes.into(), - y_bytes.into(), + z_bytes, + y_bytes, &kzg_settings ) .unwrap()); From 3efbfa0075ce3da71c78647ea520d5bdf7e35f33 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Thu, 26 Jan 2023 15:17:02 +0100 Subject: [PATCH 22/22] Fix bug --- src/c_kzg_4844.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/c_kzg_4844.c b/src/c_kzg_4844.c index a30098bfd..e3572c878 100644 --- a/src/c_kzg_4844.c +++ b/src/c_kzg_4844.c @@ -37,16 +37,6 @@ typedef struct { fr_t evals[FIELD_ELEMENTS_PER_BLOB]; } Polynomial; // Constants /////////////////////////////////////////////////////////////////////////////// -/** Serialized form of the point at infinity on the G1 group. */ -static const Bytes48 G1_POINT_AT_INFINITY = { - 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - /** Deserialized form of the G1 identity/infinity point. */ static const g1_t G1_IDENTITY = {{0L, 0L, 0L, 0L, 0L, 0L}, {0L, 0L, 0L, 0L, 0L, 0L}, {0L, 0L, 0L, 0L, 0L, 0L}}; @@ -669,17 +659,13 @@ static C_KZG_RET bytes_to_bls_field(fr_t *out, const Bytes32 *b) { * the function name is a bit misleading. */ static C_KZG_RET validate_kzg_g1(g1_t *out, const Bytes48 *b) { - /* Fast check without needing to uncompress */ - if (memcmp(G1_POINT_AT_INFINITY.bytes, b->bytes, sizeof(b)) == 0) - return C_KZG_OK; - /* Convert the bytes to a p1 point */ blst_p1_affine p1_affine; if (blst_p1_uncompress(&p1_affine, b->bytes) != BLST_SUCCESS) return C_KZG_BADARGS; blst_p1_from_affine(out, &p1_affine); - /* Duplicate check, just in case */ + /* Check if it's the point at infinity */ if (blst_p1_is_inf(out)) return C_KZG_OK;