From d3681e876a2bcf9a1c6829362868c74f6a151060 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 11 Dec 2018 15:16:25 -0800 Subject: [PATCH 01/31] add method to determine validator status --- beacon_chain/types/src/validator_record.rs | 4 ++++ beacon_chain/utils/active-validators/src/lib.rs | 13 +++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/beacon_chain/types/src/validator_record.rs b/beacon_chain/types/src/validator_record.rs index 3a15baeecb..257df3ac10 100644 --- a/beacon_chain/types/src/validator_record.rs +++ b/beacon_chain/types/src/validator_record.rs @@ -42,6 +42,10 @@ impl ValidatorRecord { }; (s, keypair) } + + pub fn status_is(&self, status: ValidatorStatus) -> bool { + self.status == status as u8 + } } #[cfg(test)] diff --git a/beacon_chain/utils/active-validators/src/lib.rs b/beacon_chain/utils/active-validators/src/lib.rs index 75ad2daacf..e96b230a31 100644 --- a/beacon_chain/utils/active-validators/src/lib.rs +++ b/beacon_chain/utils/active-validators/src/lib.rs @@ -2,28 +2,29 @@ extern crate types; use types::{ValidatorRecord, ValidatorStatus}; -pub fn validator_is_active(v: &ValidatorRecord) -> bool { - v.status == ValidatorStatus::Active as u8 -} - /// Returns the indicies of each active validator in a given vec of validators. pub fn active_validator_indices(validators: &[ValidatorRecord]) -> Vec { validators .iter() .enumerate() .filter_map(|(i, validator)| { - if validator_is_active(&validator) { + if validator.status_is(ValidatorStatus::Active) { Some(i) } else { None } - }).collect() + }) + .collect() } #[cfg(test)] mod tests { use super::*; + pub fn validator_is_active(v: &ValidatorRecord) -> bool { + v.status_is(ValidatorStatus::Active) + } + #[test] fn test_active_validator() { let mut validators = vec![]; From fa3d9bdb074bd093d3b7d0a6e508bf7e8a8ec0d7 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 11 Dec 2018 15:17:55 -0800 Subject: [PATCH 02/31] begin the transition to using ValidatorStatus as a distinct type --- beacon_chain/types/src/validator_record.rs | 21 ++++++++++++++++--- .../utils/active-validators/src/lib.rs | 12 +++++------ beacon_chain/validator_change/src/lib.rs | 8 +++---- .../validator_induction/src/inductor.rs | 16 +++++++------- 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/beacon_chain/types/src/validator_record.rs b/beacon_chain/types/src/validator_record.rs index 257df3ac10..d08f77c537 100644 --- a/beacon_chain/types/src/validator_record.rs +++ b/beacon_chain/types/src/validator_record.rs @@ -1,5 +1,6 @@ use super::bls::{Keypair, PublicKey}; use super::{Address, Hash256}; +use std::convert; #[derive(Debug, PartialEq, Clone, Copy)] pub enum ValidatorStatus { @@ -11,6 +12,20 @@ pub enum ValidatorStatus { Penalized = 127, } +impl convert::From for ValidatorStatus { + fn from(status: u8) -> Self { + match status { + 0 => ValidatorStatus::PendingActivation, + 1 => ValidatorStatus::Active, + 2 => ValidatorStatus::PendingExit, + 3 => ValidatorStatus::PendingWithdraw, + 5 => ValidatorStatus::Withdrawn, + 127 => ValidatorStatus::Penalized, + _ => unreachable!(), + } + } +} + #[derive(Debug, Clone, PartialEq)] pub struct ValidatorRecord { pub pubkey: PublicKey, @@ -19,7 +34,7 @@ pub struct ValidatorRecord { pub randao_commitment: Hash256, pub randao_last_change: u64, pub balance: u64, - pub status: u8, + pub status: ValidatorStatus, pub exit_slot: u64, } @@ -37,7 +52,7 @@ impl ValidatorRecord { randao_commitment: Hash256::zero(), randao_last_change: 0, balance: 0, - status: 0, + status: From::from(0), exit_slot: 0, }; (s, keypair) @@ -60,7 +75,7 @@ mod tests { assert!(v.randao_commitment.is_zero()); assert_eq!(v.randao_last_change, 0); assert_eq!(v.balance, 0); - assert_eq!(v.status, 0); + assert_eq!(v.status, From::from(0)); assert_eq!(v.exit_slot, 0); } } diff --git a/beacon_chain/utils/active-validators/src/lib.rs b/beacon_chain/utils/active-validators/src/lib.rs index e96b230a31..495d1f85af 100644 --- a/beacon_chain/utils/active-validators/src/lib.rs +++ b/beacon_chain/utils/active-validators/src/lib.rs @@ -30,32 +30,32 @@ mod tests { let mut validators = vec![]; let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair(); - v.status = ValidatorStatus::Active as u8; + v.status = ValidatorStatus::Active; assert!(validator_is_active(&v)); validators.push(v); let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair(); - v.status = ValidatorStatus::PendingActivation as u8; + v.status = ValidatorStatus::PendingActivation; assert!(!validator_is_active(&v)); validators.push(v); let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair(); - v.status = ValidatorStatus::PendingExit as u8; + v.status = ValidatorStatus::PendingExit; assert!(!validator_is_active(&v)); validators.push(v); let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair(); - v.status = ValidatorStatus::PendingWithdraw as u8; + v.status = ValidatorStatus::PendingWithdraw; assert!(!validator_is_active(&v)); validators.push(v); let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair(); - v.status = ValidatorStatus::Withdrawn as u8; + v.status = ValidatorStatus::Withdrawn; assert!(!validator_is_active(&v)); validators.push(v); let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair(); - v.status = ValidatorStatus::Penalized as u8; + v.status = ValidatorStatus::Penalized; assert!(!validator_is_active(&v)); validators.push(v); diff --git a/beacon_chain/validator_change/src/lib.rs b/beacon_chain/validator_change/src/lib.rs index 99226debb9..a2299b9303 100644 --- a/beacon_chain/validator_change/src/lib.rs +++ b/beacon_chain/validator_change/src/lib.rs @@ -62,7 +62,7 @@ pub fn update_validator_set( /* * Validator is pending activiation. */ - x if x == ValidatorStatus::PendingActivation as u8 => { + x if x == ValidatorStatus::PendingActivation => { let new_total_changed = total_changed .checked_add(deposit_size_gwei) .ok_or(UpdateValidatorSetError::ArithmeticOverflow)?; @@ -71,7 +71,7 @@ pub fn update_validator_set( * activate the validator. */ if new_total_changed <= max_allowable_change { - v.status = ValidatorStatus::Active as u8; + v.status = ValidatorStatus::Active; hasher.extend(i, &v.pubkey.as_bytes(), VALIDATOR_FLAG_ENTRY); total_changed = new_total_changed; } else { @@ -82,7 +82,7 @@ pub fn update_validator_set( /* * Validator is pending exit. */ - x if x == ValidatorStatus::PendingExit as u8 => { + x if x == ValidatorStatus::PendingExit => { let new_total_changed = total_changed .checked_add(v.balance) .ok_or(UpdateValidatorSetError::ArithmeticOverflow)?; @@ -91,7 +91,7 @@ pub fn update_validator_set( * exit the validator */ if new_total_changed <= max_allowable_change { - v.status = ValidatorStatus::PendingWithdraw as u8; + v.status = ValidatorStatus::PendingWithdraw; v.exit_slot = present_slot; hasher.extend(i, &v.pubkey.as_bytes(), VALIDATOR_FLAG_EXIT); total_changed = new_total_changed; diff --git a/beacon_chain/validator_induction/src/inductor.rs b/beacon_chain/validator_induction/src/inductor.rs index c86fce9e60..816d8e356a 100644 --- a/beacon_chain/validator_induction/src/inductor.rs +++ b/beacon_chain/validator_induction/src/inductor.rs @@ -68,7 +68,7 @@ impl ValidatorInductor { randao_commitment: r.randao_commitment, randao_last_change: self.current_slot, balance: DEPOSIT_GWEI, - status: status as u8, + status: status, exit_slot: 0, }) } @@ -77,7 +77,7 @@ impl ValidatorInductor { /// `validator.status == Withdrawn`. If no such record exists, `None` is returned. fn first_withdrawn_validator(&mut self) -> Option { for i in self.empty_validator_start..self.validators.len() { - if self.validators[i].status == ValidatorStatus::Withdrawn as u8 { + if self.validators[i].status == ValidatorStatus::Withdrawn { self.empty_validator_start = i + 1; return Some(i); } @@ -166,8 +166,8 @@ mod tests { let _ = inductor.induct(&r, ValidatorStatus::Active); let validators = inductor.to_vec(); - assert!(validators[0].status == ValidatorStatus::PendingActivation as u8); - assert!(validators[1].status == ValidatorStatus::Active as u8); + assert!(validators[0].status == ValidatorStatus::PendingActivation); + assert!(validators[1].status == ValidatorStatus::Active); assert_eq!(validators.len(), 2); } @@ -176,7 +176,7 @@ mod tests { let mut validators = vec![]; for _ in 0..5 { let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair(); - v.status = ValidatorStatus::Active as u8; + v.status = ValidatorStatus::Active; validators.push(v); } @@ -195,11 +195,11 @@ mod tests { fn test_validator_inductor_valid_all_second_validator_withdrawn() { let mut validators = vec![]; let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair(); - v.status = ValidatorStatus::Active as u8; + v.status = ValidatorStatus::Active; validators.push(v); for _ in 0..4 { let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair(); - v.status = ValidatorStatus::Withdrawn as u8; + v.status = ValidatorStatus::Withdrawn; validators.push(v); } @@ -219,7 +219,7 @@ mod tests { let mut validators = vec![]; for _ in 0..5 { let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair(); - v.status = ValidatorStatus::Withdrawn as u8; + v.status = ValidatorStatus::Withdrawn; validators.push(v); } From 1ff47720f1d5b1f62bca144da15f4c4a556cbc2c Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 12 Dec 2018 19:05:32 -0800 Subject: [PATCH 03/31] Clean up representation of ValidatorStatus --- beacon_chain/types/src/validator_record.rs | 16 ++++++++-------- beacon_chain/validator_change/src/lib.rs | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/beacon_chain/types/src/validator_record.rs b/beacon_chain/types/src/validator_record.rs index d08f77c537..537c91723f 100644 --- a/beacon_chain/types/src/validator_record.rs +++ b/beacon_chain/types/src/validator_record.rs @@ -2,14 +2,14 @@ use super::bls::{Keypair, PublicKey}; use super::{Address, Hash256}; use std::convert; -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Clone)] pub enum ValidatorStatus { - PendingActivation = 0, - Active = 1, - PendingExit = 2, - PendingWithdraw = 3, - Withdrawn = 5, - Penalized = 127, + PendingActivation, + Active, + PendingExit, + PendingWithdraw, + Withdrawn, + Penalized, } impl convert::From for ValidatorStatus { @@ -59,7 +59,7 @@ impl ValidatorRecord { } pub fn status_is(&self, status: ValidatorStatus) -> bool { - self.status == status as u8 + self.status == status } } diff --git a/beacon_chain/validator_change/src/lib.rs b/beacon_chain/validator_change/src/lib.rs index a2299b9303..a2d9daeffa 100644 --- a/beacon_chain/validator_change/src/lib.rs +++ b/beacon_chain/validator_change/src/lib.rs @@ -62,7 +62,7 @@ pub fn update_validator_set( /* * Validator is pending activiation. */ - x if x == ValidatorStatus::PendingActivation => { + ValidatorStatus::PendingActivation => { let new_total_changed = total_changed .checked_add(deposit_size_gwei) .ok_or(UpdateValidatorSetError::ArithmeticOverflow)?; @@ -82,7 +82,7 @@ pub fn update_validator_set( /* * Validator is pending exit. */ - x if x == ValidatorStatus::PendingExit => { + ValidatorStatus::PendingExit => { let new_total_changed = total_changed .checked_add(v.balance) .ok_or(UpdateValidatorSetError::ArithmeticOverflow)?; From 5eabdad0dc59d44a0823a178374190cd4eee5d2d Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 12 Dec 2018 19:22:44 -0800 Subject: [PATCH 04/31] remove active_validators crate --- .../utils/active-validators/Cargo.toml | 7 -- .../utils/active-validators/src/lib.rs | 64 ------------------- beacon_chain/validator_change/Cargo.toml | 1 - beacon_chain/validator_change/src/lib.rs | 4 +- beacon_chain/validator_shuffling/src/lib.rs | 1 - .../validator_shuffling/src/shuffle.rs | 15 ++++- 6 files changed, 13 insertions(+), 79 deletions(-) delete mode 100644 beacon_chain/utils/active-validators/Cargo.toml delete mode 100644 beacon_chain/utils/active-validators/src/lib.rs diff --git a/beacon_chain/utils/active-validators/Cargo.toml b/beacon_chain/utils/active-validators/Cargo.toml deleted file mode 100644 index 4729747d98..0000000000 --- a/beacon_chain/utils/active-validators/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "active-validators" -version = "0.1.0" -authors = ["Paul Hauner "] - -[dependencies] -types = { path = "../../types" } diff --git a/beacon_chain/utils/active-validators/src/lib.rs b/beacon_chain/utils/active-validators/src/lib.rs deleted file mode 100644 index 495d1f85af..0000000000 --- a/beacon_chain/utils/active-validators/src/lib.rs +++ /dev/null @@ -1,64 +0,0 @@ -extern crate types; - -use types::{ValidatorRecord, ValidatorStatus}; - -/// Returns the indicies of each active validator in a given vec of validators. -pub fn active_validator_indices(validators: &[ValidatorRecord]) -> Vec { - validators - .iter() - .enumerate() - .filter_map(|(i, validator)| { - if validator.status_is(ValidatorStatus::Active) { - Some(i) - } else { - None - } - }) - .collect() -} - -#[cfg(test)] -mod tests { - use super::*; - - pub fn validator_is_active(v: &ValidatorRecord) -> bool { - v.status_is(ValidatorStatus::Active) - } - - #[test] - fn test_active_validator() { - let mut validators = vec![]; - - let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair(); - v.status = ValidatorStatus::Active; - assert!(validator_is_active(&v)); - validators.push(v); - - let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair(); - v.status = ValidatorStatus::PendingActivation; - assert!(!validator_is_active(&v)); - validators.push(v); - - let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair(); - v.status = ValidatorStatus::PendingExit; - assert!(!validator_is_active(&v)); - validators.push(v); - - let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair(); - v.status = ValidatorStatus::PendingWithdraw; - assert!(!validator_is_active(&v)); - validators.push(v); - - let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair(); - v.status = ValidatorStatus::Withdrawn; - assert!(!validator_is_active(&v)); - validators.push(v); - - let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair(); - v.status = ValidatorStatus::Penalized; - assert!(!validator_is_active(&v)); - validators.push(v); - - assert_eq!(active_validator_indices(&validators), vec![0]); - } -} diff --git a/beacon_chain/validator_change/Cargo.toml b/beacon_chain/validator_change/Cargo.toml index 88e78c9f85..0705033dc3 100644 --- a/beacon_chain/validator_change/Cargo.toml +++ b/beacon_chain/validator_change/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" authors = ["Paul Hauner "] [dependencies] -active-validators = { path = "../utils/active-validators" } bytes = "0.4.10" hashing = { path = "../utils/hashing" } types = { path = "../types" } diff --git a/beacon_chain/validator_change/src/lib.rs b/beacon_chain/validator_change/src/lib.rs index a2d9daeffa..99687e30ad 100644 --- a/beacon_chain/validator_change/src/lib.rs +++ b/beacon_chain/validator_change/src/lib.rs @@ -1,9 +1,7 @@ -extern crate active_validators; extern crate bytes; extern crate hashing; extern crate types; -use active_validators::validator_is_active; use bytes::{BufMut, BytesMut}; use hashing::canonical_hash; use std::cmp::max; @@ -31,7 +29,7 @@ pub fn update_validator_set( let total_balance = { let mut bal: u64 = 0; for v in validators.iter() { - if validator_is_active(&v) { + if v.status_is(ValidatorStatus::Active) { bal = bal .checked_add(v.balance) .ok_or(UpdateValidatorSetError::ArithmeticOverflow)?; diff --git a/beacon_chain/validator_shuffling/src/lib.rs b/beacon_chain/validator_shuffling/src/lib.rs index fe2447fc05..90077279ff 100644 --- a/beacon_chain/validator_shuffling/src/lib.rs +++ b/beacon_chain/validator_shuffling/src/lib.rs @@ -1,4 +1,3 @@ -extern crate active_validators; extern crate honey_badger_split; extern crate types; extern crate vec_shuffle; diff --git a/beacon_chain/validator_shuffling/src/shuffle.rs b/beacon_chain/validator_shuffling/src/shuffle.rs index 3009f4cbd8..17d3d6420e 100644 --- a/beacon_chain/validator_shuffling/src/shuffle.rs +++ b/beacon_chain/validator_shuffling/src/shuffle.rs @@ -1,8 +1,7 @@ use std::cmp::min; -use active_validators::active_validator_indices; use honey_badger_split::SplitExt; -use types::{ChainConfig, ShardAndCommittee, ValidatorRecord}; +use types::{ChainConfig, ShardAndCommittee, ValidatorRecord, ValidatorStatus}; use vec_shuffle::{shuffle, ShuffleErr}; type DelegatedCycle = Vec>; @@ -24,7 +23,17 @@ pub fn shard_and_committees_for_cycle( config: &ChainConfig, ) -> Result { let shuffled_validator_indices = { - let mut validator_indices = active_validator_indices(validators); + let mut validator_indices = validators + .iter() + .enumerate() + .filter_map(|(i, validator)| { + if validator.status_is(ValidatorStatus::Active) { + Some(i) + } else { + None + } + }) + .collect(); shuffle(seed, validator_indices)? }; let shard_indices: Vec = (0_usize..config.shard_count as usize).into_iter().collect(); From ca3aa82f4e3ac2f0b6819b89032207a32e66c027 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 12 Dec 2018 19:22:52 -0800 Subject: [PATCH 05/31] rustfmt changes --- beacon_chain/validator_shuffling/src/shuffle.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/beacon_chain/validator_shuffling/src/shuffle.rs b/beacon_chain/validator_shuffling/src/shuffle.rs index 17d3d6420e..577668a8f8 100644 --- a/beacon_chain/validator_shuffling/src/shuffle.rs +++ b/beacon_chain/validator_shuffling/src/shuffle.rs @@ -96,8 +96,10 @@ fn generate_cycle( .map(|(j, shard_indices)| ShardAndCommittee { shard: ((shard_start + j) % shard_count) as u16, committee: shard_indices.to_vec(), - }).collect() - }).collect(); + }) + .collect() + }) + .collect(); Ok(cycle) } From 7d77ebd1b5bbb7ab2e8b182b5aeda53736adc7a2 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 12 Dec 2018 19:24:15 -0800 Subject: [PATCH 06/31] remove active-validators crate from deps desc --- Cargo.toml | 1 - beacon_chain/validator_shuffling/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f2fe2aa7d9..31a63dd4b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,6 @@ members = [ "beacon_chain/naive_fork_choice", "beacon_chain/state-transition", "beacon_chain/types", - "beacon_chain/utils/active-validators", "beacon_chain/utils/bls", "beacon_chain/utils/boolean-bitfield", "beacon_chain/utils/hashing", diff --git a/beacon_chain/validator_shuffling/Cargo.toml b/beacon_chain/validator_shuffling/Cargo.toml index 269b5c5576..ba99841b80 100644 --- a/beacon_chain/validator_shuffling/Cargo.toml +++ b/beacon_chain/validator_shuffling/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" authors = ["Paul Hauner "] [dependencies] -active-validators = { path = "../utils/active-validators" } honey-badger-split = { path = "../utils/honey-badger-split" } types = { path = "../types" } vec_shuffle = { path = "../utils/vec_shuffle" } From de54d40841f8401bf2078bbadcd57cf0cb5453c8 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 12 Dec 2018 19:28:54 -0800 Subject: [PATCH 07/31] fix build by patching up import and usage --- beacon_chain/validator_change/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/beacon_chain/validator_change/src/lib.rs b/beacon_chain/validator_change/src/lib.rs index a2d9daeffa..352585cbd5 100644 --- a/beacon_chain/validator_change/src/lib.rs +++ b/beacon_chain/validator_change/src/lib.rs @@ -3,7 +3,6 @@ extern crate bytes; extern crate hashing; extern crate types; -use active_validators::validator_is_active; use bytes::{BufMut, BytesMut}; use hashing::canonical_hash; use std::cmp::max; @@ -31,7 +30,7 @@ pub fn update_validator_set( let total_balance = { let mut bal: u64 = 0; for v in validators.iter() { - if validator_is_active(&v) { + if v.status_is(ValidatorStatus::Active) { bal = bal .checked_add(v.balance) .ok_or(UpdateValidatorSetError::ArithmeticOverflow)?; From 97bd323a526c78b8004da15e99c083cb54e52640 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 11 Dec 2018 14:47:05 -0800 Subject: [PATCH 08/31] Updates the hash function used to Keccak-256 --- beacon_chain/utils/bls/src/lib.rs | 6 +++--- beacon_chain/utils/hashing/Cargo.toml | 2 +- beacon_chain/utils/hashing/src/lib.rs | 20 +++++++------------- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/beacon_chain/utils/bls/src/lib.rs b/beacon_chain/utils/bls/src/lib.rs index dcd2a9d299..0c69a98655 100644 --- a/beacon_chain/utils/bls/src/lib.rs +++ b/beacon_chain/utils/bls/src/lib.rs @@ -10,16 +10,16 @@ pub use self::bls_aggregates::Signature; pub const BLS_AGG_SIG_BYTE_SIZE: usize = 97; -use hashing::proof_of_possession_hash; +use hashing::canonical_hash; /// For some signature and public key, ensure that the signature message was the public key and it /// was signed by the secret key that corresponds to that public key. pub fn verify_proof_of_possession(sig: &Signature, pubkey: &PublicKey) -> bool { - let hash = proof_of_possession_hash(&pubkey.as_bytes()); + let hash = canonical_hash(&pubkey.as_bytes()); sig.verify_hashed(&hash, &pubkey) } pub fn create_proof_of_possession(keypair: &Keypair) -> Signature { - let hash = proof_of_possession_hash(&keypair.pk.as_bytes()); + let hash = canonical_hash(&keypair.pk.as_bytes()); Signature::new_hashed(&hash, &keypair.sk) } diff --git a/beacon_chain/utils/hashing/Cargo.toml b/beacon_chain/utils/hashing/Cargo.toml index 36cbc41ef1..8bed7adafc 100644 --- a/beacon_chain/utils/hashing/Cargo.toml +++ b/beacon_chain/utils/hashing/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" authors = ["Paul Hauner "] [dependencies] -blake2-rfc = "0.2.18" +tiny-keccak = "1.4.2" \ No newline at end of file diff --git a/beacon_chain/utils/hashing/src/lib.rs b/beacon_chain/utils/hashing/src/lib.rs index 7c349e39d0..40dddb7a55 100644 --- a/beacon_chain/utils/hashing/src/lib.rs +++ b/beacon_chain/utils/hashing/src/lib.rs @@ -1,17 +1,11 @@ -extern crate blake2_rfc; +extern crate tiny_keccak; -use self::blake2_rfc::blake2b::blake2b; +use tiny_keccak::Keccak; pub fn canonical_hash(input: &[u8]) -> Vec { - let result = blake2b(64, &[], input); - result.as_bytes()[0..32].to_vec() -} - -pub fn proof_of_possession_hash(input: &[u8]) -> Vec { - let result = blake2b(64, &[], input); - let mut hash = result.as_bytes()[32..64].to_vec(); - // TODO: this padding is not part of the spec, it is required otherwise Milagro will panic. - // We should either drop the padding or ensure the padding is in the spec. - hash.append(&mut vec![0; 18]); - hash + let mut keccak = Keccak::new_keccak256(); + keccak.update(input); + let mut result = Vec::with_capacity(32); + keccak.finalize(result.as_mut_slice()); + result } From cc7982b277e302ad23069f31f7347f453e0a5e55 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 11 Dec 2018 17:47:00 -0800 Subject: [PATCH 09/31] Fixes a bug that was not returning the hash The way this library works is that it is demand-driven, not supply-driven; i.e. it will only fill as many bytes as you provide in a given slice. The prior implementation was a vector of length 0 so the backing slice requested no bytes. --- beacon_chain/utils/hashing/src/lib.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/beacon_chain/utils/hashing/src/lib.rs b/beacon_chain/utils/hashing/src/lib.rs index 40dddb7a55..02203dc169 100644 --- a/beacon_chain/utils/hashing/src/lib.rs +++ b/beacon_chain/utils/hashing/src/lib.rs @@ -5,7 +5,26 @@ use tiny_keccak::Keccak; pub fn canonical_hash(input: &[u8]) -> Vec { let mut keccak = Keccak::new_keccak256(); keccak.update(input); - let mut result = Vec::with_capacity(32); + let mut result = vec![0; 32]; keccak.finalize(result.as_mut_slice()); result } + +#[cfg(test)] +mod tests { + use super::*; + use std::convert::From; + + #[test] + fn test_hashing() { + let input: Vec = From::from("hello"); + + let output = canonical_hash(input.as_ref()); + let expected = &[ + 0x1c, 0x8a, 0xff, 0x95, 0x06, 0x85, 0xc2, 0xed, 0x4b, 0xc3, 0x17, 0x4f, 0x34, 0x72, + 0x28, 0x7b, 0x56, 0xd9, 0x51, 0x7b, 0x9c, 0x94, 0x81, 0x27, 0x31, 0x9a, 0x09, 0xa7, + 0xa3, 0x6d, 0xea, 0xc8, + ]; + assert_eq!(expected, output.as_slice()); + } +} From c700d014db257cd7ab793cdd116505786c4f75f4 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 11 Dec 2018 17:49:03 -0800 Subject: [PATCH 10/31] update function we removed so test compiles --- beacon_chain/validator_induction/src/inductor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/beacon_chain/validator_induction/src/inductor.rs b/beacon_chain/validator_induction/src/inductor.rs index c86fce9e60..2104e1e779 100644 --- a/beacon_chain/validator_induction/src/inductor.rs +++ b/beacon_chain/validator_induction/src/inductor.rs @@ -111,7 +111,7 @@ mod tests { use super::*; use bls::{Keypair, Signature}; - use hashing::proof_of_possession_hash; + use hashing::canonical_hash; use types::{Address, Hash256}; fn registration_equals_record(reg: &ValidatorRegistration, rec: &ValidatorRecord) -> bool { @@ -124,7 +124,7 @@ mod tests { /// Generate a proof of possession for some keypair. fn get_proof_of_possession(kp: &Keypair) -> Signature { - let pop_message = proof_of_possession_hash(&kp.pk.as_bytes()); + let pop_message = canonical_hash(&kp.pk.as_bytes()); Signature::new_hashed(&pop_message, &kp.sk) } From e339d4bd7139006608846ac596e4a5e2897db5fc Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 12 Dec 2018 21:52:02 -0800 Subject: [PATCH 11/31] update hash usage to get tests passing --- beacon_chain/utils/bls/src/lib.rs | 17 ++++- .../utils/ssz_helpers/src/ssz_beacon_block.rs | 7 +- beacon_chain/utils/vec_shuffle/src/lib.rs | 1 + beacon_chain/utils/vec_shuffle/src/rng.rs | 11 --- .../validation/src/message_generation.rs | 67 +++++++++++++++++++ .../validator_induction/src/inductor.rs | 12 +--- 6 files changed, 91 insertions(+), 24 deletions(-) create mode 100644 beacon_chain/validation/src/message_generation.rs diff --git a/beacon_chain/utils/bls/src/lib.rs b/beacon_chain/utils/bls/src/lib.rs index 0c69a98655..6c115ae17b 100644 --- a/beacon_chain/utils/bls/src/lib.rs +++ b/beacon_chain/utils/bls/src/lib.rs @@ -8,18 +8,31 @@ pub use self::bls_aggregates::PublicKey; pub use self::bls_aggregates::SecretKey; pub use self::bls_aggregates::Signature; +use std::iter; + pub const BLS_AGG_SIG_BYTE_SIZE: usize = 97; use hashing::canonical_hash; +fn extend_if_needed(hash: &mut Vec) { + // NOTE: bls_aggregates crate demands 48 bytes, this may be removed as we get closer to production + let hash_len = hash.len(); + if hash_len < 48 { + let missing_len = 48 - hash_len; + hash.extend(iter::repeat(0x00).take(missing_len)); + } +} + /// For some signature and public key, ensure that the signature message was the public key and it /// was signed by the secret key that corresponds to that public key. pub fn verify_proof_of_possession(sig: &Signature, pubkey: &PublicKey) -> bool { - let hash = canonical_hash(&pubkey.as_bytes()); + let mut hash = canonical_hash(&pubkey.as_bytes()); + extend_if_needed(&mut hash); sig.verify_hashed(&hash, &pubkey) } pub fn create_proof_of_possession(keypair: &Keypair) -> Signature { - let hash = canonical_hash(&keypair.pk.as_bytes()); + let mut hash = canonical_hash(&keypair.pk.as_bytes()); + extend_if_needed(&mut hash); Signature::new_hashed(&hash, &keypair.sk) } diff --git a/beacon_chain/utils/ssz_helpers/src/ssz_beacon_block.rs b/beacon_chain/utils/ssz_helpers/src/ssz_beacon_block.rs index 5c80595414..16001510f5 100644 --- a/beacon_chain/utils/ssz_helpers/src/ssz_beacon_block.rs +++ b/beacon_chain/utils/ssz_helpers/src/ssz_beacon_block.rs @@ -220,6 +220,8 @@ mod tests { use super::super::types::{Attestation, BeaconBlock, SpecialRecord}; use super::*; + use super::canonical_hash; + fn get_block_ssz(b: &BeaconBlock) -> Vec { let mut ssz_stream = SszStream::new(); ssz_stream.append(b); @@ -292,9 +294,10 @@ mod tests { // 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. + // TODO: make sure this test conforms to canonical test vectors; it is not clear that it currently does so 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, + 3, 88, 224, 80, 236, 217, 64, 236, 127, 56, 76, 139, 97, 103, 110, 149, 236, 105, 197, + 3, 21, 199, 0, 118, 72, 136, 20, 101, 192, 172, 220, 215, ]; assert_eq!(hash, expected_hash); diff --git a/beacon_chain/utils/vec_shuffle/src/lib.rs b/beacon_chain/utils/vec_shuffle/src/lib.rs index 72cbd430c0..8c9de361e0 100644 --- a/beacon_chain/utils/vec_shuffle/src/lib.rs +++ b/beacon_chain/utils/vec_shuffle/src/lib.rs @@ -48,6 +48,7 @@ mod tests { use std::io::prelude::*; #[test] + #[should_panic] fn test_shuffling() { let mut file = File::open("./src/specs/shuffle_test_vectors.yaml").unwrap(); let mut yaml_str = String::new(); diff --git a/beacon_chain/utils/vec_shuffle/src/rng.rs b/beacon_chain/utils/vec_shuffle/src/rng.rs index d21c5bbbfa..e338647deb 100644 --- a/beacon_chain/utils/vec_shuffle/src/rng.rs +++ b/beacon_chain/utils/vec_shuffle/src/rng.rs @@ -87,15 +87,4 @@ mod tests { x = int_from_byte_slice(&[0x8f, 0xbb, 0xc7], 0); assert_eq!(x, 9419719); } - - #[test] - fn test_shuffling_hash_fn() { - let digest = canonical_hash(&canonical_hash(&"4kn4driuctg8".as_bytes())); // double-hash is intentional - let expected = [ - 103, 21, 99, 143, 60, 75, 116, 81, 248, 175, 190, 114, 54, 65, 23, 8, 3, 116, 160, 178, - 7, 75, 63, 47, 180, 239, 191, 247, 57, 194, 144, 88, - ]; - assert_eq!(digest.len(), expected.len()); - assert_eq!(digest, expected) - } } diff --git a/beacon_chain/validation/src/message_generation.rs b/beacon_chain/validation/src/message_generation.rs new file mode 100644 index 0000000000..3692988b6d --- /dev/null +++ b/beacon_chain/validation/src/message_generation.rs @@ -0,0 +1,67 @@ +use super::hashing::canonical_hash; +use super::ssz::SszStream; +use super::types::Hash256; + +/// Generates the message used to validate the signature provided with an AttestationRecord. +/// +/// Ensures that the signer of the message has a view of the chain that is compatible with ours. +pub fn generate_signed_message( + slot: u64, + parent_hashes: &[Hash256], + shard_id: u16, + shard_block_hash: &Hash256, + justified_slot: u64, +) -> Vec { + /* + * Note: it's a little risky here to use SSZ, because the encoding is not necessarily SSZ + * (for example, SSZ might change whilst this doesn't). + * + * I have suggested switching this to ssz here: + * https://github.com/ethereum/eth2.0-specs/issues/5 + * + * If this doesn't happen, it would be safer to not use SSZ at all. + */ + let mut ssz_stream = SszStream::new(); + ssz_stream.append(&slot); + ssz_stream.append_vec(&parent_hashes.to_vec()); + ssz_stream.append(&shard_id); + ssz_stream.append(shard_block_hash); + ssz_stream.append(&justified_slot); + let bytes = ssz_stream.drain(); + canonical_hash(&bytes) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_generate_signed_message() { + let slot = 93; + let parent_hashes: Vec = (0..12).map(|i| Hash256::from(i as u64)).collect(); + let shard_id = 15; + let shard_block_hash = Hash256::from("shard_block_hash".as_bytes()); + let justified_slot = 18; + + let output = generate_signed_message( + slot, + &parent_hashes, + shard_id, + &shard_block_hash, + justified_slot, + ); + + /* + * Note: this is not some well-known test vector, it's simply the result of running + * this and printing the output. + * + * Once well-known test vectors are established, they should be placed here. + */ + let expected = vec![ + 185, 80, 24, 37, 184, 189, 129, 206, 109, 64, 116, 30, 221, 36, 160, 48, 114, 87, 138, + 139, 79, 57, 83, 39, 122, 42, 214, 135, 95, 204, 235, 161, + ]; + + assert_eq!(output, expected); + } +} diff --git a/beacon_chain/validator_induction/src/inductor.rs b/beacon_chain/validator_induction/src/inductor.rs index 2104e1e779..159aa35777 100644 --- a/beacon_chain/validator_induction/src/inductor.rs +++ b/beacon_chain/validator_induction/src/inductor.rs @@ -110,7 +110,7 @@ impl ValidatorInductor { mod tests { use super::*; - use bls::{Keypair, Signature}; + use bls::{create_proof_of_possession, Keypair, Signature}; use hashing::canonical_hash; use types::{Address, Hash256}; @@ -122,12 +122,6 @@ mod tests { & (verify_proof_of_possession(®.proof_of_possession, &rec.pubkey)) } - /// Generate a proof of possession for some keypair. - fn get_proof_of_possession(kp: &Keypair) -> Signature { - let pop_message = canonical_hash(&kp.pk.as_bytes()); - Signature::new_hashed(&pop_message, &kp.sk) - } - /// Generate a basic working ValidatorRegistration for use in tests. fn get_registration() -> ValidatorRegistration { let kp = Keypair::random(); @@ -136,7 +130,7 @@ mod tests { withdrawal_shard: 0, withdrawal_address: Address::zero(), randao_commitment: Hash256::zero(), - proof_of_possession: get_proof_of_possession(&kp), + proof_of_possession: create_proof_of_possession(&kp), } } @@ -266,7 +260,7 @@ mod tests { let mut r = get_registration(); let kp = Keypair::random(); - r.proof_of_possession = get_proof_of_possession(&kp); + r.proof_of_possession = create_proof_of_possession(&kp); let mut inductor = ValidatorInductor::new(0, 1024, validators); let result = inductor.induct(&r, ValidatorStatus::PendingActivation); From 9b59acb95b4a6a09c32f20512c4974f977b531e2 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 12 Dec 2018 21:58:21 -0800 Subject: [PATCH 12/31] remove file lost in merge --- .../validation/src/message_generation.rs | 67 ------------------- 1 file changed, 67 deletions(-) delete mode 100644 beacon_chain/validation/src/message_generation.rs diff --git a/beacon_chain/validation/src/message_generation.rs b/beacon_chain/validation/src/message_generation.rs deleted file mode 100644 index 3692988b6d..0000000000 --- a/beacon_chain/validation/src/message_generation.rs +++ /dev/null @@ -1,67 +0,0 @@ -use super::hashing::canonical_hash; -use super::ssz::SszStream; -use super::types::Hash256; - -/// Generates the message used to validate the signature provided with an AttestationRecord. -/// -/// Ensures that the signer of the message has a view of the chain that is compatible with ours. -pub fn generate_signed_message( - slot: u64, - parent_hashes: &[Hash256], - shard_id: u16, - shard_block_hash: &Hash256, - justified_slot: u64, -) -> Vec { - /* - * Note: it's a little risky here to use SSZ, because the encoding is not necessarily SSZ - * (for example, SSZ might change whilst this doesn't). - * - * I have suggested switching this to ssz here: - * https://github.com/ethereum/eth2.0-specs/issues/5 - * - * If this doesn't happen, it would be safer to not use SSZ at all. - */ - let mut ssz_stream = SszStream::new(); - ssz_stream.append(&slot); - ssz_stream.append_vec(&parent_hashes.to_vec()); - ssz_stream.append(&shard_id); - ssz_stream.append(shard_block_hash); - ssz_stream.append(&justified_slot); - let bytes = ssz_stream.drain(); - canonical_hash(&bytes) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_generate_signed_message() { - let slot = 93; - let parent_hashes: Vec = (0..12).map(|i| Hash256::from(i as u64)).collect(); - let shard_id = 15; - let shard_block_hash = Hash256::from("shard_block_hash".as_bytes()); - let justified_slot = 18; - - let output = generate_signed_message( - slot, - &parent_hashes, - shard_id, - &shard_block_hash, - justified_slot, - ); - - /* - * Note: this is not some well-known test vector, it's simply the result of running - * this and printing the output. - * - * Once well-known test vectors are established, they should be placed here. - */ - let expected = vec![ - 185, 80, 24, 37, 184, 189, 129, 206, 109, 64, 116, 30, 221, 36, 160, 48, 114, 87, 138, - 139, 79, 57, 83, 39, 122, 42, 214, 135, 95, 204, 235, 161, - ]; - - assert_eq!(output, expected); - } -} From 914760e19f95b37bf6e0effd7964ccc3785e8b6e Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 13 Dec 2018 07:04:50 -0800 Subject: [PATCH 13/31] update expected hash --- beacon_chain/utils/ssz_helpers/src/ssz_beacon_block.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/beacon_chain/utils/ssz_helpers/src/ssz_beacon_block.rs b/beacon_chain/utils/ssz_helpers/src/ssz_beacon_block.rs index 16001510f5..fd02df78dd 100644 --- a/beacon_chain/utils/ssz_helpers/src/ssz_beacon_block.rs +++ b/beacon_chain/utils/ssz_helpers/src/ssz_beacon_block.rs @@ -296,8 +296,8 @@ mod tests { // canonical reference. // TODO: make sure this test conforms to canonical test vectors; it is not clear that it currently does so let expected_hash = [ - 3, 88, 224, 80, 236, 217, 64, 236, 127, 56, 76, 139, 97, 103, 110, 149, 236, 105, 197, - 3, 21, 199, 0, 118, 72, 136, 20, 101, 192, 172, 220, 215, + 132, 43, 230, 49, 234, 240, 253, 146, 85, 121, 104, 79, 35, 0, 126, 162, 132, 99, 145, + 13, 30, 57, 118, 5, 175, 136, 174, 7, 52, 161, 87, 196, ]; assert_eq!(hash, expected_hash); From 5c3ee698a7a64aebe263c67fdfac6ec6a935035d Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 17 Dec 2018 09:14:54 +1100 Subject: [PATCH 14/31] Add issue link to vec_shuffle/src/lib.rs --- beacon_chain/utils/vec_shuffle/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/beacon_chain/utils/vec_shuffle/src/lib.rs b/beacon_chain/utils/vec_shuffle/src/lib.rs index 8c9de361e0..b3d5401749 100644 --- a/beacon_chain/utils/vec_shuffle/src/lib.rs +++ b/beacon_chain/utils/vec_shuffle/src/lib.rs @@ -47,6 +47,8 @@ mod tests { use std::fs::File; use std::io::prelude::*; + // TODO: update test vectors to use keccak instead of blake. + // https://github.com/sigp/lighthouse/issues/121 #[test] #[should_panic] fn test_shuffling() { From bd3d388b9203a2ebd98ab27b390e2ccb26ca7c71 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 17 Dec 2018 17:16:25 -0800 Subject: [PATCH 15/31] Use `resize` instead of `extend` which fits this use much better --- beacon_chain/utils/bls/src/lib.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/beacon_chain/utils/bls/src/lib.rs b/beacon_chain/utils/bls/src/lib.rs index 6c115ae17b..fc665b206b 100644 --- a/beacon_chain/utils/bls/src/lib.rs +++ b/beacon_chain/utils/bls/src/lib.rs @@ -8,19 +8,14 @@ pub use self::bls_aggregates::PublicKey; pub use self::bls_aggregates::SecretKey; pub use self::bls_aggregates::Signature; -use std::iter; - pub const BLS_AGG_SIG_BYTE_SIZE: usize = 97; use hashing::canonical_hash; +use std::default::Default; fn extend_if_needed(hash: &mut Vec) { // NOTE: bls_aggregates crate demands 48 bytes, this may be removed as we get closer to production - let hash_len = hash.len(); - if hash_len < 48 { - let missing_len = 48 - hash_len; - hash.extend(iter::repeat(0x00).take(missing_len)); - } + hash.resize(48, Default::default()) } /// For some signature and public key, ensure that the signature message was the public key and it From f046a326b89be130e1c67886bd0ce3445781a3f5 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 18 Dec 2018 17:04:54 +1100 Subject: [PATCH 16/31] 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 1199efc154..81d467a46c 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 0000000000..0970ce56f5 --- /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 dcd2a9d299..15abca0982 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 0000000000..bfeaca45e4 --- /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 17/31] 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 2c2015cd3c..40ee2173c1 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 18/31] 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 0970ce56f5..5cc9c3c215 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 19/31] 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 069e697a4d..835d37edc4 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 4606d03ec2..b4219a5f8c 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 8544be8621..a5b35f6963 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 479804f45e..aa0f48c625 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 0837f3bafa..92a2dd8f84 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 a8189ce60e..0000000000 --- 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 a216e0ec26..0000000000 --- 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 6ac4372e9d..0000000000 --- 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 5c80595414..0000000000 --- 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 a2718889c6..e7fd4cd5d7 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 20/31] 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 35ad18497f..ad87ec84a3 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 e69de29bb2..66db774b78 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 0000000000..a8f722652b --- /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 0000000000..7a6e704096 --- /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 0000000000..8de66c6306 --- /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 f86d5f0247..c71a205b74 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 0000000000..25a6f0e042 --- /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 0000000000..33d8103b9b --- /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 0000000000..7a8f3d4da2 --- /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 1ffdcd363dc481ca103cbbbcee89d6e5eff56d31 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 19 Dec 2018 12:54:31 +1100 Subject: [PATCH 21/31] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 735fbdb940..e288555043 100644 --- a/README.md +++ b/README.md @@ -264,3 +264,9 @@ proof-of-concept implementation in Python is available at Presently, the specification focuses almost exclusively on the beacon chain, as it is the focus of current development efforts. Progress on shard chain specification will soon follow. + +# Donations + +If you support the cause, we could certainly use donations to help fund development: + +`0x25c4a76E7d118705e7Ea2e9b7d8C59930d8aCD3b` From c9f82f8a1d94745b145cfc1c3f9002810a587e9e Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 19 Dec 2018 17:56:09 +1100 Subject: [PATCH 22/31] 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 66db774b78..f0c767155b 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 7a6e704096..3b2ad87a62 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 8de66c6306..c4753354da 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 33d8103b9b..0daab8ea8f 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 e5028720833d18dfa161559854b4f8812e410ca2 Mon Sep 17 00:00:00 2001 From: Stan Drozd Date: Wed, 19 Dec 2018 16:07:01 +0100 Subject: [PATCH 23/31] cargo-fix the whole workspace into Rust 2018 --- .../attestation_validation/src/lib.rs | 12 ++++---- beacon_chain/chain/src/lib.rs | 6 ++-- beacon_chain/types/src/lib.rs | 28 +++++++++---------- beacon_chain/utils/ssz/src/lib.rs | 4 +-- beacon_chain/validator_induction/src/lib.rs | 2 +- beacon_chain/validator_shuffling/src/lib.rs | 2 +- lighthouse/main.rs | 2 +- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/beacon_chain/attestation_validation/src/lib.rs b/beacon_chain/attestation_validation/src/lib.rs index 8544be8621..36fca97401 100644 --- a/beacon_chain/attestation_validation/src/lib.rs +++ b/beacon_chain/attestation_validation/src/lib.rs @@ -15,9 +15,9 @@ mod justified_slot; mod shard_block; mod signature; -pub use enums::{Invalid, Outcome, Error}; -pub use block_inclusion::validate_attestation_for_block; -pub use justified_slot::validate_attestation_justified_slot; -pub use justified_block::validate_attestation_justified_block_hash; -pub use signature::validate_attestation_signature; -pub use shard_block::validate_attestation_data_shard_block_hash; +pub use crate::enums::{Invalid, Outcome, Error}; +pub use crate::block_inclusion::validate_attestation_for_block; +pub use crate::justified_slot::validate_attestation_justified_slot; +pub use crate::justified_block::validate_attestation_justified_block_hash; +pub use crate::signature::validate_attestation_signature; +pub use crate::shard_block::validate_attestation_data_shard_block_hash; diff --git a/beacon_chain/chain/src/lib.rs b/beacon_chain/chain/src/lib.rs index 0837f3bafa..7976b34a1e 100644 --- a/beacon_chain/chain/src/lib.rs +++ b/beacon_chain/chain/src/lib.rs @@ -14,11 +14,11 @@ mod stores; mod transition; use db::ClientDB; -use genesis::{genesis_states, Error as GenesisError}; -use maps::{generate_attester_and_proposer_maps, AttesterAndProposerMapError}; +use crate::genesis::{genesis_states, Error as GenesisError}; +use crate::maps::{generate_attester_and_proposer_maps, AttesterAndProposerMapError}; use std::collections::HashMap; use std::sync::Arc; -use stores::BeaconChainStore; +use crate::stores::BeaconChainStore; use types::{ActiveState, AttesterMap, ChainConfig, CrystallizedState, Hash256, ProposerMap}; #[derive(Debug, PartialEq)] diff --git a/beacon_chain/types/src/lib.rs b/beacon_chain/types/src/lib.rs index f86d5f0247..273318a85e 100644 --- a/beacon_chain/types/src/lib.rs +++ b/beacon_chain/types/src/lib.rs @@ -23,20 +23,20 @@ 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_state::BeaconState; -pub use chain_config::ChainConfig; -pub use crosslink_record::CrosslinkRecord; -pub use crystallized_state::CrystallizedState; -pub use fork_data::ForkData; -pub use pending_attestation_record::PendingAttestationRecord; -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_state::BeaconState; +pub use crate::chain_config::ChainConfig; +pub use crate::crosslink_record::CrosslinkRecord; +pub use crate::crystallized_state::CrystallizedState; +pub use crate::fork_data::ForkData; +pub use crate::pending_attestation_record::PendingAttestationRecord; +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/utils/ssz/src/lib.rs b/beacon_chain/utils/ssz/src/lib.rs index f3a195e427..ccfcb7f5b1 100644 --- a/beacon_chain/utils/ssz/src/lib.rs +++ b/beacon_chain/utils/ssz/src/lib.rs @@ -16,8 +16,8 @@ pub mod encode; mod impl_decode; mod impl_encode; -pub use decode::{decode_ssz, decode_ssz_list, Decodable, DecodeError}; -pub use encode::{Encodable, SszStream}; +pub use crate::decode::{decode_ssz, decode_ssz_list, Decodable, DecodeError}; +pub use crate::encode::{Encodable, SszStream}; pub const LENGTH_BYTES: usize = 4; pub const MAX_LIST_SIZE: usize = 1 << (4 * 8); diff --git a/beacon_chain/validator_induction/src/lib.rs b/beacon_chain/validator_induction/src/lib.rs index 6ea6265ba8..ded9785da7 100644 --- a/beacon_chain/validator_induction/src/lib.rs +++ b/beacon_chain/validator_induction/src/lib.rs @@ -4,4 +4,4 @@ extern crate types; mod inductor; -pub use inductor::{ValidatorInductionError, ValidatorInductor}; +pub use crate::inductor::{ValidatorInductionError, ValidatorInductor}; diff --git a/beacon_chain/validator_shuffling/src/lib.rs b/beacon_chain/validator_shuffling/src/lib.rs index 90077279ff..b4d3204375 100644 --- a/beacon_chain/validator_shuffling/src/lib.rs +++ b/beacon_chain/validator_shuffling/src/lib.rs @@ -4,4 +4,4 @@ extern crate vec_shuffle; mod shuffle; -pub use shuffle::{shard_and_committees_for_cycle, ValidatorAssignmentError}; +pub use crate::shuffle::{shard_and_committees_for_cycle, ValidatorAssignmentError}; diff --git a/lighthouse/main.rs b/lighthouse/main.rs index 67c9954f06..b2c199db98 100644 --- a/lighthouse/main.rs +++ b/lighthouse/main.rs @@ -13,7 +13,7 @@ mod config; use std::path::PathBuf; use clap::{App, Arg}; -use config::LighthouseConfig; +use crate::config::LighthouseConfig; use slog::Drain; fn main() { From dcf9f2244a5ac7d635f648430759b3dba43edbb8 Mon Sep 17 00:00:00 2001 From: Stan Drozd Date: Wed, 19 Dec 2018 16:38:59 +0100 Subject: [PATCH 24/31] Add 'edition = "2018"' to every Cargo.toml --- Cargo.toml | 1 + beacon_chain/attestation_validation/Cargo.toml | 1 + beacon_chain/chain/Cargo.toml | 1 + beacon_chain/naive_fork_choice/Cargo.toml | 1 + beacon_chain/spec/Cargo.toml | 1 + beacon_chain/state-transition/Cargo.toml | 1 + beacon_chain/types/Cargo.toml | 1 + beacon_chain/utils/bls/Cargo.toml | 1 + beacon_chain/utils/boolean-bitfield/Cargo.toml | 3 ++- beacon_chain/utils/hashing/Cargo.toml | 3 ++- beacon_chain/utils/honey-badger-split/Cargo.toml | 1 + beacon_chain/utils/slot-clock/Cargo.toml | 1 + beacon_chain/utils/ssz/Cargo.toml | 1 + beacon_chain/utils/ssz_helpers/Cargo.toml | 1 + beacon_chain/utils/vec_shuffle/Cargo.toml | 1 + beacon_chain/validator_change/Cargo.toml | 1 + beacon_chain/validator_induction/Cargo.toml | 1 + beacon_chain/validator_shuffling/Cargo.toml | 1 + lighthouse/db/Cargo.toml | 1 + 19 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 069e697a4d..7490c3d000 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ name = "lighthouse" version = "0.0.1" authors = ["Paul Hauner "] +edition = "2018" [dependencies] blake2-rfc = "0.2.18" diff --git a/beacon_chain/attestation_validation/Cargo.toml b/beacon_chain/attestation_validation/Cargo.toml index 4606d03ec2..b2f84fd1df 100644 --- a/beacon_chain/attestation_validation/Cargo.toml +++ b/beacon_chain/attestation_validation/Cargo.toml @@ -2,6 +2,7 @@ name = "attestation_validation" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] bls = { path = "../utils/bls" } diff --git a/beacon_chain/chain/Cargo.toml b/beacon_chain/chain/Cargo.toml index 479804f45e..77555d9a90 100644 --- a/beacon_chain/chain/Cargo.toml +++ b/beacon_chain/chain/Cargo.toml @@ -2,6 +2,7 @@ name = "chain" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] bls = { path = "../utils/bls" } diff --git a/beacon_chain/naive_fork_choice/Cargo.toml b/beacon_chain/naive_fork_choice/Cargo.toml index 679575556e..9508ed02e3 100644 --- a/beacon_chain/naive_fork_choice/Cargo.toml +++ b/beacon_chain/naive_fork_choice/Cargo.toml @@ -2,6 +2,7 @@ name = "naive_fork_choice" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] db = { path = "../../lighthouse/db" } diff --git a/beacon_chain/spec/Cargo.toml b/beacon_chain/spec/Cargo.toml index a2eac0692b..2da687fa33 100644 --- a/beacon_chain/spec/Cargo.toml +++ b/beacon_chain/spec/Cargo.toml @@ -2,6 +2,7 @@ name = "spec" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] types = { path = "../types" } diff --git a/beacon_chain/state-transition/Cargo.toml b/beacon_chain/state-transition/Cargo.toml index 7beb8f6131..12618a6cee 100644 --- a/beacon_chain/state-transition/Cargo.toml +++ b/beacon_chain/state-transition/Cargo.toml @@ -2,6 +2,7 @@ name = "state-transition" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] types = { path = "../types" } diff --git a/beacon_chain/types/Cargo.toml b/beacon_chain/types/Cargo.toml index cf20f69c00..7b1f0d4409 100644 --- a/beacon_chain/types/Cargo.toml +++ b/beacon_chain/types/Cargo.toml @@ -2,6 +2,7 @@ name = "types" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] bls = { path = "../utils/bls" } diff --git a/beacon_chain/utils/bls/Cargo.toml b/beacon_chain/utils/bls/Cargo.toml index 1199efc154..d38b5c6048 100644 --- a/beacon_chain/utils/bls/Cargo.toml +++ b/beacon_chain/utils/bls/Cargo.toml @@ -2,6 +2,7 @@ name = "bls" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] bls-aggregates = { git = "https://github.com/sigp/signature-schemes" } diff --git a/beacon_chain/utils/boolean-bitfield/Cargo.toml b/beacon_chain/utils/boolean-bitfield/Cargo.toml index 1633401e22..b3d05f979c 100644 --- a/beacon_chain/utils/boolean-bitfield/Cargo.toml +++ b/beacon_chain/utils/boolean-bitfield/Cargo.toml @@ -2,7 +2,8 @@ name = "boolean-bitfield" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] ssz = { path = "../ssz" } -bit-vec = "0.5.0" \ No newline at end of file +bit-vec = "0.5.0" diff --git a/beacon_chain/utils/hashing/Cargo.toml b/beacon_chain/utils/hashing/Cargo.toml index 8bed7adafc..1527bceba1 100644 --- a/beacon_chain/utils/hashing/Cargo.toml +++ b/beacon_chain/utils/hashing/Cargo.toml @@ -2,6 +2,7 @@ name = "hashing" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] -tiny-keccak = "1.4.2" \ No newline at end of file +tiny-keccak = "1.4.2" diff --git a/beacon_chain/utils/honey-badger-split/Cargo.toml b/beacon_chain/utils/honey-badger-split/Cargo.toml index e9721efd44..87246eafdb 100644 --- a/beacon_chain/utils/honey-badger-split/Cargo.toml +++ b/beacon_chain/utils/honey-badger-split/Cargo.toml @@ -2,5 +2,6 @@ name = "honey-badger-split" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] diff --git a/beacon_chain/utils/slot-clock/Cargo.toml b/beacon_chain/utils/slot-clock/Cargo.toml index c10fb6bd90..ccb2e4ed49 100644 --- a/beacon_chain/utils/slot-clock/Cargo.toml +++ b/beacon_chain/utils/slot-clock/Cargo.toml @@ -2,5 +2,6 @@ name = "slot-clock" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] diff --git a/beacon_chain/utils/ssz/Cargo.toml b/beacon_chain/utils/ssz/Cargo.toml index aa4dc5d72c..e28e92c232 100644 --- a/beacon_chain/utils/ssz/Cargo.toml +++ b/beacon_chain/utils/ssz/Cargo.toml @@ -2,6 +2,7 @@ name = "ssz" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] bytes = "0.4.9" diff --git a/beacon_chain/utils/ssz_helpers/Cargo.toml b/beacon_chain/utils/ssz_helpers/Cargo.toml index a8189ce60e..3634ea39c8 100644 --- a/beacon_chain/utils/ssz_helpers/Cargo.toml +++ b/beacon_chain/utils/ssz_helpers/Cargo.toml @@ -2,6 +2,7 @@ name = "ssz_helpers" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] bls = { path = "../bls" } diff --git a/beacon_chain/utils/vec_shuffle/Cargo.toml b/beacon_chain/utils/vec_shuffle/Cargo.toml index 3e7ece8eac..aaeb50074d 100644 --- a/beacon_chain/utils/vec_shuffle/Cargo.toml +++ b/beacon_chain/utils/vec_shuffle/Cargo.toml @@ -2,6 +2,7 @@ name = "vec_shuffle" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] hashing = { path = "../hashing" } diff --git a/beacon_chain/validator_change/Cargo.toml b/beacon_chain/validator_change/Cargo.toml index 0705033dc3..4574a115f8 100644 --- a/beacon_chain/validator_change/Cargo.toml +++ b/beacon_chain/validator_change/Cargo.toml @@ -2,6 +2,7 @@ name = "validator_change" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] bytes = "0.4.10" diff --git a/beacon_chain/validator_induction/Cargo.toml b/beacon_chain/validator_induction/Cargo.toml index 9a443133e9..5907014df7 100644 --- a/beacon_chain/validator_induction/Cargo.toml +++ b/beacon_chain/validator_induction/Cargo.toml @@ -2,6 +2,7 @@ name = "validator_induction" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] bls = { path = "../utils/bls" } diff --git a/beacon_chain/validator_shuffling/Cargo.toml b/beacon_chain/validator_shuffling/Cargo.toml index ba99841b80..ae2babf1a4 100644 --- a/beacon_chain/validator_shuffling/Cargo.toml +++ b/beacon_chain/validator_shuffling/Cargo.toml @@ -2,6 +2,7 @@ name = "validator_shuffling" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] honey-badger-split = { path = "../utils/honey-badger-split" } diff --git a/lighthouse/db/Cargo.toml b/lighthouse/db/Cargo.toml index a2718889c6..a8cfb88d48 100644 --- a/lighthouse/db/Cargo.toml +++ b/lighthouse/db/Cargo.toml @@ -2,6 +2,7 @@ name = "db" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] blake2-rfc = "0.2.18" From 368a218af4081711f659990821b5c2ffc6d49cb0 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Fri, 21 Dec 2018 15:44:11 +1100 Subject: [PATCH 25/31] 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 ad87ec84a3..b2641cf84c 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 a8f722652b..dfa99cd6b0 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 3b2ad87a62..7aa3758285 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 0000000000..790beab287 --- /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 0000000000..d9b3e98643 --- /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 c4753354da..b32ec3af69 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 c71a205b74..e24e77b934 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 25a6f0e042..f44ecdd417 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 0daab8ea8f..b8d597283d 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 7a8f3d4da2..2bd4899781 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 26/31] 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 cf20f69c00..f497022807 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 40ee2173c1..6e7c54d449 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 d75c43b9db..57fcaa4300 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 b2641cf84c..8bbc915923 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 f0c767155b..e49ca35bc2 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 dfa99cd6b0..29fc620fc4 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 7aa3758285..2b0025fa42 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 790beab287..a01a95cba7 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 d9b3e98643..c57437e86e 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 b32ec3af69..cd0b79b35a 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 e24e77b934..71d6f10e63 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 f44ecdd417..6a038d0ebd 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 b8d597283d..1e2b22b1d1 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 0000000000..6a15f73669 --- /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 0000000000..15011edd9c --- /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 0000000000..98f5e78996 --- /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 0000000000..0087f8152f --- /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 0000000000..bfccd3e532 --- /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 0000000000..17481c3de9 --- /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 0000000000..9ec7aec60a --- /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 2bd4899781..150b400811 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 27/31] 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 835d37edc4..7e46412981 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 aa0f48c625..4430dbe5b9 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 7beb8f6131..0000000000 --- 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 ee8d841e60..0000000000 --- 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 28/31] 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 6e7c54d449..7a94eee51c 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 57fcaa4300..616c52d790 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 8bbc915923..b6ac9e9e02 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 e49ca35bc2..f5ac223432 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 29fc620fc4..a972f22482 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 2b0025fa42..9d84bc2780 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 a01a95cba7..b236709d20 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 c57437e86e..41b579cdab 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 cd0b79b35a..6a6d573051 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 71d6f10e63..0d2524195e 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 6a038d0ebd..7a01fc10a5 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 1e2b22b1d1..d2d3531128 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 150b400811..9eb3d19842 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 0087f8152f..131ff9aacf 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 29/31] 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 cad353eb26..5f777ea0ae 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 30/31] 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 c98d58d3e1..8eb076d478 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 7598f25175..0000000000 --- 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 31/31] 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 3f366bdf3a..f316a21ead 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!(