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::{
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::ser::{Serialize, Serializer};
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;
/// A BLS aggregate signature.
@ -99,8 +99,12 @@ impl AggregateSignature {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
for byte in bytes {
if *byte != 0 {
let sig =
RawAggregateSignature::from_bytes(&bytes).map_err(|_| DecodeError::Invalid)?;
let sig = RawAggregateSignature::from_bytes(&bytes).map_err(|_| {
DecodeError::BytesInvalid(
format!("Invalid AggregateSignature bytes: {:?}", bytes).to_string(),
)
})?;
return Ok(Self {
aggregate_signature: sig,
is_empty: false,
@ -127,22 +131,11 @@ impl AggregateSignature {
}
}
impl Encodable for AggregateSignature {
fn ssz_append(&self, s: &mut SszStream) {
s.append_encoded_raw(&self.as_bytes());
}
}
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_ssz!(
AggregateSignature,
BLS_AGG_SIG_BYTE_SIZE,
"AggregateSignature"
);
impl Serialize for AggregateSignature {
/// Serde serialization is compliant the Ethereum YAML test format.
@ -161,8 +154,9 @@ impl<'de> Deserialize<'de> for AggregateSignature {
D: Deserializer<'de>,
{
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)))?;
Ok(agg_sig)
}
}
@ -174,7 +168,7 @@ cached_tree_hash_ssz_encoding_as_vector!(AggregateSignature, 96);
mod tests {
use super::super::{Keypair, Signature};
use super::*;
use ssz::{decode, ssz_encode};
use ssz::Encodable;
#[test]
pub fn test_ssz_round_trip() {
@ -183,8 +177,8 @@ mod tests {
let mut original = AggregateSignature::new();
original.add(&Signature::new(&[42, 42], 0, &keypair.sk));
let bytes = ssz_encode(&original);
let decoded = decode::<AggregateSignature>(&bytes).unwrap();
let bytes = original.as_ssz_bytes();
let decoded = AggregateSignature::from_ssz_bytes(&bytes).unwrap();
assert_eq!(original, decoded);
}

View File

@ -59,25 +59,11 @@ impl FakeAggregateSignature {
}
}
impl Encodable for FakeAggregateSignature {
fn ssz_append(&self, s: &mut SszStream) {
s.append_encoded_raw(&self.bytes);
}
}
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_ssz!(
FakeAggregateSignature,
BLS_AGG_SIG_BYTE_SIZE,
"FakeAggregateSignature"
);
impl Serialize for FakeAggregateSignature {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>

View File

@ -55,25 +55,7 @@ impl FakeSignature {
}
}
impl Encodable for 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,
))
}
}
impl_ssz!(FakeSignature, BLS_SIG_BYTE_SIZE, "FakeSignature");
tree_hash_ssz_encoding_as_vector!(FakeSignature);
cached_tree_hash_ssz_encoding_as_vector!(FakeSignature, 96);

View File

@ -1,6 +1,8 @@
extern crate bls_aggregates;
extern crate ssz;
#[macro_use]
mod macros;
mod aggregate_public_key;
mod keypair;
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::ser::{Serialize, Serializer};
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::fmt;
use std::hash::{Hash, Hasher};
@ -27,9 +27,19 @@ impl PublicKey {
&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
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))
}
@ -40,8 +50,9 @@ impl PublicKey {
/// Converts (x, y) bytes to PublicKey
pub fn from_uncompressed_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
let pubkey =
RawPublicKey::from_uncompressed_bytes(&bytes).map_err(|_| DecodeError::Invalid)?;
let pubkey = RawPublicKey::from_uncompressed_bytes(&bytes).map_err(|_| {
DecodeError::BytesInvalid("Invalid PublicKey uncompressed bytes.".to_string())
})?;
Ok(PublicKey(pubkey))
}
@ -68,22 +79,7 @@ impl default::Default for PublicKey {
}
}
impl Encodable for 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_ssz!(PublicKey, BLS_PUBLIC_KEY_BYTE_SIZE, "PublicKey");
impl Serialize for PublicKey {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@ -100,7 +96,7 @@ impl<'de> Deserialize<'de> for PublicKey {
D: Deserializer<'de>,
{
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)))?;
Ok(pubkey)
}
@ -139,7 +135,7 @@ mod tests {
let original = PublicKey::from_secret_key(&sk);
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);
}

View File

@ -1,10 +1,10 @@
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 serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
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;
/// A single BLS signature.
@ -19,11 +19,21 @@ impl SecretKey {
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.
///
/// Note: this is _not_ SSZ decoding.
pub fn from_bytes(bytes: &[u8]) -> Result<SecretKey, BlsDecodeError> {
Ok(SecretKey(RawSecretKey::from_bytes(bytes)?))
pub fn from_bytes(bytes: &[u8]) -> Result<SecretKey, DecodeError> {
Ok(SecretKey(RawSecretKey::from_bytes(bytes).map_err(|e| {
DecodeError::BytesInvalid(format!(
"Invalid SecretKey bytes: {:?} Error: {:?}",
bytes, e
))
})?))
}
/// Returns the underlying secret key.
@ -32,22 +42,7 @@ impl SecretKey {
}
}
impl Encodable for 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_ssz!(SecretKey, BLS_SECRET_KEY_BYTE_SIZE, "SecretKey");
impl Serialize for SecretKey {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@ -64,7 +59,7 @@ impl<'de> Deserialize<'de> for SecretKey {
D: Deserializer<'de>,
{
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)))?;
Ok(secret_key)
}
@ -84,7 +79,7 @@ mod tests {
.unwrap();
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);
}

View File

@ -5,7 +5,7 @@ use hex::encode as hex_encode;
use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
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;
/// A single BLS signature.
@ -83,8 +83,11 @@ impl Signature {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
for byte in bytes {
if *byte != 0 {
let raw_signature =
RawSignature::from_bytes(&bytes).map_err(|_| DecodeError::Invalid)?;
let raw_signature = RawSignature::from_bytes(&bytes).map_err(|_| {
DecodeError::BytesInvalid(
format!("Invalid Signature bytes: {:?}", bytes).to_string(),
)
})?;
return Ok(Signature {
signature: raw_signature,
is_empty: false,
@ -100,21 +103,7 @@ impl Signature {
}
}
impl Encodable for 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))
}
}
impl_ssz!(Signature, BLS_SIG_BYTE_SIZE, "Signature");
tree_hash_ssz_encoding_as_vector!(Signature);
cached_tree_hash_ssz_encoding_as_vector!(Signature, 96);
@ -136,7 +125,7 @@ impl<'de> Deserialize<'de> for Signature {
D: Deserializer<'de>,
{
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)))?;
Ok(signature)
}
@ -156,7 +145,7 @@ mod tests {
let original = Signature::new(&[42, 42], 0, &keypair.sk);
let bytes = ssz_encode(&original);
let decoded = decode::<Signature>(&bytes).unwrap();
let decoded = Signature::from_ssz_bytes(&bytes).unwrap();
assert_eq!(original, decoded);
}