Implement saving BeaconChain on client drop

This commit is contained in:
Paul Hauner 2019-05-27 16:32:46 +10:00
parent 9ed8a4d380
commit faa682a9b5
No known key found for this signature in database
GPG Key ID: 5E2CFF9B75FA63DF
3 changed files with 34 additions and 9 deletions

View File

@ -336,6 +336,11 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
self.canonical_head.read() self.canonical_head.read()
} }
/// Returns the slot of the highest block in the canonical chain.
pub fn best_slot(&self) -> Slot {
self.canonical_head.read().beacon_block.slot
}
/// Updates the canonical `BeaconState` with the supplied state. /// Updates the canonical `BeaconState` with the supplied state.
/// ///
/// Advances the chain forward to the present slot. This method is better than just setting /// Advances the chain forward to the present slot. This method is better than just setting

View File

@ -5,6 +5,7 @@ use beacon_chain::{
BeaconChain, BeaconChainTypes, BeaconChain, BeaconChainTypes,
}; };
use fork_choice::ForkChoice; use fork_choice::ForkChoice;
use slog::{info, Logger};
use slot_clock::SlotClock; use slot_clock::SlotClock;
use std::sync::Arc; use std::sync::Arc;
use tree_hash::TreeHash; use tree_hash::TreeHash;
@ -14,7 +15,7 @@ use types::{
/// Provides a new, initialized `BeaconChain` /// Provides a new, initialized `BeaconChain`
pub trait InitialiseBeaconChain<T: BeaconChainTypes> { pub trait InitialiseBeaconChain<T: BeaconChainTypes> {
fn initialise_beacon_chain(store: Arc<T::Store>) -> BeaconChain<T>; fn initialise_beacon_chain(store: Arc<T::Store>, log: Logger) -> BeaconChain<T>;
} }
/// A testnet-suitable BeaconChainType, using `MemoryStore`. /// A testnet-suitable BeaconChainType, using `MemoryStore`.
@ -29,8 +30,8 @@ impl BeaconChainTypes for TestnetMemoryBeaconChainTypes {
} }
impl<T: BeaconChainTypes> InitialiseBeaconChain<T> for TestnetMemoryBeaconChainTypes { impl<T: BeaconChainTypes> InitialiseBeaconChain<T> for TestnetMemoryBeaconChainTypes {
fn initialise_beacon_chain(store: Arc<T::Store>) -> BeaconChain<T> { fn initialise_beacon_chain(store: Arc<T::Store>, log: Logger) -> BeaconChain<T> {
maybe_load_from_store_for_testnet::<_, T::Store, T::EthSpec>(store) maybe_load_from_store_for_testnet::<_, T::Store, T::EthSpec>(store, log)
} }
} }
@ -46,20 +47,31 @@ impl BeaconChainTypes for TestnetDiskBeaconChainTypes {
} }
impl<T: BeaconChainTypes> InitialiseBeaconChain<T> for TestnetDiskBeaconChainTypes { impl<T: BeaconChainTypes> InitialiseBeaconChain<T> for TestnetDiskBeaconChainTypes {
fn initialise_beacon_chain(store: Arc<T::Store>) -> BeaconChain<T> { fn initialise_beacon_chain(store: Arc<T::Store>, log: Logger) -> BeaconChain<T> {
maybe_load_from_store_for_testnet::<_, T::Store, T::EthSpec>(store) maybe_load_from_store_for_testnet::<_, T::Store, T::EthSpec>(store, log)
} }
} }
/// Loads a `BeaconChain` from `store`, if it exists. Otherwise, create a new chain from genesis. /// Loads a `BeaconChain` from `store`, if it exists. Otherwise, create a new chain from genesis.
fn maybe_load_from_store_for_testnet<T, U: Store, V: EthSpec>(store: Arc<U>) -> BeaconChain<T> fn maybe_load_from_store_for_testnet<T, U: Store, V: EthSpec>(
store: Arc<U>,
log: Logger,
) -> BeaconChain<T>
where where
T: BeaconChainTypes<Store = U>, T: BeaconChainTypes<Store = U>,
T::ForkChoice: ForkChoice<U>, T::ForkChoice: ForkChoice<U>,
{ {
if let Ok(Some(beacon_chain)) = BeaconChain::from_store(store.clone()) { if let Ok(Some(beacon_chain)) = BeaconChain::from_store(store.clone()) {
info!(
log,
"Loaded BeaconChain from store";
"slot" => beacon_chain.state.read().slot,
"best_slot" => beacon_chain.best_slot(),
);
beacon_chain beacon_chain
} else { } else {
info!(log, "Initializing new BeaconChain from genesis");
let spec = T::EthSpec::spec(); let spec = T::EthSpec::spec();
let state_builder = let state_builder =

View File

@ -28,7 +28,7 @@ pub struct Client<T: BeaconChainTypes> {
/// Configuration for the lighthouse client. /// Configuration for the lighthouse client.
_config: ClientConfig, _config: ClientConfig,
/// The beacon chain for the running client. /// The beacon chain for the running client.
_beacon_chain: Arc<BeaconChain<T>>, beacon_chain: Arc<BeaconChain<T>>,
/// Reference to the network service. /// Reference to the network service.
pub network: Arc<NetworkService<T>>, pub network: Arc<NetworkService<T>>,
/// Signal to terminate the RPC server. /// Signal to terminate the RPC server.
@ -57,7 +57,7 @@ where
let store = Arc::new(store); let store = Arc::new(store);
// Load a `BeaconChain` from the store, or create a new one if it does not exist. // Load a `BeaconChain` from the store, or create a new one if it does not exist.
let beacon_chain = Arc::new(T::initialise_beacon_chain(store)); let beacon_chain = Arc::new(T::initialise_beacon_chain(store, log.clone()));
if beacon_chain.read_slot_clock().is_none() { if beacon_chain.read_slot_clock().is_none() {
panic!("Cannot start client before genesis!") panic!("Cannot start client before genesis!")
@ -151,7 +151,7 @@ where
Ok(Client { Ok(Client {
_config: config, _config: config,
_beacon_chain: beacon_chain, beacon_chain,
http_exit_signal, http_exit_signal,
rpc_exit_signal, rpc_exit_signal,
slot_timer_exit_signal: Some(slot_timer_exit_signal), slot_timer_exit_signal: Some(slot_timer_exit_signal),
@ -162,6 +162,14 @@ where
} }
} }
impl<T: BeaconChainTypes> Drop for Client<T> {
fn drop(&mut self) {
// Save the beacon chain to it's store before dropping.
let _result = self.beacon_chain.persist();
dbg!("Saved BeaconChain to store");
}
}
fn do_state_catchup<T: BeaconChainTypes>(chain: &Arc<BeaconChain<T>>, log: &slog::Logger) { fn do_state_catchup<T: BeaconChainTypes>(chain: &Arc<BeaconChain<T>>, log: &slog::Logger) {
if let Some(genesis_height) = chain.slots_since_genesis() { if let Some(genesis_height) = chain.slots_since_genesis() {
let result = chain.catchup_state(); let result = chain.catchup_state();