mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-15 02:42:38 +00:00
Refactor ClientConfig, add serde to it
This commit is contained in:
@@ -15,6 +15,8 @@ prometheus = "^0.6"
|
||||
types = { path = "../../eth2/types" }
|
||||
tree_hash = { path = "../../eth2/utils/tree_hash" }
|
||||
slot_clock = { path = "../../eth2/utils/slot_clock" }
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
error-chain = "0.12.0"
|
||||
slog = "^2.2.3"
|
||||
ssz = { path = "../../eth2/utils/ssz" }
|
||||
|
||||
@@ -18,42 +18,32 @@ const TESTNET_VALIDATOR_COUNT: usize = 16;
|
||||
|
||||
/// Provides a new, initialized `BeaconChain`
|
||||
pub trait InitialiseBeaconChain<T: BeaconChainTypes> {
|
||||
fn initialise_beacon_chain(store: Arc<T::Store>, log: Logger) -> 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, log)
|
||||
}
|
||||
}
|
||||
|
||||
/// A testnet-suitable BeaconChainType, using `MemoryStore`.
|
||||
#[derive(Clone)]
|
||||
pub struct TestnetMemoryBeaconChainTypes;
|
||||
|
||||
impl BeaconChainTypes for TestnetMemoryBeaconChainTypes {
|
||||
type Store = MemoryStore;
|
||||
type SlotClock = SystemTimeSlotClock;
|
||||
type ForkChoice = OptimizedLMDGhost<Self::Store, Self::EthSpec>;
|
||||
type EthSpec = LighthouseTestnetEthSpec;
|
||||
}
|
||||
|
||||
impl<T: BeaconChainTypes> InitialiseBeaconChain<T> for TestnetMemoryBeaconChainTypes {
|
||||
fn initialise_beacon_chain(store: Arc<T::Store>, log: Logger) -> BeaconChain<T> {
|
||||
maybe_load_from_store_for_testnet::<_, T::Store, T::EthSpec>(store, log)
|
||||
}
|
||||
}
|
||||
impl<T: BeaconChainTypes> InitialiseBeaconChain<T> for TestnetMemoryBeaconChainTypes {}
|
||||
|
||||
/// A testnet-suitable BeaconChainType, using `DiskStore`.
|
||||
#[derive(Clone)]
|
||||
pub struct TestnetDiskBeaconChainTypes;
|
||||
|
||||
impl BeaconChainTypes for TestnetDiskBeaconChainTypes {
|
||||
type Store = DiskStore;
|
||||
type SlotClock = SystemTimeSlotClock;
|
||||
type ForkChoice = OptimizedLMDGhost<Self::Store, Self::EthSpec>;
|
||||
type EthSpec = LighthouseTestnetEthSpec;
|
||||
}
|
||||
|
||||
impl<T: BeaconChainTypes> InitialiseBeaconChain<T> for TestnetDiskBeaconChainTypes {
|
||||
fn initialise_beacon_chain(store: Arc<T::Store>, log: Logger) -> BeaconChain<T> {
|
||||
maybe_load_from_store_for_testnet::<_, T::Store, T::EthSpec>(store, log)
|
||||
}
|
||||
}
|
||||
impl<T: BeaconChainTypes> InitialiseBeaconChain<T> for TestnetDiskBeaconChainTypes {}
|
||||
|
||||
/// 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>(
|
||||
|
||||
@@ -1,164 +1,69 @@
|
||||
use clap::ArgMatches;
|
||||
use fork_choice::ForkChoiceAlgorithm;
|
||||
use http_server::HttpServerConfig;
|
||||
use network::NetworkConfig;
|
||||
use slog::error;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
use std::net::SocketAddr;
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use std::path::PathBuf;
|
||||
use types::multiaddr::Protocol;
|
||||
use types::multiaddr::ToMultiaddr;
|
||||
use types::Multiaddr;
|
||||
use types::{ChainSpec, EthSpec, LighthouseTestnetEthSpec};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DBType {
|
||||
Memory,
|
||||
Disk,
|
||||
}
|
||||
|
||||
/// Stores the client configuration for this Lighthouse instance.
|
||||
#[derive(Debug, Clone)]
|
||||
/// The core configuration of a Lighthouse beacon node.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ClientConfig {
|
||||
pub data_dir: PathBuf,
|
||||
pub spec: ChainSpec,
|
||||
pub net_conf: network::NetworkConfig,
|
||||
pub fork_choice: ForkChoiceAlgorithm,
|
||||
pub db_type: DBType,
|
||||
pub db_name: PathBuf,
|
||||
pub rpc_conf: rpc::RPCConfig,
|
||||
pub http_conf: HttpServerConfig, //pub ipc_conf:
|
||||
data_dir: String,
|
||||
pub spec: String,
|
||||
pub db_type: String,
|
||||
db_name: String,
|
||||
pub network: network::NetworkConfig,
|
||||
pub rpc: rpc::RPCConfig,
|
||||
pub http: HttpServerConfig, //pub ipc_conf:
|
||||
}
|
||||
|
||||
impl Default for ClientConfig {
|
||||
/// Build a new lighthouse configuration from defaults.
|
||||
fn default() -> Self {
|
||||
let data_dir = {
|
||||
let home = dirs::home_dir().expect("Unable to determine home dir.");
|
||||
home.join(".lighthouse/")
|
||||
};
|
||||
fs::create_dir_all(&data_dir)
|
||||
.unwrap_or_else(|_| panic!("Unable to create {:?}", &data_dir));
|
||||
|
||||
let default_spec = LighthouseTestnetEthSpec::spec();
|
||||
let default_net_conf = NetworkConfig::new(default_spec.boot_nodes.clone());
|
||||
|
||||
Self {
|
||||
data_dir: data_dir.clone(),
|
||||
// default to foundation for chain specs
|
||||
spec: default_spec,
|
||||
net_conf: default_net_conf,
|
||||
// default to bitwise LMD Ghost
|
||||
fork_choice: ForkChoiceAlgorithm::BitwiseLMDGhost,
|
||||
// default to memory db for now
|
||||
db_type: DBType::Memory,
|
||||
// default db name for disk-based dbs
|
||||
db_name: data_dir.join("chain_db"),
|
||||
rpc_conf: rpc::RPCConfig::default(),
|
||||
http_conf: HttpServerConfig::default(),
|
||||
data_dir: ".lighthouse".to_string(),
|
||||
spec: "testnet".to_string(),
|
||||
db_type: "disk".to_string(),
|
||||
db_name: "chain_db".to_string(),
|
||||
// Note: there are no default bootnodes specified.
|
||||
// Once bootnodes are established, add them here.
|
||||
network: NetworkConfig::new(vec![]),
|
||||
rpc: rpc::RPCConfig::default(),
|
||||
http: HttpServerConfig::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientConfig {
|
||||
/// Parses the CLI arguments into a `Config` struct.
|
||||
pub fn parse_args(args: ArgMatches, log: &slog::Logger) -> Result<Self, &'static str> {
|
||||
let mut config = ClientConfig::default();
|
||||
/// Returns the path to which the client may initialize an on-disk database.
|
||||
pub fn db_path(&self) -> Option<PathBuf> {
|
||||
self.data_dir()
|
||||
.and_then(|path| Some(path.join(&self.db_name)))
|
||||
}
|
||||
|
||||
/* Network related arguments */
|
||||
/// Returns the core path for the client.
|
||||
pub fn data_dir(&self) -> Option<PathBuf> {
|
||||
let path = dirs::home_dir()?.join(&self.data_dir);
|
||||
fs::create_dir_all(&path).ok()?;
|
||||
Some(path)
|
||||
}
|
||||
|
||||
// Custom p2p listen port
|
||||
if let Some(port_str) = args.value_of("port") {
|
||||
if let Ok(port) = port_str.parse::<u16>() {
|
||||
config.net_conf.listen_port = port;
|
||||
// update the listening multiaddrs
|
||||
for address in &mut config.net_conf.listen_addresses {
|
||||
address.pop();
|
||||
address.append(Protocol::Tcp(port));
|
||||
}
|
||||
} else {
|
||||
error!(log, "Invalid port"; "port" => port_str);
|
||||
return Err("Invalid port");
|
||||
}
|
||||
}
|
||||
// Custom listening address ipv4/ipv6
|
||||
// TODO: Handle list of addresses
|
||||
if let Some(listen_address_str) = args.value_of("listen-address") {
|
||||
if let Ok(listen_address) = listen_address_str.parse::<IpAddr>() {
|
||||
let multiaddr = SocketAddr::new(listen_address, config.net_conf.listen_port)
|
||||
.to_multiaddr()
|
||||
.expect("Invalid listen address format");
|
||||
config.net_conf.listen_addresses = vec![multiaddr];
|
||||
} else {
|
||||
error!(log, "Invalid IP Address"; "Address" => listen_address_str);
|
||||
return Err("Invalid IP Address");
|
||||
}
|
||||
}
|
||||
|
||||
// Custom bootnodes
|
||||
if let Some(boot_addresses_str) = args.value_of("boot-nodes") {
|
||||
let boot_addresses_split = boot_addresses_str.split(',');
|
||||
for boot_address in boot_addresses_split {
|
||||
if let Ok(boot_address) = boot_address.parse::<Multiaddr>() {
|
||||
config.net_conf.boot_nodes.append(&mut vec![boot_address]);
|
||||
} else {
|
||||
error!(log, "Invalid Bootnode multiaddress"; "Multiaddr" => boot_addresses_str);
|
||||
return Err("Invalid IP Address");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Filesystem related arguments */
|
||||
|
||||
// Custom datadir
|
||||
/// Apply the following arguments to `self`, replacing values if they are specified in `args`.
|
||||
///
|
||||
/// Returns an error if arguments are obviously invalid. May succeed even if some values are
|
||||
/// invalid.
|
||||
pub fn apply_cli_args(&mut self, args: &ArgMatches) -> Result<(), &'static str> {
|
||||
if let Some(dir) = args.value_of("datadir") {
|
||||
config.data_dir = PathBuf::from(dir.to_string());
|
||||
self.data_dir = dir.to_string();
|
||||
};
|
||||
|
||||
/* RPC related arguments */
|
||||
|
||||
if args.is_present("rpc") {
|
||||
config.rpc_conf.enabled = true;
|
||||
if let Some(dir) = args.value_of("db") {
|
||||
self.db_type = dir.to_string();
|
||||
}
|
||||
|
||||
if let Some(rpc_address) = args.value_of("rpc-address") {
|
||||
if let Ok(listen_address) = rpc_address.parse::<Ipv4Addr>() {
|
||||
config.rpc_conf.listen_address = listen_address;
|
||||
} else {
|
||||
error!(log, "Invalid RPC listen address"; "Address" => rpc_address);
|
||||
return Err("Invalid RPC listen address");
|
||||
}
|
||||
}
|
||||
self.network.apply_cli_args(args)?;
|
||||
self.rpc.apply_cli_args(args)?;
|
||||
self.http.apply_cli_args(args)?;
|
||||
|
||||
if let Some(rpc_port) = args.value_of("rpc-port") {
|
||||
if let Ok(port) = rpc_port.parse::<u16>() {
|
||||
config.rpc_conf.port = port;
|
||||
} else {
|
||||
error!(log, "Invalid RPC port"; "port" => rpc_port);
|
||||
return Err("Invalid RPC port");
|
||||
}
|
||||
}
|
||||
|
||||
/* HTTP related arguments */
|
||||
|
||||
if args.is_present("http") {
|
||||
config.http_conf.enabled = true;
|
||||
}
|
||||
|
||||
if let Some(listen_address) = args.value_of("http-address") {
|
||||
config.http_conf.listen_address = listen_address.to_string();
|
||||
}
|
||||
if let Some(listen_port) = args.value_of("http-port") {
|
||||
config.http_conf.listen_port = listen_port.to_string();
|
||||
}
|
||||
|
||||
match args.value_of("db") {
|
||||
Some("disk") => config.db_type = DBType::Disk,
|
||||
Some("memory") => config.db_type = DBType::Memory,
|
||||
_ => unreachable!(), // clap prevents this.
|
||||
};
|
||||
|
||||
Ok(config)
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,5 +6,4 @@ error_chain! {
|
||||
links {
|
||||
Network(network::error::Error, network::error::ErrorKind);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ pub mod error;
|
||||
pub mod notifier;
|
||||
|
||||
use beacon_chain::BeaconChain;
|
||||
use beacon_chain_types::InitialiseBeaconChain;
|
||||
use exit_future::Signal;
|
||||
use futures::{future::Future, Stream};
|
||||
use network::Service as NetworkService;
|
||||
@@ -18,10 +17,12 @@ use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio::runtime::TaskExecutor;
|
||||
use tokio::timer::Interval;
|
||||
use types::EthSpec;
|
||||
|
||||
pub use beacon_chain::BeaconChainTypes;
|
||||
pub use beacon_chain_types::InitialiseBeaconChain;
|
||||
pub use beacon_chain_types::{TestnetDiskBeaconChainTypes, TestnetMemoryBeaconChainTypes};
|
||||
pub use client_config::{ClientConfig, DBType};
|
||||
pub use client_config::ClientConfig;
|
||||
|
||||
/// Main beacon node client service. This provides the connection and initialisation of the clients
|
||||
/// sub-services in multiple threads.
|
||||
@@ -57,6 +58,7 @@ where
|
||||
) -> error::Result<Self> {
|
||||
let metrics_registry = Registry::new();
|
||||
let store = Arc::new(store);
|
||||
let spec = T::EthSpec::spec();
|
||||
|
||||
// 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, log.clone()));
|
||||
@@ -97,7 +99,7 @@ where
|
||||
|
||||
// Start the network service, libp2p and syncing threads
|
||||
// TODO: Add beacon_chain reference to network parameters
|
||||
let network_config = &config.net_conf;
|
||||
let network_config = &config.network;
|
||||
let network_logger = log.new(o!("Service" => "Network"));
|
||||
let (network, network_send) = NetworkService::new(
|
||||
beacon_chain.clone(),
|
||||
@@ -107,9 +109,9 @@ where
|
||||
)?;
|
||||
|
||||
// spawn the RPC server
|
||||
let rpc_exit_signal = if config.rpc_conf.enabled {
|
||||
let rpc_exit_signal = if config.rpc.enabled {
|
||||
Some(rpc::start_server(
|
||||
&config.rpc_conf,
|
||||
&config.rpc,
|
||||
executor,
|
||||
network_send.clone(),
|
||||
beacon_chain.clone(),
|
||||
@@ -122,13 +124,13 @@ where
|
||||
// Start the `http_server` service.
|
||||
//
|
||||
// Note: presently we are ignoring the config and _always_ starting a HTTP server.
|
||||
let http_exit_signal = if config.http_conf.enabled {
|
||||
let http_exit_signal = if config.http.enabled {
|
||||
Some(http_server::start_service(
|
||||
&config.http_conf,
|
||||
&config.http,
|
||||
executor,
|
||||
network_send,
|
||||
beacon_chain.clone(),
|
||||
config.db_name.clone(),
|
||||
config.db_path().expect("unable to read datadir"),
|
||||
metrics_registry,
|
||||
&log,
|
||||
))
|
||||
@@ -141,7 +143,7 @@ where
|
||||
// set up the validator work interval - start at next slot and proceed every slot
|
||||
let interval = {
|
||||
// Set the interval to start at the next slot, and every slot after
|
||||
let slot_duration = Duration::from_secs(config.spec.seconds_per_slot);
|
||||
let slot_duration = Duration::from_secs(spec.seconds_per_slot);
|
||||
//TODO: Handle checked add correctly
|
||||
Interval::new(Instant::now() + duration_to_next_slot, slot_duration)
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user