Allow downloading of large tests from EF github and fix issues with serde

This commit is contained in:
Kirk Baird
2019-03-25 18:02:37 +11:00
parent d936bc0e5d
commit d76baa1cc1
13 changed files with 166 additions and 738 deletions

View File

@@ -1,30 +1,39 @@
use super::{AggregatePublicKey, Signature};
use super::{AggregatePublicKey, Signature, BLS_AGG_SIG_BYTE_SIZE};
use bls_aggregates::{
AggregatePublicKey as RawAggregatePublicKey, AggregateSignature as RawAggregateSignature,
};
use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use serde_hex::{encode as hex_encode, PrefixedHexVisitor};
use ssz::{
decode_ssz_list, hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash,
};
use ssz::{decode_ssz_list, hash, Decodable, DecodeError, Encodable, SszStream, TreeHash};
/// A BLS aggregate signature.
///
/// This struct is a wrapper upon a base type and provides helper functions (e.g., SSZ
/// serialization).
#[derive(Debug, PartialEq, Clone, Default, Eq)]
pub struct AggregateSignature(RawAggregateSignature);
pub struct AggregateSignature {
aggregate_signature: RawAggregateSignature,
is_empty: bool,
}
impl AggregateSignature {
/// Instantiate a new AggregateSignature.
///
/// is_empty is false
/// AggregateSiganture is point at infinity
pub fn new() -> Self {
AggregateSignature(RawAggregateSignature::new())
Self {
aggregate_signature: RawAggregateSignature::new(),
is_empty: false,
}
}
/// Add (aggregate) a signature to the `AggregateSignature`.
pub fn add(&mut self, signature: &Signature) {
self.0.add(signature.as_raw())
if !self.is_empty {
self.aggregate_signature.add(signature.as_raw())
}
}
/// Verify the `AggregateSignature` against an `AggregatePublicKey`.
@@ -37,7 +46,11 @@ impl AggregateSignature {
domain: u64,
aggregate_public_key: &AggregatePublicKey,
) -> bool {
self.0.verify(msg, domain, aggregate_public_key.as_raw())
if self.is_empty {
return false;
}
self.aggregate_signature
.verify(msg, domain, aggregate_public_key.as_raw())
}
/// Verify this AggregateSignature against multiple AggregatePublickeys with multiple Messages.
@@ -50,6 +63,9 @@ impl AggregateSignature {
domain: u64,
aggregate_public_keys: &[&AggregatePublicKey],
) -> bool {
if self.is_empty {
return false;
}
let aggregate_public_keys: Vec<&RawAggregatePublicKey> =
aggregate_public_keys.iter().map(|pk| pk.as_raw()).collect();
@@ -59,14 +75,53 @@ impl AggregateSignature {
msg.extend_from_slice(message);
}
self.0
self.aggregate_signature
.verify_multiple(&msg[..], domain, &aggregate_public_keys[..])
}
/// Return AggregateSiganture as bytes
pub fn as_bytes(&self) -> Vec<u8> {
if self.is_empty {
return vec![0; BLS_AGG_SIG_BYTE_SIZE];
}
self.aggregate_signature.as_bytes()
}
/// Convert bytes to AggregateSiganture
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)?;
return Ok(Self {
aggregate_signature: sig,
is_empty: false,
});
}
}
Ok(Self::empty_signature())
}
/// Returns if the AggregateSiganture `is_empty`
pub fn is_empty(&self) -> bool {
self.is_empty
}
/// Creates a new AggregateSignature
///
/// aggregate_signature set to the point infinity
/// is_empty set to true
pub fn empty_signature() -> Self {
Self {
aggregate_signature: RawAggregateSignature::new(),
is_empty: true,
}
}
}
impl Encodable for AggregateSignature {
fn ssz_append(&self, s: &mut SszStream) {
s.append_vec(&self.0.as_bytes());
s.append_vec(&self.as_bytes());
}
}
@@ -74,35 +129,43 @@ impl Decodable for AggregateSignature {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (sig_bytes, i) = decode_ssz_list(bytes, i)?;
let raw_sig =
RawAggregateSignature::from_bytes(&sig_bytes).map_err(|_| DecodeError::TooShort)?;
Ok((AggregateSignature(raw_sig), i))
RawAggregateSignature::from_bytes(&sig_bytes).map_err(|_| DecodeError::Invalid)?;
Ok((
Self {
aggregate_signature: raw_sig,
is_empty: false,
},
i,
))
}
}
impl Serialize for AggregateSignature {
/// Serde serialization is compliant the Ethereum YAML test format.
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&hex_encode(ssz_encode(self)))
serializer.serialize_str(&hex_encode(self.as_bytes()))
}
}
impl<'de> Deserialize<'de> for AggregateSignature {
/// Serde serialization is compliant the Ethereum YAML test format.
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let bytes = deserializer.deserialize_str(PrefixedHexVisitor)?;
let (obj, _) = <_>::ssz_decode(&bytes[..], 0)
let agg_sig = AggregateSignature::from_bytes(&bytes[..])
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
Ok(obj)
Ok(agg_sig)
}
}
impl TreeHash for AggregateSignature {
fn hash_tree_root(&self) -> Vec<u8> {
hash(&self.0.as_bytes())
hash(&self.as_bytes())
}
}

View File

@@ -17,6 +17,7 @@ pub use crate::secret_key::SecretKey;
pub use crate::signature::Signature;
pub const BLS_AGG_SIG_BYTE_SIZE: usize = 96;
pub const BLS_SIG_BYTE_SIZE: usize = 96;
use hashing::hash;
use ssz::ssz_encode;

View File

@@ -1,5 +1,5 @@
use super::serde_vistors::HexVisitor;
use super::{PublicKey, SecretKey};
use super::{PublicKey, SecretKey, BLS_SIG_BYTE_SIZE};
use bls_aggregates::Signature as RawSignature;
use hex::encode as hex_encode;
use serde::de::{Deserialize, Deserializer};
@@ -63,7 +63,7 @@ impl Signature {
/// Returns a new empty signature.
pub fn empty_signature() -> Self {
// Set RawSignature = infinity
let mut empty: Vec<u8> = vec![0; 96];
let mut empty: Vec<u8> = vec![0; BLS_SIG_BYTE_SIZE];
empty[0] += u8::pow(2, 6) + u8::pow(2, 7);
Signature {
signature: RawSignature::from_bytes(&empty).unwrap(),
@@ -121,6 +121,7 @@ impl TreeHash for Signature {
}
impl Serialize for Signature {
/// Serde serialization is compliant the Ethereum YAML test format.
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
@@ -130,14 +131,15 @@ impl Serialize for Signature {
}
impl<'de> Deserialize<'de> for Signature {
/// Serde serialization is compliant the Ethereum YAML test format.
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let bytes = deserializer.deserialize_str(HexVisitor)?;
let (pubkey, _) = <_>::ssz_decode(&bytes[..], 0)
let bytes: Vec<u8> = deserializer.deserialize_str(HexVisitor)?;
let signature = Signature::from_bytes(&bytes[..])
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
Ok(pubkey)
Ok(signature)
}
}
@@ -165,7 +167,7 @@ mod tests {
let sig_as_bytes: Vec<u8> = sig.as_raw().as_bytes();
assert_eq!(sig_as_bytes.len(), 96);
assert_eq!(sig_as_bytes.len(), BLS_SIG_BYTE_SIZE);
for (i, one_byte) in sig_as_bytes.iter().enumerate() {
if i == 0 {
assert_eq!(*one_byte, u8::pow(2, 6) + u8::pow(2, 7));