From bbad4bfa19854d63bbc3237d4d4e0dea45f70bdb Mon Sep 17 00:00:00 2001 From: Age Manning Date: Mon, 18 Mar 2019 16:16:54 +1100 Subject: [PATCH] Starts initialisation of beacon chain in the client --- beacon_node/beacon_chain/src/initialise.rs | 146 +++++++++++++++++++++ beacon_node/beacon_chain/src/initialize.rs | 56 -------- beacon_node/beacon_chain/src/lib.rs | 1 + beacon_node/client/src/client_types.rs | 18 ++- beacon_node/client/src/lib.rs | 17 ++- beacon_node/network/Cargo.toml | 1 + beacon_node/network/src/message_handler.rs | 27 +++- beacon_node/network/src/service.rs | 11 +- beacon_node/src/run.rs | 2 +- eth2/types/src/chain_spec.rs | 8 +- 10 files changed, 207 insertions(+), 80 deletions(-) create mode 100644 beacon_node/beacon_chain/src/initialise.rs delete mode 100644 beacon_node/beacon_chain/src/initialize.rs diff --git a/beacon_node/beacon_chain/src/initialise.rs b/beacon_node/beacon_chain/src/initialise.rs new file mode 100644 index 0000000000..131782470b --- /dev/null +++ b/beacon_node/beacon_chain/src/initialise.rs @@ -0,0 +1,146 @@ +// Initialisation functions to generate a new BeaconChain. +// Note: A new version of ClientTypes may need to be implemented for the lighthouse +// testnet. These are examples. Also. there is code duplication which can/should be cleaned up. + +use crate::BeaconChain; +use bls; +use db::stores::{BeaconBlockStore, BeaconStateStore}; +use db::{DiskDB, MemoryDB}; +use fork_choice::BitwiseLMDGhost; +use slot_clock::SystemTimeSlotClock; +use std::path::PathBuf; +use std::sync::Arc; +use types::{ChainSpec, Deposit, DepositData, DepositInput, Eth1Data, Hash256, Keypair}; + +//TODO: Correct this for prod +//TODO: Account for historical db +pub fn initialise_beacon_chain( + chain_spec: &ChainSpec, + db_name: Option<&PathBuf>, +) -> Arc>> { + // set up the db + let db = Arc::new(DiskDB::open( + db_name.expect("Database directory must be included"), + None, + )); + let block_store = Arc::new(BeaconBlockStore::new(db.clone())); + let state_store = Arc::new(BeaconStateStore::new(db.clone())); + + // Slot clock + let genesis_time = 1_549_935_547; // 12th Feb 2018 (arbitrary value in the past). + let slot_clock = SystemTimeSlotClock::new(genesis_time, chain_spec.seconds_per_slot) + .expect("Unable to load SystemTimeSlotClock"); + // Choose the fork choice + let fork_choice = BitwiseLMDGhost::new(block_store.clone(), state_store.clone()); + + /* + * Generate some random data to start a chain with. + * + * This is will need to be replace for production usage. + */ + let latest_eth1_data = Eth1Data { + deposit_root: Hash256::zero(), + block_hash: Hash256::zero(), + }; + let keypairs: Vec = (0..10) + .collect::>() + .iter() + .map(|_| Keypair::random()) + .collect(); + let initial_validator_deposits = keypairs + .iter() + .map(|keypair| Deposit { + branch: vec![], // branch verification is not chain_specified. + index: 0, // index verification is not chain_specified. + deposit_data: DepositData { + amount: 32_000_000_000, // 32 ETH (in Gwei) + timestamp: genesis_time - 1, + deposit_input: DepositInput { + pubkey: keypair.pk.clone(), + withdrawal_credentials: Hash256::zero(), // Withdrawal not possible. + proof_of_possession: bls::create_proof_of_possession(&keypair), + }, + }, + }) + .collect(); + + // Genesis chain + // TODO:Remove the expect here. Propagate errors and handle somewhat gracefully. + Arc::new( + BeaconChain::genesis( + state_store.clone(), + block_store.clone(), + slot_clock, + genesis_time, + latest_eth1_data, + initial_validator_deposits, + chain_spec.clone(), + fork_choice, + ) + .expect("Cannot initialise a beacon chain. Exiting"), + ) +} + +/// Initialisation of a test beacon chain, uses an in memory db with fixed genesis time. +pub fn initialise_test_beacon_chain( + chain_spec: &ChainSpec, + _db_name: Option<&PathBuf>, +) -> Arc>> { + let db = Arc::new(MemoryDB::open()); + let block_store = Arc::new(BeaconBlockStore::new(db.clone())); + let state_store = Arc::new(BeaconStateStore::new(db.clone())); + + // Slot clock + let genesis_time = 1_549_935_547; // 12th Feb 2018 (arbitrary value in the past). + let slot_clock = SystemTimeSlotClock::new(genesis_time, chain_spec.seconds_per_slot) + .expect("Unable to load SystemTimeSlotClock"); + // Choose the fork choice + let fork_choice = BitwiseLMDGhost::new(block_store.clone(), state_store.clone()); + + /* + * Generate some random data to start a chain with. + * + * This is will need to be replace for production usage. + */ + let latest_eth1_data = Eth1Data { + deposit_root: Hash256::zero(), + block_hash: Hash256::zero(), + }; + let keypairs: Vec = (0..10) + .collect::>() + .iter() + .map(|_| Keypair::random()) + .collect(); + let initial_validator_deposits = keypairs + .iter() + .map(|keypair| Deposit { + branch: vec![], // branch verification is not chain_specified. + index: 0, // index verification is not chain_specified. + deposit_data: DepositData { + amount: 32_000_000_000, // 32 ETH (in Gwei) + timestamp: genesis_time - 1, + deposit_input: DepositInput { + pubkey: keypair.pk.clone(), + withdrawal_credentials: Hash256::zero(), // Withdrawal not possible. + proof_of_possession: bls::create_proof_of_possession(&keypair), + }, + }, + }) + .collect(); + + // Genesis chain + // TODO: Handle error correctly + Arc::new( + BeaconChain::genesis( + state_store.clone(), + block_store.clone(), + slot_clock, + genesis_time, + latest_eth1_data, + initial_validator_deposits, + chain_spec.clone(), + fork_choice, + ) + .expect("Cannot generate beacon chain"), + ) +} diff --git a/beacon_node/beacon_chain/src/initialize.rs b/beacon_node/beacon_chain/src/initialize.rs deleted file mode 100644 index 14d0f81a67..0000000000 --- a/beacon_node/beacon_chain/src/initialize.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Initialisation functions to generate a new BeaconChain. - -pub fn initialise_test_chain( - config: &ClientConfig, -) -> Arc> { - let spec = config.spec; - // Slot clock - let genesis_time = 1_549_935_547; // 12th Feb 2018 (arbitrary value in the past). - let slot_clock = SystemTimeSlotClock::new(genesis_time, spec.slot_duration) - .expect("Unable to load SystemTimeSlotClock"); - // Choose the fork choice - let fork_choice = BitwiseLMDGhost::new(block_store.clone(), state_store.clone()); - - /* - * Generate some random data to start a chain with. - * - * This is will need to be replace for production usage. - */ - let latest_eth1_data = Eth1Data { - deposit_root: Hash256::zero(), - block_hash: Hash256::zero(), - }; - let keypairs: Vec = (0..10) - .collect::>() - .iter() - .map(|_| Keypair::random()) - .collect(); - let initial_validator_deposits = keypairs - .iter() - .map(|keypair| Deposit { - branch: vec![], // branch verification is not specified. - index: 0, // index verification is not specified. - deposit_data: DepositData { - amount: 32_000_000_000, // 32 ETH (in Gwei) - timestamp: genesis_time - 1, - deposit_input: DepositInput { - pubkey: keypair.pk.clone(), - withdrawal_credentials: Hash256::zero(), // Withdrawal not possible. - proof_of_possession: create_proof_of_possession(&keypair), - }, - }, - }) - .collect(); - - // Genesis chain - Arc::new(BeaconChain::genesis( - state_store.clone(), - block_store.clone(), - slot_clock, - genesis_time, - latest_eth1_data, - initial_validator_deposits, - spec, - fork_choice, - )); -} diff --git a/beacon_node/beacon_chain/src/lib.rs b/beacon_node/beacon_chain/src/lib.rs index 0e879a4151..89ee2029c0 100644 --- a/beacon_node/beacon_chain/src/lib.rs +++ b/beacon_node/beacon_chain/src/lib.rs @@ -2,6 +2,7 @@ mod attestation_aggregator; mod beacon_chain; mod checkpoint; mod errors; +pub mod initialise; pub use self::beacon_chain::{BeaconChain, BlockProcessingOutcome, InvalidBlock, ValidBlock}; pub use self::checkpoint::CheckPoint; diff --git a/beacon_node/client/src/client_types.rs b/beacon_node/client/src/client_types.rs index 38ae1c8c38..744c9ab98b 100644 --- a/beacon_node/client/src/client_types.rs +++ b/beacon_node/client/src/client_types.rs @@ -1,25 +1,39 @@ use db::{ClientDB, DiskDB, MemoryDB}; use fork_choice::{BitwiseLMDGhost, ForkChoice}; use slot_clock::{SlotClock, SystemTimeSlotClock, TestingSlotClock}; +use beacon_chain::initialise; +use std::sync::Arc; +use crate::ClientConfig pub trait ClientTypes { type ForkChoice: ForkChoice; type DB: ClientDB; type SlotClock: SlotClock; + + pub fn initialise_beacon_chain(cchain_spec: &ClientConfig) -> Arc>); } -pub struct StandardClientType {} +pub struct StandardClientType impl ClientTypes for StandardClientType { type DB = DiskDB; type ForkChoice = BitwiseLMDGhost; type SlotClock = SystemTimeSlotClock; + + pub fn initialise_beacon_chain(config: &ClientConfig) -> Arc>) { + initialise::initialise_beacon_chain(config.chain_spec, config.db_name) + } + } -pub struct TestingClientType {} +pub struct TestingClientType impl ClientTypes for TestingClientType { type DB = MemoryDB; type SlotClock = TestingSlotClock; type ForkChoice = BitwiseLMDGhost; + + pub fn initialise_beacon_chain(config: &ClientConfig) -> Arc>) { + initialise::initialise_test_beacon_chain(config.chain_spec, None) + } } diff --git a/beacon_node/client/src/lib.rs b/beacon_node/client/src/lib.rs index 7312cc6c8c..46221c200b 100644 --- a/beacon_node/client/src/lib.rs +++ b/beacon_node/client/src/lib.rs @@ -21,31 +21,36 @@ use tokio::runtime::TaskExecutor; /// sub-services in multiple threads. pub struct Client { config: ClientConfig, - // beacon_chain: Arc>, + beacon_chain: Arc>, pub network: Arc, pub exit: exit_future::Exit, pub exit_signal: Signal, log: slog::Logger, - phantom: PhantomData, } impl Client { /// Generate an instance of the client. Spawn and link all internal subprocesses. pub fn new( config: ClientConfig, + client_type: T, log: slog::Logger, executor: &TaskExecutor, ) -> error::Result { let (exit_signal, exit) = exit_future::signal(); - // TODO: generate a beacon_chain service. + // generate a beacon chain + let beacon_chain = client_type.initialise_beacon_chain(&config); // Start the network service, libp2p and syncing threads // TODO: Add beacon_chain reference to network parameters - let network_config = config.net_conf.clone(); + let network_config = &config.net_conf; let network_logger = log.new(o!("Service" => "Network")); - let (network, network_send) = - NetworkService::new(network_config, executor, network_logger)?; + let (network, network_send) = NetworkService::new( + beacon_chain.clone(), + network_config, + executor, + network_logger, + )?; Ok(Client { config, diff --git a/beacon_node/network/Cargo.toml b/beacon_node/network/Cargo.toml index 19d3e82ad4..f1a7ed2589 100644 --- a/beacon_node/network/Cargo.toml +++ b/beacon_node/network/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Age Manning "] edition = "2018" [dependencies] +beacon_chain = { path = "../beacon_chain" } libp2p = { path = "../libp2p" } version = { path = "../version" } types = { path = "../../eth2/types" } diff --git a/beacon_node/network/src/message_handler.rs b/beacon_node/network/src/message_handler.rs index c059795ed4..4ebedb89a3 100644 --- a/beacon_node/network/src/message_handler.rs +++ b/beacon_node/network/src/message_handler.rs @@ -1,5 +1,6 @@ use crate::error; use crate::messages::NodeMessage; +use beacon_chain::BeaconChain; use crossbeam_channel::{unbounded as channel, Sender, TryRecvError}; use futures::future; use futures::prelude::*; @@ -7,6 +8,7 @@ use libp2p::rpc; use libp2p::{PeerId, RPCEvent}; use slog::debug; use std::collections::HashMap; +use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; use sync::SimpleSync; use types::Hash256; @@ -15,12 +17,14 @@ use types::Hash256; const HELLO_TIMEOUT: Duration = Duration::from_secs(30); /// Handles messages received from the network and client and organises syncing. -pub struct MessageHandler { +pub struct MessageHandler { + /// Currently loaded and initialised beacon chain. + chain: BeaconChain, + /// The syncing framework. sync: SimpleSync, - //TODO: Implement beacon chain - //chain: BeaconChain - /// A mapping of peers we have sent a HELLO rpc request to + /// A mapping of peers we have sent a HELLO rpc request to. hello_requests: HashMap, + /// The `MessageHandler` logger. log: slog::Logger, } @@ -37,9 +41,10 @@ pub enum HandlerMessage { RPC(RPCEvent), } -impl MessageHandler { +impl MessageHandler { /// Initializes and runs the MessageHandler. pub fn new( + beacon_chain: Arc>, executor: &tokio::runtime::TaskExecutor, log: slog::Logger, ) -> error::Result> { @@ -49,12 +54,13 @@ impl MessageHandler { // Initialise sync and begin processing in thread //TODO: Load genesis from BeaconChain + //TODO: Initialise beacon chain let temp_genesis = Hash256::zero(); // generate the Message handler let sync = SimpleSync::new(temp_genesis); - //TODO: Initialise beacon chain let mut handler = MessageHandler { + chain: beacon_chain, sync, hello_requests: HashMap::new(), log: log.clone(), @@ -74,6 +80,13 @@ impl MessageHandler { } fn handle_message(&mut self, message: HandlerMessage) { - debug!(self.log, "Message received {:?}", message); + match message { + HandlerMessage::PeerDialed(peer_id) => self.send_hello(peer_id), + //TODO: Handle all messages + _ => {} + } } + + /// Sends a HELLO RPC request to a newly connected peer. + fn send_hello(&self, peer_id: PeerId) {} } diff --git a/beacon_node/network/src/service.rs b/beacon_node/network/src/service.rs index fc91cf53a2..6b9c0aff0a 100644 --- a/beacon_node/network/src/service.rs +++ b/beacon_node/network/src/service.rs @@ -15,25 +15,28 @@ use libp2p::{Libp2pEvent, PeerId}; use slog::{debug, info, o, trace, warn, Logger}; use std::sync::{Arc, Mutex}; use tokio::runtime::TaskExecutor; +use client::ClientTypes; /// Service that handles communication between internal services and the libp2p network service. -pub struct Service { +pub struct Service { //libp2p_service: Arc>, libp2p_exit: oneshot::Sender<()>, network_send: crossbeam_channel::Sender, //message_handler: MessageHandler, //message_handler_send: Sender, + PhantomData: T, } -impl Service { +impl Service { pub fn new( - config: NetworkConfig, + beacon_chain: Arc, + config: &NetworkConfig, executor: &TaskExecutor, log: slog::Logger, ) -> error::Result<(Arc, Sender)> { // launch message handler thread let message_handler_log = log.new(o!("Service" => "MessageHandler")); - let message_handler_send = MessageHandler::new(executor, message_handler_log)?; + let message_handler_send = MessageHandler::new(beacon_chain, executor, message_handler_log)?; // launch libp2p service let libp2p_log = log.new(o!("Service" => "Libp2p")); diff --git a/beacon_node/src/run.rs b/beacon_node/src/run.rs index 810f2aeafd..b7cbf5421c 100644 --- a/beacon_node/src/run.rs +++ b/beacon_node/src/run.rs @@ -31,7 +31,7 @@ pub fn run_beacon_node(config: ClientConfig, log: slog::Logger) -> error::Result let executor = runtime.executor(); - // currently testing - using TestingNode type + // currently testing - using TestingClientType let client: Client = Client::new(config, log.clone(), &executor)?; notifier::run(&client, executor, exit); diff --git a/eth2/types/src/chain_spec.rs b/eth2/types/src/chain_spec.rs index ef2c94d653..c6093231b4 100644 --- a/eth2/types/src/chain_spec.rs +++ b/eth2/types/src/chain_spec.rs @@ -257,10 +257,10 @@ impl ChainSpec { .parse() .expect("correct multiaddr")]; - let mut standard_spec = ChainSpec::foundation(); - standard_spec.boot_nodes = boot_nodes; - - standard_spec + Self { + boot_nodes, + ..ChainSpec::foundation() + } } /// Returns a `ChainSpec` compatible with the specification suitable for 8 validators.