use crate::generic_public_key_bytes::GenericPublicKeyBytes; use crate::Error; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; use serde_utils::hex::encode as hex_encode; use ssz::{Decode, Encode}; use std::fmt; use std::hash::{Hash, Hasher}; use tree_hash::TreeHash; /// The byte-length of a BLS public key when serialized in compressed form. pub const PUBLIC_KEY_BYTES_LEN: usize = 48; /// Represents the public key at infinity. pub const INFINITY_PUBLIC_KEY: [u8; PUBLIC_KEY_BYTES_LEN] = [ 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; /// Implemented on some struct from a BLS library so it may be used as the `point` in a /// `GenericPublicKey`. pub trait TPublicKey: Sized + Clone { /// Serialize `self` as compressed bytes. fn serialize(&self) -> [u8; PUBLIC_KEY_BYTES_LEN]; /// Deserialize `self` from compressed bytes. fn deserialize(bytes: &[u8]) -> Result; } /// A BLS aggregate public key that is generic across some BLS point (`Pub`). /// /// Provides generic functionality whilst deferring all serious cryptographic operations to `Pub`. #[derive(Clone)] pub struct GenericPublicKey { /// The underlying point which performs *actual* cryptographic operations. point: Pub, } impl GenericPublicKey where Pub: TPublicKey, { /// Instantiates `Self` from a `point`. pub(crate) fn from_point(point: Pub) -> Self { Self { point } } /// Returns a reference to the underlying BLS point. pub(crate) fn point(&self) -> &Pub { &self.point } /// Returns `self.serialize()` as a `0x`-prefixed hex string. pub fn to_hex_string(&self) -> String { format!("{:?}", self) } /// Returns `self` in the compressed `PublicKeyBytes` representation. pub fn compress(&self) -> GenericPublicKeyBytes { GenericPublicKeyBytes::from(self) } /// Serialize `self` as compressed bytes. pub fn serialize(&self) -> [u8; PUBLIC_KEY_BYTES_LEN] { self.point.serialize() } /// Deserialize `self` from compressed bytes. pub fn deserialize(bytes: &[u8]) -> Result { if bytes == &INFINITY_PUBLIC_KEY[..] { Err(Error::InvalidInfinityPublicKey) } else { Ok(Self { point: Pub::deserialize(bytes)?, }) } } } impl Eq for GenericPublicKey {} impl PartialEq for GenericPublicKey { fn eq(&self, other: &Self) -> bool { self.serialize()[..] == other.serialize()[..] } } /// Hashes the `self.serialize()` bytes. impl Hash for GenericPublicKey { fn hash(&self, state: &mut H) { self.serialize()[..].hash(state); } } impl Encode for GenericPublicKey { impl_ssz_encode!(PUBLIC_KEY_BYTES_LEN); } impl Decode for GenericPublicKey { impl_ssz_decode!(PUBLIC_KEY_BYTES_LEN); } impl TreeHash for GenericPublicKey { impl_tree_hash!(PUBLIC_KEY_BYTES_LEN); } impl fmt::Display for GenericPublicKey { impl_display!(); } impl std::str::FromStr for GenericPublicKey { impl_from_str!(); } impl Serialize for GenericPublicKey { impl_serde_serialize!(); } impl<'de, Pub: TPublicKey> Deserialize<'de> for GenericPublicKey { impl_serde_deserialize!(); } impl fmt::Debug for GenericPublicKey { impl_debug!(); } #[cfg(feature = "arbitrary")] impl arbitrary::Arbitrary for GenericPublicKey { impl_arbitrary!(PUBLIC_KEY_BYTES_LEN); }