diff --git a/beacon_node/beacon_chain/Cargo.toml b/beacon_node/beacon_chain/Cargo.toml index 1d3fc03b81..31f3412865 100644 --- a/beacon_node/beacon_chain/Cargo.toml +++ b/beacon_node/beacon_chain/Cargo.toml @@ -13,6 +13,7 @@ log = "0.4" operation_pool = { path = "../../eth2/operation_pool" } serde = "1.0" serde_derive = "1.0" +serde_yaml = "0.8" slog = { version = "^2.2.3" , features = ["max_level_trace"] } sloggers = { version = "^0.3" } slot_clock = { path = "../../eth2/utils/slot_clock" } diff --git a/beacon_node/beacon_chain/src/beacon_chain_builder.rs b/beacon_node/beacon_chain/src/beacon_chain_builder.rs new file mode 100644 index 0000000000..a6c77cb63c --- /dev/null +++ b/beacon_node/beacon_chain/src/beacon_chain_builder.rs @@ -0,0 +1,68 @@ +use crate::BeaconChainTypes; +use std::fs::File; +use std::path::PathBuf; +use std::time::SystemTime; +use types::{ + test_utils::TestingBeaconStateBuilder, BeaconBlock, BeaconState, ChainSpec, EthSpec, Hash256, +}; + +pub struct BeaconChainBuilder { + genesis_state: BeaconState, + genesis_block: BeaconBlock, + spec: ChainSpec, +} + +impl BeaconChainBuilder { + pub fn recent_genesis(validator_count: usize, spec: ChainSpec) -> Self { + Self::quick_start(recent_genesis_time(), validator_count, spec) + } + + pub fn quick_start(genesis_time: u64, validator_count: usize, spec: ChainSpec) -> Self { + let (mut genesis_state, _keypairs) = + TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(validator_count, &spec) + .build(); + + genesis_state.genesis_time = genesis_time; + + Self::from_genesis_state(genesis_state, spec) + } + + pub fn yaml_state(file: PathBuf, spec: ChainSpec) -> Result { + let file = File::open(file.clone()) + .map_err(|e| format!("Unable to open YAML genesis state file {:?}: {:?}", file, e))?; + + let genesis_state = serde_yaml::from_reader(file) + .map_err(|e| format!("Unable to parse YAML genesis state file: {:?}", e))?; + + Ok(Self::from_genesis_state(genesis_state, spec)) + } + + pub fn from_genesis_state(genesis_state: BeaconState, spec: ChainSpec) -> Self { + Self { + genesis_block: genesis_block(&genesis_state, &spec), + genesis_state, + spec, + } + } +} + +fn genesis_block(genesis_state: &BeaconState, spec: &ChainSpec) -> BeaconBlock { + let mut genesis_block = BeaconBlock::empty(&spec); + + genesis_block.state_root = genesis_state.canonical_root(); + + genesis_block +} + +/// Returns the system time, mod 30 minutes. +/// +/// Used for easily creating testnets. +fn recent_genesis_time() -> u64 { + let now = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_secs(); + let secs_after_last_period = now.checked_rem(30 * 60).unwrap_or(0); + // genesis is now the last 30 minute block. + now - secs_after_last_period +} diff --git a/beacon_node/beacon_chain/src/lib.rs b/beacon_node/beacon_chain/src/lib.rs index cc7725dd83..9c833f778d 100644 --- a/beacon_node/beacon_chain/src/lib.rs +++ b/beacon_node/beacon_chain/src/lib.rs @@ -3,6 +3,7 @@ extern crate lazy_static; mod beacon_chain; +mod beacon_chain_builder; mod checkpoint; mod errors; mod fork_choice; @@ -16,6 +17,7 @@ pub use self::beacon_chain::{ }; pub use self::checkpoint::CheckPoint; pub use self::errors::{BeaconChainError, BlockProductionError}; +pub use beacon_chain_builder::BeaconChainBuilder; pub use lmd_ghost; pub use metrics::scrape_for_metrics; pub use parking_lot;