From f046a326b89be130e1c67886bd0ce3445781a3f5 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 18 Dec 2018 17:04:54 +1100 Subject: [PATCH 01/16] Implement "newtype" wrappers for BLS structs --- beacon_chain/utils/bls/Cargo.toml | 1 + .../utils/bls/src/aggregate_signature.rs | 72 +++++++++++++++++ beacon_chain/utils/bls/src/lib.rs | 9 ++- beacon_chain/utils/bls/src/signature.rs | 81 +++++++++++++++++++ 4 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 beacon_chain/utils/bls/src/aggregate_signature.rs create mode 100644 beacon_chain/utils/bls/src/signature.rs diff --git a/beacon_chain/utils/bls/Cargo.toml b/beacon_chain/utils/bls/Cargo.toml index 1199efc15..81d467a46 100644 --- a/beacon_chain/utils/bls/Cargo.toml +++ b/beacon_chain/utils/bls/Cargo.toml @@ -6,3 +6,4 @@ authors = ["Paul Hauner "] [dependencies] bls-aggregates = { git = "https://github.com/sigp/signature-schemes" } hashing = { path = "../hashing" } +ssz = { path = "../ssz" } diff --git a/beacon_chain/utils/bls/src/aggregate_signature.rs b/beacon_chain/utils/bls/src/aggregate_signature.rs new file mode 100644 index 000000000..0970ce56f --- /dev/null +++ b/beacon_chain/utils/bls/src/aggregate_signature.rs @@ -0,0 +1,72 @@ +use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; +use super::{AggregatePublicKey, Signature}; +use bls_aggregates::AggregateSignature as RawAggregateSignature; + +/// 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)] +pub struct AggregateSignature(RawAggregateSignature); + +impl AggregateSignature { + /// Instantiate a new AggregateSignature. + pub fn new() -> Self { + AggregateSignature(RawAggregateSignature::new()) + } + + /// Add (aggregate) a signature to the `AggregateSignature`. + pub fn add(&mut self, signature: &Signature) { + self.0.add(signature.as_raw()) + } + + /// Verify the `AggregateSignature` against an `AggregatePublicKey`. + /// + /// Only returns `true` if the set of keys in the `AggregatePublicKey` match the set of keys + /// that signed the `AggregateSignature`. + pub fn verify(&mut self, msg: &[u8], avk: &AggregatePublicKey) -> bool { + self.0.verify(msg, avk) + } +} + +impl Default for AggregateSignature { + /// A "default" signature is a signature across an empty message by a secret key of 48 zeros. + fn default() -> Self { + AggregateSignature::new() + } +} + +impl Encodable for AggregateSignature { + fn ssz_append(&self, s: &mut SszStream) { + s.append_vec(&self.0.as_bytes()); + } +} + +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)) + } +} + +#[cfg(test)] +mod tests { + use super::super::ssz::ssz_encode; + use super::super::{Keypair, Signature}; + use super::*; + + #[test] + pub fn test_ssz_round_trip() { + let keypair = Keypair::random(); + + let mut original = AggregateSignature::new(); + original.add(&Signature::new(&[42, 42], &keypair.sk)); + + let bytes = ssz_encode(&original); + let (decoded, _) = AggregateSignature::ssz_decode(&bytes, 0).unwrap(); + + assert_eq!(original, decoded); + } +} diff --git a/beacon_chain/utils/bls/src/lib.rs b/beacon_chain/utils/bls/src/lib.rs index dcd2a9d29..15abca098 100644 --- a/beacon_chain/utils/bls/src/lib.rs +++ b/beacon_chain/utils/bls/src/lib.rs @@ -1,12 +1,17 @@ extern crate bls_aggregates; extern crate hashing; +extern crate ssz; + +mod aggregate_signature; +mod signature; + +pub use aggregate_signature::AggregateSignature; +pub use signature::Signature; pub use self::bls_aggregates::AggregatePublicKey; -pub use self::bls_aggregates::AggregateSignature; pub use self::bls_aggregates::Keypair; pub use self::bls_aggregates::PublicKey; pub use self::bls_aggregates::SecretKey; -pub use self::bls_aggregates::Signature; pub const BLS_AGG_SIG_BYTE_SIZE: usize = 97; diff --git a/beacon_chain/utils/bls/src/signature.rs b/beacon_chain/utils/bls/src/signature.rs new file mode 100644 index 000000000..bfeaca45e --- /dev/null +++ b/beacon_chain/utils/bls/src/signature.rs @@ -0,0 +1,81 @@ +use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; +use bls_aggregates::{PublicKey, SecretKey, Signature as RawSignature}; + +/// 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 Signature(RawSignature); + +impl Signature { + /// Instantiate a new Signature from a message and a SecretKey. + pub fn new(msg: &[u8], sk: &SecretKey) -> Self { + Signature(RawSignature::new(msg, sk)) + } + + /// Instantiate a new Signature from a message and a SecretKey, where the message has already + /// been hashed. + pub fn new_hashed(msg_hashed: &[u8], sk: &SecretKey) -> Self { + Signature(RawSignature::new_hashed(msg_hashed, sk)) + } + + /// Verify the Signature against a PublicKey. + pub fn verify(&self, msg: &[u8], pk: &PublicKey) -> bool { + self.0.verify(msg, pk) + } + + /// 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) + } + + /// Returns the underlying signature. + pub fn as_raw(&self) -> &RawSignature { + &self.0 + } +} + +impl Default for Signature { + /// A "default" signature is a signature across an empty message by a secret key of 48 zeros. + fn default() -> Self { + let sk = match SecretKey::from_bytes(&[0; 48]) { + Ok(key) => key, + _ => unreachable!(), // Key is static, should not fail. + }; + Signature(RawSignature::new(&[], &sk)) + } +} + +impl Encodable for Signature { + fn ssz_append(&self, s: &mut SszStream) { + s.append_vec(&self.0.as_bytes()); + } +} + +impl Decodable for Signature { + fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { + let (sig_bytes, i) = decode_ssz_list(bytes, i)?; + let raw_sig = RawSignature::from_bytes(&sig_bytes).map_err(|_| DecodeError::TooShort)?; + Ok((Signature(raw_sig), i)) + } +} + +#[cfg(test)] +mod tests { + use super::super::ssz::ssz_encode; + use super::super::Keypair; + use super::*; + + #[test] + pub fn test_ssz_round_trip() { + let keypair = Keypair::random(); + + let original = Signature::new(&[42, 42], &keypair.sk); + + let bytes = ssz_encode(&original); + let (decoded, _) = Signature::ssz_decode(&bytes, 0).unwrap(); + + assert_eq!(original, decoded); + } +} From 92ed2ffc22b4ca750ebd7a41f9bb74f969faf515 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 18 Dec 2018 17:30:34 +1100 Subject: [PATCH 02/16] Update Attestation to use new bls structs --- beacon_chain/types/src/attestation.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/beacon_chain/types/src/attestation.rs b/beacon_chain/types/src/attestation.rs index 2c2015cd3..40ee2173c 100644 --- a/beacon_chain/types/src/attestation.rs +++ b/beacon_chain/types/src/attestation.rs @@ -1,6 +1,6 @@ use super::attestation_data::SSZ_ATTESTION_DATA_LENGTH; use super::bls::{AggregateSignature, BLS_AGG_SIG_BYTE_SIZE}; -use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream, LENGTH_BYTES}; +use super::ssz::{Decodable, DecodeError, Encodable, SszStream, LENGTH_BYTES}; use super::{AttestationData, Bitfield}; pub const MIN_SSZ_ATTESTION_RECORD_LENGTH: usize = { @@ -23,7 +23,7 @@ impl Encodable for Attestation { s.append(&self.data); s.append(&self.participation_bitfield); s.append(&self.custody_bitfield); - s.append_vec(&self.aggregate_sig.as_bytes()); + s.append(&self.aggregate_sig); } } @@ -32,9 +32,7 @@ impl Decodable for Attestation { let (data, i) = AttestationData::ssz_decode(bytes, i)?; let (participation_bitfield, i) = Bitfield::ssz_decode(bytes, i)?; let (custody_bitfield, i) = Bitfield::ssz_decode(bytes, i)?; - let (agg_sig_bytes, i) = decode_ssz_list(bytes, i)?; - let aggregate_sig = - AggregateSignature::from_bytes(&agg_sig_bytes).map_err(|_| DecodeError::TooShort)?; // also could be TooLong + let (aggregate_sig, i) = AggregateSignature::ssz_decode(bytes, i)?; let attestation_record = Self { data, From 7f00f167e3f1e2cd9bae6e8e6f53c5cb6ab6339b Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 18 Dec 2018 17:55:21 +1100 Subject: [PATCH 03/16] Fix error in agg sig newtype --- beacon_chain/utils/bls/src/aggregate_signature.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beacon_chain/utils/bls/src/aggregate_signature.rs b/beacon_chain/utils/bls/src/aggregate_signature.rs index 0970ce56f..5cc9c3c21 100644 --- a/beacon_chain/utils/bls/src/aggregate_signature.rs +++ b/beacon_chain/utils/bls/src/aggregate_signature.rs @@ -24,7 +24,7 @@ impl AggregateSignature { /// /// Only returns `true` if the set of keys in the `AggregatePublicKey` match the set of keys /// that signed the `AggregateSignature`. - pub fn verify(&mut self, msg: &[u8], avk: &AggregatePublicKey) -> bool { + pub fn verify(&self, msg: &[u8], avk: &AggregatePublicKey) -> bool { self.0.verify(msg, avk) } } From be4c6701ac39f8f57d05471bb71ea4017538827b Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 18 Dec 2018 18:00:11 +1100 Subject: [PATCH 04/16] Remove SSZ helpers --- Cargo.toml | 1 - .../attestation_validation/Cargo.toml | 1 - .../attestation_validation/src/lib.rs | 1 - beacon_chain/chain/Cargo.toml | 1 - beacon_chain/chain/src/lib.rs | 1 - beacon_chain/utils/ssz_helpers/Cargo.toml | 10 - .../src/attestation_ssz_splitter.rs | 162 ------ beacon_chain/utils/ssz_helpers/src/lib.rs | 7 - .../utils/ssz_helpers/src/ssz_beacon_block.rs | 480 ------------------ lighthouse/db/Cargo.toml | 1 - 10 files changed, 665 deletions(-) delete mode 100644 beacon_chain/utils/ssz_helpers/Cargo.toml delete mode 100644 beacon_chain/utils/ssz_helpers/src/attestation_ssz_splitter.rs delete mode 100644 beacon_chain/utils/ssz_helpers/src/lib.rs delete mode 100644 beacon_chain/utils/ssz_helpers/src/ssz_beacon_block.rs diff --git a/Cargo.toml b/Cargo.toml index 069e697a4..835d37edc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,6 @@ members = [ "beacon_chain/utils/honey-badger-split", "beacon_chain/utils/slot-clock", "beacon_chain/utils/ssz", - "beacon_chain/utils/ssz_helpers", "beacon_chain/utils/vec_shuffle", "beacon_chain/validator_change", "beacon_chain/validator_induction", diff --git a/beacon_chain/attestation_validation/Cargo.toml b/beacon_chain/attestation_validation/Cargo.toml index 4606d03ec..b4219a5f8 100644 --- a/beacon_chain/attestation_validation/Cargo.toml +++ b/beacon_chain/attestation_validation/Cargo.toml @@ -8,5 +8,4 @@ bls = { path = "../utils/bls" } db = { path = "../../lighthouse/db" } hashing = { path = "../utils/hashing" } ssz = { path = "../utils/ssz" } -ssz_helpers = { path = "../utils/ssz_helpers" } types = { path = "../types" } diff --git a/beacon_chain/attestation_validation/src/lib.rs b/beacon_chain/attestation_validation/src/lib.rs index 8544be862..a5b35f696 100644 --- a/beacon_chain/attestation_validation/src/lib.rs +++ b/beacon_chain/attestation_validation/src/lib.rs @@ -2,7 +2,6 @@ extern crate bls; extern crate db; extern crate hashing; extern crate ssz; -extern crate ssz_helpers; extern crate types; #[macro_use] diff --git a/beacon_chain/chain/Cargo.toml b/beacon_chain/chain/Cargo.toml index 479804f45..aa0f48c62 100644 --- a/beacon_chain/chain/Cargo.toml +++ b/beacon_chain/chain/Cargo.toml @@ -8,7 +8,6 @@ bls = { path = "../utils/bls" } db = { path = "../../lighthouse/db" } naive_fork_choice = { path = "../naive_fork_choice" } ssz = { path = "../utils/ssz" } -ssz_helpers = { path = "../utils/ssz_helpers" } state-transition = { path = "../state-transition" } types = { path = "../types" } validator_induction = { path = "../validator_induction" } diff --git a/beacon_chain/chain/src/lib.rs b/beacon_chain/chain/src/lib.rs index 0837f3baf..92a2dd8f8 100644 --- a/beacon_chain/chain/src/lib.rs +++ b/beacon_chain/chain/src/lib.rs @@ -1,7 +1,6 @@ extern crate db; extern crate naive_fork_choice; extern crate ssz; -extern crate ssz_helpers; extern crate state_transition; extern crate types; extern crate validator_induction; diff --git a/beacon_chain/utils/ssz_helpers/Cargo.toml b/beacon_chain/utils/ssz_helpers/Cargo.toml deleted file mode 100644 index a8189ce60..000000000 --- a/beacon_chain/utils/ssz_helpers/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "ssz_helpers" -version = "0.1.0" -authors = ["Paul Hauner "] - -[dependencies] -bls = { path = "../bls" } -hashing = { path = "../hashing" } -types = { path = "../../types" } -ssz = { path = "../ssz" } diff --git a/beacon_chain/utils/ssz_helpers/src/attestation_ssz_splitter.rs b/beacon_chain/utils/ssz_helpers/src/attestation_ssz_splitter.rs deleted file mode 100644 index a216e0ec2..000000000 --- a/beacon_chain/utils/ssz_helpers/src/attestation_ssz_splitter.rs +++ /dev/null @@ -1,162 +0,0 @@ -use super::bls::BLS_AGG_SIG_BYTE_SIZE; -use super::ssz::decode::decode_length; -use super::ssz::LENGTH_BYTES; -use super::types::attestation::MIN_SSZ_ATTESTION_RECORD_LENGTH; -use super::types::attestation_data::SSZ_ATTESTION_DATA_LENGTH; - -#[derive(Debug, PartialEq)] -pub enum AttestationSplitError { - TooShort, -} - -/// Given some ssz slice, find the bounds of each serialized Attestation and return a vec of -/// slices point to each. -pub fn split_all_attestations<'a>( - full_ssz: &'a [u8], - index: usize, -) -> Result, AttestationSplitError> { - let mut v = vec![]; - let mut index = index; - while index < full_ssz.len() - 1 { - let (slice, i) = split_one_attestation(full_ssz, index)?; - v.push(slice); - index = i; - } - Ok(v) -} - -/// Given some ssz slice, find the bounds of one serialized Attestation -/// and return a slice pointing to that. -pub fn split_one_attestation( - full_ssz: &[u8], - index: usize, -) -> Result<(&[u8], usize), AttestationSplitError> { - let length = determine_ssz_attestation_len(full_ssz, index)?; - let end = index + length; - - // The check to ensure that the slice exists _should_ be redundant as it is already checked in - // `determine_ssz_attestation_len`, however it is checked here again for additional safety - // against panics. - match full_ssz.get(index..end) { - None => Err(AttestationSplitError::TooShort), - Some(slice) => Ok((slice, end)), - } -} - -/// Given some SSZ, assume that a serialized `Attestation` begins at the `index` position and -/// attempt to find the length (in bytes) of that serialized `Attestation`. -/// -/// This function does not perform validation on the `Attestation`. It is very likely that -/// given some sufficiently long non-`Attestation` bytes it will not raise an error. -fn determine_ssz_attestation_len( - full_ssz: &[u8], - index: usize, -) -> Result { - if full_ssz.len() < MIN_SSZ_ATTESTION_RECORD_LENGTH { - return Err(AttestationSplitError::TooShort); - } - - let data_struct_end = index + SSZ_ATTESTION_DATA_LENGTH; - - // Determine the end of the first bitfield. - let participation_bitfield_len = decode_length(full_ssz, data_struct_end, LENGTH_BYTES) - .map_err(|_| AttestationSplitError::TooShort)?; - let participation_bitfield_end = data_struct_end + LENGTH_BYTES + participation_bitfield_len; - - // Determine the end of the second bitfield. - let custody_bitfield_len = decode_length(full_ssz, participation_bitfield_end, LENGTH_BYTES) - .map_err(|_| AttestationSplitError::TooShort)?; - let custody_bitfield_end = participation_bitfield_end + LENGTH_BYTES + custody_bitfield_len; - - // Determine the very end of the Attestation. - let agg_sig_end = custody_bitfield_end + LENGTH_BYTES + BLS_AGG_SIG_BYTE_SIZE; - - if agg_sig_end > full_ssz.len() { - Err(AttestationSplitError::TooShort) - } else { - Ok(agg_sig_end - index) - } -} - -#[cfg(test)] -mod tests { - use super::super::bls::AggregateSignature; - use super::super::ssz::{Decodable, SszStream}; - use super::super::types::{Attestation, AttestationData, Bitfield, Hash256}; - use super::*; - - fn get_two_records() -> Vec { - let a = Attestation { - data: AttestationData { - slot: 7, - shard: 9, - beacon_block_hash: Hash256::from("a_beacon".as_bytes()), - epoch_boundary_hash: Hash256::from("a_epoch".as_bytes()), - shard_block_hash: Hash256::from("a_shard".as_bytes()), - latest_crosslink_hash: Hash256::from("a_xlink".as_bytes()), - justified_slot: 19, - justified_block_hash: Hash256::from("a_justified".as_bytes()), - }, - participation_bitfield: Bitfield::from_bytes(&vec![17; 42][..]), - custody_bitfield: Bitfield::from_bytes(&vec![255; 12][..]), - aggregate_sig: AggregateSignature::new(), - }; - let b = Attestation { - data: AttestationData { - slot: 9, - shard: 7, - beacon_block_hash: Hash256::from("b_beacon".as_bytes()), - epoch_boundary_hash: Hash256::from("b_epoch".as_bytes()), - shard_block_hash: Hash256::from("b_shard".as_bytes()), - latest_crosslink_hash: Hash256::from("b_xlink".as_bytes()), - justified_slot: 15, - justified_block_hash: Hash256::from("b_justified".as_bytes()), - }, - participation_bitfield: Bitfield::from_bytes(&vec![1; 42][..]), - custody_bitfield: Bitfield::from_bytes(&vec![11; 3][..]), - aggregate_sig: AggregateSignature::new(), - }; - vec![a, b] - } - - #[test] - fn test_attestation_ssz_split() { - let ars = get_two_records(); - let a = ars[0].clone(); - let b = ars[1].clone(); - - /* - * Test split one - */ - let mut ssz_stream = SszStream::new(); - ssz_stream.append(&a); - let ssz = ssz_stream.drain(); - let (a_ssz, i) = split_one_attestation(&ssz, 0).unwrap(); - assert_eq!(i, ssz.len()); - let (decoded_a, _) = Attestation::ssz_decode(a_ssz, 0).unwrap(); - assert_eq!(a, decoded_a); - - /* - * Test split two - */ - let mut ssz_stream = SszStream::new(); - ssz_stream.append(&a); - ssz_stream.append(&b); - let ssz = ssz_stream.drain(); - let ssz_vec = split_all_attestations(&ssz, 0).unwrap(); - let (decoded_a, _) = Attestation::ssz_decode(ssz_vec[0], 0).unwrap(); - let (decoded_b, _) = Attestation::ssz_decode(ssz_vec[1], 0).unwrap(); - assert_eq!(a, decoded_a); - assert_eq!(b, decoded_b); - - /* - * Test split two with shortened ssz - */ - let mut ssz_stream = SszStream::new(); - ssz_stream.append(&a); - ssz_stream.append(&b); - let ssz = ssz_stream.drain(); - let ssz = &ssz[0..ssz.len() - 1]; - assert!(split_all_attestations(&ssz, 0).is_err()); - } -} diff --git a/beacon_chain/utils/ssz_helpers/src/lib.rs b/beacon_chain/utils/ssz_helpers/src/lib.rs deleted file mode 100644 index 6ac4372e9..000000000 --- a/beacon_chain/utils/ssz_helpers/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -extern crate bls; -extern crate hashing; -extern crate ssz; -extern crate types; - -pub mod attestation_ssz_splitter; -pub mod ssz_beacon_block; diff --git a/beacon_chain/utils/ssz_helpers/src/ssz_beacon_block.rs b/beacon_chain/utils/ssz_helpers/src/ssz_beacon_block.rs deleted file mode 100644 index 5c8059541..000000000 --- a/beacon_chain/utils/ssz_helpers/src/ssz_beacon_block.rs +++ /dev/null @@ -1,480 +0,0 @@ -use super::hashing::canonical_hash; -use super::ssz::decode::{decode_length, Decodable}; -use super::types::beacon_block::{MAX_SSZ_BLOCK_LENGTH, MIN_SSZ_BLOCK_LENGTH}; - -#[derive(Debug, PartialEq)] -pub enum SszBeaconBlockError { - TooShort, - TooLong, -} - -/* - * Constants used for navigating the SSZ bytes. - */ -const LENGTH_PREFIX_BYTES: usize = 4; -const SLOT_BYTES: usize = 8; -const HASH_SIZE: usize = 32; -const RANDAO_REVEAL_BYTES: usize = HASH_SIZE; -const POW_CHAIN_REF_BYTES: usize = HASH_SIZE; -const ACTIVE_STATE_BYTES: usize = HASH_SIZE; -const CRYSTALLIZED_STATE_BYTES: usize = HASH_SIZE; - -/// Allows for reading of block values directly from serialized ssz bytes. -/// -/// The purpose of this struct is to provide the functionality to read block fields directly from -/// some serialized SSZ slice allowing us to read the block without fully -/// de-serializing it. -/// -/// This struct should be as "zero-copy" as possible. The `ssz` field is a reference to some slice -/// and each function reads from that slice. -/// -/// Use this to perform intial checks before we fully de-serialize a block. It should only really -/// be used to verify blocks that come in from the network, for internal operations we should use a -/// full `BeaconBlock`. -#[derive(Debug, PartialEq)] -pub struct SszBeaconBlock<'a> { - ssz: &'a [u8], - block_ssz_len: usize, - // Ancestors - ancestors_position: usize, - ancestors_len: usize, - // Attestations - attestations_position: usize, - attestations_len: usize, - // Specials - specials_position: usize, - specials_len: usize, -} - -impl<'a> SszBeaconBlock<'a> { - /// Create a new instance from a slice reference. - /// - /// This function will validate the length of the ssz string, however it will not validate the - /// contents. - /// - /// The returned `SszBeaconBlock` instance will contain a `len` field which can be used to determine - /// how many bytes were read from the slice. In the case of multiple, sequentually serialized - /// blocks `len` can be used to assume the location of the next serialized block. - pub fn from_slice(vec: &'a [u8]) -> Result { - let untrimmed_ssz = &vec[..]; - - /* - * Ensure the SSZ is long enough to be a block - */ - if vec.len() < MIN_SSZ_BLOCK_LENGTH { - return Err(SszBeaconBlockError::TooShort); - } - - /* - * Ensure the SSZ slice isn't longer than is possible for a block. - */ - if vec.len() > MAX_SSZ_BLOCK_LENGTH { - return Err(SszBeaconBlockError::TooLong); - } - - /* - * Determine how many bytes are used to store ancestor hashes. - */ - let ancestors_position = SLOT_BYTES + RANDAO_REVEAL_BYTES + POW_CHAIN_REF_BYTES; - let ancestors_len = decode_length(untrimmed_ssz, ancestors_position, LENGTH_PREFIX_BYTES) - .map_err(|_| SszBeaconBlockError::TooShort)?; - - /* - * Determine how many bytes are used to store attestation records. - */ - let attestations_position = ancestors_position + LENGTH_PREFIX_BYTES + ancestors_len + // end of ancestor bytes - ACTIVE_STATE_BYTES + - CRYSTALLIZED_STATE_BYTES; - let attestations_len = - decode_length(untrimmed_ssz, attestations_position, LENGTH_PREFIX_BYTES) - .map_err(|_| SszBeaconBlockError::TooShort)?; - - /* - * Determine how many bytes are used to store specials. - */ - let specials_position = attestations_position + LENGTH_PREFIX_BYTES + attestations_len; - let specials_len = decode_length(untrimmed_ssz, specials_position, LENGTH_PREFIX_BYTES) - .map_err(|_| SszBeaconBlockError::TooShort)?; - - /* - * Now that all variable field lengths are known (ancestors, attestations, specials) we can - * know the exact length of the block and reject it if the slice is too short. - */ - let block_ssz_len = MIN_SSZ_BLOCK_LENGTH + ancestors_len + attestations_len + specials_len; - if vec.len() < block_ssz_len { - return Err(SszBeaconBlockError::TooShort); - } - - Ok(Self { - ssz: &untrimmed_ssz[0..block_ssz_len], - block_ssz_len, - ancestors_position, - ancestors_len, - attestations_position, - attestations_len, - specials_position, - specials_len, - }) - } - - pub fn len(&self) -> usize { - self.ssz.len() - } - pub fn is_empty(&self) -> bool { - self.ssz.is_empty() - } - - /// Returns this block as ssz. - /// - /// Does not include any excess ssz bytes that were supplied to this struct. - pub fn block_ssz(&self) -> &'a [u8] { - &self.ssz[0..self.block_ssz_len] - } - - /// Return the canonical hash for this block. - pub fn block_hash(&self) -> Vec { - canonical_hash(&self.ssz) - } - - /// Return the bytes representing `ancestor_hashes[0]`. - /// - /// The first hash in `ancestor_hashes` is the parent of the block. - pub fn parent_hash(&self) -> Option<&[u8]> { - let ancestor_ssz = self.ancestor_hashes(); - let start = LENGTH_PREFIX_BYTES; - ancestor_ssz.get(start..start + HASH_SIZE) - } - - /// Return the `slot` field. - pub fn slot(&self) -> u64 { - /* - * An error should be unreachable from this decode - * because we checked the length of the array at - * the initalization of this struct. - * - * If you can make this function panic, please report - * it to paul@sigmaprime.io - */ - if let Ok((n, _)) = u64::ssz_decode(&self.ssz, 0) { - n - } else { - unreachable!(); - } - } - - /// Return the `randao_reveal` field. - pub fn randao_reveal(&self) -> &[u8] { - let start = SLOT_BYTES; - &self.ssz[start..start + RANDAO_REVEAL_BYTES] - } - - /// Return the `pow_chain_reference` field. - pub fn pow_chain_reference(&self) -> &[u8] { - let start = SLOT_BYTES + RANDAO_REVEAL_BYTES; - &self.ssz[start..start + POW_CHAIN_REF_BYTES] - } - - /// Return the serialized `ancestor_hashes` bytes, including length prefix. - pub fn ancestor_hashes(&self) -> &[u8] { - let start = self.ancestors_position; - &self.ssz[start..(start + self.ancestors_len + LENGTH_PREFIX_BYTES)] - } - - /// Return the `active_state_root` field. - pub fn act_state_root(&self) -> &[u8] { - let start = self.ancestors_position + LENGTH_PREFIX_BYTES + self.ancestors_len; - &self.ssz[start..(start + 32)] - } - - /// Return the `active_state_root` field. - pub fn cry_state_root(&self) -> &[u8] { - let start = - self.ancestors_position + LENGTH_PREFIX_BYTES + self.ancestors_len + ACTIVE_STATE_BYTES; - &self.ssz[start..(start + 32)] - } - - /// Return the serialized `attestations` bytes, including length prefix. - pub fn attestations(&self) -> &[u8] { - let start = self.attestations_position; - &self.ssz[start..(start + self.attestations_len + LENGTH_PREFIX_BYTES)] - } - - /// Return the serialized `attestations` bytes _without_ the length prefix. - pub fn attestations_without_length(&self) -> &[u8] { - let start = self.attestations_position + LENGTH_PREFIX_BYTES; - &self.ssz[start..start + self.attestations_len] - } - - /// Return the serialized `specials` bytes, including length prefix. - pub fn specials(&self) -> &[u8] { - let start = self.specials_position; - &self.ssz[start..(start + self.specials_len + LENGTH_PREFIX_BYTES)] - } -} - -#[cfg(test)] -mod tests { - use super::super::ssz::encode::encode_length; - use super::super::ssz::SszStream; - use super::super::types::Hash256; - use super::super::types::{Attestation, BeaconBlock, SpecialRecord}; - use super::*; - - fn get_block_ssz(b: &BeaconBlock) -> Vec { - let mut ssz_stream = SszStream::new(); - ssz_stream.append(b); - ssz_stream.drain() - } - - fn get_special_record_ssz(sr: &SpecialRecord) -> Vec { - let mut ssz_stream = SszStream::new(); - ssz_stream.append(sr); - ssz_stream.drain() - } - - fn get_attestation_record_ssz(ar: &Attestation) -> Vec { - let mut ssz_stream = SszStream::new(); - ssz_stream.append(ar); - ssz_stream.drain() - } - - #[test] - fn test_ssz_block_zero_attestation_records() { - let mut b = BeaconBlock::zero(); - b.attestations = vec![]; - let ssz = get_block_ssz(&b); - - assert!(SszBeaconBlock::from_slice(&ssz[..]).is_ok()); - } - - #[test] - fn test_ssz_block_single_attestation_record_one_byte_short() { - let mut b = BeaconBlock::zero(); - b.attestations = vec![Attestation::zero()]; - let ssz = get_block_ssz(&b); - - assert_eq!( - SszBeaconBlock::from_slice(&ssz[0..(ssz.len() - 1)]), - Err(SszBeaconBlockError::TooShort) - ); - } - - #[test] - fn test_ssz_block_single_attestation_record_one_byte_long() { - let mut b = BeaconBlock::zero(); - b.attestations = vec![Attestation::zero()]; - let mut ssz = get_block_ssz(&b); - let original_len = ssz.len(); - ssz.push(42); - - let ssz_block = SszBeaconBlock::from_slice(&ssz[..]).unwrap(); - - assert_eq!(ssz_block.len(), original_len); - } - - #[test] - fn test_ssz_block_single_attestation_record() { - let mut b = BeaconBlock::zero(); - b.attestations = vec![Attestation::zero()]; - let ssz = get_block_ssz(&b); - - assert!(SszBeaconBlock::from_slice(&ssz[..]).is_ok()); - } - - #[test] - fn test_ssz_block_block_hash() { - let mut block = BeaconBlock::zero(); - block.attestations.push(Attestation::zero()); - let serialized = get_block_ssz(&block); - let ssz_block = SszBeaconBlock::from_slice(&serialized).unwrap(); - let hash = ssz_block.block_hash(); - // Note: this hash was not generated by some external program, - // it was simply printed then copied into the code. This test - // will tell us if the hash changes, not that it matches some - // canonical reference. - let expected_hash = [ - 254, 192, 124, 164, 240, 137, 162, 126, 50, 255, 118, 88, 189, 151, 221, 4, 40, 121, - 198, 33, 248, 221, 104, 255, 46, 234, 146, 161, 202, 140, 109, 175, - ]; - assert_eq!(hash, expected_hash); - - /* - * Test if you give the SszBeaconBlock too many ssz bytes - */ - let mut too_long = serialized.clone(); - too_long.push(42); - let ssz_block = SszBeaconBlock::from_slice(&too_long).unwrap(); - let hash = ssz_block.block_hash(); - assert_eq!(hash, expected_hash); - } - - #[test] - fn test_ssz_block_slot() { - let mut block = BeaconBlock::zero(); - block.attestations.push(Attestation::zero()); - block.slot = 42; - - let serialized = get_block_ssz(&block); - let ssz_block = SszBeaconBlock::from_slice(&serialized).unwrap(); - - assert_eq!(ssz_block.slot(), 42); - } - - #[test] - fn test_ssz_block_randao_reveal() { - let mut block = BeaconBlock::zero(); - block.attestations.push(Attestation::zero()); - let reference_hash = Hash256::from([42_u8; 32]); - block.randao_reveal = reference_hash.clone(); - - let serialized = get_block_ssz(&block); - let ssz_block = SszBeaconBlock::from_slice(&serialized).unwrap(); - - assert_eq!(ssz_block.randao_reveal(), &reference_hash.to_vec()[..]); - } - - #[test] - fn test_ssz_block_ancestor_hashes() { - let mut block = BeaconBlock::zero(); - let h = Hash256::from(&vec![42_u8; 32][..]); - block.ancestor_hashes.push(h); - - let serialized = get_block_ssz(&block); - let ssz_block = SszBeaconBlock::from_slice(&serialized).unwrap(); - - let mut expected = encode_length(32, LENGTH_PREFIX_BYTES); - expected.append(&mut h.to_vec()); - - assert_eq!(ssz_block.ancestor_hashes(), &expected[..]); - } - - #[test] - fn test_ssz_block_parent_hash() { - let mut block = BeaconBlock::zero(); - block.ancestor_hashes = vec![ - Hash256::from("cats".as_bytes()), - Hash256::from("dogs".as_bytes()), - Hash256::from("birds".as_bytes()), - ]; - - let serialized = get_block_ssz(&block); - let ssz_block = SszBeaconBlock::from_slice(&serialized).unwrap(); - - assert_eq!( - ssz_block.parent_hash().unwrap(), - &Hash256::from("cats".as_bytes()).to_vec()[..] - ); - } - - #[test] - fn test_ssz_block_specials() { - /* - * Without data - */ - let mut block = BeaconBlock::zero(); - let s = SpecialRecord::logout(&[]); - block.specials.push(s.clone()); - - let serialized = get_block_ssz(&block); - let ssz_block = SszBeaconBlock::from_slice(&serialized).unwrap(); - let sr_ssz = get_special_record_ssz(&s); - - let mut expected = encode_length(sr_ssz.len(), LENGTH_PREFIX_BYTES); - expected.append(&mut sr_ssz.to_vec()); - - assert_eq!(ssz_block.specials(), &expected[..]); - - /* - * With data - */ - let mut block = BeaconBlock::zero(); - let s = SpecialRecord::randao_change(&[16, 17, 18]); - block.specials.push(s.clone()); - - let serialized = get_block_ssz(&block); - let ssz_block = SszBeaconBlock::from_slice(&serialized).unwrap(); - let sr_ssz = get_special_record_ssz(&s); - - let mut expected = encode_length(sr_ssz.len(), LENGTH_PREFIX_BYTES); - expected.append(&mut sr_ssz.to_vec()); - - assert_eq!(ssz_block.specials(), &expected[..]); - } - - #[test] - fn test_ssz_block_attestations() { - /* - * Single Attestation - */ - let mut block = BeaconBlock::zero(); - block.attestations.push(Attestation::zero()); - - let serialized = get_block_ssz(&block); - let ssz_block = SszBeaconBlock::from_slice(&serialized).unwrap(); - let ssz_ar = get_attestation_record_ssz(&Attestation::zero()); - - let mut expected = encode_length(ssz_ar.len(), LENGTH_PREFIX_BYTES); - expected.append(&mut ssz_ar.to_vec()); - - assert_eq!(ssz_block.attestations(), &expected[..]); - - /* - * Multiple Attestations - */ - let mut block = BeaconBlock::zero(); - block.attestations.push(Attestation::zero()); - block.attestations.push(Attestation::zero()); - - let serialized = get_block_ssz(&block); - let ssz_block = SszBeaconBlock::from_slice(&serialized).unwrap(); - let mut ssz_ar = get_attestation_record_ssz(&Attestation::zero()); - ssz_ar.append(&mut get_attestation_record_ssz(&Attestation::zero())); - - let mut expected = encode_length(ssz_ar.len(), LENGTH_PREFIX_BYTES); - expected.append(&mut ssz_ar.to_vec()); - - assert_eq!(ssz_block.attestations(), &expected[..]); - } - - #[test] - fn test_ssz_block_pow_chain_reference() { - let mut block = BeaconBlock::zero(); - block.attestations.push(Attestation::zero()); - let reference_hash = Hash256::from([42_u8; 32]); - block.pow_chain_reference = reference_hash.clone(); - - let serialized = get_block_ssz(&block); - let ssz_block = SszBeaconBlock::from_slice(&serialized).unwrap(); - - assert_eq!( - ssz_block.pow_chain_reference(), - &reference_hash.to_vec()[..] - ); - } - - #[test] - fn test_ssz_block_act_state_root() { - let mut block = BeaconBlock::zero(); - block.attestations.push(Attestation::zero()); - let reference_hash = Hash256::from([42_u8; 32]); - block.active_state_root = reference_hash.clone(); - - let serialized = get_block_ssz(&block); - let ssz_block = SszBeaconBlock::from_slice(&serialized).unwrap(); - - assert_eq!(ssz_block.act_state_root(), &reference_hash.to_vec()[..]); - } - - #[test] - fn test_ssz_block_cry_state_root() { - let mut block = BeaconBlock::zero(); - block.attestations.push(Attestation::zero()); - let reference_hash = Hash256::from([42_u8; 32]); - block.crystallized_state_root = reference_hash.clone(); - - let serialized = get_block_ssz(&block); - let ssz_block = SszBeaconBlock::from_slice(&serialized).unwrap(); - - assert_eq!(ssz_block.cry_state_root(), &reference_hash.to_vec()[..]); - } -} diff --git a/lighthouse/db/Cargo.toml b/lighthouse/db/Cargo.toml index a2718889c..e7fd4cd5d 100644 --- a/lighthouse/db/Cargo.toml +++ b/lighthouse/db/Cargo.toml @@ -9,5 +9,4 @@ bls = { path = "../../beacon_chain/utils/bls" } bytes = "0.4.10" rocksdb = "0.10.1" ssz = { path = "../../beacon_chain/utils/ssz" } -ssz_helpers = { path = "../../beacon_chain/utils/ssz_helpers" } types = { path = "../../beacon_chain/types" } From 0260564c15a5d95d7cf021d6d14b12e17becdeb8 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 18 Dec 2018 18:09:21 +1100 Subject: [PATCH 05/16] Begin implementing new types --- beacon_chain/types/src/beacon_block.rs | 142 ++---------------- beacon_chain/types/src/beacon_block_body.rs | 23 +++ beacon_chain/types/src/casper_slashing.rs | 30 ++++ beacon_chain/types/src/deposit.rs | 24 +++ beacon_chain/types/src/exit.rs | 8 + beacon_chain/types/src/lib.rs | 14 ++ .../types/src/proposal_signed_data.rs | 54 +++++++ beacon_chain/types/src/proposer_slashing.rs | 77 ++++++++++ beacon_chain/types/src/slashable_vote_data.rs | 70 +++++++++ 9 files changed, 314 insertions(+), 128 deletions(-) create mode 100644 beacon_chain/types/src/casper_slashing.rs create mode 100644 beacon_chain/types/src/deposit.rs create mode 100644 beacon_chain/types/src/exit.rs create mode 100644 beacon_chain/types/src/proposal_signed_data.rs create mode 100644 beacon_chain/types/src/proposer_slashing.rs create mode 100644 beacon_chain/types/src/slashable_vote_data.rs diff --git a/beacon_chain/types/src/beacon_block.rs b/beacon_chain/types/src/beacon_block.rs index 35ad18497..ad87ec84a 100644 --- a/beacon_chain/types/src/beacon_block.rs +++ b/beacon_chain/types/src/beacon_block.rs @@ -1,142 +1,28 @@ -use super::attestation::Attestation; -use super::special_record::SpecialRecord; use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; -use super::Hash256; - -pub const MIN_SSZ_BLOCK_LENGTH: usize = { - 8 + // slot - 32 + // randao_reveal - 32 + // pow_chain_reference - 4 + // ancestor hashes (assuming empty) - 32 + // active_state_root - 32 + // crystallized_state_root - 4 + // attestations (assuming empty) - 4 // specials (assuming empty) -}; -pub const MAX_SSZ_BLOCK_LENGTH: usize = MIN_SSZ_BLOCK_LENGTH + (1 << 24); +use super::{BeaconBlockBody, Hash256}; +use bls::AggregateSignature; #[derive(Debug, PartialEq, Clone, Default)] pub struct BeaconBlock { pub slot: u64, + pub parent_root: Hash256, + pub state_root: Hash256, pub randao_reveal: Hash256, - pub pow_chain_reference: Hash256, - pub ancestor_hashes: Vec, - pub active_state_root: Hash256, - pub crystallized_state_root: Hash256, - pub attestations: Vec, - pub specials: Vec, -} - -impl BeaconBlock { - pub fn zero() -> Self { - Self { - slot: 0, - randao_reveal: Hash256::zero(), - pow_chain_reference: Hash256::zero(), - ancestor_hashes: vec![], - active_state_root: Hash256::zero(), - crystallized_state_root: Hash256::zero(), - attestations: vec![], - specials: vec![], - } - } - - /// Return a reference to `ancestor_hashes[0]`. - /// - /// The first hash in `ancestor_hashes` is the parent of the block. - pub fn parent_hash(&self) -> Option<&Hash256> { - self.ancestor_hashes.get(0) - } + pub candidate_pow_receipt_root: Hash256, + pub signature: AggregateSignature, + pub body: BeaconBlockBody, } +/* impl Encodable for BeaconBlock { fn ssz_append(&self, s: &mut SszStream) { s.append(&self.slot); + s.append(&self.parent_root); + s.append(&self.state_root); s.append(&self.randao_reveal); - s.append(&self.pow_chain_reference); - s.append_vec(&self.ancestor_hashes); - s.append(&self.active_state_root); - s.append(&self.crystallized_state_root); - s.append_vec(&self.attestations); - s.append_vec(&self.specials); - } -} - -impl Decodable for BeaconBlock { - fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { - let (slot, i) = u64::ssz_decode(bytes, i)?; - let (randao_reveal, i) = Hash256::ssz_decode(bytes, i)?; - let (pow_chain_reference, i) = Hash256::ssz_decode(bytes, i)?; - let (ancestor_hashes, i) = Decodable::ssz_decode(bytes, i)?; - let (active_state_root, i) = Hash256::ssz_decode(bytes, i)?; - let (crystallized_state_root, i) = Hash256::ssz_decode(bytes, i)?; - let (attestations, i) = Decodable::ssz_decode(bytes, i)?; - let (specials, i) = Decodable::ssz_decode(bytes, i)?; - let block = BeaconBlock { - slot, - randao_reveal, - pow_chain_reference, - ancestor_hashes, - active_state_root, - crystallized_state_root, - attestations, - specials, - }; - Ok((block, i)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_block_zero() { - let b = BeaconBlock::zero(); - assert_eq!(b.slot, 0); - assert!(b.randao_reveal.is_zero()); - assert!(b.pow_chain_reference.is_zero()); - assert_eq!(b.ancestor_hashes, vec![]); - assert!(b.active_state_root.is_zero()); - assert!(b.crystallized_state_root.is_zero()); - assert_eq!(b.attestations.len(), 0); - assert_eq!(b.specials.len(), 0); - } - - #[test] - pub fn test_block_ssz_encode_decode() { - let mut b = BeaconBlock::zero(); - b.ancestor_hashes = vec![Hash256::zero(); 32]; - - let mut ssz_stream = SszStream::new(); - ssz_stream.append(&b); - let ssz = ssz_stream.drain(); - - let (b_decoded, _) = BeaconBlock::ssz_decode(&ssz, 0).unwrap(); - - assert_eq!(b, b_decoded); - } - - #[test] - pub fn test_block_min_ssz_length() { - let b = BeaconBlock::zero(); - - let mut ssz_stream = SszStream::new(); - ssz_stream.append(&b); - let ssz = ssz_stream.drain(); - - assert_eq!(ssz.len(), MIN_SSZ_BLOCK_LENGTH); - } - - #[test] - pub fn test_block_parent_hash() { - let mut b = BeaconBlock::zero(); - b.ancestor_hashes = vec![ - Hash256::from("cats".as_bytes()), - Hash256::from("dogs".as_bytes()), - Hash256::from("birds".as_bytes()), - ]; - - assert_eq!(b.parent_hash().unwrap(), &Hash256::from("cats".as_bytes())); + s.append(&self.candidate_pow_receipt_root); + s.append_vec(&self.signature.as_bytes()); + s.append(&self.body); } } +*/ diff --git a/beacon_chain/types/src/beacon_block_body.rs b/beacon_chain/types/src/beacon_block_body.rs index e69de29bb..66db774b7 100644 --- a/beacon_chain/types/src/beacon_block_body.rs +++ b/beacon_chain/types/src/beacon_block_body.rs @@ -0,0 +1,23 @@ +use super::ssz::{Encodable, SszStream}; +use super::{Attestation, CasperSlashing, Deposit, Exit, ProposerSlashing}; + +#[derive(Debug, PartialEq, Clone, Default)] +pub struct BeaconBlockBody { + pub proposer_slashings: Vec, + pub casper_slashings: Vec, + pub attestations: Vec, + pub deposits: Vec, + pub exits: Vec, +} + +/* +impl Encodable for BeaconBlockBody { + fn ssz_append(&self, s: &mut SszStream) { + s.append(&self.proposer_slashings); + s.append(&self.casper_slashings); + s.append(&self.attestations); + s.append(&self.deposits); + s.append(&self.exits); + } +} +*/ diff --git a/beacon_chain/types/src/casper_slashing.rs b/beacon_chain/types/src/casper_slashing.rs new file mode 100644 index 000000000..a8f722652 --- /dev/null +++ b/beacon_chain/types/src/casper_slashing.rs @@ -0,0 +1,30 @@ +use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; +use super::SlashableVoteData; + +#[derive(Debug, PartialEq, Clone, Default)] +pub struct CasperSlashing { + pub slashable_vote_data_1: SlashableVoteData, + pub slashable_vote_data_2: SlashableVoteData, +} + +impl Encodable for CasperSlashing { + fn ssz_append(&self, s: &mut SszStream) { + s.append(&self.slashable_vote_data_1); + s.append(&self.slashable_vote_data_1); + } +} + +impl Decodable for CasperSlashing { + fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { + let (slashable_vote_data_1, i) = SlashableVoteData::ssz_decode(bytes, i)?; + let (slashable_vote_data_2, i) = SlashableVoteData::ssz_decode(bytes, i)?; + + Ok(( + CasperSlashing { + slashable_vote_data_1, + slashable_vote_data_2, + }, + i, + )) + } +} diff --git a/beacon_chain/types/src/deposit.rs b/beacon_chain/types/src/deposit.rs new file mode 100644 index 000000000..7a6e70409 --- /dev/null +++ b/beacon_chain/types/src/deposit.rs @@ -0,0 +1,24 @@ +use super::Hash256; +use bls::{AggregateSignature, PublicKey}; + +#[derive(Debug, PartialEq, Clone)] +pub struct Deposit { + pub merkle_branch: Vec, + pub merkle_tree_index: u64, + pub deposit_data: DepositData, +} + +#[derive(Debug, PartialEq, Clone)] +pub struct DepositData { + pub deposit_input: DepositInput, + pub value: u64, + pub timestamp: u64, +} + +#[derive(Debug, PartialEq, Clone)] +pub struct DepositInput { + pub pubkey: PublicKey, + pub withdrawal_credentials: Hash256, + pub randao_commitment: Hash256, + pub proof_of_possession: AggregateSignature, +} diff --git a/beacon_chain/types/src/exit.rs b/beacon_chain/types/src/exit.rs new file mode 100644 index 000000000..8de66c630 --- /dev/null +++ b/beacon_chain/types/src/exit.rs @@ -0,0 +1,8 @@ +use bls::AggregateSignature; + +#[derive(Debug, PartialEq, Clone)] +pub struct Exit { + pub slot: u64, + pub validator_index: u32, + pub signature: AggregateSignature, +} diff --git a/beacon_chain/types/src/lib.rs b/beacon_chain/types/src/lib.rs index f86d5f024..c71a205b7 100644 --- a/beacon_chain/types/src/lib.rs +++ b/beacon_chain/types/src/lib.rs @@ -7,16 +7,23 @@ pub mod active_state; pub mod attestation_data; pub mod attestation; pub mod beacon_block; +pub mod beacon_block_body; pub mod beacon_state; pub mod candidate_pow_receipt_root_record; +pub mod casper_slashing; pub mod chain_config; pub mod crosslink_record; pub mod crystallized_state; +pub mod deposit; +pub mod exit; pub mod fork_data; pub mod pending_attestation_record; +pub mod proposal_signed_data; +pub mod proposer_slashing; pub mod shard_and_committee; pub mod shard_reassignment_record; pub mod special_record; +pub mod slashable_vote_data; pub mod validator_record; pub mod validator_registration; @@ -27,12 +34,19 @@ pub use active_state::ActiveState; pub use attestation_data::AttestationData; pub use attestation::Attestation; pub use beacon_block::BeaconBlock; +pub use beacon_block_body::BeaconBlockBody; pub use beacon_state::BeaconState; +pub use casper_slashing::CasperSlashing; pub use chain_config::ChainConfig; pub use crosslink_record::CrosslinkRecord; pub use crystallized_state::CrystallizedState; +pub use deposit::{Deposit, DepositData, DepositInput}; +pub use exit::Exit; pub use fork_data::ForkData; pub use pending_attestation_record::PendingAttestationRecord; +pub use proposal_signed_data::ProposalSignedData; +pub use proposer_slashing::ProposerSlashing; +pub use slashable_vote_data::SlashableVoteData; pub use shard_and_committee::ShardAndCommittee; pub use special_record::{SpecialRecord, SpecialRecordKind}; pub use validator_record::{ValidatorRecord, ValidatorStatus}; diff --git a/beacon_chain/types/src/proposal_signed_data.rs b/beacon_chain/types/src/proposal_signed_data.rs new file mode 100644 index 000000000..25a6f0e04 --- /dev/null +++ b/beacon_chain/types/src/proposal_signed_data.rs @@ -0,0 +1,54 @@ +use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; +use super::Hash256; + +#[derive(Debug, PartialEq, Clone, Default)] +pub struct ProposalSignedData { + pub slot: u64, + pub shard: u64, + pub block_root: Hash256, +} + +impl Encodable for ProposalSignedData { + fn ssz_append(&self, s: &mut SszStream) { + s.append(&self.slot); + s.append(&self.shard); + s.append(&self.block_root); + } +} + +impl Decodable for ProposalSignedData { + fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { + let (slot, i) = u64::ssz_decode(bytes, i)?; + let (shard, i) = u64::ssz_decode(bytes, i)?; + let (block_root, i) = Hash256::ssz_decode(bytes, i)?; + + Ok(( + ProposalSignedData { + slot, + shard, + block_root, + }, + i, + )) + } +} + +#[cfg(test)] +mod tests { + use super::super::ssz::ssz_encode; + use super::*; + + #[test] + pub fn test_ssz_round_trip() { + let original = ProposalSignedData { + slot: 42, + shard: 120, + block_root: Hash256::from("cats".as_bytes()), + }; + + let bytes = ssz_encode(&original); + let (decoded, _) = ProposalSignedData::ssz_decode(&bytes, 0).unwrap(); + + assert_eq!(original, decoded); + } +} diff --git a/beacon_chain/types/src/proposer_slashing.rs b/beacon_chain/types/src/proposer_slashing.rs new file mode 100644 index 000000000..33d8103b9 --- /dev/null +++ b/beacon_chain/types/src/proposer_slashing.rs @@ -0,0 +1,77 @@ +use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; +use super::ProposalSignedData; +use bls::Signature; + +#[derive(Debug, PartialEq, Clone, Default)] +pub struct ProposerSlashing { + pub proposer_index: u32, + pub proposal_data_1: ProposalSignedData, + pub proposal_signature_1: Signature, + pub proposal_data_2: ProposalSignedData, + pub proposal_signature_2: Signature, +} + +impl Encodable for ProposerSlashing { + fn ssz_append(&self, s: &mut SszStream) { + s.append(&self.proposer_index); + s.append(&self.proposal_data_1); + s.append(&self.proposal_signature_1); + s.append(&self.proposal_data_2); + s.append(&self.proposal_signature_2); + } +} + +impl Decodable for ProposerSlashing { + fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { + let (proposer_index, i) = u32::ssz_decode(bytes, i)?; + let (proposal_data_1, i) = ProposalSignedData::ssz_decode(bytes, i)?; + let (proposal_signature_1, i) = Signature::ssz_decode(bytes, i)?; + let (proposal_data_2, i) = ProposalSignedData::ssz_decode(bytes, i)?; + let (proposal_signature_2, i) = Signature::ssz_decode(bytes, i)?; + + Ok(( + ProposerSlashing { + proposer_index, + proposal_data_1, + proposal_signature_1, + proposal_data_2, + proposal_signature_2, + }, + i, + )) + } +} + +#[cfg(test)] +mod tests { + use super::super::ssz::ssz_encode; + use super::super::Hash256; + use super::*; + use bls::{Keypair, Signature}; + + #[test] + pub fn test_ssz_round_trip() { + let keypair = Keypair::random(); + + let original = ProposerSlashing { + proposer_index: 42, + proposal_data_1: ProposalSignedData { + slot: 45, + shard: 110, + block_root: Hash256::from("cats".as_bytes()), + }, + proposal_signature_1: Signature::new(&[42, 42], &keypair.sk), + proposal_data_2: ProposalSignedData { + slot: 1, + shard: 260, + block_root: Hash256::from("lol".as_bytes()), + }, + proposal_signature_2: Signature::new(&[7, 8], &keypair.sk), + }; + + let bytes = ssz_encode(&original); + let (decoded, _) = ProposerSlashing::ssz_decode(&bytes, 0).unwrap(); + + assert_eq!(original, decoded); + } +} diff --git a/beacon_chain/types/src/slashable_vote_data.rs b/beacon_chain/types/src/slashable_vote_data.rs new file mode 100644 index 000000000..7a8f3d4da --- /dev/null +++ b/beacon_chain/types/src/slashable_vote_data.rs @@ -0,0 +1,70 @@ +use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; +use super::AttestationData; +use bls::AggregateSignature; + +#[derive(Debug, PartialEq, Clone, Default)] +pub struct SlashableVoteData { + pub aggregate_signature_poc_0_indices: Vec, + pub aggregate_signature_poc_1_indices: Vec, + pub data: AttestationData, + pub aggregate_signature: AggregateSignature, +} + +impl Encodable for SlashableVoteData { + fn ssz_append(&self, s: &mut SszStream) { + s.append_vec(&self.aggregate_signature_poc_0_indices); + s.append_vec(&self.aggregate_signature_poc_1_indices); + s.append(&self.data); + s.append(&self.aggregate_signature); + } +} + +impl Decodable for SlashableVoteData { + fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { + let (aggregate_signature_poc_0_indices, i) = decode_ssz_list(bytes, i)?; + let (aggregate_signature_poc_1_indices, i) = decode_ssz_list(bytes, i)?; + let (data, i) = AttestationData::ssz_decode(bytes, i)?; + let (aggregate_signature, i) = AggregateSignature::ssz_decode(bytes, i)?; + + Ok(( + SlashableVoteData { + aggregate_signature_poc_0_indices, + aggregate_signature_poc_1_indices, + data, + aggregate_signature, + }, + i, + )) + } +} + +#[cfg(test)] +mod tests { + use super::super::ssz::ssz_encode; + use super::super::Hash256; + use super::*; + + #[test] + pub fn test_ssz_round_trip() { + let original = SlashableVoteData { + aggregate_signature_poc_0_indices: vec![0, 1, 2], + aggregate_signature_poc_1_indices: vec![42, 42, 42], + data: AttestationData { + slot: 42, + shard: 16, + beacon_block_hash: Hash256::from("beacon".as_bytes()), + epoch_boundary_hash: Hash256::from("epoch".as_bytes()), + shard_block_hash: Hash256::from("shard".as_bytes()), + latest_crosslink_hash: Hash256::from("xlink".as_bytes()), + justified_slot: 8, + justified_block_hash: Hash256::from("justified".as_bytes()), + }, + aggregate_signature: AggregateSignature::new(), + }; + + let bytes = ssz_encode(&original); + let (decoded, _) = SlashableVoteData::ssz_decode(&bytes, 0).unwrap(); + + assert_eq!(original, decoded); + } +} From c9f82f8a1d94745b145cfc1c3f9002810a587e9e Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 19 Dec 2018 17:56:09 +1100 Subject: [PATCH 06/16] Implement ssz enc/decode for beaconblock Not yet fully tested --- beacon_chain/types/src/beacon_block_body.rs | 35 ++++++--- beacon_chain/types/src/deposit.rs | 80 +++++++++++++++++++++ beacon_chain/types/src/exit.rs | 26 +++++++ beacon_chain/types/src/proposer_slashing.rs | 2 +- 4 files changed, 134 insertions(+), 9 deletions(-) diff --git a/beacon_chain/types/src/beacon_block_body.rs b/beacon_chain/types/src/beacon_block_body.rs index 66db774b7..f0c767155 100644 --- a/beacon_chain/types/src/beacon_block_body.rs +++ b/beacon_chain/types/src/beacon_block_body.rs @@ -1,4 +1,4 @@ -use super::ssz::{Encodable, SszStream}; +use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; use super::{Attestation, CasperSlashing, Deposit, Exit, ProposerSlashing}; #[derive(Debug, PartialEq, Clone, Default)] @@ -10,14 +10,33 @@ pub struct BeaconBlockBody { pub exits: Vec, } -/* impl Encodable for BeaconBlockBody { fn ssz_append(&self, s: &mut SszStream) { - s.append(&self.proposer_slashings); - s.append(&self.casper_slashings); - s.append(&self.attestations); - s.append(&self.deposits); - s.append(&self.exits); + s.append_vec(&self.proposer_slashings); + s.append_vec(&self.casper_slashings); + s.append_vec(&self.attestations); + s.append_vec(&self.deposits); + s.append_vec(&self.exits); + } +} + +impl Decodable for BeaconBlockBody { + fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { + let (proposer_slashings, i) = decode_ssz_list(bytes, i)?; + let (casper_slashings, i) = decode_ssz_list(bytes, i)?; + let (attestations, i) = decode_ssz_list(bytes, i)?; + let (deposits, i) = decode_ssz_list(bytes, i)?; + let (exits, i) = decode_ssz_list(bytes, i)?; + + Ok(( + Self { + proposer_slashings, + casper_slashings, + attestations, + deposits, + exits, + }, + i, + )) } } -*/ diff --git a/beacon_chain/types/src/deposit.rs b/beacon_chain/types/src/deposit.rs index 7a6e70409..3b2ad87a6 100644 --- a/beacon_chain/types/src/deposit.rs +++ b/beacon_chain/types/src/deposit.rs @@ -1,3 +1,4 @@ +use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; use super::Hash256; use bls::{AggregateSignature, PublicKey}; @@ -8,6 +9,31 @@ pub struct Deposit { pub deposit_data: DepositData, } +impl Encodable for Deposit { + fn ssz_append(&self, s: &mut SszStream) { + s.append_vec(&self.merkle_branch); + s.append(&self.merkle_tree_index); + s.append(&self.deposit_data); + } +} + +impl Decodable for Deposit { + fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { + let (merkle_branch, i) = decode_ssz_list(bytes, i)?; + let (merkle_tree_index, i) = u64::ssz_decode(bytes, i)?; + let (deposit_data, i) = DepositData::ssz_decode(bytes, i)?; + + Ok(( + Self { + merkle_branch, + merkle_tree_index, + deposit_data, + }, + i, + )) + } +} + #[derive(Debug, PartialEq, Clone)] pub struct DepositData { pub deposit_input: DepositInput, @@ -15,6 +41,31 @@ pub struct DepositData { pub timestamp: u64, } +impl Encodable for DepositData { + fn ssz_append(&self, s: &mut SszStream) { + s.append(&self.deposit_input); + s.append(&self.value); + s.append(&self.timestamp); + } +} + +impl Decodable for DepositData { + fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { + let (deposit_input, i) = DepositInput::ssz_decode(bytes, i)?; + let (value, i) = u64::ssz_decode(bytes, i)?; + let (timestamp, i) = u64::ssz_decode(bytes, i)?; + + Ok(( + Self { + deposit_input, + value, + timestamp, + }, + i, + )) + } +} + #[derive(Debug, PartialEq, Clone)] pub struct DepositInput { pub pubkey: PublicKey, @@ -22,3 +73,32 @@ pub struct DepositInput { pub randao_commitment: Hash256, pub proof_of_possession: AggregateSignature, } + +impl Encodable for DepositInput { + fn ssz_append(&self, s: &mut SszStream) { + s.append_vec(&self.pubkey.as_bytes()); + s.append(&self.withdrawal_credentials); + s.append(&self.randao_commitment); + s.append(&self.proof_of_possession); + } +} + +impl Decodable for DepositInput { + fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { + let (pubkey_bytes, i) = decode_ssz_list(bytes, i)?; + let pubkey = PublicKey::from_bytes(&pubkey_bytes).map_err(|_| DecodeError::TooShort)?; + let (withdrawal_credentials, i) = Hash256::ssz_decode(bytes, i)?; + let (randao_commitment, i) = Hash256::ssz_decode(bytes, i)?; + let (proof_of_possession, i) = AggregateSignature::ssz_decode(bytes, i)?; + + Ok(( + Self { + pubkey, + withdrawal_credentials, + randao_commitment, + proof_of_possession, + }, + i, + )) + } +} diff --git a/beacon_chain/types/src/exit.rs b/beacon_chain/types/src/exit.rs index 8de66c630..c4753354d 100644 --- a/beacon_chain/types/src/exit.rs +++ b/beacon_chain/types/src/exit.rs @@ -1,3 +1,4 @@ +use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use bls::AggregateSignature; #[derive(Debug, PartialEq, Clone)] @@ -6,3 +7,28 @@ pub struct Exit { pub validator_index: u32, pub signature: AggregateSignature, } + +impl Encodable for Exit { + fn ssz_append(&self, s: &mut SszStream) { + s.append(&self.slot); + s.append(&self.validator_index); + s.append(&self.signature); + } +} + +impl Decodable for Exit { + fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { + let (slot, i) = u64::ssz_decode(bytes, i)?; + let (validator_index, i) = u32::ssz_decode(bytes, i)?; + let (signature, i) = AggregateSignature::ssz_decode(bytes, i)?; + + Ok(( + Self { + slot, + validator_index, + signature, + }, + i, + )) + } +} diff --git a/beacon_chain/types/src/proposer_slashing.rs b/beacon_chain/types/src/proposer_slashing.rs index 33d8103b9..0daab8ea8 100644 --- a/beacon_chain/types/src/proposer_slashing.rs +++ b/beacon_chain/types/src/proposer_slashing.rs @@ -1,4 +1,4 @@ -use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; +use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; use super::ProposalSignedData; use bls::Signature; From 368a218af4081711f659990821b5c2ffc6d49cb0 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Fri, 21 Dec 2018 15:44:11 +1100 Subject: [PATCH 07/16] Add types, more ssz testing for existing types --- beacon_chain/types/src/beacon_block.rs | 29 ++++- beacon_chain/types/src/casper_slashing.rs | 4 +- beacon_chain/types/src/deposit.rs | 100 ++++++------------ beacon_chain/types/src/deposit_data.rs | 63 +++++++++++ beacon_chain/types/src/deposit_input.rs | 64 +++++++++++ beacon_chain/types/src/exit.rs | 32 +++++- beacon_chain/types/src/lib.rs | 6 +- .../types/src/proposal_signed_data.rs | 6 +- beacon_chain/types/src/proposer_slashing.rs | 12 +-- beacon_chain/types/src/slashable_vote_data.rs | 4 +- 10 files changed, 233 insertions(+), 87 deletions(-) create mode 100644 beacon_chain/types/src/deposit_data.rs create mode 100644 beacon_chain/types/src/deposit_input.rs diff --git a/beacon_chain/types/src/beacon_block.rs b/beacon_chain/types/src/beacon_block.rs index ad87ec84a..b2641cf84 100644 --- a/beacon_chain/types/src/beacon_block.rs +++ b/beacon_chain/types/src/beacon_block.rs @@ -13,7 +13,6 @@ pub struct BeaconBlock { pub body: BeaconBlockBody, } -/* impl Encodable for BeaconBlock { fn ssz_append(&self, s: &mut SszStream) { s.append(&self.slot); @@ -21,8 +20,32 @@ impl Encodable for BeaconBlock { s.append(&self.state_root); s.append(&self.randao_reveal); s.append(&self.candidate_pow_receipt_root); - s.append_vec(&self.signature.as_bytes()); + s.append(&self.signature); s.append(&self.body); } } -*/ + +impl Decodable for BeaconBlock { + fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { + let (slot, i) = <_>::ssz_decode(bytes, i)?; + let (parent_root, i) = <_>::ssz_decode(bytes, i)?; + let (state_root, i) = <_>::ssz_decode(bytes, i)?; + let (randao_reveal, i) = <_>::ssz_decode(bytes, i)?; + let (candidate_pow_receipt_root, i) = <_>::ssz_decode(bytes, i)?; + let (signature, i) = <_>::ssz_decode(bytes, i)?; + let (body, i) = <_>::ssz_decode(bytes, i)?; + + Ok(( + Self { + slot, + parent_root, + state_root, + randao_reveal, + candidate_pow_receipt_root, + signature, + body, + }, + i, + )) + } +} diff --git a/beacon_chain/types/src/casper_slashing.rs b/beacon_chain/types/src/casper_slashing.rs index a8f722652..dfa99cd6b 100644 --- a/beacon_chain/types/src/casper_slashing.rs +++ b/beacon_chain/types/src/casper_slashing.rs @@ -16,8 +16,8 @@ impl Encodable for CasperSlashing { impl Decodable for CasperSlashing { fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { - let (slashable_vote_data_1, i) = SlashableVoteData::ssz_decode(bytes, i)?; - let (slashable_vote_data_2, i) = SlashableVoteData::ssz_decode(bytes, i)?; + let (slashable_vote_data_1, i) = <_>::ssz_decode(bytes, i)?; + let (slashable_vote_data_2, i) = <_>::ssz_decode(bytes, i)?; Ok(( CasperSlashing { diff --git a/beacon_chain/types/src/deposit.rs b/beacon_chain/types/src/deposit.rs index 3b2ad87a6..7aa375828 100644 --- a/beacon_chain/types/src/deposit.rs +++ b/beacon_chain/types/src/deposit.rs @@ -1,6 +1,5 @@ use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; -use super::Hash256; -use bls::{AggregateSignature, PublicKey}; +use super::{DepositData, Hash256}; #[derive(Debug, PartialEq, Clone)] pub struct Deposit { @@ -20,8 +19,8 @@ impl Encodable for Deposit { impl Decodable for Deposit { fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { let (merkle_branch, i) = decode_ssz_list(bytes, i)?; - let (merkle_tree_index, i) = u64::ssz_decode(bytes, i)?; - let (deposit_data, i) = DepositData::ssz_decode(bytes, i)?; + let (merkle_tree_index, i) = <_>::ssz_decode(bytes, i)?; + let (deposit_data, i) = <_>::ssz_decode(bytes, i)?; Ok(( Self { @@ -34,71 +33,38 @@ impl Decodable for Deposit { } } -#[derive(Debug, PartialEq, Clone)] -pub struct DepositData { - pub deposit_input: DepositInput, - pub value: u64, - pub timestamp: u64, -} +#[cfg(test)] +mod tests { + use super::super::ssz::ssz_encode; + use super::super::{DepositInput, Hash256}; + use super::*; + use bls::{Keypair, Signature}; -impl Encodable for DepositData { - fn ssz_append(&self, s: &mut SszStream) { - s.append(&self.deposit_input); - s.append(&self.value); - s.append(&self.timestamp); - } -} + #[test] + pub fn test_ssz_round_trip() { + let keypair = Keypair::random(); -impl Decodable for DepositData { - fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { - let (deposit_input, i) = DepositInput::ssz_decode(bytes, i)?; - let (value, i) = u64::ssz_decode(bytes, i)?; - let (timestamp, i) = u64::ssz_decode(bytes, i)?; - - Ok(( - Self { - deposit_input, - value, - timestamp, + let original = Deposit { + merkle_branch: vec![ + Hash256::from("one".as_bytes()), + Hash256::from("two".as_bytes()), + ], + merkle_tree_index: 19, + deposit_data: DepositData { + deposit_input: DepositInput { + pubkey: keypair.pk, + withdrawal_credentials: Hash256::from("cats".as_bytes()), + randao_commitment: Hash256::from("dogs".as_bytes()), + proof_of_possession: Signature::new(&[42, 42], &keypair.sk), + }, + value: 12, + timestamp: 100, }, - i, - )) - } -} - -#[derive(Debug, PartialEq, Clone)] -pub struct DepositInput { - pub pubkey: PublicKey, - pub withdrawal_credentials: Hash256, - pub randao_commitment: Hash256, - pub proof_of_possession: AggregateSignature, -} - -impl Encodable for DepositInput { - fn ssz_append(&self, s: &mut SszStream) { - s.append_vec(&self.pubkey.as_bytes()); - s.append(&self.withdrawal_credentials); - s.append(&self.randao_commitment); - s.append(&self.proof_of_possession); - } -} - -impl Decodable for DepositInput { - fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { - let (pubkey_bytes, i) = decode_ssz_list(bytes, i)?; - let pubkey = PublicKey::from_bytes(&pubkey_bytes).map_err(|_| DecodeError::TooShort)?; - let (withdrawal_credentials, i) = Hash256::ssz_decode(bytes, i)?; - let (randao_commitment, i) = Hash256::ssz_decode(bytes, i)?; - let (proof_of_possession, i) = AggregateSignature::ssz_decode(bytes, i)?; - - Ok(( - Self { - pubkey, - withdrawal_credentials, - randao_commitment, - proof_of_possession, - }, - i, - )) + }; + + let bytes = ssz_encode(&original); + let (decoded, _) = Deposit::ssz_decode(&bytes, 0).unwrap(); + + assert_eq!(original, decoded); } } diff --git a/beacon_chain/types/src/deposit_data.rs b/beacon_chain/types/src/deposit_data.rs new file mode 100644 index 000000000..790beab28 --- /dev/null +++ b/beacon_chain/types/src/deposit_data.rs @@ -0,0 +1,63 @@ +use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; +use super::DepositInput; + +#[derive(Debug, PartialEq, Clone)] +pub struct DepositData { + pub deposit_input: DepositInput, + pub value: u64, + pub timestamp: u64, +} + +impl Encodable for DepositData { + fn ssz_append(&self, s: &mut SszStream) { + s.append(&self.deposit_input); + s.append(&self.value); + s.append(&self.timestamp); + } +} + +impl Decodable for DepositData { + fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { + let (deposit_input, i) = <_>::ssz_decode(bytes, i)?; + let (value, i) = <_>::ssz_decode(bytes, i)?; + let (timestamp, i) = <_>::ssz_decode(bytes, i)?; + + Ok(( + Self { + deposit_input, + value, + timestamp, + }, + i, + )) + } +} + +#[cfg(test)] +mod tests { + use super::super::ssz::ssz_encode; + use super::super::Hash256; + use super::*; + use bls::{Keypair, Signature}; + + #[test] + pub fn test_ssz_round_trip() { + let keypair = Keypair::random(); + + let original = DepositData { + deposit_input: DepositInput { + pubkey: keypair.pk, + withdrawal_credentials: Hash256::from("cats".as_bytes()), + randao_commitment: Hash256::from("dogs".as_bytes()), + proof_of_possession: Signature::new(&[42, 42], &keypair.sk), + }, + value: 12, + timestamp: 100, + }; + + let bytes = ssz_encode(&original); + let (decoded, _) = DepositData::ssz_decode(&bytes, 0).unwrap(); + + assert_eq!(original, decoded); + } +} diff --git a/beacon_chain/types/src/deposit_input.rs b/beacon_chain/types/src/deposit_input.rs new file mode 100644 index 000000000..d9b3e9864 --- /dev/null +++ b/beacon_chain/types/src/deposit_input.rs @@ -0,0 +1,64 @@ +use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; +use super::Hash256; +use bls::{PublicKey, Signature}; + +#[derive(Debug, PartialEq, Clone)] +pub struct DepositInput { + pub pubkey: PublicKey, + pub withdrawal_credentials: Hash256, + pub randao_commitment: Hash256, + pub proof_of_possession: Signature, +} + +impl Encodable for DepositInput { + fn ssz_append(&self, s: &mut SszStream) { + s.append_vec(&self.pubkey.as_bytes()); + s.append(&self.withdrawal_credentials); + s.append(&self.randao_commitment); + s.append(&self.proof_of_possession); + } +} + +impl Decodable for DepositInput { + fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { + let (pubkey_bytes, i) = decode_ssz_list(bytes, i)?; + let pubkey = PublicKey::from_bytes(&pubkey_bytes).map_err(|_| DecodeError::TooShort)?; + let (withdrawal_credentials, i) = <_>::ssz_decode(bytes, i)?; + let (randao_commitment, i) = <_>::ssz_decode(bytes, i)?; + let (proof_of_possession, i) = <_>::ssz_decode(bytes, i)?; + + Ok(( + Self { + pubkey, + withdrawal_credentials, + randao_commitment, + proof_of_possession, + }, + i, + )) + } +} + +#[cfg(test)] +mod tests { + use super::super::ssz::ssz_encode; + use super::*; + use bls::{Keypair, Signature}; + + #[test] + pub fn test_ssz_round_trip() { + let keypair = Keypair::random(); + + let original = DepositInput { + pubkey: keypair.pk, + withdrawal_credentials: Hash256::from("cats".as_bytes()), + randao_commitment: Hash256::from("dogs".as_bytes()), + proof_of_possession: Signature::new(&[42, 42], &keypair.sk), + }; + + let bytes = ssz_encode(&original); + let (decoded, _) = DepositInput::ssz_decode(&bytes, 0).unwrap(); + + assert_eq!(original, decoded); + } +} diff --git a/beacon_chain/types/src/exit.rs b/beacon_chain/types/src/exit.rs index c4753354d..b32ec3af6 100644 --- a/beacon_chain/types/src/exit.rs +++ b/beacon_chain/types/src/exit.rs @@ -18,9 +18,9 @@ impl Encodable for Exit { impl Decodable for Exit { fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { - let (slot, i) = u64::ssz_decode(bytes, i)?; - let (validator_index, i) = u32::ssz_decode(bytes, i)?; - let (signature, i) = AggregateSignature::ssz_decode(bytes, i)?; + let (slot, i) = <_>::ssz_decode(bytes, i)?; + let (validator_index, i) = <_>::ssz_decode(bytes, i)?; + let (signature, i) = <_>::ssz_decode(bytes, i)?; Ok(( Self { @@ -32,3 +32,29 @@ impl Decodable for Exit { )) } } + +#[cfg(test)] +mod tests { + use super::super::ssz::ssz_encode; + use super::*; + use bls::{AggregateSignature, Keypair, Signature}; + + #[test] + pub fn test_ssz_round_trip() { + let keypair = Keypair::random(); + let single_signature = Signature::new(&[42, 42], &keypair.sk); + let mut signature = AggregateSignature::new(); + signature.add(&single_signature); + + let original = Exit { + slot: 42, + validator_index: 12, + signature, + }; + + let bytes = ssz_encode(&original); + let (decoded, _) = Exit::ssz_decode(&bytes, 0).unwrap(); + + assert_eq!(original, decoded); + } +} diff --git a/beacon_chain/types/src/lib.rs b/beacon_chain/types/src/lib.rs index c71a205b7..e24e77b93 100644 --- a/beacon_chain/types/src/lib.rs +++ b/beacon_chain/types/src/lib.rs @@ -15,6 +15,8 @@ pub mod chain_config; pub mod crosslink_record; pub mod crystallized_state; pub mod deposit; +pub mod deposit_data; +pub mod deposit_input; pub mod exit; pub mod fork_data; pub mod pending_attestation_record; @@ -40,7 +42,9 @@ pub use casper_slashing::CasperSlashing; pub use chain_config::ChainConfig; pub use crosslink_record::CrosslinkRecord; pub use crystallized_state::CrystallizedState; -pub use deposit::{Deposit, DepositData, DepositInput}; +pub use deposit::Deposit; +pub use deposit_data::DepositData; +pub use deposit_input::DepositInput; pub use exit::Exit; pub use fork_data::ForkData; pub use pending_attestation_record::PendingAttestationRecord; diff --git a/beacon_chain/types/src/proposal_signed_data.rs b/beacon_chain/types/src/proposal_signed_data.rs index 25a6f0e04..f44ecdd41 100644 --- a/beacon_chain/types/src/proposal_signed_data.rs +++ b/beacon_chain/types/src/proposal_signed_data.rs @@ -18,9 +18,9 @@ impl Encodable for ProposalSignedData { impl Decodable for ProposalSignedData { fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { - let (slot, i) = u64::ssz_decode(bytes, i)?; - let (shard, i) = u64::ssz_decode(bytes, i)?; - let (block_root, i) = Hash256::ssz_decode(bytes, i)?; + let (slot, i) = <_>::ssz_decode(bytes, i)?; + let (shard, i) = <_>::ssz_decode(bytes, i)?; + let (block_root, i) = <_>::ssz_decode(bytes, i)?; Ok(( ProposalSignedData { diff --git a/beacon_chain/types/src/proposer_slashing.rs b/beacon_chain/types/src/proposer_slashing.rs index 0daab8ea8..b8d597283 100644 --- a/beacon_chain/types/src/proposer_slashing.rs +++ b/beacon_chain/types/src/proposer_slashing.rs @@ -1,4 +1,4 @@ -use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; +use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::ProposalSignedData; use bls::Signature; @@ -23,11 +23,11 @@ impl Encodable for ProposerSlashing { impl Decodable for ProposerSlashing { fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { - let (proposer_index, i) = u32::ssz_decode(bytes, i)?; - let (proposal_data_1, i) = ProposalSignedData::ssz_decode(bytes, i)?; - let (proposal_signature_1, i) = Signature::ssz_decode(bytes, i)?; - let (proposal_data_2, i) = ProposalSignedData::ssz_decode(bytes, i)?; - let (proposal_signature_2, i) = Signature::ssz_decode(bytes, i)?; + let (proposer_index, i) = <_>::ssz_decode(bytes, i)?; + let (proposal_data_1, i) = <_>::ssz_decode(bytes, i)?; + let (proposal_signature_1, i) = <_>::ssz_decode(bytes, i)?; + let (proposal_data_2, i) = <_>::ssz_decode(bytes, i)?; + let (proposal_signature_2, i) = <_>::ssz_decode(bytes, i)?; Ok(( ProposerSlashing { diff --git a/beacon_chain/types/src/slashable_vote_data.rs b/beacon_chain/types/src/slashable_vote_data.rs index 7a8f3d4da..2bd489978 100644 --- a/beacon_chain/types/src/slashable_vote_data.rs +++ b/beacon_chain/types/src/slashable_vote_data.rs @@ -23,8 +23,8 @@ impl Decodable for SlashableVoteData { fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { let (aggregate_signature_poc_0_indices, i) = decode_ssz_list(bytes, i)?; let (aggregate_signature_poc_1_indices, i) = decode_ssz_list(bytes, i)?; - let (data, i) = AttestationData::ssz_decode(bytes, i)?; - let (aggregate_signature, i) = AggregateSignature::ssz_decode(bytes, i)?; + let (data, i) = <_>::ssz_decode(bytes, i)?; + let (aggregate_signature, i) = <_>::ssz_decode(bytes, i)?; Ok(( SlashableVoteData { From 6f039e6e6a0a38640b39d7f987c9d4fca499ca4c Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Sun, 23 Dec 2018 23:41:22 +1100 Subject: [PATCH 08/16] Add ssz enc/dec for beacon block --- beacon_chain/types/Cargo.toml | 3 +- beacon_chain/types/src/attestation.rs | 49 +++++++++---------- beacon_chain/types/src/attestation_data.rs | 38 ++++++++------ beacon_chain/types/src/beacon_block.rs | 35 +++++++++++++ beacon_chain/types/src/beacon_block_body.rs | 45 ++++++++++++++--- beacon_chain/types/src/casper_slashing.rs | 32 +++++++++++- beacon_chain/types/src/deposit.rs | 43 +++++++--------- beacon_chain/types/src/deposit_data.rs | 32 ++++++------ beacon_chain/types/src/deposit_input.rs | 28 +++++++---- beacon_chain/types/src/exit.rs | 33 +++++++------ beacon_chain/types/src/lib.rs | 48 +++++++++--------- .../types/src/proposal_signed_data.rs | 23 ++++++--- beacon_chain/types/src/proposer_slashing.rs | 39 +++++++-------- .../types/src/random/aggregate_signature.rs | 12 +++++ beacon_chain/types/src/random/bitfield.rs | 11 +++++ beacon_chain/types/src/random/hash256.rs | 11 +++++ beacon_chain/types/src/random/mod.rs | 38 ++++++++++++++ beacon_chain/types/src/random/public_key.rs | 10 ++++ beacon_chain/types/src/random/secret_key.rs | 19 +++++++ beacon_chain/types/src/random/signature.rs | 13 +++++ beacon_chain/types/src/slashable_vote_data.rs | 41 ++++++++-------- 21 files changed, 422 insertions(+), 181 deletions(-) create mode 100644 beacon_chain/types/src/random/aggregate_signature.rs create mode 100644 beacon_chain/types/src/random/bitfield.rs create mode 100644 beacon_chain/types/src/random/hash256.rs create mode 100644 beacon_chain/types/src/random/mod.rs create mode 100644 beacon_chain/types/src/random/public_key.rs create mode 100644 beacon_chain/types/src/random/secret_key.rs create mode 100644 beacon_chain/types/src/random/signature.rs diff --git a/beacon_chain/types/Cargo.toml b/beacon_chain/types/Cargo.toml index cf20f69c0..f49702280 100644 --- a/beacon_chain/types/Cargo.toml +++ b/beacon_chain/types/Cargo.toml @@ -2,10 +2,11 @@ name = "types" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] bls = { path = "../utils/bls" } boolean-bitfield = { path = "../utils/boolean-bitfield" } ethereum-types = "0.4.0" -rand = "0.3" +rand = "0.5.5" ssz = { path = "../utils/ssz" } diff --git a/beacon_chain/types/src/attestation.rs b/beacon_chain/types/src/attestation.rs index 40ee2173c..6e7c54d44 100644 --- a/beacon_chain/types/src/attestation.rs +++ b/beacon_chain/types/src/attestation.rs @@ -1,14 +1,8 @@ -use super::attestation_data::SSZ_ATTESTION_DATA_LENGTH; -use super::bls::{AggregateSignature, BLS_AGG_SIG_BYTE_SIZE}; -use super::ssz::{Decodable, DecodeError, Encodable, SszStream, LENGTH_BYTES}; +use super::bls::AggregateSignature; +use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::{AttestationData, Bitfield}; - -pub const MIN_SSZ_ATTESTION_RECORD_LENGTH: usize = { - SSZ_ATTESTION_DATA_LENGTH + // data - 5 + // participation_bitfield (assuming 1 byte of bitfield) - 5 + // custody_bitfield (assuming 1 byte of bitfield) - LENGTH_BYTES + BLS_AGG_SIG_BYTE_SIZE // aggregate sig -}; +use crate::random::TestRandom; +use rand::RngCore; #[derive(Debug, Clone, PartialEq)] pub struct Attestation { @@ -55,30 +49,31 @@ impl Attestation { } } +impl TestRandom for Attestation { + fn random_for_test(rng: &mut T) -> Self { + Self { + data: <_>::random_for_test(rng), + participation_bitfield: <_>::random_for_test(rng), + custody_bitfield: <_>::random_for_test(rng), + aggregate_sig: <_>::random_for_test(rng), + } + } +} + #[cfg(test)] mod tests { use super::super::ssz::ssz_encode; use super::*; + use crate::random::TestRandom; + use rand::{prng::XorShiftRng, SeedableRng}; #[test] - pub fn test_attestation_record_min_ssz_length() { - let ar = Attestation::zero(); - let ssz = ssz_encode(&ar); + pub fn test_ssz_round_trip() { + let mut rng = XorShiftRng::from_seed([42; 16]); + let original = Attestation::random_for_test(&mut rng); - assert_eq!(ssz.len(), MIN_SSZ_ATTESTION_RECORD_LENGTH); - } - - #[test] - pub fn test_attestation_record_ssz_round_trip() { - let original = Attestation { - data: AttestationData::zero(), - participation_bitfield: Bitfield::from_bytes(&vec![17; 42][..]), - custody_bitfield: Bitfield::from_bytes(&vec![18; 12][..]), - aggregate_sig: AggregateSignature::new(), - }; - - let ssz = ssz_encode(&original); - let (decoded, _) = Attestation::ssz_decode(&ssz, 0).unwrap(); + let bytes = ssz_encode(&original); + let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); assert_eq!(original, decoded); } diff --git a/beacon_chain/types/src/attestation_data.rs b/beacon_chain/types/src/attestation_data.rs index d75c43b9d..57fcaa430 100644 --- a/beacon_chain/types/src/attestation_data.rs +++ b/beacon_chain/types/src/attestation_data.rs @@ -1,5 +1,7 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::Hash256; +use crate::random::TestRandom; +use rand::RngCore; pub const SSZ_ATTESTION_DATA_LENGTH: usize = { 8 + // slot @@ -83,27 +85,35 @@ impl Decodable for AttestationData { } } +impl TestRandom for AttestationData { + fn random_for_test(rng: &mut T) -> Self { + Self { + slot: <_>::random_for_test(rng), + shard: <_>::random_for_test(rng), + beacon_block_hash: <_>::random_for_test(rng), + epoch_boundary_hash: <_>::random_for_test(rng), + shard_block_hash: <_>::random_for_test(rng), + latest_crosslink_hash: <_>::random_for_test(rng), + justified_slot: <_>::random_for_test(rng), + justified_block_hash: <_>::random_for_test(rng), + } + } +} + #[cfg(test)] mod tests { use super::super::ssz::ssz_encode; use super::*; + use crate::random::TestRandom; + use rand::{prng::XorShiftRng, SeedableRng}; #[test] - pub fn test_attestation_record_ssz_round_trip() { - let original = AttestationData { - slot: 42, - shard: 16, - beacon_block_hash: Hash256::from("beacon".as_bytes()), - epoch_boundary_hash: Hash256::from("epoch".as_bytes()), - shard_block_hash: Hash256::from("shard".as_bytes()), - latest_crosslink_hash: Hash256::from("xlink".as_bytes()), - justified_slot: 8, - justified_block_hash: Hash256::from("justified".as_bytes()), - }; + pub fn test_ssz_round_trip() { + let mut rng = XorShiftRng::from_seed([42; 16]); + let original = AttestationData::random_for_test(&mut rng); - let ssz = ssz_encode(&original); - - let (decoded, _) = AttestationData::ssz_decode(&ssz, 0).unwrap(); + let bytes = ssz_encode(&original); + let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); assert_eq!(original, decoded); } diff --git a/beacon_chain/types/src/beacon_block.rs b/beacon_chain/types/src/beacon_block.rs index b2641cf84..8bbc91592 100644 --- a/beacon_chain/types/src/beacon_block.rs +++ b/beacon_chain/types/src/beacon_block.rs @@ -1,6 +1,8 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::{BeaconBlockBody, Hash256}; +use crate::random::TestRandom; use bls::AggregateSignature; +use rand::RngCore; #[derive(Debug, PartialEq, Clone, Default)] pub struct BeaconBlock { @@ -49,3 +51,36 @@ impl Decodable for BeaconBlock { )) } } + +impl TestRandom for BeaconBlock { + fn random_for_test(rng: &mut T) -> Self { + Self { + slot: <_>::random_for_test(rng), + parent_root: <_>::random_for_test(rng), + state_root: <_>::random_for_test(rng), + randao_reveal: <_>::random_for_test(rng), + candidate_pow_receipt_root: <_>::random_for_test(rng), + signature: <_>::random_for_test(rng), + body: <_>::random_for_test(rng), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::ssz::ssz_encode; + use super::*; + use crate::random::TestRandom; + use rand::{prng::XorShiftRng, SeedableRng}; + + #[test] + pub fn test_ssz_round_trip() { + let mut rng = XorShiftRng::from_seed([42; 16]); + let original = BeaconBlock::random_for_test(&mut rng); + + let bytes = ssz_encode(&original); + let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); + + assert_eq!(original, decoded); + } +} diff --git a/beacon_chain/types/src/beacon_block_body.rs b/beacon_chain/types/src/beacon_block_body.rs index f0c767155..e49ca35bc 100644 --- a/beacon_chain/types/src/beacon_block_body.rs +++ b/beacon_chain/types/src/beacon_block_body.rs @@ -1,5 +1,7 @@ -use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; +use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::{Attestation, CasperSlashing, Deposit, Exit, ProposerSlashing}; +use crate::random::TestRandom; +use rand::RngCore; #[derive(Debug, PartialEq, Clone, Default)] pub struct BeaconBlockBody { @@ -22,11 +24,11 @@ impl Encodable for BeaconBlockBody { impl Decodable for BeaconBlockBody { fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { - let (proposer_slashings, i) = decode_ssz_list(bytes, i)?; - let (casper_slashings, i) = decode_ssz_list(bytes, i)?; - let (attestations, i) = decode_ssz_list(bytes, i)?; - let (deposits, i) = decode_ssz_list(bytes, i)?; - let (exits, i) = decode_ssz_list(bytes, i)?; + let (proposer_slashings, i) = <_>::ssz_decode(bytes, i)?; + let (casper_slashings, i) = <_>::ssz_decode(bytes, i)?; + let (attestations, i) = <_>::ssz_decode(bytes, i)?; + let (deposits, i) = <_>::ssz_decode(bytes, i)?; + let (exits, i) = <_>::ssz_decode(bytes, i)?; Ok(( Self { @@ -40,3 +42,34 @@ impl Decodable for BeaconBlockBody { )) } } + +impl TestRandom for BeaconBlockBody { + fn random_for_test(rng: &mut T) -> Self { + Self { + proposer_slashings: <_>::random_for_test(rng), + casper_slashings: <_>::random_for_test(rng), + attestations: <_>::random_for_test(rng), + deposits: <_>::random_for_test(rng), + exits: <_>::random_for_test(rng), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::ssz::ssz_encode; + use super::*; + use crate::random::TestRandom; + use rand::{prng::XorShiftRng, SeedableRng}; + + #[test] + pub fn test_ssz_round_trip() { + let mut rng = XorShiftRng::from_seed([42; 16]); + let original = BeaconBlockBody::random_for_test(&mut rng); + + let bytes = ssz_encode(&original); + let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); + + assert_eq!(original, decoded); + } +} diff --git a/beacon_chain/types/src/casper_slashing.rs b/beacon_chain/types/src/casper_slashing.rs index dfa99cd6b..29fc620fc 100644 --- a/beacon_chain/types/src/casper_slashing.rs +++ b/beacon_chain/types/src/casper_slashing.rs @@ -1,5 +1,7 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::SlashableVoteData; +use crate::random::TestRandom; +use rand::RngCore; #[derive(Debug, PartialEq, Clone, Default)] pub struct CasperSlashing { @@ -10,7 +12,7 @@ pub struct CasperSlashing { impl Encodable for CasperSlashing { fn ssz_append(&self, s: &mut SszStream) { s.append(&self.slashable_vote_data_1); - s.append(&self.slashable_vote_data_1); + s.append(&self.slashable_vote_data_2); } } @@ -28,3 +30,31 @@ impl Decodable for CasperSlashing { )) } } + +impl TestRandom for CasperSlashing { + fn random_for_test(rng: &mut T) -> Self { + Self { + slashable_vote_data_1: <_>::random_for_test(rng), + slashable_vote_data_2: <_>::random_for_test(rng), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::ssz::ssz_encode; + use super::*; + use crate::random::TestRandom; + use rand::{prng::XorShiftRng, SeedableRng}; + + #[test] + pub fn test_ssz_round_trip() { + let mut rng = XorShiftRng::from_seed([42; 16]); + let original = CasperSlashing::random_for_test(&mut rng); + + let bytes = ssz_encode(&original); + let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); + + assert_eq!(original, decoded); + } +} diff --git a/beacon_chain/types/src/deposit.rs b/beacon_chain/types/src/deposit.rs index 7aa375828..2b0025fa4 100644 --- a/beacon_chain/types/src/deposit.rs +++ b/beacon_chain/types/src/deposit.rs @@ -1,5 +1,7 @@ -use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; +use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::{DepositData, Hash256}; +use crate::random::TestRandom; +use rand::RngCore; #[derive(Debug, PartialEq, Clone)] pub struct Deposit { @@ -18,7 +20,7 @@ impl Encodable for Deposit { impl Decodable for Deposit { fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { - let (merkle_branch, i) = decode_ssz_list(bytes, i)?; + let (merkle_branch, i) = <_>::ssz_decode(bytes, i)?; let (merkle_tree_index, i) = <_>::ssz_decode(bytes, i)?; let (deposit_data, i) = <_>::ssz_decode(bytes, i)?; @@ -33,37 +35,30 @@ impl Decodable for Deposit { } } +impl TestRandom for Deposit { + fn random_for_test(rng: &mut T) -> Self { + Self { + merkle_branch: <_>::random_for_test(rng), + merkle_tree_index: <_>::random_for_test(rng), + deposit_data: <_>::random_for_test(rng), + } + } +} + #[cfg(test)] mod tests { use super::super::ssz::ssz_encode; - use super::super::{DepositInput, Hash256}; use super::*; - use bls::{Keypair, Signature}; + use crate::random::TestRandom; + use rand::{prng::XorShiftRng, SeedableRng}; #[test] pub fn test_ssz_round_trip() { - let keypair = Keypair::random(); - - let original = Deposit { - merkle_branch: vec![ - Hash256::from("one".as_bytes()), - Hash256::from("two".as_bytes()), - ], - merkle_tree_index: 19, - deposit_data: DepositData { - deposit_input: DepositInput { - pubkey: keypair.pk, - withdrawal_credentials: Hash256::from("cats".as_bytes()), - randao_commitment: Hash256::from("dogs".as_bytes()), - proof_of_possession: Signature::new(&[42, 42], &keypair.sk), - }, - value: 12, - timestamp: 100, - }, - }; + let mut rng = XorShiftRng::from_seed([42; 16]); + let original = Deposit::random_for_test(&mut rng); let bytes = ssz_encode(&original); - let (decoded, _) = Deposit::ssz_decode(&bytes, 0).unwrap(); + let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); assert_eq!(original, decoded); } diff --git a/beacon_chain/types/src/deposit_data.rs b/beacon_chain/types/src/deposit_data.rs index 790beab28..a01a95cba 100644 --- a/beacon_chain/types/src/deposit_data.rs +++ b/beacon_chain/types/src/deposit_data.rs @@ -1,5 +1,7 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::DepositInput; +use crate::random::TestRandom; +use rand::RngCore; #[derive(Debug, PartialEq, Clone)] pub struct DepositData { @@ -33,30 +35,30 @@ impl Decodable for DepositData { } } +impl TestRandom for DepositData { + fn random_for_test(rng: &mut T) -> Self { + Self { + deposit_input: <_>::random_for_test(rng), + value: <_>::random_for_test(rng), + timestamp: <_>::random_for_test(rng), + } + } +} + #[cfg(test)] mod tests { use super::super::ssz::ssz_encode; - use super::super::Hash256; use super::*; - use bls::{Keypair, Signature}; + use crate::random::TestRandom; + use rand::{prng::XorShiftRng, SeedableRng}; #[test] pub fn test_ssz_round_trip() { - let keypair = Keypair::random(); - - let original = DepositData { - deposit_input: DepositInput { - pubkey: keypair.pk, - withdrawal_credentials: Hash256::from("cats".as_bytes()), - randao_commitment: Hash256::from("dogs".as_bytes()), - proof_of_possession: Signature::new(&[42, 42], &keypair.sk), - }, - value: 12, - timestamp: 100, - }; + let mut rng = XorShiftRng::from_seed([42; 16]); + let original = DepositData::random_for_test(&mut rng); let bytes = ssz_encode(&original); - let (decoded, _) = DepositData::ssz_decode(&bytes, 0).unwrap(); + let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); assert_eq!(original, decoded); } diff --git a/beacon_chain/types/src/deposit_input.rs b/beacon_chain/types/src/deposit_input.rs index d9b3e9864..c57437e86 100644 --- a/beacon_chain/types/src/deposit_input.rs +++ b/beacon_chain/types/src/deposit_input.rs @@ -1,6 +1,8 @@ use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; use super::Hash256; +use crate::random::TestRandom; use bls::{PublicKey, Signature}; +use rand::RngCore; #[derive(Debug, PartialEq, Clone)] pub struct DepositInput { @@ -39,25 +41,31 @@ impl Decodable for DepositInput { } } +impl TestRandom for DepositInput { + fn random_for_test(rng: &mut T) -> Self { + Self { + pubkey: <_>::random_for_test(rng), + withdrawal_credentials: <_>::random_for_test(rng), + randao_commitment: <_>::random_for_test(rng), + proof_of_possession: <_>::random_for_test(rng), + } + } +} + #[cfg(test)] mod tests { use super::super::ssz::ssz_encode; use super::*; - use bls::{Keypair, Signature}; + use crate::random::TestRandom; + use rand::{prng::XorShiftRng, SeedableRng}; #[test] pub fn test_ssz_round_trip() { - let keypair = Keypair::random(); - - let original = DepositInput { - pubkey: keypair.pk, - withdrawal_credentials: Hash256::from("cats".as_bytes()), - randao_commitment: Hash256::from("dogs".as_bytes()), - proof_of_possession: Signature::new(&[42, 42], &keypair.sk), - }; + let mut rng = XorShiftRng::from_seed([42; 16]); + let original = DepositInput::random_for_test(&mut rng); let bytes = ssz_encode(&original); - let (decoded, _) = DepositInput::ssz_decode(&bytes, 0).unwrap(); + let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); assert_eq!(original, decoded); } diff --git a/beacon_chain/types/src/exit.rs b/beacon_chain/types/src/exit.rs index b32ec3af6..cd0b79b35 100644 --- a/beacon_chain/types/src/exit.rs +++ b/beacon_chain/types/src/exit.rs @@ -1,11 +1,13 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; -use bls::AggregateSignature; +use crate::random::TestRandom; +use bls::Signature; +use rand::RngCore; #[derive(Debug, PartialEq, Clone)] pub struct Exit { pub slot: u64, pub validator_index: u32, - pub signature: AggregateSignature, + pub signature: Signature, } impl Encodable for Exit { @@ -33,27 +35,30 @@ impl Decodable for Exit { } } +impl TestRandom for Exit { + fn random_for_test(rng: &mut T) -> Self { + Self { + slot: <_>::random_for_test(rng), + validator_index: <_>::random_for_test(rng), + signature: <_>::random_for_test(rng), + } + } +} + #[cfg(test)] mod tests { use super::super::ssz::ssz_encode; use super::*; - use bls::{AggregateSignature, Keypair, Signature}; + use crate::random::TestRandom; + use rand::{prng::XorShiftRng, SeedableRng}; #[test] pub fn test_ssz_round_trip() { - let keypair = Keypair::random(); - let single_signature = Signature::new(&[42, 42], &keypair.sk); - let mut signature = AggregateSignature::new(); - signature.add(&single_signature); - - let original = Exit { - slot: 42, - validator_index: 12, - signature, - }; + let mut rng = XorShiftRng::from_seed([42; 16]); + let original = Exit::random_for_test(&mut rng); let bytes = ssz_encode(&original); - let (decoded, _) = Exit::ssz_decode(&bytes, 0).unwrap(); + let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); assert_eq!(original, decoded); } diff --git a/beacon_chain/types/src/lib.rs b/beacon_chain/types/src/lib.rs index e24e77b93..71d6f10e6 100644 --- a/beacon_chain/types/src/lib.rs +++ b/beacon_chain/types/src/lib.rs @@ -3,6 +3,8 @@ extern crate boolean_bitfield; extern crate ethereum_types; extern crate ssz; +mod random; + pub mod active_state; pub mod attestation_data; pub mod attestation; @@ -32,29 +34,29 @@ pub mod validator_registration; use self::ethereum_types::{H160, H256, U256}; use std::collections::HashMap; -pub use active_state::ActiveState; -pub use attestation_data::AttestationData; -pub use attestation::Attestation; -pub use beacon_block::BeaconBlock; -pub use beacon_block_body::BeaconBlockBody; -pub use beacon_state::BeaconState; -pub use casper_slashing::CasperSlashing; -pub use chain_config::ChainConfig; -pub use crosslink_record::CrosslinkRecord; -pub use crystallized_state::CrystallizedState; -pub use deposit::Deposit; -pub use deposit_data::DepositData; -pub use deposit_input::DepositInput; -pub use exit::Exit; -pub use fork_data::ForkData; -pub use pending_attestation_record::PendingAttestationRecord; -pub use proposal_signed_data::ProposalSignedData; -pub use proposer_slashing::ProposerSlashing; -pub use slashable_vote_data::SlashableVoteData; -pub use shard_and_committee::ShardAndCommittee; -pub use special_record::{SpecialRecord, SpecialRecordKind}; -pub use validator_record::{ValidatorRecord, ValidatorStatus}; -pub use validator_registration::ValidatorRegistration; +pub use crate::active_state::ActiveState; +pub use crate::attestation_data::AttestationData; +pub use crate::attestation::Attestation; +pub use crate::beacon_block::BeaconBlock; +pub use crate::beacon_block_body::BeaconBlockBody; +pub use crate::beacon_state::BeaconState; +pub use crate::casper_slashing::CasperSlashing; +pub use crate::chain_config::ChainConfig; +pub use crate::crosslink_record::CrosslinkRecord; +pub use crate::crystallized_state::CrystallizedState; +pub use crate::deposit::Deposit; +pub use crate::deposit_data::DepositData; +pub use crate::deposit_input::DepositInput; +pub use crate::exit::Exit; +pub use crate::fork_data::ForkData; +pub use crate::pending_attestation_record::PendingAttestationRecord; +pub use crate::proposal_signed_data::ProposalSignedData; +pub use crate::proposer_slashing::ProposerSlashing; +pub use crate::slashable_vote_data::SlashableVoteData; +pub use crate::shard_and_committee::ShardAndCommittee; +pub use crate::special_record::{SpecialRecord, SpecialRecordKind}; +pub use crate::validator_record::{ValidatorRecord, ValidatorStatus}; +pub use crate::validator_registration::ValidatorRegistration; pub type Hash256 = H256; pub type Address = H160; diff --git a/beacon_chain/types/src/proposal_signed_data.rs b/beacon_chain/types/src/proposal_signed_data.rs index f44ecdd41..6a038d0eb 100644 --- a/beacon_chain/types/src/proposal_signed_data.rs +++ b/beacon_chain/types/src/proposal_signed_data.rs @@ -1,5 +1,7 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::Hash256; +use crate::random::TestRandom; +use rand::RngCore; #[derive(Debug, PartialEq, Clone, Default)] pub struct ProposalSignedData { @@ -33,21 +35,30 @@ impl Decodable for ProposalSignedData { } } +impl TestRandom for ProposalSignedData { + fn random_for_test(rng: &mut T) -> Self { + Self { + slot: <_>::random_for_test(rng), + shard: <_>::random_for_test(rng), + block_root: <_>::random_for_test(rng), + } + } +} + #[cfg(test)] mod tests { use super::super::ssz::ssz_encode; use super::*; + use crate::random::TestRandom; + use rand::{prng::XorShiftRng, SeedableRng}; #[test] pub fn test_ssz_round_trip() { - let original = ProposalSignedData { - slot: 42, - shard: 120, - block_root: Hash256::from("cats".as_bytes()), - }; + let mut rng = XorShiftRng::from_seed([42; 16]); + let original = ProposalSignedData::random_for_test(&mut rng); let bytes = ssz_encode(&original); - let (decoded, _) = ProposalSignedData::ssz_decode(&bytes, 0).unwrap(); + let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); assert_eq!(original, decoded); } diff --git a/beacon_chain/types/src/proposer_slashing.rs b/beacon_chain/types/src/proposer_slashing.rs index b8d597283..1e2b22b1d 100644 --- a/beacon_chain/types/src/proposer_slashing.rs +++ b/beacon_chain/types/src/proposer_slashing.rs @@ -1,6 +1,8 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::ProposalSignedData; +use crate::random::TestRandom; use bls::Signature; +use rand::RngCore; #[derive(Debug, PartialEq, Clone, Default)] pub struct ProposerSlashing { @@ -42,35 +44,32 @@ impl Decodable for ProposerSlashing { } } +impl TestRandom for ProposerSlashing { + fn random_for_test(rng: &mut T) -> Self { + Self { + proposer_index: <_>::random_for_test(rng), + proposal_data_1: <_>::random_for_test(rng), + proposal_signature_1: <_>::random_for_test(rng), + proposal_data_2: <_>::random_for_test(rng), + proposal_signature_2: <_>::random_for_test(rng), + } + } +} + #[cfg(test)] mod tests { use super::super::ssz::ssz_encode; - use super::super::Hash256; use super::*; - use bls::{Keypair, Signature}; + use crate::random::TestRandom; + use rand::{prng::XorShiftRng, SeedableRng}; #[test] pub fn test_ssz_round_trip() { - let keypair = Keypair::random(); - - let original = ProposerSlashing { - proposer_index: 42, - proposal_data_1: ProposalSignedData { - slot: 45, - shard: 110, - block_root: Hash256::from("cats".as_bytes()), - }, - proposal_signature_1: Signature::new(&[42, 42], &keypair.sk), - proposal_data_2: ProposalSignedData { - slot: 1, - shard: 260, - block_root: Hash256::from("lol".as_bytes()), - }, - proposal_signature_2: Signature::new(&[7, 8], &keypair.sk), - }; + let mut rng = XorShiftRng::from_seed([42; 16]); + let original = ProposerSlashing::random_for_test(&mut rng); let bytes = ssz_encode(&original); - let (decoded, _) = ProposerSlashing::ssz_decode(&bytes, 0).unwrap(); + let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); assert_eq!(original, decoded); } diff --git a/beacon_chain/types/src/random/aggregate_signature.rs b/beacon_chain/types/src/random/aggregate_signature.rs new file mode 100644 index 000000000..6a15f7366 --- /dev/null +++ b/beacon_chain/types/src/random/aggregate_signature.rs @@ -0,0 +1,12 @@ +use super::TestRandom; +use bls::{AggregateSignature, Signature}; +use rand::RngCore; + +impl TestRandom for AggregateSignature { + fn random_for_test(rng: &mut T) -> Self { + let signature = Signature::random_for_test(rng); + let mut aggregate_signature = AggregateSignature::new(); + aggregate_signature.add(&signature); + aggregate_signature + } +} diff --git a/beacon_chain/types/src/random/bitfield.rs b/beacon_chain/types/src/random/bitfield.rs new file mode 100644 index 000000000..15011edd9 --- /dev/null +++ b/beacon_chain/types/src/random/bitfield.rs @@ -0,0 +1,11 @@ +use super::super::Bitfield; +use super::TestRandom; +use rand::RngCore; + +impl TestRandom for Bitfield { + fn random_for_test(rng: &mut T) -> Self { + let mut raw_bytes = vec![0; 32]; + rng.fill_bytes(&mut raw_bytes); + Bitfield::from_bytes(&raw_bytes) + } +} diff --git a/beacon_chain/types/src/random/hash256.rs b/beacon_chain/types/src/random/hash256.rs new file mode 100644 index 000000000..98f5e7899 --- /dev/null +++ b/beacon_chain/types/src/random/hash256.rs @@ -0,0 +1,11 @@ +use super::TestRandom; +use crate::Hash256; +use rand::RngCore; + +impl TestRandom for Hash256 { + fn random_for_test(rng: &mut T) -> Self { + let mut key_bytes = vec![0; 32]; + rng.fill_bytes(&mut key_bytes); + Hash256::from(&key_bytes[..]) + } +} diff --git a/beacon_chain/types/src/random/mod.rs b/beacon_chain/types/src/random/mod.rs new file mode 100644 index 000000000..0087f8152 --- /dev/null +++ b/beacon_chain/types/src/random/mod.rs @@ -0,0 +1,38 @@ +use rand::RngCore; + +pub mod aggregate_signature; +pub mod bitfield; +pub mod hash256; +pub mod signature; +pub mod secret_key; +pub mod public_key; + +pub trait TestRandom +where T: RngCore +{ + fn random_for_test(rng: &mut T) -> Self; +} + +impl TestRandom for u64 { + fn random_for_test(rng: &mut T) -> Self { + rng.next_u64() + } +} + +impl TestRandom for u32 { + fn random_for_test(rng: &mut T) -> Self { + rng.next_u32() + } +} + +impl TestRandom for Vec +where U: TestRandom +{ + fn random_for_test(rng: &mut T) -> Self { + vec![ + ::random_for_test(rng), + ::random_for_test(rng), + ::random_for_test(rng), + ] + } +} diff --git a/beacon_chain/types/src/random/public_key.rs b/beacon_chain/types/src/random/public_key.rs new file mode 100644 index 000000000..bfccd3e53 --- /dev/null +++ b/beacon_chain/types/src/random/public_key.rs @@ -0,0 +1,10 @@ +use super::TestRandom; +use bls::{PublicKey, SecretKey}; +use rand::RngCore; + +impl TestRandom for PublicKey { + fn random_for_test(rng: &mut T) -> Self { + let secret_key = SecretKey::random_for_test(rng); + PublicKey::from_secret_key(&secret_key) + } +} diff --git a/beacon_chain/types/src/random/secret_key.rs b/beacon_chain/types/src/random/secret_key.rs new file mode 100644 index 000000000..17481c3de --- /dev/null +++ b/beacon_chain/types/src/random/secret_key.rs @@ -0,0 +1,19 @@ +use super::TestRandom; +use bls::SecretKey; +use rand::RngCore; + +impl TestRandom for SecretKey { + fn random_for_test(rng: &mut T) -> Self { + let mut key_bytes = vec![0; 48]; + rng.fill_bytes(&mut key_bytes); + /* + * An `unreachable!` is used here as there's no reason why you cannot constuct a key from a + * fixed-length byte slice. Also, this should only be used during testing so a panic is + * acceptable. + */ + match SecretKey::from_bytes(&key_bytes) { + Ok(key) => key, + Err(_) => unreachable!(), + } + } +} diff --git a/beacon_chain/types/src/random/signature.rs b/beacon_chain/types/src/random/signature.rs new file mode 100644 index 000000000..9ec7aec60 --- /dev/null +++ b/beacon_chain/types/src/random/signature.rs @@ -0,0 +1,13 @@ +use super::TestRandom; +use bls::{SecretKey, Signature}; +use rand::RngCore; + +impl TestRandom for Signature { + fn random_for_test(rng: &mut T) -> Self { + let secret_key = SecretKey::random_for_test(rng); + let mut message = vec![0; 32]; + rng.fill_bytes(&mut message); + + Signature::new(&message, &secret_key) + } +} diff --git a/beacon_chain/types/src/slashable_vote_data.rs b/beacon_chain/types/src/slashable_vote_data.rs index 2bd489978..150b40081 100644 --- a/beacon_chain/types/src/slashable_vote_data.rs +++ b/beacon_chain/types/src/slashable_vote_data.rs @@ -1,6 +1,8 @@ -use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; +use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::AttestationData; +use crate::random::TestRandom; use bls::AggregateSignature; +use rand::RngCore; #[derive(Debug, PartialEq, Clone, Default)] pub struct SlashableVoteData { @@ -21,8 +23,8 @@ impl Encodable for SlashableVoteData { impl Decodable for SlashableVoteData { fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { - let (aggregate_signature_poc_0_indices, i) = decode_ssz_list(bytes, i)?; - let (aggregate_signature_poc_1_indices, i) = decode_ssz_list(bytes, i)?; + let (aggregate_signature_poc_0_indices, i) = <_>::ssz_decode(bytes, i)?; + let (aggregate_signature_poc_1_indices, i) = <_>::ssz_decode(bytes, i)?; let (data, i) = <_>::ssz_decode(bytes, i)?; let (aggregate_signature, i) = <_>::ssz_decode(bytes, i)?; @@ -38,32 +40,31 @@ impl Decodable for SlashableVoteData { } } +impl TestRandom for SlashableVoteData { + fn random_for_test(rng: &mut T) -> Self { + Self { + aggregate_signature_poc_0_indices: <_>::random_for_test(rng), + aggregate_signature_poc_1_indices: <_>::random_for_test(rng), + data: <_>::random_for_test(rng), + aggregate_signature: <_>::random_for_test(rng), + } + } +} + #[cfg(test)] mod tests { use super::super::ssz::ssz_encode; - use super::super::Hash256; use super::*; + use crate::random::TestRandom; + use rand::{prng::XorShiftRng, SeedableRng}; #[test] pub fn test_ssz_round_trip() { - let original = SlashableVoteData { - aggregate_signature_poc_0_indices: vec![0, 1, 2], - aggregate_signature_poc_1_indices: vec![42, 42, 42], - data: AttestationData { - slot: 42, - shard: 16, - beacon_block_hash: Hash256::from("beacon".as_bytes()), - epoch_boundary_hash: Hash256::from("epoch".as_bytes()), - shard_block_hash: Hash256::from("shard".as_bytes()), - latest_crosslink_hash: Hash256::from("xlink".as_bytes()), - justified_slot: 8, - justified_block_hash: Hash256::from("justified".as_bytes()), - }, - aggregate_signature: AggregateSignature::new(), - }; + let mut rng = XorShiftRng::from_seed([42; 16]); + let original = SlashableVoteData::random_for_test(&mut rng); let bytes = ssz_encode(&original); - let (decoded, _) = SlashableVoteData::ssz_decode(&bytes, 0).unwrap(); + let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); assert_eq!(original, decoded); } From a42d931d66ae5ee504119cd060a7a94b10831743 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 24 Dec 2018 10:00:52 +1100 Subject: [PATCH 09/16] Remove `state-transition` crate --- Cargo.toml | 1 - beacon_chain/chain/Cargo.toml | 1 - beacon_chain/state-transition/Cargo.toml | 7 - beacon_chain/state-transition/src/lib.rs | 194 ----------------------- 4 files changed, 203 deletions(-) delete mode 100644 beacon_chain/state-transition/Cargo.toml delete mode 100644 beacon_chain/state-transition/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 835d37edc..7e4641298 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,6 @@ members = [ "beacon_chain/chain", "beacon_chain/naive_fork_choice", "beacon_chain/spec", - "beacon_chain/state-transition", "beacon_chain/types", "beacon_chain/utils/bls", "beacon_chain/utils/boolean-bitfield", diff --git a/beacon_chain/chain/Cargo.toml b/beacon_chain/chain/Cargo.toml index aa0f48c62..4430dbe5b 100644 --- a/beacon_chain/chain/Cargo.toml +++ b/beacon_chain/chain/Cargo.toml @@ -8,7 +8,6 @@ bls = { path = "../utils/bls" } db = { path = "../../lighthouse/db" } naive_fork_choice = { path = "../naive_fork_choice" } ssz = { path = "../utils/ssz" } -state-transition = { path = "../state-transition" } types = { path = "../types" } validator_induction = { path = "../validator_induction" } validator_shuffling = { path = "../validator_shuffling" } diff --git a/beacon_chain/state-transition/Cargo.toml b/beacon_chain/state-transition/Cargo.toml deleted file mode 100644 index 7beb8f613..000000000 --- a/beacon_chain/state-transition/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "state-transition" -version = "0.1.0" -authors = ["Paul Hauner "] - -[dependencies] -types = { path = "../types" } diff --git a/beacon_chain/state-transition/src/lib.rs b/beacon_chain/state-transition/src/lib.rs deleted file mode 100644 index ee8d841e6..000000000 --- a/beacon_chain/state-transition/src/lib.rs +++ /dev/null @@ -1,194 +0,0 @@ -extern crate types; - -use types::{ActiveState, BeaconBlock, Hash256}; - -#[derive(Debug, PartialEq)] -pub enum StateTransitionError { - BlockSlotBeforeRecalcSlot, - InvalidParentHashes, - DBError(String), -} - -pub fn extend_active_state( - act_state: &ActiveState, - block: &BeaconBlock, - block_hash: &Hash256, -) -> Result { - /* - * Extend the pending attestations in the active state with the new attestations included - * in the block. - * - * Using the concat method to avoid reallocations. - */ - let pending_attestations = - [&act_state.pending_attestations[..], &block.attestations[..]].concat(); - - /* - * Extend the pending specials in the active state with the new specials included in the - * block. - * - * Using the concat method to avoid reallocations. - */ - let pending_specials = [&act_state.pending_specials[..], &block.specials[..]].concat(); - - /* - * Update the active state recent_block_hashes: - * - * - Drop the hash from the earliest position. - * - Push the block_hash into the latest position. - * - * Using the concat method to avoid reallocations. - */ - let (_first_hash, last_hashes) = act_state - .recent_block_hashes - .split_first() - .ok_or(StateTransitionError::InvalidParentHashes)?; - let new_hash = &[block_hash.clone()]; - let recent_block_hashes = [&last_hashes, &new_hash[..]].concat(); - - /* - * The new `randao_mix` is set to the XOR of the previous active state randao mix and the - * randao reveal in this block. - */ - let randao_mix = act_state.randao_mix ^ block.randao_reveal; - - Ok(ActiveState { - pending_attestations, - pending_specials, - recent_block_hashes, - randao_mix, - }) -} - -#[cfg(test)] -mod tests { - use super::*; - use types::SpecialRecord; - - fn empty_active_state() -> ActiveState { - ActiveState { - pending_attestations: vec![], - pending_specials: vec![], - recent_block_hashes: vec![], - randao_mix: Hash256::zero(), - } - } - - #[test] - fn test_extend_active_state_minimal() { - let mut act_state = empty_active_state(); - - let parent_hash = Hash256::from("parent_hash".as_bytes()); - act_state.recent_block_hashes = vec![parent_hash]; - - let block = BeaconBlock::zero(); - let block_hash = Hash256::from("block_hash".as_bytes()); - - let new_act_state = extend_active_state(&act_state, &block, &block_hash).unwrap(); - - assert_eq!(new_act_state.pending_attestations, vec![]); - assert_eq!(new_act_state.pending_specials, vec![]); - assert_eq!(new_act_state.recent_block_hashes, vec![block_hash]); - assert_eq!(new_act_state.randao_mix, Hash256::zero()); - } - - #[test] - fn test_extend_active_state_specials() { - let mut act_state = empty_active_state(); - - let parent_hash = Hash256::from("parent_hash".as_bytes()); - act_state.recent_block_hashes = vec![parent_hash]; - - let mut block = BeaconBlock::zero(); - let special = SpecialRecord { - kind: 0, - data: vec![42, 42], - }; - - block.specials.push(special.clone()); - - let block_hash = Hash256::from("block_hash".as_bytes()); - - let new_act_state = extend_active_state(&act_state, &block, &block_hash).unwrap(); - - assert_eq!(new_act_state.pending_attestations, vec![]); - assert_eq!(new_act_state.pending_specials, vec![special.clone()]); - assert_eq!(new_act_state.recent_block_hashes, vec![block_hash]); - assert_eq!(new_act_state.randao_mix, Hash256::zero()); - - let new_new_act_state = extend_active_state(&new_act_state, &block, &block_hash).unwrap(); - - assert_eq!(new_new_act_state.pending_attestations, vec![]); - assert_eq!( - new_new_act_state.pending_specials, - vec![special.clone(), special.clone()] - ); - assert_eq!(new_new_act_state.recent_block_hashes, vec![block_hash]); - assert_eq!(new_new_act_state.randao_mix, Hash256::zero()); - } - - #[test] - fn test_extend_active_state_empty_recent_block_hashes() { - let act_state = empty_active_state(); - - let block = BeaconBlock::zero(); - - let block_hash = Hash256::from("block_hash".as_bytes()); - - let result = extend_active_state(&act_state, &block, &block_hash); - - assert_eq!(result, Err(StateTransitionError::InvalidParentHashes)); - } - - #[test] - fn test_extend_active_recent_block_hashes() { - let mut act_state = empty_active_state(); - - let parent_hashes = vec![ - Hash256::from("one".as_bytes()), - Hash256::from("two".as_bytes()), - Hash256::from("three".as_bytes()), - ]; - act_state.recent_block_hashes = parent_hashes.clone(); - - let block = BeaconBlock::zero(); - - let block_hash = Hash256::from("four".as_bytes()); - - let new_act_state = extend_active_state(&act_state, &block, &block_hash).unwrap(); - - assert_eq!(new_act_state.pending_attestations, vec![]); - assert_eq!(new_act_state.pending_specials, vec![]); - assert_eq!( - new_act_state.recent_block_hashes, - vec![ - Hash256::from("two".as_bytes()), - Hash256::from("three".as_bytes()), - Hash256::from("four".as_bytes()), - ] - ); - assert_eq!(new_act_state.randao_mix, Hash256::zero()); - } - - #[test] - fn test_extend_active_state_randao() { - let mut act_state = empty_active_state(); - - let parent_hash = Hash256::from("parent_hash".as_bytes()); - act_state.recent_block_hashes = vec![parent_hash]; - - act_state.randao_mix = Hash256::from(0b00000000); - - let mut block = BeaconBlock::zero(); - block.randao_reveal = Hash256::from(0b00000001); - - let block_hash = Hash256::from("block_hash".as_bytes()); - - let new_act_state = extend_active_state(&act_state, &block, &block_hash).unwrap(); - - assert_eq!(new_act_state.pending_attestations, vec![]); - assert_eq!(new_act_state.pending_specials, vec![]); - assert_eq!(new_act_state.recent_block_hashes, vec![block_hash]); - assert_eq!(new_act_state.randao_mix, Hash256::from(0b00000001)); - } -} From b95395d1e157ff2a4b902a646a3b83f0b1d8c0fe Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 25 Dec 2018 10:36:49 +1100 Subject: [PATCH 10/16] Rename `types::random` `types::test_utils` --- beacon_chain/types/src/attestation.rs | 4 ++-- beacon_chain/types/src/attestation_data.rs | 4 ++-- beacon_chain/types/src/beacon_block.rs | 4 ++-- beacon_chain/types/src/beacon_block_body.rs | 4 ++-- beacon_chain/types/src/casper_slashing.rs | 4 ++-- beacon_chain/types/src/deposit.rs | 5 ++--- beacon_chain/types/src/deposit_data.rs | 4 ++-- beacon_chain/types/src/deposit_input.rs | 4 ++-- beacon_chain/types/src/exit.rs | 4 ++-- beacon_chain/types/src/lib.rs | 2 +- beacon_chain/types/src/proposal_signed_data.rs | 4 ++-- beacon_chain/types/src/proposer_slashing.rs | 4 ++-- beacon_chain/types/src/slashable_vote_data.rs | 4 ++-- .../types/src/{random => test_utils}/aggregate_signature.rs | 0 beacon_chain/types/src/{random => test_utils}/bitfield.rs | 0 beacon_chain/types/src/{random => test_utils}/hash256.rs | 0 beacon_chain/types/src/{random => test_utils}/mod.rs | 2 ++ beacon_chain/types/src/{random => test_utils}/public_key.rs | 0 beacon_chain/types/src/{random => test_utils}/secret_key.rs | 0 beacon_chain/types/src/{random => test_utils}/signature.rs | 0 20 files changed, 27 insertions(+), 26 deletions(-) rename beacon_chain/types/src/{random => test_utils}/aggregate_signature.rs (100%) rename beacon_chain/types/src/{random => test_utils}/bitfield.rs (100%) rename beacon_chain/types/src/{random => test_utils}/hash256.rs (100%) rename beacon_chain/types/src/{random => test_utils}/mod.rs (93%) rename beacon_chain/types/src/{random => test_utils}/public_key.rs (100%) rename beacon_chain/types/src/{random => test_utils}/secret_key.rs (100%) rename beacon_chain/types/src/{random => test_utils}/signature.rs (100%) diff --git a/beacon_chain/types/src/attestation.rs b/beacon_chain/types/src/attestation.rs index 6e7c54d44..7a94eee51 100644 --- a/beacon_chain/types/src/attestation.rs +++ b/beacon_chain/types/src/attestation.rs @@ -1,7 +1,7 @@ use super::bls::AggregateSignature; use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::{AttestationData, Bitfield}; -use crate::random::TestRandom; +use crate::test_utils::TestRandom; use rand::RngCore; #[derive(Debug, Clone, PartialEq)] @@ -64,7 +64,7 @@ impl TestRandom for Attestation { mod tests { use super::super::ssz::ssz_encode; use super::*; - use crate::random::TestRandom; + use crate::test_utils::TestRandom; use rand::{prng::XorShiftRng, SeedableRng}; #[test] diff --git a/beacon_chain/types/src/attestation_data.rs b/beacon_chain/types/src/attestation_data.rs index 57fcaa430..616c52d79 100644 --- a/beacon_chain/types/src/attestation_data.rs +++ b/beacon_chain/types/src/attestation_data.rs @@ -1,6 +1,6 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::Hash256; -use crate::random::TestRandom; +use crate::test_utils::TestRandom; use rand::RngCore; pub const SSZ_ATTESTION_DATA_LENGTH: usize = { @@ -104,7 +104,7 @@ impl TestRandom for AttestationData { mod tests { use super::super::ssz::ssz_encode; use super::*; - use crate::random::TestRandom; + use crate::test_utils::TestRandom; use rand::{prng::XorShiftRng, SeedableRng}; #[test] diff --git a/beacon_chain/types/src/beacon_block.rs b/beacon_chain/types/src/beacon_block.rs index 8bbc91592..b6ac9e9e0 100644 --- a/beacon_chain/types/src/beacon_block.rs +++ b/beacon_chain/types/src/beacon_block.rs @@ -1,6 +1,6 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::{BeaconBlockBody, Hash256}; -use crate::random::TestRandom; +use crate::test_utils::TestRandom; use bls::AggregateSignature; use rand::RngCore; @@ -70,7 +70,7 @@ impl TestRandom for BeaconBlock { mod tests { use super::super::ssz::ssz_encode; use super::*; - use crate::random::TestRandom; + use crate::test_utils::TestRandom; use rand::{prng::XorShiftRng, SeedableRng}; #[test] diff --git a/beacon_chain/types/src/beacon_block_body.rs b/beacon_chain/types/src/beacon_block_body.rs index e49ca35bc..f5ac22343 100644 --- a/beacon_chain/types/src/beacon_block_body.rs +++ b/beacon_chain/types/src/beacon_block_body.rs @@ -1,6 +1,6 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::{Attestation, CasperSlashing, Deposit, Exit, ProposerSlashing}; -use crate::random::TestRandom; +use crate::test_utils::TestRandom; use rand::RngCore; #[derive(Debug, PartialEq, Clone, Default)] @@ -59,7 +59,7 @@ impl TestRandom for BeaconBlockBody { mod tests { use super::super::ssz::ssz_encode; use super::*; - use crate::random::TestRandom; + use crate::test_utils::TestRandom; use rand::{prng::XorShiftRng, SeedableRng}; #[test] diff --git a/beacon_chain/types/src/casper_slashing.rs b/beacon_chain/types/src/casper_slashing.rs index 29fc620fc..a972f2248 100644 --- a/beacon_chain/types/src/casper_slashing.rs +++ b/beacon_chain/types/src/casper_slashing.rs @@ -1,6 +1,6 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::SlashableVoteData; -use crate::random::TestRandom; +use crate::test_utils::TestRandom; use rand::RngCore; #[derive(Debug, PartialEq, Clone, Default)] @@ -44,7 +44,7 @@ impl TestRandom for CasperSlashing { mod tests { use super::super::ssz::ssz_encode; use super::*; - use crate::random::TestRandom; + use crate::test_utils::TestRandom; use rand::{prng::XorShiftRng, SeedableRng}; #[test] diff --git a/beacon_chain/types/src/deposit.rs b/beacon_chain/types/src/deposit.rs index 2b0025fa4..9d84bc278 100644 --- a/beacon_chain/types/src/deposit.rs +++ b/beacon_chain/types/src/deposit.rs @@ -1,6 +1,6 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::{DepositData, Hash256}; -use crate::random::TestRandom; +use crate::test_utils::TestRandom; use rand::RngCore; #[derive(Debug, PartialEq, Clone)] @@ -49,8 +49,7 @@ impl TestRandom for Deposit { mod tests { use super::super::ssz::ssz_encode; use super::*; - use crate::random::TestRandom; - use rand::{prng::XorShiftRng, SeedableRng}; + use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; #[test] pub fn test_ssz_round_trip() { diff --git a/beacon_chain/types/src/deposit_data.rs b/beacon_chain/types/src/deposit_data.rs index a01a95cba..b236709d2 100644 --- a/beacon_chain/types/src/deposit_data.rs +++ b/beacon_chain/types/src/deposit_data.rs @@ -1,6 +1,6 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::DepositInput; -use crate::random::TestRandom; +use crate::test_utils::TestRandom; use rand::RngCore; #[derive(Debug, PartialEq, Clone)] @@ -49,7 +49,7 @@ impl TestRandom for DepositData { mod tests { use super::super::ssz::ssz_encode; use super::*; - use crate::random::TestRandom; + use crate::test_utils::TestRandom; use rand::{prng::XorShiftRng, SeedableRng}; #[test] diff --git a/beacon_chain/types/src/deposit_input.rs b/beacon_chain/types/src/deposit_input.rs index c57437e86..41b579cda 100644 --- a/beacon_chain/types/src/deposit_input.rs +++ b/beacon_chain/types/src/deposit_input.rs @@ -1,6 +1,6 @@ use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; use super::Hash256; -use crate::random::TestRandom; +use crate::test_utils::TestRandom; use bls::{PublicKey, Signature}; use rand::RngCore; @@ -56,7 +56,7 @@ impl TestRandom for DepositInput { mod tests { use super::super::ssz::ssz_encode; use super::*; - use crate::random::TestRandom; + use crate::test_utils::TestRandom; use rand::{prng::XorShiftRng, SeedableRng}; #[test] diff --git a/beacon_chain/types/src/exit.rs b/beacon_chain/types/src/exit.rs index cd0b79b35..6a6d57305 100644 --- a/beacon_chain/types/src/exit.rs +++ b/beacon_chain/types/src/exit.rs @@ -1,5 +1,5 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; -use crate::random::TestRandom; +use crate::test_utils::TestRandom; use bls::Signature; use rand::RngCore; @@ -49,7 +49,7 @@ impl TestRandom for Exit { mod tests { use super::super::ssz::ssz_encode; use super::*; - use crate::random::TestRandom; + use crate::test_utils::TestRandom; use rand::{prng::XorShiftRng, SeedableRng}; #[test] diff --git a/beacon_chain/types/src/lib.rs b/beacon_chain/types/src/lib.rs index 71d6f10e6..0d2524195 100644 --- a/beacon_chain/types/src/lib.rs +++ b/beacon_chain/types/src/lib.rs @@ -3,7 +3,7 @@ extern crate boolean_bitfield; extern crate ethereum_types; extern crate ssz; -mod random; +pub mod test_utils; pub mod active_state; pub mod attestation_data; diff --git a/beacon_chain/types/src/proposal_signed_data.rs b/beacon_chain/types/src/proposal_signed_data.rs index 6a038d0eb..7a01fc10a 100644 --- a/beacon_chain/types/src/proposal_signed_data.rs +++ b/beacon_chain/types/src/proposal_signed_data.rs @@ -1,6 +1,6 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::Hash256; -use crate::random::TestRandom; +use crate::test_utils::TestRandom; use rand::RngCore; #[derive(Debug, PartialEq, Clone, Default)] @@ -49,7 +49,7 @@ impl TestRandom for ProposalSignedData { mod tests { use super::super::ssz::ssz_encode; use super::*; - use crate::random::TestRandom; + use crate::test_utils::TestRandom; use rand::{prng::XorShiftRng, SeedableRng}; #[test] diff --git a/beacon_chain/types/src/proposer_slashing.rs b/beacon_chain/types/src/proposer_slashing.rs index 1e2b22b1d..d2d353112 100644 --- a/beacon_chain/types/src/proposer_slashing.rs +++ b/beacon_chain/types/src/proposer_slashing.rs @@ -1,6 +1,6 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::ProposalSignedData; -use crate::random::TestRandom; +use crate::test_utils::TestRandom; use bls::Signature; use rand::RngCore; @@ -60,7 +60,7 @@ impl TestRandom for ProposerSlashing { mod tests { use super::super::ssz::ssz_encode; use super::*; - use crate::random::TestRandom; + use crate::test_utils::TestRandom; use rand::{prng::XorShiftRng, SeedableRng}; #[test] diff --git a/beacon_chain/types/src/slashable_vote_data.rs b/beacon_chain/types/src/slashable_vote_data.rs index 150b40081..9eb3d1984 100644 --- a/beacon_chain/types/src/slashable_vote_data.rs +++ b/beacon_chain/types/src/slashable_vote_data.rs @@ -1,6 +1,6 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::AttestationData; -use crate::random::TestRandom; +use crate::test_utils::TestRandom; use bls::AggregateSignature; use rand::RngCore; @@ -55,7 +55,7 @@ impl TestRandom for SlashableVoteData { mod tests { use super::super::ssz::ssz_encode; use super::*; - use crate::random::TestRandom; + use crate::test_utils::TestRandom; use rand::{prng::XorShiftRng, SeedableRng}; #[test] diff --git a/beacon_chain/types/src/random/aggregate_signature.rs b/beacon_chain/types/src/test_utils/aggregate_signature.rs similarity index 100% rename from beacon_chain/types/src/random/aggregate_signature.rs rename to beacon_chain/types/src/test_utils/aggregate_signature.rs diff --git a/beacon_chain/types/src/random/bitfield.rs b/beacon_chain/types/src/test_utils/bitfield.rs similarity index 100% rename from beacon_chain/types/src/random/bitfield.rs rename to beacon_chain/types/src/test_utils/bitfield.rs diff --git a/beacon_chain/types/src/random/hash256.rs b/beacon_chain/types/src/test_utils/hash256.rs similarity index 100% rename from beacon_chain/types/src/random/hash256.rs rename to beacon_chain/types/src/test_utils/hash256.rs diff --git a/beacon_chain/types/src/random/mod.rs b/beacon_chain/types/src/test_utils/mod.rs similarity index 93% rename from beacon_chain/types/src/random/mod.rs rename to beacon_chain/types/src/test_utils/mod.rs index 0087f8152..131ff9aac 100644 --- a/beacon_chain/types/src/random/mod.rs +++ b/beacon_chain/types/src/test_utils/mod.rs @@ -1,5 +1,7 @@ use rand::RngCore; +pub use rand::{prng::XorShiftRng, SeedableRng}; + pub mod aggregate_signature; pub mod bitfield; pub mod hash256; diff --git a/beacon_chain/types/src/random/public_key.rs b/beacon_chain/types/src/test_utils/public_key.rs similarity index 100% rename from beacon_chain/types/src/random/public_key.rs rename to beacon_chain/types/src/test_utils/public_key.rs diff --git a/beacon_chain/types/src/random/secret_key.rs b/beacon_chain/types/src/test_utils/secret_key.rs similarity index 100% rename from beacon_chain/types/src/random/secret_key.rs rename to beacon_chain/types/src/test_utils/secret_key.rs diff --git a/beacon_chain/types/src/random/signature.rs b/beacon_chain/types/src/test_utils/signature.rs similarity index 100% rename from beacon_chain/types/src/random/signature.rs rename to beacon_chain/types/src/test_utils/signature.rs From f140e2938fa075e78a550485263bc4efc9e6be7f Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 25 Dec 2018 10:38:40 +1100 Subject: [PATCH 11/16] Update beacon_block_store for new block struct --- .../db/src/stores/beacon_block_store.rs | 123 +++++++++--------- 1 file changed, 63 insertions(+), 60 deletions(-) diff --git a/lighthouse/db/src/stores/beacon_block_store.rs b/lighthouse/db/src/stores/beacon_block_store.rs index cad353eb2..5f777ea0a 100644 --- a/lighthouse/db/src/stores/beacon_block_store.rs +++ b/lighthouse/db/src/stores/beacon_block_store.rs @@ -1,9 +1,8 @@ -extern crate ssz_helpers; - -use self::ssz_helpers::ssz_beacon_block::SszBeaconBlock; use super::BLOCKS_DB_COLUMN as DB_COLUMN; use super::{ClientDB, DBError}; +use ssz::{Decodable, DecodeError}; use std::sync::Arc; +use types::Hash256; type BeaconBlockHash = Vec; type BeaconBlockSsz = Vec; @@ -60,21 +59,29 @@ impl BeaconBlockStore { match self.get_serialized_block(head_hash)? { None => Err(BeaconBlockAtSlotError::UnknownBeaconBlock), Some(ssz) => { - let block = SszBeaconBlock::from_slice(&ssz) + let (retrieved_slot, parent_hash) = slot_and_parent_from_block_ssz(&ssz, 0) .map_err(|_| BeaconBlockAtSlotError::InvalidBeaconBlock)?; - match block.slot() { + match retrieved_slot { s if s == slot => Ok(Some((head_hash.to_vec(), ssz.to_vec()))), s if s < slot => Ok(None), - _ => match block.parent_hash() { - Some(parent_hash) => self.block_at_slot(parent_hash, slot), - None => Err(BeaconBlockAtSlotError::UnknownBeaconBlock), - }, + _ => self.block_at_slot(&parent_hash, slot), } } } } } +/// Read `block.slot` and `block.parent_root` from a SSZ-encoded block bytes. +/// +/// Assumes the block starts at byte `i`. +fn slot_and_parent_from_block_ssz(ssz: &[u8], i: usize) -> Result<(u64, Hash256), DecodeError> { + // Assuming the slot is the first field on a block. + let (slot, i) = u64::ssz_decode(&ssz, i)?; + // Assuming the parent has is the second field on a block. + let (parent_root, _) = Hash256::ssz_decode(&ssz, i)?; + Ok((slot, parent_root)) +} + impl From for BeaconBlockAtSlotError { fn from(e: DBError) -> Self { BeaconBlockAtSlotError::DBError(e.message) @@ -83,19 +90,17 @@ impl From for BeaconBlockAtSlotError { #[cfg(test)] mod tests { - extern crate ssz; - extern crate types; - - use self::ssz::SszStream; - use self::types::attestation::Attestation; - use self::types::beacon_block::BeaconBlock; - use self::types::Hash256; - use super::super::super::MemoryDB; use super::*; + use std::sync::Arc; use std::thread; + use ssz::ssz_encode; + use types::test_utils::{SeedableRng, TestRandom, XorShiftRng}; + use types::BeaconBlock; + use types::Hash256; + #[test] fn test_put_serialized_block() { let db = Arc::new(MemoryDB::open()); @@ -247,60 +252,58 @@ mod tests { fn test_block_at_slot() { let db = Arc::new(MemoryDB::open()); let bs = Arc::new(BeaconBlockStore::new(db.clone())); + let mut rng = XorShiftRng::from_seed([42; 16]); - let blocks = (0..5).into_iter().map(|_| { - let mut block = BeaconBlock::zero(); - let ar = Attestation::zero(); - block.attestations.push(ar); - block - }); - + // Specify test block parameters. let hashes = [ - Hash256::from("zero".as_bytes()), - Hash256::from("one".as_bytes()), - Hash256::from("two".as_bytes()), - Hash256::from("three".as_bytes()), - Hash256::from("four".as_bytes()), + Hash256::from(&[0; 32][..]), + Hash256::from(&[1; 32][..]), + Hash256::from(&[2; 32][..]), + Hash256::from(&[3; 32][..]), + Hash256::from(&[4; 32][..]), ]; - let parent_hashes = [ - Hash256::from("genesis".as_bytes()), - Hash256::from("zero".as_bytes()), - Hash256::from("one".as_bytes()), - Hash256::from("two".as_bytes()), - Hash256::from("three".as_bytes()), + Hash256::from(&[255; 32][..]), // Genesis block. + Hash256::from(&[0; 32][..]), + Hash256::from(&[1; 32][..]), + Hash256::from(&[2; 32][..]), + Hash256::from(&[3; 32][..]), ]; - let slots = [0, 1, 3, 4, 5]; - for (i, mut block) in blocks.enumerate() { - block.ancestor_hashes.push(parent_hashes[i]); + // Generate a vec of random blocks and store them in the DB. + let block_count = 5; + let mut blocks: Vec = Vec::with_capacity(5); + for i in 0..block_count { + let mut block = BeaconBlock::random_for_test(&mut rng); + + block.parent_root = parent_hashes[i]; block.slot = slots[i]; - let mut s = SszStream::new(); - s.append(&block); - let ssz = s.drain(); + + let ssz = ssz_encode(&block); db.put(DB_COLUMN, &hashes[i].to_vec(), &ssz).unwrap(); + + // Ensure the slot and parent_root decoding fn works correctly. + let (decoded_slot, decoded_parent_root) = + slot_and_parent_from_block_ssz(&ssz, 0).unwrap(); + assert_eq!(decoded_slot, block.slot); + assert_eq!(decoded_parent_root, block.parent_root); + + blocks.push(block); } - let tuple = bs.block_at_slot(&hashes[4], 5).unwrap().unwrap(); - let block = SszBeaconBlock::from_slice(&tuple.1).unwrap(); - assert_eq!(block.slot(), 5); - assert_eq!(tuple.0, hashes[4].to_vec()); - - let tuple = bs.block_at_slot(&hashes[4], 4).unwrap().unwrap(); - let block = SszBeaconBlock::from_slice(&tuple.1).unwrap(); - assert_eq!(block.slot(), 4); - assert_eq!(tuple.0, hashes[3].to_vec()); - - let tuple = bs.block_at_slot(&hashes[4], 3).unwrap().unwrap(); - let block = SszBeaconBlock::from_slice(&tuple.1).unwrap(); - assert_eq!(block.slot(), 3); - assert_eq!(tuple.0, hashes[2].to_vec()); - - let tuple = bs.block_at_slot(&hashes[4], 0).unwrap().unwrap(); - let block = SszBeaconBlock::from_slice(&tuple.1).unwrap(); - assert_eq!(block.slot(), 0); - assert_eq!(tuple.0, hashes[0].to_vec()); + // Test that certain slots can be reached from certain hashes. + let test_cases = vec![(4, 4), (4, 3), (4, 2), (4, 1), (4, 0)]; + for (hashes_index, slot_index) in test_cases { + let (matched_block_hash, matched_block_ssz) = bs + .block_at_slot(&hashes[hashes_index], slots[slot_index]) + .unwrap() + .unwrap(); + let (retrieved_slot, _) = + slot_and_parent_from_block_ssz(&matched_block_ssz, 0).unwrap(); + assert_eq!(retrieved_slot, slots[slot_index]); + assert_eq!(matched_block_hash, hashes[slot_index].to_vec()); + } let ssz = bs.block_at_slot(&hashes[4], 2).unwrap(); assert_eq!(ssz, None); From a7756ea4b5acda2abf5c7b806fe5258d1b0c947f Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 25 Dec 2018 18:22:46 +1100 Subject: [PATCH 12/16] Remove old chain state transition code --- beacon_chain/chain/src/lib.rs | 2 -- beacon_chain/chain/src/transition.rs | 29 ---------------------------- 2 files changed, 31 deletions(-) delete mode 100644 beacon_chain/chain/src/transition.rs diff --git a/beacon_chain/chain/src/lib.rs b/beacon_chain/chain/src/lib.rs index c98d58d3e..8eb076d47 100644 --- a/beacon_chain/chain/src/lib.rs +++ b/beacon_chain/chain/src/lib.rs @@ -1,7 +1,6 @@ extern crate db; extern crate naive_fork_choice; extern crate ssz; -extern crate state_transition; extern crate types; extern crate validator_induction; extern crate validator_shuffling; @@ -10,7 +9,6 @@ mod block_processing; mod genesis; mod maps; mod stores; -mod transition; use db::ClientDB; use crate::genesis::{genesis_states, Error as GenesisError}; diff --git a/beacon_chain/chain/src/transition.rs b/beacon_chain/chain/src/transition.rs deleted file mode 100644 index 7598f2517..000000000 --- a/beacon_chain/chain/src/transition.rs +++ /dev/null @@ -1,29 +0,0 @@ -use super::BeaconChain; -use db::ClientDB; -use state_transition::{extend_active_state, StateTransitionError}; -use types::{ActiveState, BeaconBlock, CrystallizedState, Hash256}; - -impl BeaconChain -where - T: ClientDB + Sized, -{ - pub(crate) fn transition_states( - &self, - act_state: &ActiveState, - cry_state: &CrystallizedState, - block: &BeaconBlock, - block_hash: &Hash256, - ) -> Result<(ActiveState, Option), StateTransitionError> { - let state_recalc_distance = block - .slot - .checked_sub(cry_state.last_state_recalculation_slot) - .ok_or(StateTransitionError::BlockSlotBeforeRecalcSlot)?; - - if state_recalc_distance >= u64::from(self.config.cycle_length) { - panic!("Not implemented!") - } else { - let new_act_state = extend_active_state(act_state, block, block_hash)?; - Ok((new_act_state, None)) - } - } -} From e635423eacbb1f4ccd51025fa46fd77d15ffc40c Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 25 Dec 2018 18:34:45 +1100 Subject: [PATCH 13/16] Fix clippy lint in ssz --- beacon_chain/utils/ssz/src/impl_encode.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beacon_chain/utils/ssz/src/impl_encode.rs b/beacon_chain/utils/ssz/src/impl_encode.rs index 3f366bdf3..f316a21ea 100644 --- a/beacon_chain/utils/ssz/src/impl_encode.rs +++ b/beacon_chain/utils/ssz/src/impl_encode.rs @@ -12,7 +12,7 @@ use super::{Encodable, SszStream}; macro_rules! impl_encodable_for_uint { ($type: ident, $bit_size: expr) => { impl Encodable for $type { - #[allow(cast_lossless)] + #[allow(clippy::cast_lossless)] fn ssz_append(&self, s: &mut SszStream) { // Ensure bit size is valid assert!( From 810156a0fb347ffc54ddbd71b1e970ae772d175f Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 26 Dec 2018 08:46:37 +1100 Subject: [PATCH 14/16] Remove Default impls for BLS newtypes --- beacon_chain/utils/bls/src/aggregate_signature.rs | 7 ------- beacon_chain/utils/bls/src/signature.rs | 11 ----------- 2 files changed, 18 deletions(-) diff --git a/beacon_chain/utils/bls/src/aggregate_signature.rs b/beacon_chain/utils/bls/src/aggregate_signature.rs index 5cc9c3c21..656b7e4ad 100644 --- a/beacon_chain/utils/bls/src/aggregate_signature.rs +++ b/beacon_chain/utils/bls/src/aggregate_signature.rs @@ -29,13 +29,6 @@ impl AggregateSignature { } } -impl Default for AggregateSignature { - /// A "default" signature is a signature across an empty message by a secret key of 48 zeros. - fn default() -> Self { - AggregateSignature::new() - } -} - impl Encodable for AggregateSignature { fn ssz_append(&self, s: &mut SszStream) { s.append_vec(&self.0.as_bytes()); diff --git a/beacon_chain/utils/bls/src/signature.rs b/beacon_chain/utils/bls/src/signature.rs index bfeaca45e..ebdb5b817 100644 --- a/beacon_chain/utils/bls/src/signature.rs +++ b/beacon_chain/utils/bls/src/signature.rs @@ -36,17 +36,6 @@ impl Signature { } } -impl Default for Signature { - /// A "default" signature is a signature across an empty message by a secret key of 48 zeros. - fn default() -> Self { - let sk = match SecretKey::from_bytes(&[0; 48]) { - Ok(key) => key, - _ => unreachable!(), // Key is static, should not fail. - }; - Signature(RawSignature::new(&[], &sk)) - } -} - impl Encodable for Signature { fn ssz_append(&self, s: &mut SszStream) { s.append_vec(&self.0.as_bytes()); From 4330acdd96a548186adba93f2b3a15603108406a Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 26 Dec 2018 08:54:26 +1100 Subject: [PATCH 15/16] Tidy up var name in BLS --- beacon_chain/utils/bls/src/aggregate_signature.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/beacon_chain/utils/bls/src/aggregate_signature.rs b/beacon_chain/utils/bls/src/aggregate_signature.rs index 656b7e4ad..2e3630268 100644 --- a/beacon_chain/utils/bls/src/aggregate_signature.rs +++ b/beacon_chain/utils/bls/src/aggregate_signature.rs @@ -24,8 +24,8 @@ impl AggregateSignature { /// /// Only returns `true` if the set of keys in the `AggregatePublicKey` match the set of keys /// that signed the `AggregateSignature`. - pub fn verify(&self, msg: &[u8], avk: &AggregatePublicKey) -> bool { - self.0.verify(msg, avk) + pub fn verify(&self, msg: &[u8], aggregate_public_key: &AggregatePublicKey) -> bool { + self.0.verify(msg, aggregate_public_key) } } From 9764cb0ef33a9724a72a476709c7991f0453a31b Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 26 Dec 2018 09:12:11 +1100 Subject: [PATCH 16/16] Remove some Default impls from types --- beacon_chain/types/src/beacon_block.rs | 2 +- beacon_chain/types/src/casper_slashing.rs | 2 +- beacon_chain/types/src/proposer_slashing.rs | 2 +- beacon_chain/types/src/slashable_vote_data.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/beacon_chain/types/src/beacon_block.rs b/beacon_chain/types/src/beacon_block.rs index b6ac9e9e0..df8f939e3 100644 --- a/beacon_chain/types/src/beacon_block.rs +++ b/beacon_chain/types/src/beacon_block.rs @@ -4,7 +4,7 @@ use crate::test_utils::TestRandom; use bls::AggregateSignature; use rand::RngCore; -#[derive(Debug, PartialEq, Clone, Default)] +#[derive(Debug, PartialEq, Clone)] pub struct BeaconBlock { pub slot: u64, pub parent_root: Hash256, diff --git a/beacon_chain/types/src/casper_slashing.rs b/beacon_chain/types/src/casper_slashing.rs index a972f2248..f3c1b5d18 100644 --- a/beacon_chain/types/src/casper_slashing.rs +++ b/beacon_chain/types/src/casper_slashing.rs @@ -3,7 +3,7 @@ use super::SlashableVoteData; use crate::test_utils::TestRandom; use rand::RngCore; -#[derive(Debug, PartialEq, Clone, Default)] +#[derive(Debug, PartialEq, Clone)] pub struct CasperSlashing { pub slashable_vote_data_1: SlashableVoteData, pub slashable_vote_data_2: SlashableVoteData, diff --git a/beacon_chain/types/src/proposer_slashing.rs b/beacon_chain/types/src/proposer_slashing.rs index d2d353112..0ae1c6e66 100644 --- a/beacon_chain/types/src/proposer_slashing.rs +++ b/beacon_chain/types/src/proposer_slashing.rs @@ -4,7 +4,7 @@ use crate::test_utils::TestRandom; use bls::Signature; use rand::RngCore; -#[derive(Debug, PartialEq, Clone, Default)] +#[derive(Debug, PartialEq, Clone)] pub struct ProposerSlashing { pub proposer_index: u32, pub proposal_data_1: ProposalSignedData, diff --git a/beacon_chain/types/src/slashable_vote_data.rs b/beacon_chain/types/src/slashable_vote_data.rs index 9eb3d1984..4d8e2eab3 100644 --- a/beacon_chain/types/src/slashable_vote_data.rs +++ b/beacon_chain/types/src/slashable_vote_data.rs @@ -4,7 +4,7 @@ use crate::test_utils::TestRandom; use bls::AggregateSignature; use rand::RngCore; -#[derive(Debug, PartialEq, Clone, Default)] +#[derive(Debug, PartialEq, Clone)] pub struct SlashableVoteData { pub aggregate_signature_poc_0_indices: Vec, pub aggregate_signature_poc_1_indices: Vec,