diff --git a/beacon_chain/utils/bls/src/lib.rs b/beacon_chain/utils/bls/src/lib.rs index d3a01fb10..2b5d56a7c 100644 --- a/beacon_chain/utils/bls/src/lib.rs +++ b/beacon_chain/utils/bls/src/lib.rs @@ -3,20 +3,22 @@ extern crate hashing; extern crate ssz; mod aggregate_signature; +mod public_key; mod signature; pub use crate::aggregate_signature::AggregateSignature; pub use crate::signature::Signature; +pub use crate::public_key::PublicKey; pub use self::bls_aggregates::AggregatePublicKey; pub use self::bls_aggregates::Keypair; -pub use self::bls_aggregates::PublicKey; pub use self::bls_aggregates::SecretKey; pub const BLS_AGG_SIG_BYTE_SIZE: usize = 97; use hashing::canonical_hash; use std::default::Default; +use ssz::ssz_encode; fn extend_if_needed(hash: &mut Vec) { // NOTE: bls_aggregates crate demands 48 bytes, this may be removed as we get closer to production @@ -26,7 +28,7 @@ fn extend_if_needed(hash: &mut Vec) { /// For some signature and public key, ensure that the signature message was the public key and it /// was signed by the secret key that corresponds to that public key. pub fn verify_proof_of_possession(sig: &Signature, pubkey: &PublicKey) -> bool { - let mut hash = canonical_hash(&pubkey.as_bytes()); + let mut hash = canonical_hash(&ssz_encode(pubkey)); extend_if_needed(&mut hash); sig.verify_hashed(&hash, &pubkey) } diff --git a/beacon_chain/utils/bls/src/public_key.rs b/beacon_chain/utils/bls/src/public_key.rs new file mode 100644 index 000000000..b5d85eff7 --- /dev/null +++ b/beacon_chain/utils/bls/src/public_key.rs @@ -0,0 +1,52 @@ +use super::SecretKey; +use bls_aggregates::PublicKey as RawPublicKey; +use ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; + +/// A single BLS signature. +/// +/// This struct is a wrapper upon a base type and provides helper functions (e.g., SSZ +/// serialization). +#[derive(Debug, PartialEq, Clone)] +pub struct PublicKey(RawPublicKey); + +impl PublicKey { + pub fn from_secret_key(secret_key: &SecretKey) -> Self { + PublicKey(RawPublicKey::from_secret_key(secret_key)) + } + + /// Returns the underlying signature. + pub fn as_raw(&self) -> &RawPublicKey { + &self.0 + } +} + +impl Encodable for PublicKey { + fn ssz_append(&self, s: &mut SszStream) { + s.append_vec(&self.0.as_bytes()); + } +} + +impl Decodable for PublicKey { + fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { + let (sig_bytes, i) = decode_ssz_list(bytes, i)?; + let raw_sig = RawPublicKey::from_bytes(&sig_bytes).map_err(|_| DecodeError::TooShort)?; + Ok((PublicKey(raw_sig), i)) + } +} + +#[cfg(test)] +mod tests { + use super::super::ssz::ssz_encode; + use super::*; + + #[test] + pub fn test_ssz_round_trip() { + let sk = SecretKey::random(); + let original = PublicKey::from_secret_key(&sk); + + let bytes = ssz_encode(&original); + let (decoded, _) = PublicKey::ssz_decode(&bytes, 0).unwrap(); + + assert_eq!(original, decoded); + } +} diff --git a/beacon_chain/utils/bls/src/signature.rs b/beacon_chain/utils/bls/src/signature.rs index ebdb5b817..8854d9019 100644 --- a/beacon_chain/utils/bls/src/signature.rs +++ b/beacon_chain/utils/bls/src/signature.rs @@ -1,5 +1,6 @@ use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; -use bls_aggregates::{PublicKey, SecretKey, Signature as RawSignature}; +use super::PublicKey; +use bls_aggregates::{SecretKey, Signature as RawSignature}; /// A single BLS signature. /// @@ -22,12 +23,12 @@ impl Signature { /// Verify the Signature against a PublicKey. pub fn verify(&self, msg: &[u8], pk: &PublicKey) -> bool { - self.0.verify(msg, pk) + self.0.verify(msg, pk.as_raw()) } /// Verify the Signature against a PublicKey, where the message has already been hashed. pub fn verify_hashed(&self, msg_hash: &[u8], pk: &PublicKey) -> bool { - self.0.verify_hashed(msg_hash, pk) + self.0.verify_hashed(msg_hash, pk.as_raw()) } /// Returns the underlying signature.