diff --git a/ec/src/hashing/tests/mod.rs b/ec/src/hashing/tests.rs similarity index 95% rename from ec/src/hashing/tests/mod.rs rename to ec/src/hashing/tests.rs index 6760c4603..1aaca09cb 100644 --- a/ec/src/hashing/tests/mod.rs +++ b/ec/src/hashing/tests.rs @@ -1,11 +1,6 @@ use crate::hashing::curve_maps::swu::parity; use ark_test_curves::bls12_381::{Fq, Fq2, Fq6}; -#[cfg(all(test, feature = "std"))] -mod json; -#[cfg(all(test, feature = "std"))] -mod suites; - #[test] fn test_parity_of_prime_field_elements() { let a1 = Fq::from(0); diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs deleted file mode 100644 index 872789264..000000000 --- a/ec/src/hashing/tests/suites.rs +++ /dev/null @@ -1,121 +0,0 @@ -use std::{ - fs::{read_dir, File}, - io::BufReader, -}; - -use super::json::SuiteVector; -use ark_ff::field_hashers::{DefaultFieldHasher, HashToField}; -use libtest_mimic::{run, Arguments, Failed, Trial}; - -use ark_test_curves::{ - hashing::{curve_maps::wb::WBMap, map_to_curve_hasher::MapToCurveBasedHasher, HashToCurve}, - short_weierstrass::{Affine, Projective}, -}; - -use ark_ff::{Field, PrimeField}; -use ark_test_curves::bls12_381::{g1::Config as G1Config, g2::Config as G2Config, Fq, Fq2}; -use sha2::Sha256; - -#[test] -fn suites() { - let args = Arguments::from_args(); - let mut tests_weierstrass = Vec::::new(); - - for filename in read_dir("./src/hashing/tests/testdata").unwrap() { - let file = File::open(filename.unwrap().path()).unwrap(); - let u: SuiteVector = serde_json::from_reader(BufReader::new(file)).unwrap(); - let test = Trial::test(u.ciphersuite.clone(), move || run_test_w(&u)); - tests_weierstrass.push(test); - } - run(&args, tests_weierstrass).exit_if_failed(); -} - -fn run_test_w(data: &SuiteVector) -> Result<(), Failed> { - assert_eq!(data.hash, "sha256"); - let dst = data.dst.as_bytes(); - let hasher; - let m; - let g1_mapper = MapToCurveBasedHasher::< - Projective, - DefaultFieldHasher, - WBMap, - >::new(dst) - .unwrap(); - let g2_mapper = MapToCurveBasedHasher::< - Projective, - DefaultFieldHasher, - WBMap, - >::new(dst) - .unwrap(); - match data.curve.as_str() { - "BLS12-381 G1" => { - m = 1; - hasher = as HashToField>::new(dst); - }, - "BLS12-381 G2" => { - m = 2; - hasher = as HashToField>::new(dst); - }, - _ => return Err("unsupported test suite".into()), - } - - for v in data.vectors.iter() { - // first, hash-to-field tests - let got: Vec = hasher.hash_to_field(&v.msg.as_bytes(), 2 * m); - let want: Vec = v.u.iter().map(read_fq_vec).flatten().collect(); - if got != want { - return Err(format!( - "Suite: {:?}\ngot: {}\nwant: {}", - data.ciphersuite, got[0], want[0], - ) - .into()); - } - - // then, test curve points - let x = read_fq_vec(&v.p.x); - let y = read_fq_vec(&v.p.y); - match data.curve.as_str() { - "BLS12-381 G1" => { - let got = g1_mapper.hash(&v.msg.as_bytes()).unwrap(); - let want = Affine::::new_unchecked( - Fq::from_base_prime_field_elems(&x[..]).unwrap(), - Fq::from_base_prime_field_elems(&y[..]).unwrap(), - ); - assert!(got.is_on_curve()); - assert!(want.is_on_curve()); - if got != want { - return Err(format!( - "Suite: {:?}\ngot: {}\nwant: {}", - data.ciphersuite, got, want, - ) - .into()); - } - }, - "BLS12-381 G2" => { - let got = g2_mapper.hash(&v.msg.as_bytes()).unwrap(); - let want = Affine::::new_unchecked( - Fq2::from_base_prime_field_elems(&x[..]).unwrap(), - Fq2::from_base_prime_field_elems(&y[..]).unwrap(), - ); - assert!(got.is_on_curve()); - assert!(want.is_on_curve()); - if got != want { - return Err(format!( - "Suite: {:?}\nmsg: {}\n\ngot: {}\nwant: {}", - data.ciphersuite, v.msg, got, want, - ) - .into()); - } - }, - _ => return Err("unsupported test suite".into()), - } - } - Ok(()) -} - -fn read_fq_vec(input: &String) -> Vec { - input - .split(",") - .map(|f| Fq::from_be_bytes_mod_order(&hex::decode(f.trim_start_matches("0x")).unwrap())) - .collect() -} diff --git a/test-curves/src/bls12_381/tests.rs b/test-curves/src/bls12_381/tests.rs index 9ff71eb71..863be4afc 100644 --- a/test-curves/src/bls12_381/tests.rs +++ b/test-curves/src/bls12_381/tests.rs @@ -18,3 +18,7 @@ test_group!(g2; G2Projective; sw); test_group!(pairing_output; ark_ec::pairing::PairingOutput; msm); #[cfg(feature = "bls12_381_curve")] test_pairing!(pairing; crate::bls12_381::Bls12_381); +#[cfg(feature = "bls12_381_curve")] +test_h2c!(g1_h2c; "./src/testdata"; "BLS12381G1"; crate::bls12_381::g1::Config; crate::bls12_381::Fq; crate::bls12_381::Fq; 1); +#[cfg(feature = "bls12_381_curve")] +test_h2c!(g2_hc2; "./src/testdata"; "BLS12381G2"; crate::bls12_381::g2::Config; crate::bls12_381::Fq2; crate::bls12_381::Fq; 2); diff --git a/ec/src/hashing/tests/testdata/BLS12381G1_XMD-SHA-256_SSWU_RO_.json b/test-curves/src/testdata/BLS12381G1_XMD-SHA-256_SSWU_RO_.json similarity index 100% rename from ec/src/hashing/tests/testdata/BLS12381G1_XMD-SHA-256_SSWU_RO_.json rename to test-curves/src/testdata/BLS12381G1_XMD-SHA-256_SSWU_RO_.json diff --git a/ec/src/hashing/tests/testdata/BLS12381G2_XMD-SHA-256_SSWU_RO_.json b/test-curves/src/testdata/BLS12381G2_XMD-SHA-256_SSWU_RO_.json similarity index 100% rename from ec/src/hashing/tests/testdata/BLS12381G2_XMD-SHA-256_SSWU_RO_.json rename to test-curves/src/testdata/BLS12381G2_XMD-SHA-256_SSWU_RO_.json diff --git a/test-templates/Cargo.toml b/test-templates/Cargo.toml index 0f76126e1..94bed0ec1 100644 --- a/test-templates/Cargo.toml +++ b/test-templates/Cargo.toml @@ -21,6 +21,11 @@ ark-ec = { version = "^0.3.0", path = "../ec", default-features = false } num-bigint = { version = "0.4", default-features = false } num-integer = { version = "0.1", default-features = false } num-traits = { version = "0.2", default-features = false } +serde = "1.0" +serde_json = "1.0" +serde_derive = "1.0" +hex = "0.4" +sha2 = { version = "0.10", default-features = false } [features] default = [] diff --git a/test-templates/src/fields.rs b/test-templates/src/fields.rs index 302f241e5..a2914eb7f 100644 --- a/test-templates/src/fields.rs +++ b/test-templates/src/fields.rs @@ -513,7 +513,7 @@ macro_rules! __test_field { assert_eq!(r, <$field>::R.into()); assert_eq!(r2, <$field>::R2.into()); - assert_eq!(inv, <$field>::INV.into()); + assert_eq!(inv, u64::from(<$field>::INV)); assert_eq!(inv2, <$field>::INV); } } diff --git a/ec/src/hashing/tests/json.rs b/test-templates/src/h2c/json.rs similarity index 100% rename from ec/src/hashing/tests/json.rs rename to test-templates/src/h2c/json.rs diff --git a/test-templates/src/h2c/mod.rs b/test-templates/src/h2c/mod.rs new file mode 100644 index 000000000..520ad7979 --- /dev/null +++ b/test-templates/src/h2c/mod.rs @@ -0,0 +1,87 @@ +pub mod json; +extern crate hex; +extern crate serde_json; +extern crate sha2; +pub use hex::decode; +pub use serde_json::from_reader; +pub use sha2::Sha256; + +#[macro_export] +macro_rules! test_h2c { + ($mod_name: ident; $test_path: literal; $test_name: literal; $group: ty; $field: ty; $base_prime_field: ty; $m: literal) => { + mod $mod_name { + use ark_ff::PrimeField; + + extern crate std; + use ark_ec::{ + hashing::{ + curve_maps::wb::WBMap, map_to_curve_hasher::MapToCurveBasedHasher, HashToCurve, + }, + short_weierstrass::{Affine, Projective}, + }; + use ark_ff::{ + field_hashers::{DefaultFieldHasher, HashToField}, + fields::Field, + One, UniformRand, Zero, + }; + use ark_std::{format, string::String, vec::Vec}; + use std::{ + fs::{read_dir, File}, + io::BufReader, + }; + use $crate::decode; + use $crate::Sha256; + + use $crate::json::SuiteVector; + #[test] + fn test_h2c() { + let filename = format!("{}/{}_XMD-SHA-256_SSWU_RO_.json", $test_path, $test_name); + + let file = File::open(filename).unwrap(); + let data: SuiteVector = $crate::from_reader(BufReader::new(file)).unwrap(); + + assert_eq!(data.hash, "sha256"); + let dst = data.dst.as_bytes(); + let hasher; + let g1_mapper = MapToCurveBasedHasher::< + Projective<$group>, + DefaultFieldHasher, + WBMap<$group>, + >::new(dst) + .unwrap(); + hasher = as HashToField<$field>>::new(dst); + + for v in data.vectors.iter() { + // first, hash-to-field tests + let got: Vec<$base_prime_field> = + hasher.hash_to_field(&v.msg.as_bytes(), 2 * $m); + let want: Vec<$base_prime_field> = + v.u.iter().map(read_fq_vec).flatten().collect(); + assert_eq!(got, want); + + // then, test curve points + let x = read_fq_vec(&v.p.x); + let y = read_fq_vec(&v.p.y); + let got = g1_mapper.hash(&v.msg.as_bytes()).unwrap(); + let want = Affine::<$group>::new_unchecked( + <$field>::from_base_prime_field_elems(&x[..]).unwrap(), + <$field>::from_base_prime_field_elems(&y[..]).unwrap(), + ); + assert!(got.is_on_curve()); + assert!(want.is_on_curve()); + assert_eq!(got, want); + } + } + pub fn read_fq_vec(input: &String) -> Vec<$base_prime_field> { + input + .split(",") + .map(|f| { + <$base_prime_field>::from_be_bytes_mod_order( + &decode(f.trim_start_matches("0x")).unwrap(), + ) + }) + .collect() + } + } + }; +} diff --git a/test-templates/src/lib.rs b/test-templates/src/lib.rs index 13fc45d85..37fa548fb 100644 --- a/test-templates/src/lib.rs +++ b/test-templates/src/lib.rs @@ -5,6 +5,9 @@ pub mod fields; pub mod msm; #[macro_use] pub mod pairing; +#[macro_use] +pub mod h2c; +pub use h2c::*; pub use num_bigint; pub use num_integer;