Upgrade BLS to new SSZ

This commit is contained in:
Paul Hauner 2019-05-06 15:03:20 +10:00
parent ebbeb03349
commit 5550d14d62
No known key found for this signature in database
GPG Key ID: D362883A9218FCC6
8 changed files with 108 additions and 126 deletions

View File

@ -1,4 +1,4 @@
use super::{AggregatePublicKey, Signature, BLS_AGG_SIG_BYTE_SIZE}; use super::*;
use bls_aggregates::{ use bls_aggregates::{
AggregatePublicKey as RawAggregatePublicKey, AggregateSignature as RawAggregateSignature, AggregatePublicKey as RawAggregatePublicKey, AggregateSignature as RawAggregateSignature,
}; };
@ -6,7 +6,7 @@ use cached_tree_hash::cached_tree_hash_ssz_encoding_as_vector;
use serde::de::{Deserialize, Deserializer}; use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer}; use serde::ser::{Serialize, Serializer};
use serde_hex::{encode as hex_encode, HexVisitor}; use serde_hex::{encode as hex_encode, HexVisitor};
use ssz::{decode, Decodable, DecodeError, Encodable, SszStream}; use ssz::{Decodable, DecodeError};
use tree_hash::tree_hash_ssz_encoding_as_vector; use tree_hash::tree_hash_ssz_encoding_as_vector;
/// A BLS aggregate signature. /// A BLS aggregate signature.
@ -99,8 +99,12 @@ impl AggregateSignature {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, DecodeError> { pub fn from_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
for byte in bytes { for byte in bytes {
if *byte != 0 { if *byte != 0 {
let sig = let sig = RawAggregateSignature::from_bytes(&bytes).map_err(|_| {
RawAggregateSignature::from_bytes(&bytes).map_err(|_| DecodeError::Invalid)?; DecodeError::BytesInvalid(
format!("Invalid AggregateSignature bytes: {:?}", bytes).to_string(),
)
})?;
return Ok(Self { return Ok(Self {
aggregate_signature: sig, aggregate_signature: sig,
is_empty: false, is_empty: false,
@ -127,22 +131,11 @@ impl AggregateSignature {
} }
} }
impl Encodable for AggregateSignature { impl_ssz!(
fn ssz_append(&self, s: &mut SszStream) { AggregateSignature,
s.append_encoded_raw(&self.as_bytes()); BLS_AGG_SIG_BYTE_SIZE,
} "AggregateSignature"
} );
impl Decodable for AggregateSignature {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
if bytes.len() - i < BLS_AGG_SIG_BYTE_SIZE {
return Err(DecodeError::TooShort);
}
let agg_sig = AggregateSignature::from_bytes(&bytes[i..(i + BLS_AGG_SIG_BYTE_SIZE)])
.map_err(|_| DecodeError::Invalid)?;
Ok((agg_sig, i + BLS_AGG_SIG_BYTE_SIZE))
}
}
impl Serialize for AggregateSignature { impl Serialize for AggregateSignature {
/// Serde serialization is compliant the Ethereum YAML test format. /// Serde serialization is compliant the Ethereum YAML test format.
@ -161,8 +154,9 @@ impl<'de> Deserialize<'de> for AggregateSignature {
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let bytes = deserializer.deserialize_str(HexVisitor)?; let bytes = deserializer.deserialize_str(HexVisitor)?;
let agg_sig = decode(&bytes[..]) let agg_sig = AggregateSignature::from_ssz_bytes(&bytes)
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?; .map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
Ok(agg_sig) Ok(agg_sig)
} }
} }
@ -174,7 +168,7 @@ cached_tree_hash_ssz_encoding_as_vector!(AggregateSignature, 96);
mod tests { mod tests {
use super::super::{Keypair, Signature}; use super::super::{Keypair, Signature};
use super::*; use super::*;
use ssz::{decode, ssz_encode}; use ssz::Encodable;
#[test] #[test]
pub fn test_ssz_round_trip() { pub fn test_ssz_round_trip() {
@ -183,8 +177,8 @@ mod tests {
let mut original = AggregateSignature::new(); let mut original = AggregateSignature::new();
original.add(&Signature::new(&[42, 42], 0, &keypair.sk)); original.add(&Signature::new(&[42, 42], 0, &keypair.sk));
let bytes = ssz_encode(&original); let bytes = original.as_ssz_bytes();
let decoded = decode::<AggregateSignature>(&bytes).unwrap(); let decoded = AggregateSignature::from_ssz_bytes(&bytes).unwrap();
assert_eq!(original, decoded); assert_eq!(original, decoded);
} }

View File

@ -59,25 +59,11 @@ impl FakeAggregateSignature {
} }
} }
impl Encodable for FakeAggregateSignature { impl_ssz!(
fn ssz_append(&self, s: &mut SszStream) { FakeAggregateSignature,
s.append_encoded_raw(&self.bytes); BLS_AGG_SIG_BYTE_SIZE,
} "FakeAggregateSignature"
} );
impl Decodable for FakeAggregateSignature {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
if bytes.len() - i < BLS_AGG_SIG_BYTE_SIZE {
return Err(DecodeError::TooShort);
}
Ok((
FakeAggregateSignature {
bytes: bytes[i..(i + BLS_AGG_SIG_BYTE_SIZE)].to_vec(),
},
i + BLS_AGG_SIG_BYTE_SIZE,
))
}
}
impl Serialize for FakeAggregateSignature { impl Serialize for FakeAggregateSignature {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>

View File

@ -55,25 +55,7 @@ impl FakeSignature {
} }
} }
impl Encodable for FakeSignature { impl_ssz!(FakeSignature, BLS_SIG_BYTE_SIZE, "FakeSignature");
fn ssz_append(&self, s: &mut SszStream) {
s.append_encoded_raw(&self.bytes);
}
}
impl Decodable for FakeSignature {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
if bytes.len() - i < BLS_SIG_BYTE_SIZE {
return Err(DecodeError::TooShort);
}
Ok((
FakeSignature {
bytes: bytes[i..(i + BLS_SIG_BYTE_SIZE)].to_vec(),
},
i + BLS_SIG_BYTE_SIZE,
))
}
}
tree_hash_ssz_encoding_as_vector!(FakeSignature); tree_hash_ssz_encoding_as_vector!(FakeSignature);
cached_tree_hash_ssz_encoding_as_vector!(FakeSignature, 96); cached_tree_hash_ssz_encoding_as_vector!(FakeSignature, 96);

View File

@ -1,6 +1,8 @@
extern crate bls_aggregates; extern crate bls_aggregates;
extern crate ssz; extern crate ssz;
#[macro_use]
mod macros;
mod aggregate_public_key; mod aggregate_public_key;
mod keypair; mod keypair;
mod public_key; mod public_key;

View File

@ -0,0 +1,38 @@
macro_rules! impl_ssz {
($type: ident, $byte_size: expr, $item_str: expr) => {
impl ssz::Encodable for $type {
fn is_ssz_fixed_len() -> bool {
true
}
fn ssz_fixed_len() -> usize {
$byte_size
}
fn ssz_append(&self, buf: &mut Vec<u8>) {
buf.append(&mut self.as_bytes())
}
}
impl ssz::Decodable for $type {
fn is_ssz_fixed_len() -> bool {
true
}
fn ssz_fixed_len() -> usize {
$byte_size
}
fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
let len = bytes.len();
let expected = <Self as ssz::Decodable>::ssz_fixed_len();
if len != expected {
Err(ssz::DecodeError::InvalidByteLength { len, expected })
} else {
$type::from_bytes(bytes)
}
}
}
};
}

View File

@ -4,7 +4,7 @@ use cached_tree_hash::cached_tree_hash_ssz_encoding_as_vector;
use serde::de::{Deserialize, Deserializer}; use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer}; use serde::ser::{Serialize, Serializer};
use serde_hex::{encode as hex_encode, HexVisitor}; use serde_hex::{encode as hex_encode, HexVisitor};
use ssz::{decode, ssz_encode, Decodable, DecodeError, Encodable, SszStream}; use ssz::{ssz_encode, Decodable, DecodeError};
use std::default; use std::default;
use std::fmt; use std::fmt;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
@ -27,9 +27,19 @@ impl PublicKey {
&self.0 &self.0
} }
/// Returns the underlying point as compressed bytes.
///
/// Identical to `self.as_uncompressed_bytes()`.
fn as_bytes(&self) -> Vec<u8> {
self.as_raw().as_bytes()
}
/// Converts compressed bytes to PublicKey /// Converts compressed bytes to PublicKey
pub fn from_bytes(bytes: &[u8]) -> Result<Self, DecodeError> { pub fn from_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
let pubkey = RawPublicKey::from_bytes(&bytes).map_err(|_| DecodeError::Invalid)?; let pubkey = RawPublicKey::from_bytes(&bytes).map_err(|_| {
DecodeError::BytesInvalid(format!("Invalid PublicKey bytes: {:?}", bytes).to_string())
})?;
Ok(PublicKey(pubkey)) Ok(PublicKey(pubkey))
} }
@ -40,8 +50,9 @@ impl PublicKey {
/// Converts (x, y) bytes to PublicKey /// Converts (x, y) bytes to PublicKey
pub fn from_uncompressed_bytes(bytes: &[u8]) -> Result<Self, DecodeError> { pub fn from_uncompressed_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
let pubkey = let pubkey = RawPublicKey::from_uncompressed_bytes(&bytes).map_err(|_| {
RawPublicKey::from_uncompressed_bytes(&bytes).map_err(|_| DecodeError::Invalid)?; DecodeError::BytesInvalid("Invalid PublicKey uncompressed bytes.".to_string())
})?;
Ok(PublicKey(pubkey)) Ok(PublicKey(pubkey))
} }
@ -68,22 +79,7 @@ impl default::Default for PublicKey {
} }
} }
impl Encodable for PublicKey { impl_ssz!(PublicKey, BLS_PUBLIC_KEY_BYTE_SIZE, "PublicKey");
fn ssz_append(&self, s: &mut SszStream) {
s.append_encoded_raw(&self.0.as_bytes());
}
}
impl Decodable for PublicKey {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
if bytes.len() - i < BLS_PUBLIC_KEY_BYTE_SIZE {
return Err(DecodeError::TooShort);
}
let raw_sig = RawPublicKey::from_bytes(&bytes[i..(i + BLS_PUBLIC_KEY_BYTE_SIZE)])
.map_err(|_| DecodeError::TooShort)?;
Ok((PublicKey(raw_sig), i + BLS_PUBLIC_KEY_BYTE_SIZE))
}
}
impl Serialize for PublicKey { impl Serialize for PublicKey {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@ -100,7 +96,7 @@ impl<'de> Deserialize<'de> for PublicKey {
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let bytes = deserializer.deserialize_str(HexVisitor)?; let bytes = deserializer.deserialize_str(HexVisitor)?;
let pubkey = decode(&bytes[..]) let pubkey = Self::from_ssz_bytes(&bytes[..])
.map_err(|e| serde::de::Error::custom(format!("invalid pubkey ({:?})", e)))?; .map_err(|e| serde::de::Error::custom(format!("invalid pubkey ({:?})", e)))?;
Ok(pubkey) Ok(pubkey)
} }
@ -139,7 +135,7 @@ mod tests {
let original = PublicKey::from_secret_key(&sk); let original = PublicKey::from_secret_key(&sk);
let bytes = ssz_encode(&original); let bytes = ssz_encode(&original);
let (decoded, _) = PublicKey::ssz_decode(&bytes, 0).unwrap(); let decoded = PublicKey::from_ssz_bytes(&bytes).unwrap();
assert_eq!(original, decoded); assert_eq!(original, decoded);
} }

View File

@ -1,10 +1,10 @@
use super::BLS_SECRET_KEY_BYTE_SIZE; use super::BLS_SECRET_KEY_BYTE_SIZE;
use bls_aggregates::{DecodeError as BlsDecodeError, SecretKey as RawSecretKey}; use bls_aggregates::SecretKey as RawSecretKey;
use hex::encode as hex_encode; use hex::encode as hex_encode;
use serde::de::{Deserialize, Deserializer}; use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer}; use serde::ser::{Serialize, Serializer};
use serde_hex::HexVisitor; use serde_hex::HexVisitor;
use ssz::{decode, ssz_encode, Decodable, DecodeError, Encodable, SszStream}; use ssz::{ssz_encode, Decodable, DecodeError};
use tree_hash::tree_hash_ssz_encoding_as_vector; use tree_hash::tree_hash_ssz_encoding_as_vector;
/// A single BLS signature. /// A single BLS signature.
@ -19,11 +19,21 @@ impl SecretKey {
SecretKey(RawSecretKey::random()) SecretKey(RawSecretKey::random())
} }
/// Returns the underlying point as compressed bytes.
fn as_bytes(&self) -> Vec<u8> {
self.as_raw().as_bytes()
}
/// Instantiate a SecretKey from existing bytes. /// Instantiate a SecretKey from existing bytes.
/// ///
/// Note: this is _not_ SSZ decoding. /// Note: this is _not_ SSZ decoding.
pub fn from_bytes(bytes: &[u8]) -> Result<SecretKey, BlsDecodeError> { pub fn from_bytes(bytes: &[u8]) -> Result<SecretKey, DecodeError> {
Ok(SecretKey(RawSecretKey::from_bytes(bytes)?)) Ok(SecretKey(RawSecretKey::from_bytes(bytes).map_err(|e| {
DecodeError::BytesInvalid(format!(
"Invalid SecretKey bytes: {:?} Error: {:?}",
bytes, e
))
})?))
} }
/// Returns the underlying secret key. /// Returns the underlying secret key.
@ -32,22 +42,7 @@ impl SecretKey {
} }
} }
impl Encodable for SecretKey { impl_ssz!(SecretKey, BLS_SECRET_KEY_BYTE_SIZE, "SecretKey");
fn ssz_append(&self, s: &mut SszStream) {
s.append_encoded_raw(&self.0.as_bytes());
}
}
impl Decodable for SecretKey {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
if bytes.len() - i < BLS_SECRET_KEY_BYTE_SIZE {
return Err(DecodeError::TooShort);
}
let raw_sig = RawSecretKey::from_bytes(&bytes[i..(i + BLS_SECRET_KEY_BYTE_SIZE)])
.map_err(|_| DecodeError::TooShort)?;
Ok((SecretKey(raw_sig), i + BLS_SECRET_KEY_BYTE_SIZE))
}
}
impl Serialize for SecretKey { impl Serialize for SecretKey {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@ -64,7 +59,7 @@ impl<'de> Deserialize<'de> for SecretKey {
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let bytes = deserializer.deserialize_str(HexVisitor)?; let bytes = deserializer.deserialize_str(HexVisitor)?;
let secret_key = decode::<SecretKey>(&bytes[..]) let secret_key = SecretKey::from_ssz_bytes(&bytes[..])
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?; .map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
Ok(secret_key) Ok(secret_key)
} }
@ -84,7 +79,7 @@ mod tests {
.unwrap(); .unwrap();
let bytes = ssz_encode(&original); let bytes = ssz_encode(&original);
let (decoded, _) = SecretKey::ssz_decode(&bytes, 0).unwrap(); let decoded = SecretKey::from_ssz_bytes(&bytes).unwrap();
assert_eq!(original, decoded); assert_eq!(original, decoded);
} }

View File

@ -5,7 +5,7 @@ use hex::encode as hex_encode;
use serde::de::{Deserialize, Deserializer}; use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer}; use serde::ser::{Serialize, Serializer};
use serde_hex::HexVisitor; use serde_hex::HexVisitor;
use ssz::{decode, ssz_encode, Decodable, DecodeError, Encodable, SszStream}; use ssz::{ssz_encode, Decodable, DecodeError};
use tree_hash::tree_hash_ssz_encoding_as_vector; use tree_hash::tree_hash_ssz_encoding_as_vector;
/// A single BLS signature. /// A single BLS signature.
@ -83,8 +83,11 @@ impl Signature {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, DecodeError> { pub fn from_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
for byte in bytes { for byte in bytes {
if *byte != 0 { if *byte != 0 {
let raw_signature = let raw_signature = RawSignature::from_bytes(&bytes).map_err(|_| {
RawSignature::from_bytes(&bytes).map_err(|_| DecodeError::Invalid)?; DecodeError::BytesInvalid(
format!("Invalid Signature bytes: {:?}", bytes).to_string(),
)
})?;
return Ok(Signature { return Ok(Signature {
signature: raw_signature, signature: raw_signature,
is_empty: false, is_empty: false,
@ -100,21 +103,7 @@ impl Signature {
} }
} }
impl Encodable for Signature { impl_ssz!(Signature, BLS_SIG_BYTE_SIZE, "Signature");
fn ssz_append(&self, s: &mut SszStream) {
s.append_encoded_raw(&self.as_bytes());
}
}
impl Decodable for Signature {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
if bytes.len() - i < BLS_SIG_BYTE_SIZE {
return Err(DecodeError::TooShort);
}
let signature = Signature::from_bytes(&bytes[i..(i + BLS_SIG_BYTE_SIZE)])?;
Ok((signature, i + BLS_SIG_BYTE_SIZE))
}
}
tree_hash_ssz_encoding_as_vector!(Signature); tree_hash_ssz_encoding_as_vector!(Signature);
cached_tree_hash_ssz_encoding_as_vector!(Signature, 96); cached_tree_hash_ssz_encoding_as_vector!(Signature, 96);
@ -136,7 +125,7 @@ impl<'de> Deserialize<'de> for Signature {
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let bytes = deserializer.deserialize_str(HexVisitor)?; let bytes = deserializer.deserialize_str(HexVisitor)?;
let signature = decode(&bytes[..]) let signature = Self::from_ssz_bytes(&bytes[..])
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?; .map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
Ok(signature) Ok(signature)
} }
@ -156,7 +145,7 @@ mod tests {
let original = Signature::new(&[42, 42], 0, &keypair.sk); let original = Signature::new(&[42, 42], 0, &keypair.sk);
let bytes = ssz_encode(&original); let bytes = ssz_encode(&original);
let decoded = decode::<Signature>(&bytes).unwrap(); let decoded = Signature::from_ssz_bytes(&bytes).unwrap();
assert_eq!(original, decoded); assert_eq!(original, decoded);
} }