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())
}
}