From d73e068686addd254e69dc9e7ddce6b20fc79ab0 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 14 May 2019 22:09:57 +1000 Subject: [PATCH] Add additional fake_crypto objects --- .../bls/src/fake_aggregate_public_key.rs | 28 +++ .../utils/bls/src/fake_aggregate_signature.rs | 9 +- eth2/utils/bls/src/fake_public_key.rs | 164 ++++++++++++++++++ eth2/utils/bls/src/lib.rs | 52 ++++-- tests/ef_tests/Cargo.toml | 4 + 5 files changed, 236 insertions(+), 21 deletions(-) create mode 100644 eth2/utils/bls/src/fake_aggregate_public_key.rs create mode 100644 eth2/utils/bls/src/fake_public_key.rs diff --git a/eth2/utils/bls/src/fake_aggregate_public_key.rs b/eth2/utils/bls/src/fake_aggregate_public_key.rs new file mode 100644 index 000000000..602269bdb --- /dev/null +++ b/eth2/utils/bls/src/fake_aggregate_public_key.rs @@ -0,0 +1,28 @@ +use super::{PublicKey, BLS_PUBLIC_KEY_BYTE_SIZE}; +use bls_aggregates::AggregatePublicKey as RawAggregatePublicKey; + +/// A BLS aggregate public key. +/// +/// This struct is a wrapper upon a base type and provides helper functions (e.g., SSZ +/// serialization). +#[derive(Debug, Clone, Default)] +pub struct FakeAggregatePublicKey { + bytes: Vec, +} + +impl FakeAggregatePublicKey { + pub fn new() -> Self { + Self::zero() + } + + /// Creates a new all-zero's aggregate public key + pub fn zero() -> Self { + Self { + bytes: vec![0; BLS_PUBLIC_KEY_BYTE_SIZE], + } + } + + pub fn add(&mut self, _public_key: &PublicKey) { + // No nothing. + } +} diff --git a/eth2/utils/bls/src/fake_aggregate_signature.rs b/eth2/utils/bls/src/fake_aggregate_signature.rs index 12532d080..709c008aa 100644 --- a/eth2/utils/bls/src/fake_aggregate_signature.rs +++ b/eth2/utils/bls/src/fake_aggregate_signature.rs @@ -1,4 +1,7 @@ -use super::{fake_signature::FakeSignature, AggregatePublicKey, BLS_AGG_SIG_BYTE_SIZE}; +use super::{ + fake_aggregate_public_key::FakeAggregatePublicKey, fake_signature::FakeSignature, + BLS_AGG_SIG_BYTE_SIZE, +}; use cached_tree_hash::cached_tree_hash_ssz_encoding_as_vector; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; @@ -43,7 +46,7 @@ impl FakeAggregateSignature { &self, _msg: &[u8], _domain: u64, - _aggregate_public_key: &AggregatePublicKey, + _aggregate_public_key: &FakeAggregatePublicKey, ) -> bool { true } @@ -53,7 +56,7 @@ impl FakeAggregateSignature { &self, _messages: &[&[u8]], _domain: u64, - _aggregate_public_keys: &[&AggregatePublicKey], + _aggregate_public_keys: &[&FakeAggregatePublicKey], ) -> bool { true } diff --git a/eth2/utils/bls/src/fake_public_key.rs b/eth2/utils/bls/src/fake_public_key.rs new file mode 100644 index 000000000..16cdba53e --- /dev/null +++ b/eth2/utils/bls/src/fake_public_key.rs @@ -0,0 +1,164 @@ +use super::{SecretKey, BLS_PUBLIC_KEY_BYTE_SIZE}; +use bls_aggregates::PublicKey as RawPublicKey; +use cached_tree_hash::cached_tree_hash_ssz_encoding_as_vector; +use serde::de::{Deserialize, Deserializer}; +use serde::ser::{Serialize, Serializer}; +use serde_hex::{encode as hex_encode, HexVisitor}; +use ssz::{ssz_encode, Decode, DecodeError}; +use std::default; +use std::fmt; +use std::hash::{Hash, Hasher}; +use tree_hash::tree_hash_ssz_encoding_as_vector; + +/// A single BLS signature. +/// +/// This struct is a wrapper upon a base type and provides helper functions (e.g., SSZ +/// serialization). +#[derive(Debug, Clone, Eq)] +pub struct FakePublicKey { + bytes: Vec +} + +impl FakePublicKey { + pub fn from_secret_key(_secret_key: &SecretKey) -> Self { + Self::zero() + } + + /// Creates a new all-zero's public key + pub fn zero() -> Self { + Self { + bytes: vec![0; BLS_PUBLIC_KEY_BYTE_SIZE], + } + } + + /// Returns the underlying point as compressed bytes. + /// + /// Identical to `self.as_uncompressed_bytes()`. + fn as_bytes(&self) -> Vec { + self.bytes.clone() + } + + /// Converts compressed bytes to FakePublicKey + pub fn from_bytes(bytes: &[u8]) -> Result { + Ok(Self { + bytes: bytes.to_vec() + }) + } + + /// Returns the FakePublicKey as (x, y) bytes + pub fn as_uncompressed_bytes(&self) -> Vec { + self.as_bytes() + } + + /// Converts (x, y) bytes to FakePublicKey + pub fn from_uncompressed_bytes(bytes: &[u8]) -> Result { + Self::from_bytes(bytes) + } + + /// Returns the last 6 bytes of the SSZ encoding of the public key, as a hex string. + /// + /// Useful for providing a short identifier to the user. + pub fn concatenated_hex_id(&self) -> String { + let bytes = ssz_encode(self); + let end_bytes = &bytes[bytes.len().saturating_sub(6)..bytes.len()]; + hex_encode(end_bytes) + } +} + +impl fmt::Display for FakePublicKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.concatenated_hex_id()) + } +} + +impl default::Default for FakePublicKey { + fn default() -> Self { + let secret_key = SecretKey::random(); + FakePublicKey::from_secret_key(&secret_key) + } +} + +impl_ssz!(FakePublicKey, BLS_PUBLIC_KEY_BYTE_SIZE, "FakePublicKey"); + +impl Serialize for FakePublicKey { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&hex_encode(self.as_bytes())) + } +} + +impl<'de> Deserialize<'de> for FakePublicKey { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let bytes = deserializer.deserialize_str(HexVisitor)?; + let pubkey = Self::from_ssz_bytes(&bytes[..]) + .map_err(|e| serde::de::Error::custom(format!("invalid pubkey ({:?})", e)))?; + Ok(pubkey) + } +} + +tree_hash_ssz_encoding_as_vector!(FakePublicKey); +cached_tree_hash_ssz_encoding_as_vector!(FakePublicKey, 48); + +impl PartialEq for FakePublicKey { + fn eq(&self, other: &FakePublicKey) -> bool { + ssz_encode(self) == ssz_encode(other) + } +} + +impl Hash for FakePublicKey { + /// Note: this is distinct from consensus serialization, it will produce a different hash. + /// + /// This method uses the uncompressed bytes, which are much faster to obtain than the + /// compressed bytes required for consensus serialization. + /// + /// Use `ssz::Encode` to obtain the bytes required for consensus hashing. + fn hash(&self, state: &mut H) { + self.as_uncompressed_bytes().hash(state) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use ssz::ssz_encode; + use tree_hash::TreeHash; + + #[test] + pub fn test_ssz_round_trip() { + let sk = SecretKey::random(); + let original = FakePublicKey::from_secret_key(&sk); + + let bytes = ssz_encode(&original); + let decoded = FakePublicKey::from_ssz_bytes(&bytes).unwrap(); + + assert_eq!(original, decoded); + } + + #[test] + pub fn test_cached_tree_hash() { + let sk = SecretKey::random(); + let original = FakePublicKey::from_secret_key(&sk); + + let mut cache = cached_tree_hash::TreeHashCache::new(&original).unwrap(); + + assert_eq!( + cache.tree_hash_root().unwrap().to_vec(), + original.tree_hash_root() + ); + + let sk = SecretKey::random(); + let modified = FakePublicKey::from_secret_key(&sk); + + cache.update(&modified).unwrap(); + + assert_eq!( + cache.tree_hash_root().unwrap().to_vec(), + modified.tree_hash_root() + ); + } +} diff --git a/eth2/utils/bls/src/lib.rs b/eth2/utils/bls/src/lib.rs index afe655939..7ffcce452 100644 --- a/eth2/utils/bls/src/lib.rs +++ b/eth2/utils/bls/src/lib.rs @@ -3,33 +3,49 @@ extern crate ssz; #[macro_use] mod macros; -mod aggregate_public_key; mod keypair; -mod public_key; mod secret_key; -#[cfg(not(feature = "fake_crypto"))] -mod aggregate_signature; -#[cfg(not(feature = "fake_crypto"))] -mod signature; -#[cfg(not(feature = "fake_crypto"))] -pub use crate::aggregate_signature::AggregateSignature; -#[cfg(not(feature = "fake_crypto"))] -pub use crate::signature::Signature; +pub use crate::keypair::Keypair; +pub use crate::secret_key::SecretKey; +#[cfg(feature = "fake_crypto")] +mod fake_aggregate_public_key; #[cfg(feature = "fake_crypto")] mod fake_aggregate_signature; #[cfg(feature = "fake_crypto")] +mod fake_public_key; +#[cfg(feature = "fake_crypto")] mod fake_signature; -#[cfg(feature = "fake_crypto")] -pub use crate::fake_aggregate_signature::FakeAggregateSignature as AggregateSignature; -#[cfg(feature = "fake_crypto")] -pub use crate::fake_signature::FakeSignature as Signature; -pub use crate::aggregate_public_key::AggregatePublicKey; -pub use crate::keypair::Keypair; -pub use crate::public_key::PublicKey; -pub use crate::secret_key::SecretKey; +#[cfg(not(feature = "fake_crypto"))] +mod aggregate_public_key; +#[cfg(not(feature = "fake_crypto"))] +mod aggregate_signature; +#[cfg(not(feature = "fake_crypto"))] +mod public_key; +#[cfg(not(feature = "fake_crypto"))] +mod signature; + +#[cfg(feature = "fake_crypto")] +pub use fakes::*; +#[cfg(feature = "fake_crypto")] +mod fakes { + pub use crate::fake_aggregate_public_key::FakeAggregatePublicKey as AggregatePublicKey; + pub use crate::fake_aggregate_signature::FakeAggregateSignature as AggregateSignature; + pub use crate::fake_public_key::FakePublicKey as PublicKey; + pub use crate::fake_signature::FakeSignature as Signature; +} + +#[cfg(not(feature = "fake_crypto"))] +pub use reals::*; +#[cfg(not(feature = "fake_crypto"))] +mod reals { + pub use crate::aggregate_public_key::AggregatePublicKey; + pub use crate::aggregate_signature::AggregateSignature; + pub use crate::public_key::PublicKey; + pub use crate::signature::Signature; +} pub const BLS_AGG_SIG_BYTE_SIZE: usize = 96; pub const BLS_SIG_BYTE_SIZE: usize = 96; diff --git a/tests/ef_tests/Cargo.toml b/tests/ef_tests/Cargo.toml index c4e1e9041..fee9f07cd 100644 --- a/tests/ef_tests/Cargo.toml +++ b/tests/ef_tests/Cargo.toml @@ -4,7 +4,11 @@ version = "0.1.0" authors = ["Paul Hauner "] edition = "2018" +[features] +fake_crypto = ["bls/fake_crypto"] + [dependencies] +bls = { path = "../../eth2/utils/bls" } ethereum-types = "0.5" hex = "0.3" serde = "1.0"