Create BeaconChainTypes, thread through runtime

This commit is contained in:
Paul Hauner
2019-05-25 20:51:15 +10:00
parent 45e3a1759c
commit ee8d13573f
24 changed files with 254 additions and 452 deletions

View File

@@ -0,0 +1,109 @@
use crate::ClientConfig;
use beacon_chain::{
fork_choice::BitwiseLMDGhost,
slot_clock::SystemTimeSlotClock,
store::{DiskStore, MemoryStore, Store},
BeaconChain, BeaconChainTypes,
};
use std::sync::Arc;
use tree_hash::TreeHash;
use types::{
test_utils::TestingBeaconStateBuilder, BeaconBlock, EthSpec, FewValidatorsEthSpec, Hash256,
};
/// Provides a new, initialized `BeaconChain`
pub trait InitialiseBeaconChain<T: BeaconChainTypes> {
fn initialise_beacon_chain(config: &ClientConfig) -> BeaconChain<T>;
}
/// A testnet-suitable BeaconChainType, using `MemoryStore`.
#[derive(Clone)]
pub struct TestnetMemoryBeaconChainTypes;
impl BeaconChainTypes for TestnetMemoryBeaconChainTypes {
type Store = MemoryStore;
type SlotClock = SystemTimeSlotClock;
type ForkChoice = BitwiseLMDGhost<Self::Store, Self::EthSpec>;
type EthSpec = FewValidatorsEthSpec;
}
impl<T> InitialiseBeaconChain<T> for TestnetMemoryBeaconChainTypes
where
T: BeaconChainTypes<
Store = MemoryStore,
SlotClock = SystemTimeSlotClock,
ForkChoice = BitwiseLMDGhost<MemoryStore, FewValidatorsEthSpec>,
>,
{
fn initialise_beacon_chain(_config: &ClientConfig) -> BeaconChain<T> {
initialize_chain(MemoryStore::open())
}
}
/// A testnet-suitable BeaconChainType, using `DiskStore`.
#[derive(Clone)]
pub struct TestnetDiskBeaconChainTypes;
impl BeaconChainTypes for TestnetDiskBeaconChainTypes {
type Store = DiskStore;
type SlotClock = SystemTimeSlotClock;
type ForkChoice = BitwiseLMDGhost<Self::Store, Self::EthSpec>;
type EthSpec = FewValidatorsEthSpec;
}
impl<T> InitialiseBeaconChain<T> for TestnetDiskBeaconChainTypes
where
T: BeaconChainTypes<
Store = DiskStore,
SlotClock = SystemTimeSlotClock,
ForkChoice = BitwiseLMDGhost<DiskStore, FewValidatorsEthSpec>,
>,
{
fn initialise_beacon_chain(config: &ClientConfig) -> BeaconChain<T> {
let store = DiskStore::open(&config.db_name).expect("Unable to open DB.");
initialize_chain(store)
}
}
/// Produces a `BeaconChain` given some pre-initialized `Store`.
fn initialize_chain<T, U: Store, V: EthSpec>(store: U) -> BeaconChain<T>
where
T: BeaconChainTypes<
Store = U,
SlotClock = SystemTimeSlotClock,
ForkChoice = BitwiseLMDGhost<U, V>,
>,
{
let spec = T::EthSpec::spec();
let store = Arc::new(store);
let state_builder = TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(8, &spec);
let (genesis_state, _keypairs) = state_builder.build();
let mut genesis_block = BeaconBlock::empty(&spec);
genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root());
// Slot clock
let slot_clock = SystemTimeSlotClock::new(
spec.genesis_slot,
genesis_state.genesis_time,
spec.seconds_per_slot,
)
.expect("Unable to load SystemTimeSlotClock");
// Choose the fork choice
let fork_choice = BitwiseLMDGhost::new(store.clone());
// Genesis chain
//TODO: Handle error correctly
BeaconChain::from_genesis(
store,
slot_clock,
genesis_state,
genesis_block,
spec.clone(),
fork_choice,
)
.expect("Terminate if beacon chain generation fails")
}

View File

@@ -1,65 +0,0 @@
use crate::{ArcBeaconChain, ClientConfig};
use beacon_chain::{
fork_choice::BitwiseLMDGhost,
initialise,
slot_clock::{SlotClock, SystemTimeSlotClock},
store::{DiskStore, MemoryStore, Store},
};
use fork_choice::ForkChoice;
use types::{EthSpec, FewValidatorsEthSpec, FoundationEthSpec};
pub trait ClientTypes {
type DB: Store + 'static;
type SlotClock: SlotClock + 'static;
type ForkChoice: ForkChoice + 'static;
type EthSpec: EthSpec + 'static;
fn initialise_beacon_chain(
config: &ClientConfig,
) -> ArcBeaconChain<Self::DB, Self::SlotClock, Self::ForkChoice, Self::EthSpec>;
}
pub struct StandardClientType;
impl ClientTypes for StandardClientType {
type DB = DiskStore;
type SlotClock = SystemTimeSlotClock;
type ForkChoice = BitwiseLMDGhost<Self::DB, Self::EthSpec>;
type EthSpec = FoundationEthSpec;
fn initialise_beacon_chain(
config: &ClientConfig,
) -> ArcBeaconChain<Self::DB, Self::SlotClock, Self::ForkChoice, Self::EthSpec> {
initialise::initialise_beacon_chain(&config.spec, Some(&config.db_name))
}
}
pub struct MemoryStoreTestingClientType;
impl ClientTypes for MemoryStoreTestingClientType {
type DB = MemoryStore;
type SlotClock = SystemTimeSlotClock;
type ForkChoice = BitwiseLMDGhost<Self::DB, Self::EthSpec>;
type EthSpec = FewValidatorsEthSpec;
fn initialise_beacon_chain(
config: &ClientConfig,
) -> ArcBeaconChain<Self::DB, Self::SlotClock, Self::ForkChoice, Self::EthSpec> {
initialise::initialise_test_beacon_chain_with_memory_db(&config.spec, None)
}
}
pub struct DiskStoreTestingClientType;
impl ClientTypes for DiskStoreTestingClientType {
type DB = DiskStore;
type SlotClock = SystemTimeSlotClock;
type ForkChoice = BitwiseLMDGhost<Self::DB, Self::EthSpec>;
type EthSpec = FewValidatorsEthSpec;
fn initialise_beacon_chain(
config: &ClientConfig,
) -> ArcBeaconChain<Self::DB, Self::SlotClock, Self::ForkChoice, Self::EthSpec> {
initialise::initialise_test_beacon_chain_with_disk_db(&config.spec, Some(&config.db_name))
}
}

View File

@@ -1,15 +1,13 @@
extern crate slog;
mod beacon_chain_types;
mod client_config;
pub mod client_types;
pub mod error;
pub mod notifier;
use beacon_chain::BeaconChain;
pub use client_config::{ClientConfig, DBType};
pub use client_types::ClientTypes;
use beacon_chain_types::InitialiseBeaconChain;
use exit_future::Signal;
use fork_choice::ForkChoice;
use futures::{future::Future, Stream};
use network::Service as NetworkService;
use slog::{error, info, o};
@@ -17,22 +15,22 @@ use slot_clock::SlotClock;
use std::marker::PhantomData;
use std::sync::Arc;
use std::time::{Duration, Instant};
use store::Store;
use tokio::runtime::TaskExecutor;
use tokio::timer::Interval;
use types::EthSpec;
type ArcBeaconChain<D, S, F, B> = Arc<BeaconChain<D, S, F, B>>;
pub use beacon_chain::BeaconChainTypes;
pub use beacon_chain_types::{TestnetDiskBeaconChainTypes, TestnetMemoryBeaconChainTypes};
pub use client_config::{ClientConfig, DBType};
/// Main beacon node client service. This provides the connection and initialisation of the clients
/// sub-services in multiple threads.
pub struct Client<T: ClientTypes> {
pub struct Client<T: BeaconChainTypes> {
/// Configuration for the lighthouse client.
_config: ClientConfig,
/// The beacon chain for the running client.
_beacon_chain: ArcBeaconChain<T::DB, T::SlotClock, T::ForkChoice, T::EthSpec>,
_beacon_chain: Arc<BeaconChain<T>>,
/// Reference to the network service.
pub network: Arc<NetworkService<T::EthSpec>>,
pub network: Arc<NetworkService<T>>,
/// Signal to terminate the RPC server.
pub rpc_exit_signal: Option<Signal>,
/// Signal to terminate the HTTP server.
@@ -45,7 +43,10 @@ pub struct Client<T: ClientTypes> {
phantom: PhantomData<T>,
}
impl<TClientType: ClientTypes> Client<TClientType> {
impl<T> Client<T>
where
T: BeaconChainTypes + InitialiseBeaconChain<T> + Clone + 'static,
{
/// Generate an instance of the client. Spawn and link all internal sub-processes.
pub fn new(
config: ClientConfig,
@@ -53,7 +54,7 @@ impl<TClientType: ClientTypes> Client<TClientType> {
executor: &TaskExecutor,
) -> error::Result<Self> {
// generate a beacon chain
let beacon_chain = TClientType::initialise_beacon_chain(&config);
let beacon_chain = Arc::new(T::initialise_beacon_chain(&config));
if beacon_chain.read_slot_clock().is_none() {
panic!("Cannot start client before genesis!")
@@ -158,13 +159,7 @@ impl<TClientType: ClientTypes> Client<TClientType> {
}
}
fn do_state_catchup<T, U, F, E>(chain: &Arc<BeaconChain<T, U, F, E>>, log: &slog::Logger)
where
T: Store,
U: SlotClock,
F: ForkChoice,
E: EthSpec,
{
fn do_state_catchup<T: BeaconChainTypes>(chain: &Arc<BeaconChain<T>>, log: &slog::Logger) {
if let Some(genesis_height) = chain.slots_since_genesis() {
let result = chain.catchup_state();

View File

@@ -1,5 +1,5 @@
use crate::Client;
use crate::ClientTypes;
use beacon_chain::BeaconChainTypes;
use exit_future::Exit;
use futures::{Future, Stream};
use slog::{debug, o};
@@ -10,7 +10,11 @@ use tokio::timer::Interval;
/// Thread that monitors the client and reports useful statistics to the user.
pub fn run<T: ClientTypes>(client: &Client<T>, executor: TaskExecutor, exit: Exit) {
pub fn run<T: BeaconChainTypes + Send + Sync + 'static>(
client: &Client<T>,
executor: TaskExecutor,
exit: Exit,
) {
// notification heartbeat
let interval = Interval::new(Instant::now(), Duration::from_secs(5));