Allow validator client to start before genesis
This commit is contained in:
parent
940ddd0d13
commit
8b69a48fc5
@ -178,7 +178,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
genesis_state.genesis_time,
|
genesis_state.genesis_time,
|
||||||
Duration::from_millis(spec.milliseconds_per_slot),
|
Duration::from_millis(spec.milliseconds_per_slot),
|
||||||
)
|
)
|
||||||
.ok_or_else(|| Error::SlotClockDidNotStart)?;
|
.map_err(|_| Error::SlotClockDidNotStart)?;
|
||||||
|
|
||||||
info!(log, "Beacon chain initialized from genesis";
|
info!(log, "Beacon chain initialized from genesis";
|
||||||
"validator_count" => genesis_state.validators.len(),
|
"validator_count" => genesis_state.validators.len(),
|
||||||
@ -220,7 +220,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
state.genesis_time,
|
state.genesis_time,
|
||||||
Duration::from_millis(spec.milliseconds_per_slot),
|
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_root = p.canonical_head.beacon_state.finalized_checkpoint.root;
|
||||||
let last_finalized_block = &p.canonical_head.beacon_block;
|
let last_finalized_block = &p.canonical_head.beacon_block;
|
||||||
|
@ -16,7 +16,7 @@ use slog::{crit, error, info, o};
|
|||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
|
||||||
use tokio::runtime::TaskExecutor;
|
use tokio::runtime::TaskExecutor;
|
||||||
use tokio::timer::Interval;
|
use tokio::timer::Interval;
|
||||||
use types::EthSpec;
|
use types::EthSpec;
|
||||||
@ -177,8 +177,18 @@ where
|
|||||||
.map_err(error::Error::from)?,
|
.map_err(error::Error::from)?,
|
||||||
);
|
);
|
||||||
|
|
||||||
if beacon_chain.slot().is_err() {
|
let since_epoch = SystemTime::now()
|
||||||
panic!("Cannot start client before genesis!")
|
.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;
|
let network_config = &client_config.network;
|
||||||
|
@ -5,7 +5,7 @@ mod metrics;
|
|||||||
mod system_time_slot_clock;
|
mod system_time_slot_clock;
|
||||||
mod testing_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::system_time_slot_clock::SystemTimeSlotClock;
|
||||||
pub use crate::testing_slot_clock::TestingSlotClock;
|
pub use crate::testing_slot_clock::TestingSlotClock;
|
||||||
@ -17,18 +17,21 @@ pub trait SlotClock: Send + Sync + Sized {
|
|||||||
genesis_slot: Slot,
|
genesis_slot: Slot,
|
||||||
genesis_seconds: u64,
|
genesis_seconds: u64,
|
||||||
slot_duration: Duration,
|
slot_duration: Duration,
|
||||||
) -> Option<Self> {
|
) -> Result<Self, SystemTimeError> {
|
||||||
let duration_between_now_and_unix_epoch =
|
let duration_between_now_and_unix_epoch = SystemTime::now().duration_since(UNIX_EPOCH)?;
|
||||||
SystemTime::now().duration_since(UNIX_EPOCH).ok()?;
|
|
||||||
let duration_between_unix_epoch_and_genesis = Duration::from_secs(genesis_seconds);
|
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 {
|
let genesis_instant = if duration_between_now_and_unix_epoch
|
||||||
None
|
< duration_between_unix_epoch_and_genesis
|
||||||
|
{
|
||||||
|
Instant::now()
|
||||||
|
+ (duration_between_unix_epoch_and_genesis - duration_between_now_and_unix_epoch)
|
||||||
} else {
|
} else {
|
||||||
let genesis_instant = Instant::now()
|
Instant::now()
|
||||||
- (duration_between_now_and_unix_epoch - duration_between_unix_epoch_and_genesis);
|
- (duration_between_now_and_unix_epoch - duration_between_unix_epoch_and_genesis)
|
||||||
Some(Self::new(genesis_slot, genesis_instant, slot_duration))
|
};
|
||||||
}
|
|
||||||
|
Ok(Self::new(genesis_slot, genesis_instant, slot_duration))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(genesis_slot: Slot, genesis: Instant, slot_duration: Duration) -> Self;
|
fn new(genesis_slot: Slot, genesis: Instant, slot_duration: Duration) -> Self;
|
||||||
|
@ -42,7 +42,7 @@ impl SlotClock for SystemTimeSlotClock {
|
|||||||
fn duration_to_next_slot(&self) -> Option<Duration> {
|
fn duration_to_next_slot(&self) -> Option<Duration> {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
if now < self.genesis {
|
if now < self.genesis {
|
||||||
None
|
Some(self.genesis - now)
|
||||||
} else {
|
} else {
|
||||||
let duration_since_genesis = now - self.genesis;
|
let duration_since_genesis = now - self.genesis;
|
||||||
let millis_since_genesis = duration_since_genesis.as_millis();
|
let millis_since_genesis = duration_since_genesis.as_millis();
|
||||||
|
@ -27,7 +27,7 @@ use slot_clock::{SlotClock, SystemTimeSlotClock};
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
use std::time::{Duration, Instant, SystemTime};
|
use std::time::{Duration, Instant};
|
||||||
use tokio::prelude::*;
|
use tokio::prelude::*;
|
||||||
use tokio::runtime::Builder;
|
use tokio::runtime::Builder;
|
||||||
use tokio::timer::Interval;
|
use tokio::timer::Interval;
|
||||||
@ -100,19 +100,6 @@ impl<B: BeaconNodeDuties + 'static, S: Signer + 'static, E: EthSpec> Service<B,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Ok(info) => {
|
Ok(info) => {
|
||||||
// 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
|
// verify the node's network id
|
||||||
if eth2_config.spec.network_id != info.network_id as u8 {
|
if eth2_config.spec.network_id != info.network_id as u8 {
|
||||||
error!(
|
error!(
|
||||||
@ -177,13 +164,11 @@ impl<B: BeaconNodeDuties + 'static, S: Signer + 'static, E: EthSpec> Service<B,
|
|||||||
genesis_time,
|
genesis_time,
|
||||||
Duration::from_millis(eth2_config.spec.milliseconds_per_slot),
|
Duration::from_millis(eth2_config.spec.milliseconds_per_slot),
|
||||||
)
|
)
|
||||||
.ok_or_else::<error_chain::Error, _>(|| {
|
.map_err::<error_chain::Error, _>(|e| {
|
||||||
"Unable to start slot clock. Genesis may not have occurred yet. Exiting.".into()
|
format!("Unable to start slot clock: {}.", e).into()
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let current_slot = slot_clock.now().ok_or_else::<error_chain::Error, _>(|| {
|
let current_slot = slot_clock.now().unwrap_or_else(|| Slot::new(0));
|
||||||
"Genesis has not yet occurred. Exiting.".into()
|
|
||||||
})?;
|
|
||||||
|
|
||||||
/* Generate the duties manager */
|
/* Generate the duties manager */
|
||||||
|
|
||||||
@ -237,7 +222,7 @@ impl<B: BeaconNodeDuties + 'static, S: Signer + 'static, E: EthSpec> Service<B,
|
|||||||
let mut service = Service::<ValidatorServiceClient, Keypair, E>::initialize_service(
|
let mut service = Service::<ValidatorServiceClient, Keypair, E>::initialize_service(
|
||||||
client_config,
|
client_config,
|
||||||
eth2_config,
|
eth2_config,
|
||||||
log,
|
log.clone(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// we have connected to a node and established its parameters. Spin up the core service
|
// we have connected to a node and established its parameters. Spin up the core service
|
||||||
@ -253,7 +238,7 @@ impl<B: BeaconNodeDuties + 'static, S: Signer + 'static, E: EthSpec> Service<B,
|
|||||||
.slot_clock
|
.slot_clock
|
||||||
.duration_to_next_slot()
|
.duration_to_next_slot()
|
||||||
.ok_or_else::<error_chain::Error, _>(|| {
|
.ok_or_else::<error_chain::Error, _>(|| {
|
||||||
"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
|
// set up the validator work interval - start at next slot and proceed every slot
|
||||||
@ -264,6 +249,19 @@ impl<B: BeaconNodeDuties + 'static, S: Signer + 'static, E: EthSpec> Service<B,
|
|||||||
Interval::new(Instant::now() + duration_to_next_slot, slot_duration)
|
Interval::new(Instant::now() + duration_to_next_slot, slot_duration)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if service.slot_clock.now().is_none() {
|
||||||
|
warn!(
|
||||||
|
log,
|
||||||
|
"Starting node prior to genesis";
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
info!(
|
||||||
|
log,
|
||||||
|
"Waiting for next slot";
|
||||||
|
"seconds_to_wait" => duration_to_next_slot.as_secs()
|
||||||
|
);
|
||||||
|
|
||||||
/* kick off the core service */
|
/* kick off the core service */
|
||||||
runtime.block_on(
|
runtime.block_on(
|
||||||
interval
|
interval
|
||||||
|
Loading…
Reference in New Issue
Block a user