diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index 5409d3728..0f76507fe 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -178,7 +178,7 @@ impl BeaconChain { genesis_state.genesis_time, Duration::from_millis(spec.milliseconds_per_slot), ) - .ok_or_else(|| Error::SlotClockDidNotStart)?; + .map_err(|_| Error::SlotClockDidNotStart)?; info!(log, "Beacon chain initialized from genesis"; "validator_count" => genesis_state.validators.len(), @@ -220,7 +220,7 @@ impl BeaconChain { state.genesis_time, Duration::from_millis(spec.milliseconds_per_slot), ) - .ok_or_else(|| Error::SlotClockDidNotStart)?; + .map_err(|_| Error::SlotClockDidNotStart)?; let last_finalized_root = p.canonical_head.beacon_state.finalized_checkpoint.root; let last_finalized_block = &p.canonical_head.beacon_block; diff --git a/beacon_node/client/src/lib.rs b/beacon_node/client/src/lib.rs index 1d3cb40ec..afcd538b5 100644 --- a/beacon_node/client/src/lib.rs +++ b/beacon_node/client/src/lib.rs @@ -16,7 +16,7 @@ use slog::{crit, error, info, o}; use slot_clock::SlotClock; use std::marker::PhantomData; use std::sync::Arc; -use std::time::{Duration, Instant}; +use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use tokio::runtime::TaskExecutor; use tokio::timer::Interval; use types::EthSpec; @@ -177,8 +177,18 @@ where .map_err(error::Error::from)?, ); - if beacon_chain.slot().is_err() { - panic!("Cannot start client before genesis!") + let since_epoch = SystemTime::now() + .duration_since(UNIX_EPOCH) + .map_err(|e| format!("Unable to read system time: {}", e))?; + let since_genesis = Duration::from_secs(beacon_chain.head().beacon_state.genesis_time); + + if since_genesis > since_epoch { + info!( + log, + "Starting node prior to genesis"; + "now" => since_epoch.as_secs(), + "genesis_seconds" => since_genesis.as_secs(), + ); } let network_config = &client_config.network; diff --git a/eth2/utils/slot_clock/src/lib.rs b/eth2/utils/slot_clock/src/lib.rs index fd3bf029b..6192d1b6f 100644 --- a/eth2/utils/slot_clock/src/lib.rs +++ b/eth2/utils/slot_clock/src/lib.rs @@ -5,7 +5,7 @@ mod metrics; mod system_time_slot_clock; mod testing_slot_clock; -use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; +use std::time::{Duration, Instant, SystemTime, SystemTimeError, UNIX_EPOCH}; pub use crate::system_time_slot_clock::SystemTimeSlotClock; pub use crate::testing_slot_clock::TestingSlotClock; @@ -17,18 +17,21 @@ pub trait SlotClock: Send + Sync + Sized { genesis_slot: Slot, genesis_seconds: u64, slot_duration: Duration, - ) -> Option { - let duration_between_now_and_unix_epoch = - SystemTime::now().duration_since(UNIX_EPOCH).ok()?; + ) -> Result { + let duration_between_now_and_unix_epoch = SystemTime::now().duration_since(UNIX_EPOCH)?; let duration_between_unix_epoch_and_genesis = Duration::from_secs(genesis_seconds); - if duration_between_now_and_unix_epoch < duration_between_unix_epoch_and_genesis { - None + let genesis_instant = if duration_between_now_and_unix_epoch + < duration_between_unix_epoch_and_genesis + { + Instant::now() + + (duration_between_unix_epoch_and_genesis - duration_between_now_and_unix_epoch) } else { - let genesis_instant = Instant::now() - - (duration_between_now_and_unix_epoch - duration_between_unix_epoch_and_genesis); - Some(Self::new(genesis_slot, genesis_instant, slot_duration)) - } + Instant::now() + - (duration_between_now_and_unix_epoch - duration_between_unix_epoch_and_genesis) + }; + + Ok(Self::new(genesis_slot, genesis_instant, slot_duration)) } fn new(genesis_slot: Slot, genesis: Instant, slot_duration: Duration) -> Self; diff --git a/eth2/utils/slot_clock/src/system_time_slot_clock.rs b/eth2/utils/slot_clock/src/system_time_slot_clock.rs index 0d4a52ef6..aae12c18c 100644 --- a/eth2/utils/slot_clock/src/system_time_slot_clock.rs +++ b/eth2/utils/slot_clock/src/system_time_slot_clock.rs @@ -42,7 +42,7 @@ impl SlotClock for SystemTimeSlotClock { fn duration_to_next_slot(&self) -> Option { let now = Instant::now(); if now < self.genesis { - None + Some(self.genesis - now) } else { let duration_since_genesis = now - self.genesis; let millis_since_genesis = duration_since_genesis.as_millis(); diff --git a/validator_client/src/service.rs b/validator_client/src/service.rs index 8adc79b91..8cdba537a 100644 --- a/validator_client/src/service.rs +++ b/validator_client/src/service.rs @@ -27,7 +27,7 @@ use slot_clock::{SlotClock, SystemTimeSlotClock}; use std::marker::PhantomData; use std::sync::Arc; use std::sync::RwLock; -use std::time::{Duration, Instant, SystemTime}; +use std::time::{Duration, Instant}; use tokio::prelude::*; use tokio::runtime::Builder; use tokio::timer::Interval; @@ -100,19 +100,6 @@ impl Service { - // verify the node's genesis time - if SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap() - .as_secs() - < info.genesis_time - { - error!( - log, - "Beacon Node's genesis time is in the future. No work to do.\n Exiting" - ); - return Err("Genesis time in the future".into()); - } // verify the node's network id if eth2_config.spec.network_id != info.network_id as u8 { error!( @@ -177,13 +164,11 @@ impl Service(|| { - "Unable to start slot clock. Genesis may not have occurred yet. Exiting.".into() + .map_err::(|e| { + format!("Unable to start slot clock: {}.", e).into() })?; - let current_slot = slot_clock.now().ok_or_else::(|| { - "Genesis has not yet occurred. Exiting.".into() - })?; + let current_slot = slot_clock.now().unwrap_or_else(|| Slot::new(0)); /* Generate the duties manager */ @@ -237,7 +222,7 @@ impl Service::initialize_service( client_config, eth2_config, - log, + log.clone(), )?; // we have connected to a node and established its parameters. Spin up the core service @@ -253,7 +238,7 @@ impl Service(|| { - "Genesis is not in the past. Exiting.".into() + "Unable to determine duration to next slot. Exiting.".into() })?; // set up the validator work interval - start at next slot and proceed every slot @@ -264,6 +249,19 @@ impl Service duration_to_next_slot.as_secs() + ); + /* kick off the core service */ runtime.block_on( interval