From f0ea69120813638277d12117a2fbddffd2877d35 Mon Sep 17 00:00:00 2001 From: thojest Date: Fri, 1 Mar 2019 18:19:08 +0100 Subject: [PATCH 01/13] now possible to select ChainSpec by using CLI flag (lighthouse-252) --- validator_client/src/config.rs | 9 ++++++++- validator_client/src/main.rs | 27 ++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/validator_client/src/config.rs b/validator_client/src/config.rs index 104a4bbe6..68405ed2f 100644 --- a/validator_client/src/config.rs +++ b/validator_client/src/config.rs @@ -1,11 +1,13 @@ use std::fs; use std::path::PathBuf; +use types::ChainSpec; /// Stores the core configuration for this validator instance. #[derive(Clone)] pub struct ClientConfig { pub data_dir: PathBuf, pub server: String, + pub spec: ChainSpec, } const DEFAULT_LIGHTHOUSE_DIR: &str = ".lighthouse-validators"; @@ -20,6 +22,11 @@ impl ClientConfig { fs::create_dir_all(&data_dir) .unwrap_or_else(|_| panic!("Unable to create {:?}", &data_dir)); let server = "localhost:50051".to_string(); - Self { data_dir, server } + let spec = ChainSpec::foundation(); + Self { + data_dir, + server, + spec, + } } } diff --git a/validator_client/src/main.rs b/validator_client/src/main.rs index c835300b5..e9a7b15a3 100644 --- a/validator_client/src/main.rs +++ b/validator_client/src/main.rs @@ -43,6 +43,15 @@ fn main() { .help("Address to connect to BeaconNode.") .takes_value(true), ) + .arg( + Arg::with_name("spec") + .long("spec") + .value_name("spec") + .short("s") + .help("Configuration of Beacon Chain") + .takes_value(true) + .possible_values(&["foundation", "few_validators"]), + ) .get_matches(); let mut config = ClientConfig::default(); @@ -62,6 +71,17 @@ fn main() { } } + // TODO: Permit loading a custom spec from file. + // Custom spec + if let Some(spec_str) = matches.value_of("spec") { + match spec_str { + "foundation" => config.spec = ChainSpec::foundation(), + "few_validators" => config.spec = ChainSpec::few_validators(), + // Should be impossible + _ => error!(log, "Invalid spec defined"; "spec" => format!("{:?}", config.spec)), + }; + } + // Log configuration info!(log, ""; "data_dir" => &config.data_dir.to_str(), @@ -81,11 +101,8 @@ fn main() { Arc::new(ValidatorServiceClient::new(ch)) }; - // Ethereum - // - // TODO: Permit loading a custom spec from file. - // https://github.com/sigp/lighthouse/issues/160 - let spec = Arc::new(ChainSpec::foundation()); + // Spec + let spec = Arc::new(config.spec.clone()); // Clock for determining the present slot. // TODO: this shouldn't be a static time, instead it should be pulled from the beacon node. From ed7a0810080475fabffdd7cd01e35edfabddb049 Mon Sep 17 00:00:00 2001 From: thojest Date: Fri, 1 Mar 2019 18:23:25 +0100 Subject: [PATCH 02/13] slightly adapted impossible error for validator_client (lighthouse-252) --- validator_client/src/main.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/validator_client/src/main.rs b/validator_client/src/main.rs index e9a7b15a3..f81c3e40c 100644 --- a/validator_client/src/main.rs +++ b/validator_client/src/main.rs @@ -78,7 +78,10 @@ fn main() { "foundation" => config.spec = ChainSpec::foundation(), "few_validators" => config.spec = ChainSpec::few_validators(), // Should be impossible - _ => error!(log, "Invalid spec defined"; "spec" => format!("{:?}", config.spec)), + _ => { + error!(log, "Invalid ChainSpec defined"; "spec" => spec_str); + return; + } }; } From c28c07c17d40f7c5f8a647ee40f3bf14e535a075 Mon Sep 17 00:00:00 2001 From: thojest Date: Sun, 3 Mar 2019 14:15:00 +0100 Subject: [PATCH 03/13] validator_client: added default_value for spec; used unreachable macro for custom spec (lighthouse-252) --- validator_client/src/main.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/validator_client/src/main.rs b/validator_client/src/main.rs index f81c3e40c..4344bc16e 100644 --- a/validator_client/src/main.rs +++ b/validator_client/src/main.rs @@ -50,7 +50,8 @@ fn main() { .short("s") .help("Configuration of Beacon Chain") .takes_value(true) - .possible_values(&["foundation", "few_validators"]), + .possible_values(&["foundation", "few_validators"]) + .default_value("foundation"), ) .get_matches(); @@ -77,11 +78,8 @@ fn main() { match spec_str { "foundation" => config.spec = ChainSpec::foundation(), "few_validators" => config.spec = ChainSpec::few_validators(), - // Should be impossible - _ => { - error!(log, "Invalid ChainSpec defined"; "spec" => spec_str); - return; - } + // Should be impossible due to clap's `possible_values(..)` function. + _ => unreachable!(), }; } From 3aaa3ea0243bb355fc9c2ead3cb6a8e939c4eec1 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 4 Mar 2019 09:30:09 +1100 Subject: [PATCH 04/13] Use clearer types in test_harness::Config --- .../test_harness/src/test_case/config.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/beacon_node/beacon_chain/test_harness/src/test_case/config.rs b/beacon_node/beacon_chain/test_harness/src/test_case/config.rs index 8c88ee5d1..d08e7fe40 100644 --- a/beacon_node/beacon_chain/test_harness/src/test_case/config.rs +++ b/beacon_node/beacon_chain/test_harness/src/test_case/config.rs @@ -3,9 +3,12 @@ use bls::create_proof_of_possession; use types::*; use yaml_rust::Yaml; -pub type DepositTuple = (u64, Deposit, Keypair); -pub type ProposerSlashingTuple = (u64, u64); -pub type AttesterSlashingTuple = (u64, Vec); +pub type ValidatorIndex = u64; +pub type ValidatorIndices = Vec; + +pub type DepositTuple = (SlotHeight, Deposit, Keypair); +pub type ProposerSlashingTuple = (SlotHeight, ValidatorIndex); +pub type AttesterSlashingTuple = (SlotHeight, ValidatorIndices); /// Defines the execution of a `BeaconStateHarness` across a series of slots. #[derive(Debug)] @@ -53,7 +56,7 @@ fn parse_attester_slashings(yaml: &Yaml) -> Option> { let validator_indices = as_vec_u64(slashing, "validator_indices") .expect("Incomplete attester_slashing (validator_indices)"); - slashings.push((slot, validator_indices)); + slashings.push((SlotHeight::from(slot), validator_indices)); } Some(slashings) @@ -68,7 +71,7 @@ fn parse_proposer_slashings(yaml: &Yaml) -> Option> { let validator_index = as_u64(slashing, "validator_index") .expect("Incomplete proposer slashing (validator_index)"); - slashings.push((slot, validator_index)); + slashings.push((SlotHeight::from(slot), validator_index)); } Some(slashings) @@ -102,7 +105,7 @@ fn parse_deposits(yaml: &Yaml) -> Option> { }, }; - deposits.push((slot, deposit, keypair)); + deposits.push((SlotHeight::from(slot), deposit, keypair)); } Some(deposits) From bc4acd9a5cb1fc31b1a480ca701721de0b3f8daf Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 4 Mar 2019 09:43:19 +1100 Subject: [PATCH 05/13] Re-work module structure in test_harness Obeys the standard where structs live in files with the same name --- .../test_harness/src/{test_case/mod.rs => test_case.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename beacon_node/beacon_chain/test_harness/src/{test_case/mod.rs => test_case.rs} (100%) diff --git a/beacon_node/beacon_chain/test_harness/src/test_case/mod.rs b/beacon_node/beacon_chain/test_harness/src/test_case.rs similarity index 100% rename from beacon_node/beacon_chain/test_harness/src/test_case/mod.rs rename to beacon_node/beacon_chain/test_harness/src/test_case.rs From f4d8b41a0919e6c68c0b0b13fcc4a340c62269fe Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 4 Mar 2019 12:20:59 +1100 Subject: [PATCH 06/13] Add Exit inclusion queue to BeaconChain --- beacon_node/beacon_chain/src/beacon_chain.rs | 66 ++++++++++++++++++-- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index e6fd2a134..81d17f024 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -65,6 +65,7 @@ pub struct BeaconChain { pub slot_clock: U, pub attestation_aggregator: RwLock, pub deposits_for_inclusion: RwLock>, + pub exits_for_inclusion: RwLock>, pub proposer_slashings_for_inclusion: RwLock>, pub attester_slashings_for_inclusion: RwLock>, canonical_head: RwLock, @@ -134,6 +135,7 @@ where slot_clock, attestation_aggregator, deposits_for_inclusion: RwLock::new(vec![]), + exits_for_inclusion: RwLock::new(vec![]), proposer_slashings_for_inclusion: RwLock::new(vec![]), attester_slashings_for_inclusion: RwLock::new(vec![]), state: RwLock::new(genesis_state), @@ -370,13 +372,17 @@ where /// Accept some deposit and queue it for inclusion in an appropriate block. pub fn receive_deposit_for_inclusion(&self, deposit: Deposit) { - // TODO: deposits are not check for validity; check them. + // TODO: deposits are not checked for validity; check them. + // + // https://github.com/sigp/lighthouse/issues/276 self.deposits_for_inclusion.write().push(deposit); } /// Return a vec of deposits suitable for inclusion in some block. pub fn get_deposits_for_block(&self) -> Vec { // TODO: deposits are indiscriminately included; check them for validity. + // + // https://github.com/sigp/lighthouse/issues/275 self.deposits_for_inclusion.read().clone() } @@ -386,6 +392,8 @@ where /// This ensures that `Deposits` are not included twice in successive blocks. pub fn set_deposits_as_included(&self, included_deposits: &[Deposit]) { // TODO: method does not take forks into account; consider this. + // + // https://github.com/sigp/lighthouse/issues/275 let mut indices_to_delete = vec![]; for included in included_deposits { @@ -402,9 +410,49 @@ where } } + /// Accept some exit and queue it for inclusion in an appropriate block. + pub fn receive_exit_for_inclusion(&self, exit: Exit) { + // TODO: exits are not checked for validity; check them. + // + // https://github.com/sigp/lighthouse/issues/276 + self.exits_for_inclusion.write().push(exit); + } + + /// Return a vec of exits suitable for inclusion in some block. + pub fn get_exits_for_block(&self) -> Vec { + // TODO: exits are indiscriminately included; check them for validity. + // + // https://github.com/sigp/lighthouse/issues/275 + self.exits_for_inclusion.read().clone() + } + + /// Takes a list of `Deposits` that were included in recent blocks and removes them from the + /// inclusion queue. + /// + /// This ensures that `Deposits` are not included twice in successive blocks. + pub fn set_exits_as_included(&self, included_exits: &[Exit]) { + // TODO: method does not take forks into account; consider this. + let mut indices_to_delete = vec![]; + + for included in included_exits { + for (i, for_inclusion) in self.exits_for_inclusion.read().iter().enumerate() { + if included == for_inclusion { + indices_to_delete.push(i); + } + } + } + + let exits_for_inclusion = &mut self.exits_for_inclusion.write(); + for i in indices_to_delete { + exits_for_inclusion.remove(i); + } + } + /// Accept some proposer slashing and queue it for inclusion in an appropriate block. pub fn receive_proposer_slashing_for_inclusion(&self, proposer_slashing: ProposerSlashing) { - // TODO: proposer_slashings are not check for validity; check them. + // TODO: proposer_slashings are not checked for validity; check them. + // + // https://github.com/sigp/lighthouse/issues/276 self.proposer_slashings_for_inclusion .write() .push(proposer_slashing); @@ -413,6 +461,8 @@ where /// Return a vec of proposer slashings suitable for inclusion in some block. pub fn get_proposer_slashings_for_block(&self) -> Vec { // TODO: proposer_slashings are indiscriminately included; check them for validity. + // + // https://github.com/sigp/lighthouse/issues/275 self.proposer_slashings_for_inclusion.read().clone() } @@ -425,6 +475,8 @@ where included_proposer_slashings: &[ProposerSlashing], ) { // TODO: method does not take forks into account; consider this. + // + // https://github.com/sigp/lighthouse/issues/275 let mut indices_to_delete = vec![]; for included in included_proposer_slashings { @@ -448,7 +500,9 @@ where /// Accept some attester slashing and queue it for inclusion in an appropriate block. pub fn receive_attester_slashing_for_inclusion(&self, attester_slashing: AttesterSlashing) { - // TODO: attester_slashings are not check for validity; check them. + // TODO: attester_slashings are not checked for validity; check them. + // + // https://github.com/sigp/lighthouse/issues/276 self.attester_slashings_for_inclusion .write() .push(attester_slashing); @@ -457,6 +511,8 @@ where /// Return a vec of attester slashings suitable for inclusion in some block. pub fn get_attester_slashings_for_block(&self) -> Vec { // TODO: attester_slashings are indiscriminately included; check them for validity. + // + // https://github.com/sigp/lighthouse/issues/275 self.attester_slashings_for_inclusion.read().clone() } @@ -469,6 +525,8 @@ where included_attester_slashings: &[AttesterSlashing], ) { // TODO: method does not take forks into account; consider this. + // + // https://github.com/sigp/lighthouse/issues/275 let mut indices_to_delete = vec![]; for included in included_attester_slashings { @@ -678,7 +736,7 @@ where attester_slashings: self.get_attester_slashings_for_block(), attestations, deposits: self.get_deposits_for_block(), - exits: vec![], + exits: self.get_exits_for_block(), }, }; From ef006bfb2cc30bc5906f4e1bb7210847dca42e2c Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 4 Mar 2019 12:21:24 +1100 Subject: [PATCH 07/13] Add Exit support to test_harness --- .../specs/validator_registry.yaml | 5 +++ .../test_harness/src/beacon_chain_harness.rs | 9 ++++ .../test_harness/src/test_case.rs | 42 +++++++++++++++++++ .../test_harness/src/test_case/config.rs | 19 +++++++++ .../test_harness/src/test_case/state_check.rs | 32 +++++++++++++- eth2/types/src/validator.rs | 5 +++ 6 files changed, 111 insertions(+), 1 deletion(-) diff --git a/beacon_node/beacon_chain/test_harness/specs/validator_registry.yaml b/beacon_node/beacon_chain/test_harness/specs/validator_registry.yaml index b7fdda9bf..5851d6d12 100644 --- a/beacon_node/beacon_chain/test_harness/specs/validator_registry.yaml +++ b/beacon_node/beacon_chain/test_harness/specs/validator_registry.yaml @@ -18,6 +18,10 @@ test_cases: amount: 32 - slot: 5 amount: 32 + exits: + # At slot 10, submit an exit for validator #50. + - slot: 10 + validator_index: 50 proposer_slashings: # At slot 2, trigger a proposer slashing for validator #42. - slot: 2 @@ -39,4 +43,5 @@ test_cases: num_validators: 1003 slashed_validators: [11, 12, 13, 14, 42] exited_validators: [] + exit_initiated_validators: [50] diff --git a/beacon_node/beacon_chain/test_harness/src/beacon_chain_harness.rs b/beacon_node/beacon_chain/test_harness/src/beacon_chain_harness.rs index 2f375f7fa..40672c11a 100644 --- a/beacon_node/beacon_chain/test_harness/src/beacon_chain_harness.rs +++ b/beacon_node/beacon_chain/test_harness/src/beacon_chain_harness.rs @@ -280,6 +280,15 @@ impl BeaconChainHarness { } } + /// Submit an exit to the `BeaconChain` for inclusion in some block. + /// + /// Note: the `ValidatorHarness` for this validator continues to exist. Once it is exited it + /// will stop receiving duties from the beacon chain and just do nothing when prompted to + /// produce/attest. + pub fn add_exit(&mut self, exit: Exit) { + self.beacon_chain.receive_exit_for_inclusion(exit); + } + /// Submit a proposer slashing to the `BeaconChain` for inclusion in some block. pub fn add_proposer_slashing(&mut self, proposer_slashing: ProposerSlashing) { self.beacon_chain diff --git a/beacon_node/beacon_chain/test_harness/src/test_case.rs b/beacon_node/beacon_chain/test_harness/src/test_case.rs index f6d8d42e8..cdac7d3cc 100644 --- a/beacon_node/beacon_chain/test_harness/src/test_case.rs +++ b/beacon_node/beacon_chain/test_harness/src/test_case.rs @@ -4,6 +4,7 @@ use crate::beacon_chain_harness::BeaconChainHarness; use beacon_chain::CheckPoint; use log::{info, warn}; +use ssz::TreeHash; use types::*; use types::{ attester_slashing::AttesterSlashingBuilder, proposer_slashing::ProposerSlashingBuilder, @@ -121,6 +122,20 @@ impl TestCase { } } + // Feed exits to the BeaconChain. + if let Some(ref exits) = self.config.exits { + for (slot, validator_index) in exits { + if *slot == slot_height { + info!( + "Including exit at slot height {} for validator {}.", + slot_height, validator_index + ); + let exit = build_exit(&harness, *validator_index); + harness.add_exit(exit); + } + } + } + // Build a block or skip a slot. match self.config.skip_slots { Some(ref skip_slots) if skip_slots.contains(&slot_height) => { @@ -185,6 +200,33 @@ impl TestCase { } } +fn build_exit(harness: &BeaconChainHarness, validator_index: u64) -> Exit { + let epoch = harness + .beacon_chain + .state + .read() + .current_epoch(&harness.spec); + + let mut exit = Exit { + epoch, + validator_index, + signature: Signature::empty_signature(), + }; + + let message = exit.hash_tree_root(); + + exit.signature = harness + .validator_sign( + validator_index as usize, + &message[..], + epoch, + harness.spec.domain_exit, + ) + .expect("Unable to sign Exit"); + + exit +} + /// Builds an `AttesterSlashing` for some `validator_indices`. /// /// Signs the message using a `BeaconChainHarness`. diff --git a/beacon_node/beacon_chain/test_harness/src/test_case/config.rs b/beacon_node/beacon_chain/test_harness/src/test_case/config.rs index d08e7fe40..19bce8e76 100644 --- a/beacon_node/beacon_chain/test_harness/src/test_case/config.rs +++ b/beacon_node/beacon_chain/test_harness/src/test_case/config.rs @@ -7,6 +7,7 @@ pub type ValidatorIndex = u64; pub type ValidatorIndices = Vec; pub type DepositTuple = (SlotHeight, Deposit, Keypair); +pub type ExitTuple = (SlotHeight, ValidatorIndex); pub type ProposerSlashingTuple = (SlotHeight, ValidatorIndex); pub type AttesterSlashingTuple = (SlotHeight, ValidatorIndices); @@ -27,6 +28,8 @@ pub struct Config { pub proposer_slashings: Option>, /// Attester slashings to be including during execution. pub attester_slashings: Option>, + /// Exits to be including during execution. + pub exits: Option>, } impl Config { @@ -43,10 +46,26 @@ impl Config { deposits: parse_deposits(&yaml), proposer_slashings: parse_proposer_slashings(&yaml), attester_slashings: parse_attester_slashings(&yaml), + exits: parse_exits(&yaml), } } } +/// Parse the `attester_slashings` section of the YAML document. +fn parse_exits(yaml: &Yaml) -> Option> { + let mut tuples = vec![]; + + for exit in yaml["exits"].as_vec()? { + let slot = as_u64(exit, "slot").expect("Incomplete exit (slot)"); + let validator_index = + as_u64(exit, "validator_index").expect("Incomplete exit (validator_index)"); + + tuples.push((SlotHeight::from(slot), validator_index)); + } + + Some(tuples) +} + /// Parse the `attester_slashings` section of the YAML document. fn parse_attester_slashings(yaml: &Yaml) -> Option> { let mut slashings = vec![]; diff --git a/beacon_node/beacon_chain/test_harness/src/test_case/state_check.rs b/beacon_node/beacon_chain/test_harness/src/test_case/state_check.rs index 90c622894..c44992a97 100644 --- a/beacon_node/beacon_chain/test_harness/src/test_case/state_check.rs +++ b/beacon_node/beacon_chain/test_harness/src/test_case/state_check.rs @@ -13,8 +13,10 @@ pub struct StateCheck { pub num_validators: Option, /// A list of validator indices which have been penalized. Must be in ascending order. pub slashed_validators: Option>, - /// A list of validator indices which have been exited. Must be in ascending order. + /// A list of validator indices which have been fully exited. Must be in ascending order. pub exited_validators: Option>, + /// A list of validator indices which have had an exit initiated. Must be in ascending order. + pub exit_initiated_validators: Option>, } impl StateCheck { @@ -27,6 +29,7 @@ impl StateCheck { num_validators: as_usize(&yaml, "num_validators"), slashed_validators: as_vec_u64(&yaml, "slashed_validators"), exited_validators: as_vec_u64(&yaml, "exited_validators"), + exit_initiated_validators: as_vec_u64(&yaml, "exit_initiated_validators"), } } @@ -40,6 +43,7 @@ impl StateCheck { info!("Running state check for slot height {}.", self.slot); + // Check the state slot. assert_eq!( self.slot, state.slot - spec.genesis_epoch.start_slot(spec.epoch_length), @@ -55,6 +59,7 @@ impl StateCheck { info!("OK: num_validators = {}.", num_validators); } + // Check for slashed validators. if let Some(ref slashed_validators) = self.slashed_validators { let actually_slashed_validators: Vec = state .validator_registry @@ -75,6 +80,7 @@ impl StateCheck { info!("OK: slashed_validators = {:?}.", slashed_validators); } + // Check for exited validators. if let Some(ref exited_validators) = self.exited_validators { let actually_exited_validators: Vec = state .validator_registry @@ -94,5 +100,29 @@ impl StateCheck { ); info!("OK: exited_validators = {:?}.", exited_validators); } + + // Check for validators that have initiated exit. + if let Some(ref exit_initiated_validators) = self.exit_initiated_validators { + let actual: Vec = state + .validator_registry + .iter() + .enumerate() + .filter_map(|(i, validator)| { + if validator.has_initiated_exit() { + Some(i as u64) + } else { + None + } + }) + .collect(); + assert_eq!( + actual, *exit_initiated_validators, + "Exit initiated validators != expected." + ); + info!( + "OK: exit_initiated_validators = {:?}.", + exit_initiated_validators + ); + } } } diff --git a/eth2/types/src/validator.rs b/eth2/types/src/validator.rs index 587a48a1f..42a2b31f2 100644 --- a/eth2/types/src/validator.rs +++ b/eth2/types/src/validator.rs @@ -68,6 +68,11 @@ impl Validator { pub fn is_penalized_at(&self, epoch: Epoch) -> bool { self.penalized_epoch <= epoch } + + /// Returns `true` if the validator is considered penalized at some epoch. + pub fn has_initiated_exit(&self) -> bool { + self.status_flags == Some(StatusFlags::InitiatedExit) + } } impl Default for Validator { From 0eddfa5556393a4ae689b561bea13f58fb6ba17b Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Mon, 4 Mar 2019 14:46:56 +0100 Subject: [PATCH 08/13] docs: Fix typos --- docs/onboarding.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/onboarding.md b/docs/onboarding.md index 8af3b0a83..275f95484 100644 --- a/docs/onboarding.md +++ b/docs/onboarding.md @@ -122,7 +122,7 @@ project. * **Module**: A collection of items: functions, structs, traits, and even other modules. Modules allow you to hierarchically split code into logical units and manage visibility. -* **Attribute**: Metadaata applied to some module, crate or item. +* **Attribute**: Metadata applied to some module, crate or item. * **Macros**: Macros are powerful meta-programming statements that get expanded into source code that gets compiled with the rest of the code (Unlike `C` macros that are pre-processed, Rust macros form an Abstract Syntax Tree). @@ -185,7 +185,7 @@ check your code. | Function / Method | ``snake_case`` | | Macro Names | ``snake_case`` | | Constants | ``SCREAMING_SNAKE_CASE`` | -| Forbidden name | Trialing Underscore: ``name_`` | +| Forbidden name | Trailing Underscore: ``name_`` | Other general rust docs: From 2b1549358ff2012eb5623e0e00fc090d3a9e4a3d Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Mon, 4 Mar 2019 14:53:52 +0100 Subject: [PATCH 09/13] docs: Fix typo --- docs/lighthouse.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/lighthouse.md b/docs/lighthouse.md index 8ca2387f8..16da13b56 100644 --- a/docs/lighthouse.md +++ b/docs/lighthouse.md @@ -67,7 +67,7 @@ into individual crates wherever possible. Generally, tests can be kept in the same file, as is typical in Rust. Integration tests should be placed in the `tests` directory in the crate's -root. Particularity large (line-count) tests should be placed into a separate +root. Particularly large (line-count) tests should be placed into a separate file. A function is not considered complete until a test exists for it. We produce From d519bc1388505371df464dd1b169e8176cea96d0 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Tue, 5 Mar 2019 17:18:41 +1100 Subject: [PATCH 10/13] Use cfg(test) for test macros --- beacon_node/db/src/stores/macros.rs | 2 +- eth2/types/src/slot_epoch_macros.rs | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/beacon_node/db/src/stores/macros.rs b/beacon_node/db/src/stores/macros.rs index 36b8aef8e..e26e101c9 100644 --- a/beacon_node/db/src/stores/macros.rs +++ b/beacon_node/db/src/stores/macros.rs @@ -20,7 +20,7 @@ macro_rules! impl_crud_for_store { }; } -#[allow(unused_macros)] +#[cfg(test)] macro_rules! test_crud_for_store { ($store: ident, $db_column: expr) => { #[test] diff --git a/eth2/types/src/slot_epoch_macros.rs b/eth2/types/src/slot_epoch_macros.rs index b0550f2f8..22355fefe 100644 --- a/eth2/types/src/slot_epoch_macros.rs +++ b/eth2/types/src/slot_epoch_macros.rs @@ -21,6 +21,7 @@ macro_rules! impl_from_into_u64 { } // need to truncate for some fork-choice algorithms +#[allow(unused_macros)] macro_rules! impl_into_u32 { ($main: ident) => { impl Into for $main { @@ -267,7 +268,7 @@ macro_rules! impl_common { } // test macros -#[allow(unused_macros)] +#[cfg(test)] macro_rules! new_tests { ($type: ident) => { #[test] @@ -279,7 +280,7 @@ macro_rules! new_tests { }; } -#[allow(unused_macros)] +#[cfg(test)] macro_rules! from_into_tests { ($type: ident, $other: ident) => { #[test] @@ -305,7 +306,7 @@ macro_rules! from_into_tests { }; } -#[allow(unused_macros)] +#[cfg(test)] macro_rules! math_between_tests { ($type: ident, $other: ident) => { #[test] @@ -453,7 +454,7 @@ macro_rules! math_between_tests { }; } -#[allow(unused_macros)] +#[cfg(test)] macro_rules! math_tests { ($type: ident) => { #[test] @@ -575,7 +576,7 @@ macro_rules! ssz_tests { }; } -#[allow(unused_macros)] +#[cfg(test)] macro_rules! all_tests { ($type: ident) => { new_tests!($type); From 33a3161905561c9ae52914ab0b95775f49fc4051 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Tue, 5 Mar 2019 17:28:51 +1100 Subject: [PATCH 11/13] Remove SSZ round-trip test duplication Closes #244 --- eth2/types/src/attestation.rs | 25 +------------- eth2/types/src/attestation_data.rs | 25 +------------- .../src/attestation_data_and_custody_bit.rs | 27 +-------------- eth2/types/src/attester_slashing.rs | 25 +------------- eth2/types/src/beacon_block.rs | 25 +------------- eth2/types/src/beacon_block_body.rs | 25 +------------- eth2/types/src/beacon_state/tests.rs | 24 +------------ eth2/types/src/casper_slashing.rs | 25 +------------- eth2/types/src/crosslink.rs | 25 +------------- eth2/types/src/deposit.rs | 25 +------------- eth2/types/src/deposit_data.rs | 25 +------------- eth2/types/src/deposit_input.rs | 25 +------------- eth2/types/src/eth1_data.rs | 25 +------------- eth2/types/src/eth1_data_vote.rs | 25 +------------- eth2/types/src/exit.rs | 25 +------------- eth2/types/src/fork.rs | 25 +------------- eth2/types/src/lib.rs | 1 + eth2/types/src/pending_attestation.rs | 25 +------------- eth2/types/src/proposal_signed_data.rs | 25 +------------- eth2/types/src/proposer_slashing.rs | 25 +------------- eth2/types/src/shard_reassignment_record.rs | 25 +------------- eth2/types/src/slashable_attestation.rs | 24 +------------ eth2/types/src/slashable_vote_data.rs | 24 +------------ eth2/types/src/slot_epoch.rs | 4 --- eth2/types/src/slot_epoch_macros.rs | 28 --------------- eth2/types/src/slot_height.rs | 3 -- eth2/types/src/test_utils/macros.rs | 34 +++++++++++++++++++ eth2/types/src/test_utils/mod.rs | 2 ++ eth2/types/src/validator.rs | 24 +------------ .../src/validator_registry_delta_block.rs | 25 +------------- 30 files changed, 61 insertions(+), 609 deletions(-) create mode 100644 eth2/types/src/test_utils/macros.rs diff --git a/eth2/types/src/attestation.rs b/eth2/types/src/attestation.rs index a0c8505b8..4ac81bb4c 100644 --- a/eth2/types/src/attestation.rs +++ b/eth2/types/src/attestation.rs @@ -40,29 +40,6 @@ impl Attestation { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = Attestation::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = Attestation::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(Attestation); } diff --git a/eth2/types/src/attestation_data.rs b/eth2/types/src/attestation_data.rs index e23cdab46..73b5facfa 100644 --- a/eth2/types/src/attestation_data.rs +++ b/eth2/types/src/attestation_data.rs @@ -50,29 +50,6 @@ impl AttestationData { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = AttestationData::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = AttestationData::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(AttestationData); } diff --git a/eth2/types/src/attestation_data_and_custody_bit.rs b/eth2/types/src/attestation_data_and_custody_bit.rs index 9175863ae..89a795292 100644 --- a/eth2/types/src/attestation_data_and_custody_bit.rs +++ b/eth2/types/src/attestation_data_and_custody_bit.rs @@ -23,31 +23,6 @@ impl TestRandom for AttestationDataAndCustodyBit { #[cfg(test)] mod test { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - - let original = AttestationDataAndCustodyBit::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = AttestationDataAndCustodyBit::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(AttestationDataAndCustodyBit); } diff --git a/eth2/types/src/attester_slashing.rs b/eth2/types/src/attester_slashing.rs index ac75a2562..cfa96a166 100644 --- a/eth2/types/src/attester_slashing.rs +++ b/eth2/types/src/attester_slashing.rs @@ -17,29 +17,6 @@ pub struct AttesterSlashing { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = AttesterSlashing::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = AttesterSlashing::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(AttesterSlashing); } diff --git a/eth2/types/src/beacon_block.rs b/eth2/types/src/beacon_block.rs index cb4e6668b..a10fd2a6e 100644 --- a/eth2/types/src/beacon_block.rs +++ b/eth2/types/src/beacon_block.rs @@ -64,29 +64,6 @@ impl BeaconBlock { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[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); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = BeaconBlock::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(BeaconBlock); } diff --git a/eth2/types/src/beacon_block_body.rs b/eth2/types/src/beacon_block_body.rs index 2b343b970..72733789c 100644 --- a/eth2/types/src/beacon_block_body.rs +++ b/eth2/types/src/beacon_block_body.rs @@ -17,29 +17,6 @@ pub struct BeaconBlockBody { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[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); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = BeaconBlockBody::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(BeaconBlockBody); } diff --git a/eth2/types/src/beacon_state/tests.rs b/eth2/types/src/beacon_state/tests.rs index bb8561511..71e98e9b9 100644 --- a/eth2/types/src/beacon_state/tests.rs +++ b/eth2/types/src/beacon_state/tests.rs @@ -3,7 +3,6 @@ use super::*; use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; use crate::{BeaconState, ChainSpec}; -use ssz::{ssz_encode, Decodable}; #[test] pub fn can_produce_genesis_block() { @@ -60,25 +59,4 @@ pub fn get_attestation_participants_consistency() { } } -#[test] -pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = BeaconState::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); -} - -#[test] -pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = BeaconState::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 -} +ssz_tests!(BeaconState); diff --git a/eth2/types/src/casper_slashing.rs b/eth2/types/src/casper_slashing.rs index cb1e46ee5..d6a6ac9fe 100644 --- a/eth2/types/src/casper_slashing.rs +++ b/eth2/types/src/casper_slashing.rs @@ -14,29 +14,6 @@ pub struct CasperSlashing { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[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); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = CasperSlashing::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(CasperSlashing); } diff --git a/eth2/types/src/crosslink.rs b/eth2/types/src/crosslink.rs index 11fb3386d..198a039e9 100644 --- a/eth2/types/src/crosslink.rs +++ b/eth2/types/src/crosslink.rs @@ -26,29 +26,6 @@ impl Crosslink { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = Crosslink::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = Crosslink::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(Crosslink); } diff --git a/eth2/types/src/deposit.rs b/eth2/types/src/deposit.rs index 02da32cfe..23772f222 100644 --- a/eth2/types/src/deposit.rs +++ b/eth2/types/src/deposit.rs @@ -15,29 +15,6 @@ pub struct Deposit { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = Deposit::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = Deposit::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(Deposit); } diff --git a/eth2/types/src/deposit_data.rs b/eth2/types/src/deposit_data.rs index 349207791..ba380378a 100644 --- a/eth2/types/src/deposit_data.rs +++ b/eth2/types/src/deposit_data.rs @@ -15,29 +15,6 @@ pub struct DepositData { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = DepositData::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = DepositData::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(DepositData); } diff --git a/eth2/types/src/deposit_input.rs b/eth2/types/src/deposit_input.rs index 1f3b22779..47a803359 100644 --- a/eth2/types/src/deposit_input.rs +++ b/eth2/types/src/deposit_input.rs @@ -16,29 +16,6 @@ pub struct DepositInput { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = DepositInput::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = DepositInput::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(DepositInput); } diff --git a/eth2/types/src/eth1_data.rs b/eth2/types/src/eth1_data.rs index 8eabbabc7..c68e73aa8 100644 --- a/eth2/types/src/eth1_data.rs +++ b/eth2/types/src/eth1_data.rs @@ -15,29 +15,6 @@ pub struct Eth1Data { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = Eth1Data::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = Eth1Data::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(Eth1Data); } diff --git a/eth2/types/src/eth1_data_vote.rs b/eth2/types/src/eth1_data_vote.rs index fa30b9052..8e4cbb4e2 100644 --- a/eth2/types/src/eth1_data_vote.rs +++ b/eth2/types/src/eth1_data_vote.rs @@ -15,29 +15,6 @@ pub struct Eth1DataVote { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = Eth1DataVote::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = Eth1DataVote::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(Eth1DataVote); } diff --git a/eth2/types/src/exit.rs b/eth2/types/src/exit.rs index 5b41fcc7a..3beaa2a22 100644 --- a/eth2/types/src/exit.rs +++ b/eth2/types/src/exit.rs @@ -15,29 +15,6 @@ pub struct Exit { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = Exit::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = Exit::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(Exit); } diff --git a/eth2/types/src/fork.rs b/eth2/types/src/fork.rs index 5b13a2388..9da7c29c2 100644 --- a/eth2/types/src/fork.rs +++ b/eth2/types/src/fork.rs @@ -30,29 +30,6 @@ impl Fork { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = Fork::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = Fork::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(Fork); } diff --git a/eth2/types/src/lib.rs b/eth2/types/src/lib.rs index 4f196b9e9..32927ad1f 100644 --- a/eth2/types/src/lib.rs +++ b/eth2/types/src/lib.rs @@ -1,3 +1,4 @@ +#[macro_use] pub mod test_utils; pub mod attestation; diff --git a/eth2/types/src/pending_attestation.rs b/eth2/types/src/pending_attestation.rs index 84eb59207..5afdf1f2c 100644 --- a/eth2/types/src/pending_attestation.rs +++ b/eth2/types/src/pending_attestation.rs @@ -16,29 +16,6 @@ pub struct PendingAttestation { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = PendingAttestation::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = PendingAttestation::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(PendingAttestation); } diff --git a/eth2/types/src/proposal_signed_data.rs b/eth2/types/src/proposal_signed_data.rs index 6f6048ffc..58f45a41d 100644 --- a/eth2/types/src/proposal_signed_data.rs +++ b/eth2/types/src/proposal_signed_data.rs @@ -15,29 +15,6 @@ pub struct ProposalSignedData { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = ProposalSignedData::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = ProposalSignedData::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(ProposalSignedData); } diff --git a/eth2/types/src/proposer_slashing.rs b/eth2/types/src/proposer_slashing.rs index ea30d46ec..93629c588 100644 --- a/eth2/types/src/proposer_slashing.rs +++ b/eth2/types/src/proposer_slashing.rs @@ -22,29 +22,6 @@ pub struct ProposerSlashing { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = ProposerSlashing::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = ProposerSlashing::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(ProposerSlashing); } diff --git a/eth2/types/src/shard_reassignment_record.rs b/eth2/types/src/shard_reassignment_record.rs index f5dfa8676..9f1705f16 100644 --- a/eth2/types/src/shard_reassignment_record.rs +++ b/eth2/types/src/shard_reassignment_record.rs @@ -14,29 +14,6 @@ pub struct ShardReassignmentRecord { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = ShardReassignmentRecord::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = ShardReassignmentRecord::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(ShardReassignmentRecord); } diff --git a/eth2/types/src/slashable_attestation.rs b/eth2/types/src/slashable_attestation.rs index 8ad582ce6..0aff549ac 100644 --- a/eth2/types/src/slashable_attestation.rs +++ b/eth2/types/src/slashable_attestation.rs @@ -39,7 +39,6 @@ mod tests { use crate::chain_spec::ChainSpec; use crate::slot_epoch::{Epoch, Slot}; use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; #[test] pub fn test_is_double_vote_true() { @@ -113,28 +112,7 @@ mod tests { ); } - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = SlashableAttestation::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = SlashableAttestation::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(SlashableAttestation); fn create_slashable_attestation( slot_factor: u64, diff --git a/eth2/types/src/slashable_vote_data.rs b/eth2/types/src/slashable_vote_data.rs index 31dd9e0a8..73cf91c61 100644 --- a/eth2/types/src/slashable_vote_data.rs +++ b/eth2/types/src/slashable_vote_data.rs @@ -42,7 +42,6 @@ mod tests { use crate::chain_spec::ChainSpec; use crate::slot_epoch::{Epoch, Slot}; use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; #[test] pub fn test_is_double_vote_true() { @@ -116,28 +115,7 @@ mod tests { ); } - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = SlashableVoteData::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = SlashableVoteData::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(SlashableVoteData); fn create_slashable_vote_data( slot_factor: u64, diff --git a/eth2/types/src/slot_epoch.rs b/eth2/types/src/slot_epoch.rs index ff4fd5b9b..0c9c37e9a 100644 --- a/eth2/types/src/slot_epoch.rs +++ b/eth2/types/src/slot_epoch.rs @@ -103,8 +103,6 @@ impl<'a> Iterator for SlotIter<'a> { #[cfg(test)] mod slot_tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::ssz_encode; all_tests!(Slot); } @@ -112,8 +110,6 @@ mod slot_tests { #[cfg(test)] mod epoch_tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::ssz_encode; all_tests!(Epoch); diff --git a/eth2/types/src/slot_epoch_macros.rs b/eth2/types/src/slot_epoch_macros.rs index 22355fefe..b8af53ae1 100644 --- a/eth2/types/src/slot_epoch_macros.rs +++ b/eth2/types/src/slot_epoch_macros.rs @@ -548,34 +548,6 @@ macro_rules! math_tests { }; } -#[allow(unused_macros)] -macro_rules! ssz_tests { - ($type: ident) => { - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = $type::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = $type::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = $type::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } - }; -} - #[cfg(test)] macro_rules! all_tests { ($type: ident) => { diff --git a/eth2/types/src/slot_height.rs b/eth2/types/src/slot_height.rs index f9370f485..e3a7b449a 100644 --- a/eth2/types/src/slot_height.rs +++ b/eth2/types/src/slot_height.rs @@ -33,11 +33,8 @@ impl SlotHeight { } #[cfg(test)] - mod slot_height_tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::ssz_encode; all_tests!(SlotHeight); } diff --git a/eth2/types/src/test_utils/macros.rs b/eth2/types/src/test_utils/macros.rs new file mode 100644 index 000000000..b7c0a6522 --- /dev/null +++ b/eth2/types/src/test_utils/macros.rs @@ -0,0 +1,34 @@ +#[cfg(test)] +#[macro_export] +macro_rules! ssz_tests { + ($type: ident) => { + #[test] + pub fn test_ssz_round_trip() { + use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; + use ssz::{ssz_encode, Decodable}; + + let mut rng = XorShiftRng::from_seed([42; 16]); + let original = $type::random_for_test(&mut rng); + + let bytes = ssz_encode(&original); + let (decoded, _) = $type::ssz_decode(&bytes, 0).unwrap(); + + assert_eq!(original, decoded); + } + + #[test] + pub fn test_hash_tree_root_internal() { + use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; + use ssz::TreeHash; + + let mut rng = XorShiftRng::from_seed([42; 16]); + let original = $type::random_for_test(&mut rng); + + let result = original.hash_tree_root_internal(); + + assert_eq!(result.len(), 32); + // TODO: Add further tests + // https://github.com/sigp/lighthouse/issues/170 + } + }; +} diff --git a/eth2/types/src/test_utils/mod.rs b/eth2/types/src/test_utils/mod.rs index eb54f2a53..2203d40d6 100644 --- a/eth2/types/src/test_utils/mod.rs +++ b/eth2/types/src/test_utils/mod.rs @@ -6,6 +6,8 @@ pub mod address; pub mod aggregate_signature; pub mod bitfield; pub mod hash256; +#[macro_use] +mod macros; pub mod public_key; pub mod secret_key; pub mod signature; diff --git a/eth2/types/src/validator.rs b/eth2/types/src/validator.rs index 42a2b31f2..6c0e7506d 100644 --- a/eth2/types/src/validator.rs +++ b/eth2/types/src/validator.rs @@ -170,18 +170,6 @@ impl TestRandom for Validator { mod tests { use super::*; use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::ssz_encode; - - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = Validator::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } #[test] fn test_validator_can_be_active() { @@ -206,15 +194,5 @@ mod tests { } } - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = Validator::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(Validator); } diff --git a/eth2/types/src/validator_registry_delta_block.rs b/eth2/types/src/validator_registry_delta_block.rs index 0746875f0..e9a075052 100644 --- a/eth2/types/src/validator_registry_delta_block.rs +++ b/eth2/types/src/validator_registry_delta_block.rs @@ -31,29 +31,6 @@ impl Default for ValidatorRegistryDeltaBlock { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use ssz::{ssz_encode, Decodable, TreeHash}; - #[test] - pub fn test_ssz_round_trip() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = ValidatorRegistryDeltaBlock::random_for_test(&mut rng); - - let bytes = ssz_encode(&original); - let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); - - assert_eq!(original, decoded); - } - - #[test] - pub fn test_hash_tree_root_internal() { - let mut rng = XorShiftRng::from_seed([42; 16]); - let original = ValidatorRegistryDeltaBlock::random_for_test(&mut rng); - - let result = original.hash_tree_root_internal(); - - assert_eq!(result.len(), 32); - // TODO: Add further tests - // https://github.com/sigp/lighthouse/issues/170 - } + ssz_tests!(ValidatorRegistryDeltaBlock); } From 6253167cacfb34a317ce4915920af3db2d1055f8 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Mon, 4 Mar 2019 17:19:25 +1100 Subject: [PATCH 12/13] Update ethereum-types to 0.5 --- .../db/src/stores/beacon_block_store.rs | 51 +++++++++---------- beacon_node/db/src/stores/macros.rs | 40 +++++++-------- beacon_node/db/src/stores/pow_chain_store.rs | 8 +-- eth2/fork_choice/src/bitwise_lmd_ghost.rs | 2 +- .../state_processing/src/block_processable.rs | 3 +- .../state_processing/src/epoch_processable.rs | 2 +- eth2/types/Cargo.toml | 3 +- eth2/types/src/attestation.rs | 2 +- eth2/types/src/attestation_data.rs | 2 +- eth2/types/src/attester_slashing/builder.rs | 4 +- eth2/types/src/beacon_block.rs | 4 +- eth2/types/src/beacon_state.rs | 12 +++-- eth2/types/src/beacon_state/builder.rs | 4 +- eth2/types/src/proposer_slashing/builder.rs | 4 +- eth2/types/src/test_utils/address.rs | 2 +- eth2/types/src/test_utils/hash256.rs | 2 +- eth2/utils/ssz/Cargo.toml | 2 +- eth2/utils/ssz/src/impl_decode.rs | 8 +-- eth2/utils/ssz/src/impl_encode.rs | 4 +- 19 files changed, 80 insertions(+), 79 deletions(-) diff --git a/beacon_node/db/src/stores/beacon_block_store.rs b/beacon_node/db/src/stores/beacon_block_store.rs index 8a1fc2b0d..bd5149cfd 100644 --- a/beacon_node/db/src/stores/beacon_block_store.rs +++ b/beacon_node/db/src/stores/beacon_block_store.rs @@ -134,9 +134,9 @@ mod tests { let store = BeaconBlockStore::new(db.clone()); let ssz = "definitly not a valid block".as_bytes(); - let hash = &Hash256::from("some hash".as_bytes()); + let hash = &Hash256::from([0xAA; 32]); - db.put(DB_COLUMN, hash, ssz).unwrap(); + db.put(DB_COLUMN, hash.as_bytes(), ssz).unwrap(); assert_eq!( store.block_at_slot(hash, Slot::from(42_u64)), Err(BeaconBlockAtSlotError::DBError( @@ -151,10 +151,10 @@ mod tests { let store = BeaconBlockStore::new(db.clone()); let ssz = "some bytes".as_bytes(); - let hash = &Hash256::from("some hash".as_bytes()); - let other_hash = &Hash256::from("another hash".as_bytes()); + let hash = &Hash256::from([0xAA; 32]); + let other_hash = &Hash256::from([0xBB; 32]); - db.put(DB_COLUMN, hash, ssz).unwrap(); + db.put(DB_COLUMN, hash.as_bytes(), ssz).unwrap(); assert_eq!( store.block_at_slot(other_hash, Slot::from(42_u64)), Err(BeaconBlockAtSlotError::UnknownBeaconBlock(*other_hash)) @@ -169,18 +169,15 @@ mod tests { let thread_count = 10; let write_count = 10; - // We're expecting the product of these numbers to fit in one byte. - assert!(thread_count * write_count <= 255); - let mut handles = vec![]; for t in 0..thread_count { let wc = write_count; let bs = bs.clone(); let handle = thread::spawn(move || { for w in 0..wc { - let key = (t * w) as u8; + let key = t * w; let val = 42; - bs.put(&[key][..].into(), &vec![val]).unwrap(); + bs.put(&Hash256::from_low_u64_le(key), &vec![val]).unwrap(); } }); handles.push(handle); @@ -192,9 +189,9 @@ mod tests { for t in 0..thread_count { for w in 0..write_count { - let key = (t * w) as u8; - assert!(bs.exists(&[key][..].into()).unwrap()); - let val = bs.get(&[key][..].into()).unwrap().unwrap(); + let key = t * w; + assert!(bs.exists(&Hash256::from_low_u64_le(key)).unwrap()); + let val = bs.get(&Hash256::from_low_u64_le(key)).unwrap().unwrap(); assert_eq!(vec![42], val); } } @@ -208,19 +205,20 @@ mod tests { // Specify test block parameters. let hashes = [ - Hash256::from(&[0; 32][..]), - Hash256::from(&[1; 32][..]), - Hash256::from(&[2; 32][..]), - Hash256::from(&[3; 32][..]), - Hash256::from(&[4; 32][..]), + 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(&[255; 32][..]), // Genesis block. - Hash256::from(&[0; 32][..]), - Hash256::from(&[1; 32][..]), - Hash256::from(&[2; 32][..]), - Hash256::from(&[3; 32][..]), + Hash256::from([255; 32]), // Genesis block. + Hash256::from([0; 32]), + Hash256::from([1; 32]), + Hash256::from([2; 32]), + Hash256::from([3; 32]), ]; + let unknown_hash = Hash256::from([101; 32]); // different from all above let slots: Vec = vec![0, 1, 3, 4, 5].iter().map(|x| Slot::new(*x)).collect(); // Generate a vec of random blocks and store them in the DB. @@ -233,7 +231,7 @@ mod tests { block.slot = slots[i]; let ssz = ssz_encode(&block); - db.put(DB_COLUMN, &hashes[i], &ssz).unwrap(); + db.put(DB_COLUMN, hashes[i].as_bytes(), &ssz).unwrap(); blocks.push(block); } @@ -255,11 +253,10 @@ mod tests { let ssz = bs.block_at_slot(&hashes[4], Slot::new(6)).unwrap(); assert_eq!(ssz, None); - let bad_hash = &Hash256::from("unknown".as_bytes()); - let ssz = bs.block_at_slot(bad_hash, Slot::new(2)); + let ssz = bs.block_at_slot(&unknown_hash, Slot::new(2)); assert_eq!( ssz, - Err(BeaconBlockAtSlotError::UnknownBeaconBlock(*bad_hash)) + Err(BeaconBlockAtSlotError::UnknownBeaconBlock(unknown_hash)) ); } } diff --git a/beacon_node/db/src/stores/macros.rs b/beacon_node/db/src/stores/macros.rs index e26e101c9..6c53e40ee 100644 --- a/beacon_node/db/src/stores/macros.rs +++ b/beacon_node/db/src/stores/macros.rs @@ -2,19 +2,19 @@ macro_rules! impl_crud_for_store { ($store: ident, $db_column: expr) => { impl $store { pub fn put(&self, hash: &Hash256, ssz: &[u8]) -> Result<(), DBError> { - self.db.put($db_column, hash, ssz) + self.db.put($db_column, hash.as_bytes(), ssz) } pub fn get(&self, hash: &Hash256) -> Result>, DBError> { - self.db.get($db_column, hash) + self.db.get($db_column, hash.as_bytes()) } pub fn exists(&self, hash: &Hash256) -> Result { - self.db.exists($db_column, hash) + self.db.exists($db_column, hash.as_bytes()) } pub fn delete(&self, hash: &Hash256) -> Result<(), DBError> { - self.db.delete($db_column, hash) + self.db.delete($db_column, hash.as_bytes()) } } }; @@ -29,10 +29,10 @@ macro_rules! test_crud_for_store { let store = $store::new(db.clone()); let ssz = "some bytes".as_bytes(); - let hash = &Hash256::from("some hash".as_bytes()); + let hash = &Hash256::from([0xAA; 32]); store.put(hash, ssz).unwrap(); - assert_eq!(db.get(DB_COLUMN, hash).unwrap().unwrap(), ssz); + assert_eq!(db.get(DB_COLUMN, hash.as_bytes()).unwrap().unwrap(), ssz); } #[test] @@ -41,9 +41,9 @@ macro_rules! test_crud_for_store { let store = $store::new(db.clone()); let ssz = "some bytes".as_bytes(); - let hash = &Hash256::from("some hash".as_bytes()); + let hash = &Hash256::from([0xAA; 32]); - db.put(DB_COLUMN, hash, ssz).unwrap(); + db.put(DB_COLUMN, hash.as_bytes(), ssz).unwrap(); assert_eq!(store.get(hash).unwrap().unwrap(), ssz); } @@ -53,10 +53,10 @@ macro_rules! test_crud_for_store { let store = $store::new(db.clone()); let ssz = "some bytes".as_bytes(); - let hash = &Hash256::from("some hash".as_bytes()); - let other_hash = &Hash256::from("another hash".as_bytes()); + let hash = &Hash256::from([0xAA; 32]); + let other_hash = &Hash256::from([0xBB; 32]); - db.put(DB_COLUMN, other_hash, ssz).unwrap(); + db.put(DB_COLUMN, other_hash.as_bytes(), ssz).unwrap(); assert_eq!(store.get(hash).unwrap(), None); } @@ -66,9 +66,9 @@ macro_rules! test_crud_for_store { let store = $store::new(db.clone()); let ssz = "some bytes".as_bytes(); - let hash = &Hash256::from("some hash".as_bytes()); + let hash = &Hash256::from([0xAA; 32]); - db.put(DB_COLUMN, hash, ssz).unwrap(); + db.put(DB_COLUMN, hash.as_bytes(), ssz).unwrap(); assert!(store.exists(hash).unwrap()); } @@ -78,10 +78,10 @@ macro_rules! test_crud_for_store { let store = $store::new(db.clone()); let ssz = "some bytes".as_bytes(); - let hash = &Hash256::from("some hash".as_bytes()); - let other_hash = &Hash256::from("another hash".as_bytes()); + let hash = &Hash256::from([0xAA; 32]); + let other_hash = &Hash256::from([0xBB; 32]); - db.put(DB_COLUMN, hash, ssz).unwrap(); + db.put(DB_COLUMN, hash.as_bytes(), ssz).unwrap(); assert!(!store.exists(other_hash).unwrap()); } @@ -91,13 +91,13 @@ macro_rules! test_crud_for_store { let store = $store::new(db.clone()); let ssz = "some bytes".as_bytes(); - let hash = &Hash256::from("some hash".as_bytes()); + let hash = &Hash256::from([0xAA; 32]); - db.put(DB_COLUMN, hash, ssz).unwrap(); - assert!(db.exists(DB_COLUMN, hash).unwrap()); + db.put(DB_COLUMN, hash.as_bytes(), ssz).unwrap(); + assert!(db.exists(DB_COLUMN, hash.as_bytes()).unwrap()); store.delete(hash).unwrap(); - assert!(!db.exists(DB_COLUMN, hash).unwrap()); + assert!(!db.exists(DB_COLUMN, hash.as_bytes()).unwrap()); } }; } diff --git a/beacon_node/db/src/stores/pow_chain_store.rs b/beacon_node/db/src/stores/pow_chain_store.rs index a7c77bab5..5c8b97907 100644 --- a/beacon_node/db/src/stores/pow_chain_store.rs +++ b/beacon_node/db/src/stores/pow_chain_store.rs @@ -37,7 +37,7 @@ mod tests { let db = Arc::new(MemoryDB::open()); let store = PoWChainStore::new(db.clone()); - let hash = &Hash256::from("some hash".as_bytes()).to_vec(); + let hash = &Hash256::from([0xAA; 32]).as_bytes().to_vec(); store.put_block_hash(hash).unwrap(); assert!(db.exists(DB_COLUMN, hash).unwrap()); @@ -48,7 +48,7 @@ mod tests { let db = Arc::new(MemoryDB::open()); let store = PoWChainStore::new(db.clone()); - let hash = &Hash256::from("some hash".as_bytes()).to_vec(); + let hash = &Hash256::from([0xAA; 32]).as_bytes().to_vec(); db.put(DB_COLUMN, hash, &[0]).unwrap(); assert!(store.block_hash_exists(hash).unwrap()); @@ -59,8 +59,8 @@ mod tests { let db = Arc::new(MemoryDB::open()); let store = PoWChainStore::new(db.clone()); - let hash = &Hash256::from("some hash".as_bytes()).to_vec(); - let other_hash = &Hash256::from("another hash".as_bytes()).to_vec(); + let hash = &Hash256::from([0xAA; 32]).as_bytes().to_vec(); + let other_hash = &Hash256::from([0xBB; 32]).as_bytes().to_vec(); db.put(DB_COLUMN, hash, &[0]).unwrap(); assert!(!store.block_hash_exists(other_hash).unwrap()); diff --git a/eth2/fork_choice/src/bitwise_lmd_ghost.rs b/eth2/fork_choice/src/bitwise_lmd_ghost.rs index 60aa38fe7..8a26b3e3c 100644 --- a/eth2/fork_choice/src/bitwise_lmd_ghost.rs +++ b/eth2/fork_choice/src/bitwise_lmd_ghost.rs @@ -210,7 +210,7 @@ where trace!("Child vote length: {}", votes.len()); for (candidate, votes) in votes.iter() { - let candidate_bit: BitVec = BitVec::from_bytes(&candidate); + let candidate_bit: BitVec = BitVec::from_bytes(candidate.as_bytes()); // if the bitmasks don't match, exclude candidate if !bitmask.iter().eq(candidate_bit.iter().take(bit)) { diff --git a/eth2/state_processing/src/block_processable.rs b/eth2/state_processing/src/block_processable.rs index 32327aad3..a54bb96d4 100644 --- a/eth2/state_processing/src/block_processable.rs +++ b/eth2/state_processing/src/block_processable.rs @@ -134,9 +134,10 @@ fn per_block_processing_signature_optional( let new_mix = { let mut mix = state.latest_randao_mixes [state.slot.as_usize() % spec.latest_randao_mixes_length] + .as_bytes() .to_vec(); mix.append(&mut ssz_encode(&block.randao_reveal)); - Hash256::from(&hash(&mix)[..]) + Hash256::from_slice(&hash(&mix)[..]) }; state.latest_randao_mixes[state.slot.as_usize() % spec.latest_randao_mixes_length] = new_mix; diff --git a/eth2/state_processing/src/epoch_processable.rs b/eth2/state_processing/src/epoch_processable.rs index 0ecd1bbd1..ff6f18113 100644 --- a/eth2/state_processing/src/epoch_processable.rs +++ b/eth2/state_processing/src/epoch_processable.rs @@ -626,7 +626,7 @@ impl EpochProcessable for BeaconState { } fn hash_tree_root(input: Vec) -> Hash256 { - Hash256::from(&input.hash_tree_root()[..]) + Hash256::from_slice(&input.hash_tree_root()[..]) } fn winning_root( diff --git a/eth2/types/Cargo.toml b/eth2/types/Cargo.toml index f70e8b490..1b9eed9b8 100644 --- a/eth2/types/Cargo.toml +++ b/eth2/types/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] bls = { path = "../utils/bls" } boolean-bitfield = { path = "../utils/boolean-bitfield" } -ethereum-types = "0.4.0" +ethereum-types = "0.5" hashing = { path = "../utils/hashing" } honey-badger-split = { path = "../utils/honey-badger-split" } log = "0.4" @@ -21,6 +21,7 @@ ssz = { path = "../utils/ssz" } ssz_derive = { path = "../utils/ssz_derive" } swap_or_not_shuffle = { path = "../utils/swap_or_not_shuffle" } test_random_derive = { path = "../utils/test_random_derive" } +int_to_bytes = { path = "../utils/int_to_bytes" } [dev-dependencies] env_logger = "0.6.0" diff --git a/eth2/types/src/attestation.rs b/eth2/types/src/attestation.rs index 4ac81bb4c..eff9512ab 100644 --- a/eth2/types/src/attestation.rs +++ b/eth2/types/src/attestation.rs @@ -16,7 +16,7 @@ pub struct Attestation { impl Attestation { pub fn canonical_root(&self) -> Hash256 { - Hash256::from(&self.hash_tree_root()[..]) + Hash256::from_slice(&self.hash_tree_root()[..]) } pub fn signable_message(&self, custody_bit: bool) -> Vec { diff --git a/eth2/types/src/attestation_data.rs b/eth2/types/src/attestation_data.rs index 73b5facfa..a7351125f 100644 --- a/eth2/types/src/attestation_data.rs +++ b/eth2/types/src/attestation_data.rs @@ -35,7 +35,7 @@ impl Eq for AttestationData {} impl AttestationData { pub fn canonical_root(&self) -> Hash256 { - Hash256::from(&self.hash_tree_root()[..]) + Hash256::from_slice(&self.hash_tree_root()[..]) } pub fn signable_message(&self, custody_bit: bool) -> Vec { diff --git a/eth2/types/src/attester_slashing/builder.rs b/eth2/types/src/attester_slashing/builder.rs index ed203d6e1..abade77c9 100644 --- a/eth2/types/src/attester_slashing/builder.rs +++ b/eth2/types/src/attester_slashing/builder.rs @@ -27,8 +27,8 @@ impl AttesterSlashingBuilder { let shard = 0; let justified_epoch = Epoch::new(0); let epoch = Epoch::new(0); - let hash_1 = Hash256::from(&[1][..]); - let hash_2 = Hash256::from(&[2][..]); + let hash_1 = Hash256::from_low_u64_le(1); + let hash_2 = Hash256::from_low_u64_le(2); let mut slashable_attestation_1 = SlashableAttestation { validator_indices: validator_indices.to_vec(), diff --git a/eth2/types/src/beacon_block.rs b/eth2/types/src/beacon_block.rs index a10fd2a6e..f69cdaec9 100644 --- a/eth2/types/src/beacon_block.rs +++ b/eth2/types/src/beacon_block.rs @@ -42,7 +42,7 @@ impl BeaconBlock { } pub fn canonical_root(&self) -> Hash256 { - Hash256::from(&self.hash_tree_root()[..]) + Hash256::from_slice(&self.hash_tree_root()[..]) } pub fn proposal_root(&self, spec: &ChainSpec) -> Hash256 { @@ -57,7 +57,7 @@ impl BeaconBlock { shard: spec.beacon_chain_shard_number, block_root: block_without_signature_root, }; - Hash256::from(&proposal.hash_tree_root()[..]) + Hash256::from_slice(&proposal.hash_tree_root()[..]) } } diff --git a/eth2/types/src/beacon_state.rs b/eth2/types/src/beacon_state.rs index a9e2f2673..5c87d274a 100644 --- a/eth2/types/src/beacon_state.rs +++ b/eth2/types/src/beacon_state.rs @@ -3,6 +3,7 @@ use crate::test_utils::TestRandom; use crate::{validator::StatusFlags, validator_registry::get_active_validator_indices, *}; use bls::verify_proof_of_possession; use honey_badger_split::SplitExt; +use int_to_bytes::int_to_bytes32; use log::{debug, error, trace}; use rand::RngCore; use rayon::prelude::*; @@ -326,7 +327,7 @@ impl BeaconState { /// /// Spec v0.2.0 pub fn canonical_root(&self) -> Hash256 { - Hash256::from(&self.hash_tree_root()[..]) + Hash256::from_slice(&self.hash_tree_root()[..]) } /// The epoch corresponding to `self.slot`. @@ -487,19 +488,20 @@ impl BeaconState { let mut input = self .get_randao_mix(epoch, spec) .ok_or_else(|| Error::InsufficientRandaoMixes)? + .as_bytes() .to_vec(); input.append( &mut self .get_active_index_root(epoch, spec) .ok_or_else(|| Error::InsufficientIndexRoots)? + .as_bytes() .to_vec(), ); - // TODO: ensure `Hash256::from(u64)` == `int_to_bytes32`. - input.append(&mut Hash256::from(epoch.as_u64()).to_vec()); + input.append(&mut int_to_bytes32(epoch.as_u64())); - Ok(Hash256::from(&hash(&input[..])[..])) + Ok(Hash256::from_slice(&hash(&input[..])[..])) } /// Returns the crosslink committees for some slot. @@ -1311,7 +1313,7 @@ impl BeaconState { } fn hash_tree_root(input: Vec) -> Hash256 { - Hash256::from(&input.hash_tree_root()[..]) + Hash256::from_slice(&input.hash_tree_root()[..]) } impl From for InclusionError { diff --git a/eth2/types/src/beacon_state/builder.rs b/eth2/types/src/beacon_state/builder.rs index 02886a86e..4889b5b5a 100644 --- a/eth2/types/src/beacon_state/builder.rs +++ b/eth2/types/src/beacon_state/builder.rs @@ -145,8 +145,8 @@ impl BeaconStateBuilder { state.previous_calculation_epoch = epoch - 1; state.current_calculation_epoch = epoch; - state.previous_epoch_seed = Hash256::from(&b"previous_seed"[..]); - state.current_epoch_seed = Hash256::from(&b"current_seed"[..]); + state.previous_epoch_seed = Hash256::from([0x01; 32]); + state.current_epoch_seed = Hash256::from([0x02; 32]); state.previous_justified_epoch = epoch - 2; state.justified_epoch = epoch - 1; diff --git a/eth2/types/src/proposer_slashing/builder.rs b/eth2/types/src/proposer_slashing/builder.rs index 7923ff74d..c9d2ff272 100644 --- a/eth2/types/src/proposer_slashing/builder.rs +++ b/eth2/types/src/proposer_slashing/builder.rs @@ -25,13 +25,13 @@ impl ProposerSlashingBuilder { let proposal_data_1 = ProposalSignedData { slot, shard, - block_root: Hash256::from(&[1][..]), + block_root: Hash256::from_low_u64_le(1), }; let proposal_data_2 = ProposalSignedData { slot, shard, - block_root: Hash256::from(&[2][..]), + block_root: Hash256::from_low_u64_le(2), }; let proposal_signature_1 = { diff --git a/eth2/types/src/test_utils/address.rs b/eth2/types/src/test_utils/address.rs index 2d60b72da..13de2dec9 100644 --- a/eth2/types/src/test_utils/address.rs +++ b/eth2/types/src/test_utils/address.rs @@ -6,6 +6,6 @@ impl TestRandom for Address { fn random_for_test(rng: &mut T) -> Self { let mut key_bytes = vec![0; 20]; rng.fill_bytes(&mut key_bytes); - Address::from(&key_bytes[..]) + Address::from_slice(&key_bytes[..]) } } diff --git a/eth2/types/src/test_utils/hash256.rs b/eth2/types/src/test_utils/hash256.rs index 98f5e7899..a227679da 100644 --- a/eth2/types/src/test_utils/hash256.rs +++ b/eth2/types/src/test_utils/hash256.rs @@ -6,6 +6,6 @@ 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[..]) + Hash256::from_slice(&key_bytes[..]) } } diff --git a/eth2/utils/ssz/Cargo.toml b/eth2/utils/ssz/Cargo.toml index 25326cb5b..f13db5def 100644 --- a/eth2/utils/ssz/Cargo.toml +++ b/eth2/utils/ssz/Cargo.toml @@ -6,5 +6,5 @@ edition = "2018" [dependencies] bytes = "0.4.9" -ethereum-types = "0.4.0" +ethereum-types = "0.5" hashing = { path = "../hashing" } diff --git a/eth2/utils/ssz/src/impl_decode.rs b/eth2/utils/ssz/src/impl_decode.rs index b9ca48f9b..b13cbeb5d 100644 --- a/eth2/utils/ssz/src/impl_decode.rs +++ b/eth2/utils/ssz/src/impl_decode.rs @@ -59,7 +59,7 @@ impl Decodable for H256 { if bytes.len() < 32 || bytes.len() - 32 < index { Err(DecodeError::TooShort) } else { - Ok((H256::from(&bytes[index..(index + 32)]), index + 32)) + Ok((H256::from_slice(&bytes[index..(index + 32)]), index + 32)) } } } @@ -69,7 +69,7 @@ impl Decodable for Address { if bytes.len() < 20 || bytes.len() - 20 < index { Err(DecodeError::TooShort) } else { - Ok((Address::from(&bytes[index..(index + 20)]), index + 20)) + Ok((Address::from_slice(&bytes[index..(index + 20)]), index + 20)) } } } @@ -95,7 +95,7 @@ mod tests { */ let input = vec![42_u8; 32]; let (decoded, i) = H256::ssz_decode(&input, 0).unwrap(); - assert_eq!(decoded.to_vec(), input); + assert_eq!(decoded.as_bytes(), &input[..]); assert_eq!(i, 32); /* @@ -104,7 +104,7 @@ mod tests { let mut input = vec![42_u8; 32]; input.push(12); let (decoded, i) = H256::ssz_decode(&input, 0).unwrap(); - assert_eq!(decoded.to_vec()[..], input[0..32]); + assert_eq!(decoded.as_bytes(), &input[0..32]); assert_eq!(i, 32); /* diff --git a/eth2/utils/ssz/src/impl_encode.rs b/eth2/utils/ssz/src/impl_encode.rs index 5f73b8483..bb1ec42d5 100644 --- a/eth2/utils/ssz/src/impl_encode.rs +++ b/eth2/utils/ssz/src/impl_encode.rs @@ -55,13 +55,13 @@ impl Encodable for bool { impl Encodable for H256 { fn ssz_append(&self, s: &mut SszStream) { - s.append_encoded_raw(&self.to_vec()); + s.append_encoded_raw(self.as_bytes()); } } impl Encodable for Address { fn ssz_append(&self, s: &mut SszStream) { - s.append_encoded_raw(&self.to_vec()); + s.append_encoded_raw(self.as_bytes()); } } From 7bb5e1c1512729100c6d773456d65258ccbcedcc Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Wed, 6 Mar 2019 16:59:36 +1100 Subject: [PATCH 13/13] Implement library for verifying Merkle proofs. --- Cargo.toml | 1 + eth2/utils/merkle_proof/Cargo.toml | 9 ++ eth2/utils/merkle_proof/src/lib.rs | 148 +++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 eth2/utils/merkle_proof/Cargo.toml create mode 100644 eth2/utils/merkle_proof/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 42d69489b..c5aae7f43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ members = [ "eth2/utils/boolean-bitfield", "eth2/utils/hashing", "eth2/utils/honey-badger-split", + "eth2/utils/merkle_proof", "eth2/utils/int_to_bytes", "eth2/utils/slot_clock", "eth2/utils/ssz", diff --git a/eth2/utils/merkle_proof/Cargo.toml b/eth2/utils/merkle_proof/Cargo.toml new file mode 100644 index 000000000..b7cd81216 --- /dev/null +++ b/eth2/utils/merkle_proof/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "merkle_proof" +version = "0.1.0" +authors = ["Michael Sproul "] +edition = "2018" + +[dependencies] +ethereum-types = "0.5" +hashing = { path = "../hashing" } diff --git a/eth2/utils/merkle_proof/src/lib.rs b/eth2/utils/merkle_proof/src/lib.rs new file mode 100644 index 000000000..4d0abcea3 --- /dev/null +++ b/eth2/utils/merkle_proof/src/lib.rs @@ -0,0 +1,148 @@ +use ethereum_types::H256; +use hashing::hash; + +/// Verify a proof that `leaf` exists at `index` in a Merkle tree rooted at `root`. +/// +/// The `branch` argument is the main component of the proof: it should be a list of internal +/// node hashes such that the root can be reconstructed (in bottom-up order). +pub fn verify_merkle_proof( + leaf: H256, + branch: &[H256], + depth: usize, + index: usize, + root: H256, +) -> bool { + if branch.len() == depth { + merkle_root_from_branch(leaf, branch, depth, index) == root + } else { + false + } +} + +/// Compute a root hash from a leaf and a Merkle proof. +fn merkle_root_from_branch(leaf: H256, branch: &[H256], depth: usize, index: usize) -> H256 { + assert_eq!(branch.len(), depth, "proof length should equal depth"); + + let mut merkle_root = leaf.as_bytes().to_vec(); + + for i in 0..depth { + let ith_bit = (index >> i) & 0x01; + if ith_bit == 1 { + let input = concat(branch[i].as_bytes().to_vec(), merkle_root); + merkle_root = hash(&input); + } else { + let mut input = merkle_root; + input.extend_from_slice(branch[i].as_bytes()); + merkle_root = hash(&input); + } + } + + H256::from_slice(&merkle_root) +} + +/// Concatenate two vectors. +fn concat(mut vec1: Vec, mut vec2: Vec) -> Vec { + vec1.append(&mut vec2); + vec1 +} + +#[cfg(test)] +mod tests { + use super::*; + + fn hash_concat(h1: H256, h2: H256) -> H256 { + H256::from_slice(&hash(&concat( + h1.as_bytes().to_vec(), + h2.as_bytes().to_vec(), + ))) + } + + #[test] + fn verify_small_example() { + // Construct a small merkle tree manually + let leaf_b00 = H256::from([0xAA; 32]); + let leaf_b01 = H256::from([0xBB; 32]); + let leaf_b10 = H256::from([0xCC; 32]); + let leaf_b11 = H256::from([0xDD; 32]); + + let node_b0x = hash_concat(leaf_b00, leaf_b01); + let node_b1x = hash_concat(leaf_b10, leaf_b11); + + let root = hash_concat(node_b0x, node_b1x); + + // Run some proofs + assert!(verify_merkle_proof( + leaf_b00, + &[leaf_b01, node_b1x], + 2, + 0b00, + root + )); + assert!(verify_merkle_proof( + leaf_b01, + &[leaf_b00, node_b1x], + 2, + 0b01, + root + )); + assert!(verify_merkle_proof( + leaf_b10, + &[leaf_b11, node_b0x], + 2, + 0b10, + root + )); + assert!(verify_merkle_proof( + leaf_b11, + &[leaf_b10, node_b0x], + 2, + 0b11, + root + )); + assert!(verify_merkle_proof( + leaf_b11, + &[leaf_b10], + 1, + 0b11, + node_b1x + )); + + // Ensure that incorrect proofs fail + // Zero-length proof + assert!(!verify_merkle_proof(leaf_b01, &[], 2, 0b01, root)); + // Proof in reverse order + assert!(!verify_merkle_proof( + leaf_b01, + &[node_b1x, leaf_b00], + 2, + 0b01, + root + )); + // Proof too short + assert!(!verify_merkle_proof(leaf_b01, &[leaf_b00], 2, 0b01, root)); + // Wrong index + assert!(!verify_merkle_proof( + leaf_b01, + &[leaf_b00, node_b1x], + 2, + 0b10, + root + )); + // Wrong root + assert!(!verify_merkle_proof( + leaf_b01, + &[leaf_b00, node_b1x], + 2, + 0b01, + node_b1x + )); + } + + #[test] + fn verify_zero_depth() { + let leaf = H256::from([0xD6; 32]); + let junk = H256::from([0xD7; 32]); + assert!(verify_merkle_proof(leaf, &[], 0, 0, leaf)); + assert!(!verify_merkle_proof(leaf, &[], 0, 7, junk)); + } +}