diff --git a/Cargo.lock b/Cargo.lock index 84c949b50..36652d090 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1402,8 +1402,10 @@ dependencies = [ "ark-bn254", "ark-ec", "ark-ff 0.4.2", - "eigen-crypto-bn254", + "eigensdk-crypto-bn254", + "rand", "thiserror", + "tokio", ] [[package]] @@ -1414,7 +1416,9 @@ dependencies = [ "ark-bn254", "ark-ff 0.4.2", "ethers", + "rand", "thiserror", + "tokio", ] [[package]] diff --git a/crates/chainio/clients/avsregistry/src/writer.rs b/crates/chainio/clients/avsregistry/src/writer.rs index 83f71fd15..dc8a7e237 100644 --- a/crates/chainio/clients/avsregistry/src/writer.rs +++ b/crates/chainio/clients/avsregistry/src/writer.rs @@ -168,7 +168,7 @@ impl AvsRegistryChainWriter { let g1_pubkey_bn254 = convert_to_bn254_g1_point(bls_key_pair.get_pub_key_g1()); let g2_projective = bls_key_pair - .gt_pub_key_g2() + .get_pub_key_g2() .expect("Failed to get g2 projective"); let g2_pubkey_bn254 = convert_to_bn254_g2_point(g2_projective); diff --git a/crates/crypto/bls/Cargo.toml b/crates/crypto/bls/Cargo.toml index eb1772535..7ea749513 100644 --- a/crates/crypto/bls/Cargo.toml +++ b/crates/crypto/bls/Cargo.toml @@ -14,4 +14,8 @@ ark-ff.workspace = true eigen-crypto-bn254.workspace = true thiserror.workspace = true ark-ec = "0.4.2" -alloy-primitives.workspace = true \ No newline at end of file +alloy-primitives.workspace = true + +[dev-dependencies] +rand = "0.8.4" +tokio = { workspace = true, features = ["full"] } diff --git a/crates/crypto/bls/src/attestation.rs b/crates/crypto/bls/src/attestation.rs index 0b50716b4..6b2c59d70 100644 --- a/crates/crypto/bls/src/attestation.rs +++ b/crates/crypto/bls/src/attestation.rs @@ -5,7 +5,7 @@ use ark_ec::{ pairing::{prepare_g1, prepare_g2, Pairing}, AffineRepr, CurveGroup, }; -use ark_ff::{BigInteger256, Field, One}; +use ark_ff::{BigInteger256, Field, One, Zero}; use eigen_crypto_bn254::utils::{ get_g2_generator, mul_by_generator_g1, mul_by_generator_g2, u256_to_bigint256, }; @@ -108,7 +108,7 @@ impl KeyPair { self.pub_key } - pub fn gt_pub_key_g2(&self) -> Result { + pub fn get_pub_key_g2(&self) -> Result { let mul_result = mul_by_generator_g2(self.priv_key); match mul_result { @@ -185,3 +185,78 @@ impl G1Point { ) } } + +#[cfg(test)] +mod tests { + use super::*; + use ark_ff::UniformRand; + use rand::{thread_rng, RngCore}; + + #[tokio::test] + async fn test_keypair_generation() { + let mut rng = thread_rng(); + let private_key = Fr::rand(&mut rng); + let keypair = KeyPair::new(private_key).unwrap(); + let pub_key = keypair.get_pub_key_g1(); + + // Check that the public key is not zero + assert_ne!(pub_key, G1Projective::zero()); + } + + #[tokio::test] + async fn test_signature_generation() { + let mut rng = thread_rng(); + let private_key = Fr::rand(&mut rng); + let keypair = KeyPair::new(private_key).unwrap(); + + let message = [0u8; 32]; + let msg_hash = hash_to_g1(&message); + + let signature = keypair.sign_hashes_to_curve_message(msg_hash.into()); + + // Check that the signature is not zero + assert_ne!(signature.sig(), G1Projective::zero()); + } + + #[tokio::test] + async fn test_signature_verification() { + let mut rng = thread_rng(); + let private_key = Fr::rand(&mut rng); + let keypair = KeyPair::new(private_key).unwrap(); + let pub_key_g2 = keypair.get_pub_key_g2().unwrap(); + // generate a random message + let mut message = [0u8; 32]; + rng.fill_bytes(&mut message); + + let msg_hash = hash_to_g1(&message); + + let signature = keypair.sign_hashes_to_curve_message(msg_hash.into()); + + // Check that the signature is not zero + assert_ne!(signature.sig(), G1Projective::zero()); + + // Check that the signature verifies + assert!(signature.verify_signature(pub_key_g2, &message)); + } + + #[tokio::test] + async fn test_signature_verification_invalid() { + let mut rng = thread_rng(); + let private_key = Fr::rand(&mut rng); + let keypair = KeyPair::new(private_key).unwrap(); + + let mut message = [0u8; 32]; + rng.fill_bytes(&mut message); + + let msg_hash = hash_to_g1(&message); + + let signature = keypair.sign_hashes_to_curve_message(msg_hash.into()); + + // Check that the signature is not zero + assert_ne!(signature.sig(), G1Projective::zero()); + + // Check that the signature does not verify with a different public key + let different_pub_key = G2Projective::rand(&mut rng); + assert!(!signature.verify_signature(different_pub_key, &message)); + } +} diff --git a/crates/crypto/bn254/Cargo.toml b/crates/crypto/bn254/Cargo.toml index 3d422e95f..b1778939d 100644 --- a/crates/crypto/bn254/Cargo.toml +++ b/crates/crypto/bn254/Cargo.toml @@ -13,4 +13,8 @@ ark-ff.workspace = true ark-bn254 = "0.4.0" ethers.workspace = true thiserror.workspace = true -alloy-primitives.workspace = true \ No newline at end of file +alloy-primitives.workspace = true + +[dev-dependencies] +tokio = { workspace = true, features = ["full"] } +rand = "0.8.4" diff --git a/crates/crypto/bn254/src/utils.rs b/crates/crypto/bn254/src/utils.rs index 0e400cc10..a9ec357a5 100644 --- a/crates/crypto/bn254/src/utils.rs +++ b/crates/crypto/bn254/src/utils.rs @@ -4,20 +4,23 @@ use ark_bn254::{Fq, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective}; use ark_ff::{BigInteger, BigInteger256}; use std::ops::Mul; use std::str::FromStr; + /// Converts [U256] to [BigInteger256] pub fn u256_to_bigint256(value: U256) -> BigInteger256 { - // Convert U256 to a byte array - let bytes = value.to_be_bytes::<32>(); - // Convert the byte array to a bit array - let mut bits = [false; 256]; - for (byte_idx, byte) in bytes.iter().enumerate() { - for bit_idx in 0..8 { - let bit = byte & (1 << bit_idx) != 0; - bits[byte_idx * 8 + bit_idx] = bit; - } + // Convert U256 to a big-endian byte array + let bytes: [u8; 32] = value.to_be_bytes(); + + // BigInteger256 expects a 4-element array of 64-bit values in little-endian order + let mut data = [0u64; 4]; + + // Iterate over the bytes in chunks of 8 bytes and convert to u64 + for (i, chunk) in bytes.chunks(8).enumerate() { + let mut chunk_array = [0u8; 8]; + chunk_array.copy_from_slice(chunk); + data[3 - i] = u64::from_be_bytes(chunk_array); } - // Create a BigInteger256 from the byte array - BigInteger256::from_bits_be(&bits) + + BigInteger256::new(data) } pub fn biginteger256_to_u256(bi: BigInteger256) -> U256 { @@ -115,3 +118,22 @@ pub fn mul_by_generator_g2(pvt_key: Fr) -> Result { pub fn verify_sig(sig: G1Affine, pub_key: G2Affine, msg: [u8; 32]) { let g2_gen = get_g1_generator().unwrap(); } + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_u256_to_bigint256() { + let u256 = U256::from(123456789); + let result = u256_to_bigint256(u256); + assert_eq!(result, BigInteger256::from(123456789u32)); + } + + #[tokio::test] + async fn test_bigint256_to_u256() { + let bi = BigInteger256::from(123456789u32); + let result = biginteger256_to_u256(bi); + assert_eq!(result, U256::from(123456789)); + } +} diff --git a/crates/services/bls_aggregation/Cargo.toml b/crates/services/bls_aggregation/Cargo.toml index 690e02e85..92c3eedd8 100644 --- a/crates/services/bls_aggregation/Cargo.toml +++ b/crates/services/bls_aggregation/Cargo.toml @@ -16,6 +16,7 @@ eigen-types.workspace = true eigen-crypto-bls.workspace = true eigen-services-avsregistry.workspace = true parking_lot.workspace = true -tokio = {workspace = true, features = ["full"]} eigen-crypto-bn254.workspace = true -alloy-primitives.workspace = true \ No newline at end of file +alloy-primitives.workspace = true +tokio = { workspace = true, features = ["full"] } +