From 4f6447a62b0dbef619db58c8489bee07c34c4286 Mon Sep 17 00:00:00 2001 From: Kirk Baird Date: Tue, 21 May 2019 10:32:14 +1000 Subject: [PATCH] Begin working on bls test --- eth2/utils/bls/Cargo.toml | 2 +- .../bls/src/fake_aggregate_public_key.rs | 8 ++ eth2/utils/bls/src/lib.rs | 1 + tests/ef_tests/src/cases.rs | 4 + .../src/cases/bls_aggregate_pubkeys.rs | 54 +++++++++++++ .../ef_tests/src/cases/bls_aggregate_sigs.rs | 54 +++++++++++++ tests/ef_tests/src/cases/g2_compressed.rs | 75 +++++++++++++++++++ tests/ef_tests/src/doc.rs | 3 + tests/ef_tests/tests/tests.rs | 11 +++ 9 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 tests/ef_tests/src/cases/bls_aggregate_pubkeys.rs create mode 100644 tests/ef_tests/src/cases/bls_aggregate_sigs.rs create mode 100644 tests/ef_tests/src/cases/g2_compressed.rs diff --git a/eth2/utils/bls/Cargo.toml b/eth2/utils/bls/Cargo.toml index dcace15c8..cd132bb62 100644 --- a/eth2/utils/bls/Cargo.toml +++ b/eth2/utils/bls/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Paul Hauner "] edition = "2018" [dependencies] -bls-aggregates = { git = "https://github.com/sigp/signature-schemes", tag = "0.6.1" } +bls-aggregates = { git = "https://github.com/sigp/signature-schemes", branch = "secret-key-serialization" } cached_tree_hash = { path = "../cached_tree_hash" } hashing = { path = "../hashing" } hex = "0.3" diff --git a/eth2/utils/bls/src/fake_aggregate_public_key.rs b/eth2/utils/bls/src/fake_aggregate_public_key.rs index 602269bdb..80256034a 100644 --- a/eth2/utils/bls/src/fake_aggregate_public_key.rs +++ b/eth2/utils/bls/src/fake_aggregate_public_key.rs @@ -25,4 +25,12 @@ impl FakeAggregatePublicKey { pub fn add(&mut self, _public_key: &PublicKey) { // No nothing. } + + pub fn as_raw(&self) -> &FakeAggregatePublicKey { + &self + } + + pub fn as_bytes(&self) -> Vec { + self.bytes.clone() + } } diff --git a/eth2/utils/bls/src/lib.rs b/eth2/utils/bls/src/lib.rs index 7ffcce452..2c257d326 100644 --- a/eth2/utils/bls/src/lib.rs +++ b/eth2/utils/bls/src/lib.rs @@ -8,6 +8,7 @@ mod secret_key; pub use crate::keypair::Keypair; pub use crate::secret_key::SecretKey; +pub use bls_aggregates::{compress_g2, hash_on_g2}; #[cfg(feature = "fake_crypto")] mod fake_aggregate_public_key; diff --git a/tests/ef_tests/src/cases.rs b/tests/ef_tests/src/cases.rs index 5bb1bdc2f..fe6b22432 100644 --- a/tests/ef_tests/src/cases.rs +++ b/tests/ef_tests/src/cases.rs @@ -4,9 +4,13 @@ use yaml_rust::YamlLoader; mod ssz_generic; mod ssz_static; +mod bls_aggregate_pubkeys; +mod bls_aggregate_sigs; pub use ssz_generic::*; pub use ssz_static::*; +pub use bls_aggregate_pubkeys::*; +pub use bls_aggregate_sigs::*; #[derive(Debug)] pub struct Cases { diff --git a/tests/ef_tests/src/cases/bls_aggregate_pubkeys.rs b/tests/ef_tests/src/cases/bls_aggregate_pubkeys.rs new file mode 100644 index 000000000..7a2a62207 --- /dev/null +++ b/tests/ef_tests/src/cases/bls_aggregate_pubkeys.rs @@ -0,0 +1,54 @@ +use super::*; +use crate::case_result::compare_result; +use bls::{AggregatePublicKey, PublicKey}; +use ethereum_types::{U128, U256}; +use serde_derive::Deserialize; +use ssz::Decode; +use std::fmt::Debug; +use types::EthSpec; + +#[derive(Debug, Clone, Deserialize)] +pub struct BlsAggregatePubkeys { + pub input: Vec, + pub output: String, +} + +impl YamlDecode for BlsAggregatePubkeys { + fn yaml_decode(yaml: &String) -> Result { + Ok(serde_yaml::from_str(&yaml.as_str()).unwrap()) + } +} + +impl EfTest for Cases { + fn test_results(&self) -> Vec { + self.test_cases + .iter() + .enumerate() + .map(|(i, tc)| { + let result = bls_add_aggregates::(&tc.input, &tc.output); + + CaseResult::new(i, tc, result) + }) + .collect() + } +} + +/// Execute a `aggregate_pubkeys` test case. +fn bls_add_aggregates( + inputs: &[String], + output: &String, +) -> Result<(), Error> { + let mut aggregate_pubkey = AggregatePublicKey::new(); + + for key_str in inputs { + let key = hex::decode(&key_str[2..]).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; + let key = PublicKey::from_bytes(&key).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; + + aggregate_pubkey.add(&key); + } + + let output_bytes = Some(hex::decode(&output[2..]).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?); + let aggregate_pubkey = Ok(aggregate_pubkey.as_raw().as_bytes()); + + compare_result::, Vec>(&aggregate_pubkey, &output_bytes) +} diff --git a/tests/ef_tests/src/cases/bls_aggregate_sigs.rs b/tests/ef_tests/src/cases/bls_aggregate_sigs.rs new file mode 100644 index 000000000..8d337a1ee --- /dev/null +++ b/tests/ef_tests/src/cases/bls_aggregate_sigs.rs @@ -0,0 +1,54 @@ +use super::*; +use crate::case_result::compare_result; +use bls::{AggregateSignature, Signature}; +use ethereum_types::{U128, U256}; +use serde_derive::Deserialize; +use ssz::Decode; +use std::fmt::Debug; +use types::EthSpec; + +#[derive(Debug, Clone, Deserialize)] +pub struct BlsAggregateSigs { + pub input: Vec, + pub output: String, +} + +impl YamlDecode for BlsAggregateSigs { + fn yaml_decode(yaml: &String) -> Result { + Ok(serde_yaml::from_str(&yaml.as_str()).unwrap()) + } +} + +impl EfTest for Cases { + fn test_results(&self) -> Vec { + self.test_cases + .iter() + .enumerate() + .map(|(i, tc)| { + let result = bls_add_aggregates::(&tc.input, &tc.output); + + CaseResult::new(i, tc, result) + }) + .collect() + } +} + +/// Execute a `aggregate_sigs` test case. +fn bls_add_aggregates( + inputs: &[String], + output: &String, +) -> Result<(), Error> { + let mut aggregate_signature = AggregateSignature::new(); + + for key_str in inputs { + let sig = hex::decode(&key_str[2..]).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; + let sig = Signature::from_bytes(&sig).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; + + aggregate_signature.add(&sig); + } + + let output_bytes = Some(hex::decode(&output[2..]).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?); + let aggregate_signature = Ok(aggregate_signature.as_bytes()); + + compare_result::, Vec>(&aggregate_signature, &output_bytes) +} diff --git a/tests/ef_tests/src/cases/g2_compressed.rs b/tests/ef_tests/src/cases/g2_compressed.rs new file mode 100644 index 000000000..306d34604 --- /dev/null +++ b/tests/ef_tests/src/cases/g2_compressed.rs @@ -0,0 +1,75 @@ +use super::*; +use crate::case_result::compare_result; +use bls::{compress_g2, hash_on_g2}; +use ethereum_types::{U128, U256}; +use serde_derive::Deserialize; +use ssz::Decode; +use std::fmt::Debug; +use types::EthSpec; + +#[derive(Debug, Clone, Deserialize)] +pub struct BlsG2CompressedInput { + pub message: String, + pub domain: String, +} + +#[derive(Debug, Clone, Deserialize)] +pub struct BlsG2Compressed { + pub input: BlsG2CompressedInput, + pub output: Vec, +} + +impl YamlDecode for BlsG2Compressed { + fn yaml_decode(yaml: &String) -> Result { + Ok(serde_yaml::from_str(&yaml.as_str()).unwrap()) + } +} + +impl EfTest for Cases { + fn test_results(&self) -> Vec { + self.test_cases + .iter() + .enumerate() + .map(|(i, tc)| { + let result = compressed_hash(&tc.input.message, &tc.input.domain, &tc.output); + + CaseResult::new(i, tc, result) + }) + .collect() + } +} + +/// Execute a `compressed hash to g2` test case. +fn compressed_hash( + message: &String, + domain: &String, + output: &Vec, +) -> Result<(), Error> { + let msg = hex::decode(&message[2..]).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; + let d = hex::decode(&domain[2..]).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; + let d = bytes_to_u64(&d); + + let point = hash_on_g2 + + + let mut output = hex::decode(&output[0][2..]).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; + let output_y = hex::decode(&output[1][2..]).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; + output.append(&output_y); + + let point = hash_on_g2(&msg, d); + let point = compress_g2(&point); + + compare_result::, Vec>(Ok(point), Some(output)) +} + +// Converts a vector to u64 (from little endian) +fn bytes_to_u64(array: &Vec) -> u64 { + let mut result: u64 = 0; + for (i, value) in array.iter().enumerate() { + if i == 8 { + break; + } + result += u64::pow(2, i * 8) * *value; + } + result +} diff --git a/tests/ef_tests/src/doc.rs b/tests/ef_tests/src/doc.rs index 1a93c738a..1d7d3994c 100644 --- a/tests/ef_tests/src/doc.rs +++ b/tests/ef_tests/src/doc.rs @@ -35,6 +35,9 @@ impl Doc { ("ssz", "uint", _) => run_test::(&self.yaml), ("ssz", "static", "minimal") => run_test::(&self.yaml), ("ssz", "static", "mainnet") => run_test::(&self.yaml), + ("bls", "aggregate_pubkeys", "mainnet") => run_test::(&self.yaml), + ("bls", "aggregate_sigs", "mainnet") => run_test::(&self.yaml), + (runner, handler, config) => panic!( "No implementation for runner: \"{}\", handler: \"{}\", config: \"{}\"", runner, handler, config diff --git a/tests/ef_tests/tests/tests.rs b/tests/ef_tests/tests/tests.rs index ebdace0a8..88059eaba 100644 --- a/tests/ef_tests/tests/tests.rs +++ b/tests/ef_tests/tests/tests.rs @@ -26,6 +26,7 @@ fn yaml_files_in_test_dir(dir: &str) -> Vec { .collect() } +/* #[test] fn ssz_generic() { yaml_files_in_test_dir("ssz_generic") @@ -43,3 +44,13 @@ fn ssz_static() { Doc::assert_tests_pass(file); }); } +*/ + +#[test] +fn bls() { + yaml_files_in_test_dir("bls") + .into_par_iter() + .for_each(|file| { + Doc::assert_tests_pass(file); + }); +}