From da39d6e9d60a8c3c2af64b810033a9f7ff9725fe Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Sat, 30 Nov 2019 13:57:44 +1100 Subject: [PATCH] Extend BeaconChain persistence testing --- beacon_node/beacon_chain/src/fork_choice.rs | 10 ++++ .../beacon_chain/tests/persistence_tests.rs | 50 +++++++++++-------- eth2/lmd_ghost/src/lib.rs | 4 +- eth2/lmd_ghost/src/reduced_tree.rs | 18 ++++++- tests/beacon_chain_sim/src/main.rs | 3 ++ 5 files changed, 61 insertions(+), 24 deletions(-) diff --git a/beacon_node/beacon_chain/src/fork_choice.rs b/beacon_node/beacon_chain/src/fork_choice.rs index e0434b3f04..beed9de031 100644 --- a/beacon_node/beacon_chain/src/fork_choice.rs +++ b/beacon_node/beacon_chain/src/fork_choice.rs @@ -35,6 +35,16 @@ pub struct ForkChoice { best_justified_checkpoint: RwLock, } +impl PartialEq for ForkChoice { + /// This implementation ignores the `store`. + fn eq(&self, other: &Self) -> bool { + self.backend == other.backend + && self.genesis_block_root == other.genesis_block_root + && *self.justified_checkpoint.read() == *other.justified_checkpoint.read() + && *self.best_justified_checkpoint.read() == *other.best_justified_checkpoint.read() + } +} + impl ForkChoice { /// Instantiate a new fork chooser. /// diff --git a/beacon_node/beacon_chain/tests/persistence_tests.rs b/beacon_node/beacon_chain/tests/persistence_tests.rs index bcd31ac228..9b89b2325e 100644 --- a/beacon_node/beacon_chain/tests/persistence_tests.rs +++ b/beacon_node/beacon_chain/tests/persistence_tests.rs @@ -3,7 +3,10 @@ #[macro_use] extern crate lazy_static; -use beacon_chain::test_utils::{AttestationStrategy, BeaconChainHarness, BlockStrategy}; +use beacon_chain::{ + test_utils::{AttestationStrategy, BeaconChainHarness, BlockStrategy}, + BeaconChain, BeaconChainTypes, +}; use sloggers::{null::NullLoggerBuilder, Build}; use std::sync::Arc; use store::DiskStore; @@ -55,15 +58,7 @@ fn finalizes_after_resuming_from_db() { let latest_slot = harness.chain.slot().expect("should have a slot"); - let original_head = harness.chain.head(); - let original_heads = harness.chain.heads(); - - assert_eq!( - original_head.beacon_state.slot, first_half, - "head should be half way through test" - ); - - drop(harness); + harness.chain.persist().expect("should persist the chain"); let resumed_harness = BeaconChainHarness::resume_from_disk_store( MinimalEthSpec, @@ -71,6 +66,14 @@ fn finalizes_after_resuming_from_db() { KEYPAIRS[0..validator_count].to_vec(), ); + assert_chains_pretty_much_the_same(&harness.chain, &resumed_harness.chain); + + // Ensures we don't accidentally use it again. + // + // Note: this will persist the chain again, but that shouldn't matter since nothing has + // changed. + drop(harness); + // Set the slot clock of the resumed harness to be in the slot following the previous harness. // // This allows us to produce the block at the next slot. @@ -79,18 +82,6 @@ fn finalizes_after_resuming_from_db() { .slot_clock .set_slot(latest_slot.as_u64() + 1); - assert_eq!( - original_head, - resumed_harness.chain.head(), - "resumed head should be same as previous head" - ); - - assert_eq!( - original_heads, - resumed_harness.chain.heads(), - "resumed heads should be same as previous heads" - ); - resumed_harness.extend_chain( (num_blocks_produced - first_half) as usize, BlockStrategy::OnCanonicalHead, @@ -118,3 +109,18 @@ fn finalizes_after_resuming_from_db() { "the head should be finalized two behind the current epoch" ); } + +fn assert_chains_pretty_much_the_same(a: &BeaconChain, b: &BeaconChain) { + assert_eq!(a.spec, b.spec, "spec should be equal"); + assert_eq!(a.op_pool, b.op_pool, "op_pool should be equal"); + assert_eq!(a.head(), b.head(), "head() should be equal"); + assert_eq!(a.heads(), b.heads(), "heads() should be equal"); + assert_eq!( + a.genesis_block_root, b.genesis_block_root, + "genesis_block_root should be equal" + ); + assert!( + a.fork_choice == b.fork_choice, + "fork_choice should be equal" + ); +} diff --git a/eth2/lmd_ghost/src/lib.rs b/eth2/lmd_ghost/src/lib.rs index c5fd95bc55..ac42120882 100644 --- a/eth2/lmd_ghost/src/lib.rs +++ b/eth2/lmd_ghost/src/lib.rs @@ -8,7 +8,9 @@ pub use reduced_tree::ThreadSafeReducedTree; pub type Result = std::result::Result; -pub trait LmdGhost: Send + Sync + Sized { +// Note: the `PartialEq` bound is only required for testing. If it becomes a serious annoyance we +// can remove it. +pub trait LmdGhost: PartialEq + Send + Sync + Sized { /// Create a new instance, with the given `store` and `finalized_root`. fn new(store: Arc, finalized_block: &BeaconBlock, finalized_root: Hash256) -> Self; diff --git a/eth2/lmd_ghost/src/reduced_tree.rs b/eth2/lmd_ghost/src/reduced_tree.rs index c6cb71a334..65aa22e584 100644 --- a/eth2/lmd_ghost/src/reduced_tree.rs +++ b/eth2/lmd_ghost/src/reduced_tree.rs @@ -55,6 +55,13 @@ impl fmt::Debug for ThreadSafeReducedTree { } } +impl PartialEq for ThreadSafeReducedTree { + /// This implementation ignores the `store`. + fn eq(&self, other: &Self) -> bool { + *self.core.read() == *other.core.read() + } +} + impl LmdGhost for ThreadSafeReducedTree where T: Store, @@ -200,6 +207,15 @@ impl fmt::Debug for ReducedTree { } } +impl PartialEq for ReducedTree { + /// This implementation ignores the `store` field. + fn eq(&self, other: &Self) -> bool { + self.nodes == other.nodes + && self.latest_votes == other.latest_votes + && self.root == other.root + } +} + impl ReducedTree where T: Store, @@ -918,7 +934,7 @@ pub struct Vote { /// /// E.g., a `get` or `insert` to an out-of-bounds element will cause the Vec to grow (using /// Default) to the smallest size required to fulfill the request. -#[derive(Default, Clone, Debug)] +#[derive(Default, Clone, Debug, PartialEq)] pub struct ElasticList(Vec); impl ElasticList diff --git a/tests/beacon_chain_sim/src/main.rs b/tests/beacon_chain_sim/src/main.rs index a93a309eef..8f422ebb77 100644 --- a/tests/beacon_chain_sim/src/main.rs +++ b/tests/beacon_chain_sim/src/main.rs @@ -1,3 +1,5 @@ +// mod simulated_network; + use node_test_rig::{ environment::{Environment, EnvironmentBuilder, RuntimeContext}, testing_client_config, ClientConfig, ClientGenesis, LocalBeaconNode, LocalValidatorClient, @@ -7,6 +9,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; use types::EthSpec; pub type BeaconNode = LocalBeaconNode>; +pub type ValidatorClient = LocalValidatorClient; fn main() { let nodes = 4;