Refactor ClientConfig, add serde to it
This commit is contained in:
parent
39ec96ad82
commit
e73a31c37f
@ -8,6 +8,7 @@ edition = "2018"
|
|||||||
types = { path = "../eth2/types" }
|
types = { path = "../eth2/types" }
|
||||||
store = { path = "./store" }
|
store = { path = "./store" }
|
||||||
client = { path = "client" }
|
client = { path = "client" }
|
||||||
|
fork_choice = { path = "../eth2/fork_choice" }
|
||||||
version = { path = "version" }
|
version = { path = "version" }
|
||||||
clap = "2.32.0"
|
clap = "2.32.0"
|
||||||
slog = { version = "^2.2.3" , features = ["max_level_trace", "release_max_level_debug"] }
|
slog = { version = "^2.2.3" , features = ["max_level_trace", "release_max_level_debug"] }
|
||||||
|
@ -15,6 +15,8 @@ prometheus = "^0.6"
|
|||||||
types = { path = "../../eth2/types" }
|
types = { path = "../../eth2/types" }
|
||||||
tree_hash = { path = "../../eth2/utils/tree_hash" }
|
tree_hash = { path = "../../eth2/utils/tree_hash" }
|
||||||
slot_clock = { path = "../../eth2/utils/slot_clock" }
|
slot_clock = { path = "../../eth2/utils/slot_clock" }
|
||||||
|
serde = "1.0"
|
||||||
|
serde_derive = "1.0"
|
||||||
error-chain = "0.12.0"
|
error-chain = "0.12.0"
|
||||||
slog = "^2.2.3"
|
slog = "^2.2.3"
|
||||||
ssz = { path = "../../eth2/utils/ssz" }
|
ssz = { path = "../../eth2/utils/ssz" }
|
||||||
|
@ -18,42 +18,32 @@ const TESTNET_VALIDATOR_COUNT: usize = 16;
|
|||||||
|
|
||||||
/// 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>, 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`.
|
/// A testnet-suitable BeaconChainType, using `MemoryStore`.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TestnetMemoryBeaconChainTypes;
|
pub struct TestnetMemoryBeaconChainTypes;
|
||||||
|
|
||||||
impl BeaconChainTypes for TestnetMemoryBeaconChainTypes {
|
impl BeaconChainTypes for TestnetMemoryBeaconChainTypes {
|
||||||
type Store = MemoryStore;
|
type Store = MemoryStore;
|
||||||
type SlotClock = SystemTimeSlotClock;
|
type SlotClock = SystemTimeSlotClock;
|
||||||
type ForkChoice = OptimizedLMDGhost<Self::Store, Self::EthSpec>;
|
type ForkChoice = OptimizedLMDGhost<Self::Store, Self::EthSpec>;
|
||||||
type EthSpec = LighthouseTestnetEthSpec;
|
type EthSpec = LighthouseTestnetEthSpec;
|
||||||
}
|
}
|
||||||
|
impl<T: BeaconChainTypes> InitialiseBeaconChain<T> for TestnetMemoryBeaconChainTypes {}
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A testnet-suitable BeaconChainType, using `DiskStore`.
|
/// A testnet-suitable BeaconChainType, using `DiskStore`.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TestnetDiskBeaconChainTypes;
|
pub struct TestnetDiskBeaconChainTypes;
|
||||||
|
|
||||||
impl BeaconChainTypes for TestnetDiskBeaconChainTypes {
|
impl BeaconChainTypes for TestnetDiskBeaconChainTypes {
|
||||||
type Store = DiskStore;
|
type Store = DiskStore;
|
||||||
type SlotClock = SystemTimeSlotClock;
|
type SlotClock = SystemTimeSlotClock;
|
||||||
type ForkChoice = OptimizedLMDGhost<Self::Store, Self::EthSpec>;
|
type ForkChoice = OptimizedLMDGhost<Self::Store, Self::EthSpec>;
|
||||||
type EthSpec = LighthouseTestnetEthSpec;
|
type EthSpec = LighthouseTestnetEthSpec;
|
||||||
}
|
}
|
||||||
|
impl<T: BeaconChainTypes> InitialiseBeaconChain<T> for TestnetDiskBeaconChainTypes {}
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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>(
|
fn maybe_load_from_store_for_testnet<T, U: Store, V: EthSpec>(
|
||||||
|
@ -1,164 +1,69 @@
|
|||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use fork_choice::ForkChoiceAlgorithm;
|
|
||||||
use http_server::HttpServerConfig;
|
use http_server::HttpServerConfig;
|
||||||
use network::NetworkConfig;
|
use network::NetworkConfig;
|
||||||
use slog::error;
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::net::SocketAddr;
|
|
||||||
use std::net::{IpAddr, Ipv4Addr};
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use types::multiaddr::Protocol;
|
|
||||||
use types::multiaddr::ToMultiaddr;
|
|
||||||
use types::Multiaddr;
|
|
||||||
use types::{ChainSpec, EthSpec, LighthouseTestnetEthSpec};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
/// The core configuration of a Lighthouse beacon node.
|
||||||
pub enum DBType {
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
Memory,
|
|
||||||
Disk,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Stores the client configuration for this Lighthouse instance.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct ClientConfig {
|
pub struct ClientConfig {
|
||||||
pub data_dir: PathBuf,
|
data_dir: String,
|
||||||
pub spec: ChainSpec,
|
pub spec: String,
|
||||||
pub net_conf: network::NetworkConfig,
|
pub db_type: String,
|
||||||
pub fork_choice: ForkChoiceAlgorithm,
|
db_name: String,
|
||||||
pub db_type: DBType,
|
pub network: network::NetworkConfig,
|
||||||
pub db_name: PathBuf,
|
pub rpc: rpc::RPCConfig,
|
||||||
pub rpc_conf: rpc::RPCConfig,
|
pub http: HttpServerConfig, //pub ipc_conf:
|
||||||
pub http_conf: HttpServerConfig, //pub ipc_conf:
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ClientConfig {
|
impl Default for ClientConfig {
|
||||||
/// Build a new lighthouse configuration from defaults.
|
|
||||||
fn default() -> Self {
|
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 {
|
Self {
|
||||||
data_dir: data_dir.clone(),
|
data_dir: ".lighthouse".to_string(),
|
||||||
// default to foundation for chain specs
|
spec: "testnet".to_string(),
|
||||||
spec: default_spec,
|
db_type: "disk".to_string(),
|
||||||
net_conf: default_net_conf,
|
db_name: "chain_db".to_string(),
|
||||||
// default to bitwise LMD Ghost
|
// Note: there are no default bootnodes specified.
|
||||||
fork_choice: ForkChoiceAlgorithm::BitwiseLMDGhost,
|
// Once bootnodes are established, add them here.
|
||||||
// default to memory db for now
|
network: NetworkConfig::new(vec![]),
|
||||||
db_type: DBType::Memory,
|
rpc: rpc::RPCConfig::default(),
|
||||||
// default db name for disk-based dbs
|
http: HttpServerConfig::default(),
|
||||||
db_name: data_dir.join("chain_db"),
|
|
||||||
rpc_conf: rpc::RPCConfig::default(),
|
|
||||||
http_conf: HttpServerConfig::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientConfig {
|
impl ClientConfig {
|
||||||
/// Parses the CLI arguments into a `Config` struct.
|
/// Returns the path to which the client may initialize an on-disk database.
|
||||||
pub fn parse_args(args: ArgMatches, log: &slog::Logger) -> Result<Self, &'static str> {
|
pub fn db_path(&self) -> Option<PathBuf> {
|
||||||
let mut config = ClientConfig::default();
|
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
|
/// Apply the following arguments to `self`, replacing values if they are specified in `args`.
|
||||||
if let Some(port_str) = args.value_of("port") {
|
///
|
||||||
if let Ok(port) = port_str.parse::<u16>() {
|
/// Returns an error if arguments are obviously invalid. May succeed even if some values are
|
||||||
config.net_conf.listen_port = port;
|
/// invalid.
|
||||||
// update the listening multiaddrs
|
pub fn apply_cli_args(&mut self, args: &ArgMatches) -> Result<(), &'static str> {
|
||||||
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
|
|
||||||
if let Some(dir) = args.value_of("datadir") {
|
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 let Some(dir) = args.value_of("db") {
|
||||||
|
self.db_type = dir.to_string();
|
||||||
if args.is_present("rpc") {
|
|
||||||
config.rpc_conf.enabled = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(rpc_address) = args.value_of("rpc-address") {
|
self.network.apply_cli_args(args)?;
|
||||||
if let Ok(listen_address) = rpc_address.parse::<Ipv4Addr>() {
|
self.rpc.apply_cli_args(args)?;
|
||||||
config.rpc_conf.listen_address = listen_address;
|
self.http.apply_cli_args(args)?;
|
||||||
} else {
|
|
||||||
error!(log, "Invalid RPC listen address"; "Address" => rpc_address);
|
|
||||||
return Err("Invalid RPC listen address");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(rpc_port) = args.value_of("rpc-port") {
|
Ok(())
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,5 +6,4 @@ error_chain! {
|
|||||||
links {
|
links {
|
||||||
Network(network::error::Error, network::error::ErrorKind);
|
Network(network::error::Error, network::error::ErrorKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ pub mod error;
|
|||||||
pub mod notifier;
|
pub mod notifier;
|
||||||
|
|
||||||
use beacon_chain::BeaconChain;
|
use beacon_chain::BeaconChain;
|
||||||
use beacon_chain_types::InitialiseBeaconChain;
|
|
||||||
use exit_future::Signal;
|
use exit_future::Signal;
|
||||||
use futures::{future::Future, Stream};
|
use futures::{future::Future, Stream};
|
||||||
use network::Service as NetworkService;
|
use network::Service as NetworkService;
|
||||||
@ -18,10 +17,12 @@ use std::sync::Arc;
|
|||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use tokio::runtime::TaskExecutor;
|
use tokio::runtime::TaskExecutor;
|
||||||
use tokio::timer::Interval;
|
use tokio::timer::Interval;
|
||||||
|
use types::EthSpec;
|
||||||
|
|
||||||
pub use beacon_chain::BeaconChainTypes;
|
pub use beacon_chain::BeaconChainTypes;
|
||||||
|
pub use beacon_chain_types::InitialiseBeaconChain;
|
||||||
pub use beacon_chain_types::{TestnetDiskBeaconChainTypes, TestnetMemoryBeaconChainTypes};
|
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
|
/// Main beacon node client service. This provides the connection and initialisation of the clients
|
||||||
/// sub-services in multiple threads.
|
/// sub-services in multiple threads.
|
||||||
@ -57,6 +58,7 @@ where
|
|||||||
) -> error::Result<Self> {
|
) -> error::Result<Self> {
|
||||||
let metrics_registry = Registry::new();
|
let metrics_registry = Registry::new();
|
||||||
let store = Arc::new(store);
|
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.
|
// 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()));
|
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
|
// Start the network service, libp2p and syncing threads
|
||||||
// TODO: Add beacon_chain reference to network parameters
|
// 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_logger = log.new(o!("Service" => "Network"));
|
||||||
let (network, network_send) = NetworkService::new(
|
let (network, network_send) = NetworkService::new(
|
||||||
beacon_chain.clone(),
|
beacon_chain.clone(),
|
||||||
@ -107,9 +109,9 @@ where
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
// spawn the RPC server
|
// 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(
|
Some(rpc::start_server(
|
||||||
&config.rpc_conf,
|
&config.rpc,
|
||||||
executor,
|
executor,
|
||||||
network_send.clone(),
|
network_send.clone(),
|
||||||
beacon_chain.clone(),
|
beacon_chain.clone(),
|
||||||
@ -122,13 +124,13 @@ where
|
|||||||
// Start the `http_server` service.
|
// Start the `http_server` service.
|
||||||
//
|
//
|
||||||
// Note: presently we are ignoring the config and _always_ starting a HTTP server.
|
// 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(
|
Some(http_server::start_service(
|
||||||
&config.http_conf,
|
&config.http,
|
||||||
executor,
|
executor,
|
||||||
network_send,
|
network_send,
|
||||||
beacon_chain.clone(),
|
beacon_chain.clone(),
|
||||||
config.db_name.clone(),
|
config.db_path().expect("unable to read datadir"),
|
||||||
metrics_registry,
|
metrics_registry,
|
||||||
&log,
|
&log,
|
||||||
))
|
))
|
||||||
@ -141,7 +143,7 @@ where
|
|||||||
// 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
|
||||||
let interval = {
|
let interval = {
|
||||||
// Set the interval to start at the next slot, and every slot after
|
// 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
|
//TODO: Handle checked add correctly
|
||||||
Interval::new(Instant::now() + duration_to_next_slot, slot_duration)
|
Interval::new(Instant::now() + duration_to_next_slot, slot_duration)
|
||||||
};
|
};
|
||||||
|
@ -6,9 +6,12 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
beacon_chain = { path = "../beacon_chain" }
|
beacon_chain = { path = "../beacon_chain" }
|
||||||
|
clap = "2.32.0"
|
||||||
# SigP repository until PR is merged
|
# SigP repository until PR is merged
|
||||||
libp2p = { git = "https://github.com/SigP/rust-libp2p", rev = "b3c32d9a821ae6cc89079499cc6e8a6bab0bffc3" }
|
libp2p = { git = "https://github.com/SigP/rust-libp2p", rev = "b3c32d9a821ae6cc89079499cc6e8a6bab0bffc3" }
|
||||||
types = { path = "../../eth2/types" }
|
types = { path = "../../eth2/types" }
|
||||||
|
serde = "1.0"
|
||||||
|
serde_derive = "1.0"
|
||||||
ssz = { path = "../../eth2/utils/ssz" }
|
ssz = { path = "../../eth2/utils/ssz" }
|
||||||
ssz_derive = { path = "../../eth2/utils/ssz_derive" }
|
ssz_derive = { path = "../../eth2/utils/ssz_derive" }
|
||||||
slog = "2.4.1"
|
slog = "2.4.1"
|
||||||
|
@ -1,20 +1,22 @@
|
|||||||
use crate::Multiaddr;
|
use clap::ArgMatches;
|
||||||
use libp2p::gossipsub::{GossipsubConfig, GossipsubConfigBuilder};
|
use libp2p::gossipsub::{GossipsubConfig, GossipsubConfigBuilder};
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
use types::multiaddr::{Error as MultiaddrError, Multiaddr};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(default)]
|
||||||
/// Network configuration for lighthouse.
|
/// Network configuration for lighthouse.
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
//TODO: stubbing networking initial params, change in the future
|
|
||||||
/// IP address to listen on.
|
/// IP address to listen on.
|
||||||
pub listen_addresses: Vec<Multiaddr>,
|
listen_addresses: Vec<String>,
|
||||||
/// Listen port UDP/TCP.
|
|
||||||
pub listen_port: u16,
|
|
||||||
/// Gossipsub configuration parameters.
|
/// Gossipsub configuration parameters.
|
||||||
|
#[serde(skip)]
|
||||||
pub gs_config: GossipsubConfig,
|
pub gs_config: GossipsubConfig,
|
||||||
/// Configuration parameters for node identification protocol.
|
/// Configuration parameters for node identification protocol.
|
||||||
|
#[serde(skip)]
|
||||||
pub identify_config: IdentifyConfig,
|
pub identify_config: IdentifyConfig,
|
||||||
/// List of nodes to initially connect to.
|
/// List of nodes to initially connect to.
|
||||||
pub boot_nodes: Vec<Multiaddr>,
|
boot_nodes: Vec<String>,
|
||||||
/// Client version
|
/// Client version
|
||||||
pub client_version: String,
|
pub client_version: String,
|
||||||
/// List of topics to subscribe to as strings
|
/// List of topics to subscribe to as strings
|
||||||
@ -25,15 +27,12 @@ impl Default for Config {
|
|||||||
/// Generate a default network configuration.
|
/// Generate a default network configuration.
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Config {
|
Config {
|
||||||
listen_addresses: vec!["/ip4/127.0.0.1/tcp/9000"
|
listen_addresses: vec!["/ip4/127.0.0.1/tcp/9000".to_string()],
|
||||||
.parse()
|
|
||||||
.expect("is a correct multi-address")],
|
|
||||||
listen_port: 9000,
|
|
||||||
gs_config: GossipsubConfigBuilder::new()
|
gs_config: GossipsubConfigBuilder::new()
|
||||||
.max_gossip_size(4_000_000)
|
.max_gossip_size(4_000_000)
|
||||||
.build(),
|
.build(),
|
||||||
identify_config: IdentifyConfig::default(),
|
identify_config: IdentifyConfig::default(),
|
||||||
boot_nodes: Vec::new(),
|
boot_nodes: vec![],
|
||||||
client_version: version::version(),
|
client_version: version::version(),
|
||||||
topics: vec![String::from("beacon_chain")],
|
topics: vec![String::from("beacon_chain")],
|
||||||
}
|
}
|
||||||
@ -41,12 +40,34 @@ impl Default for Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn new(boot_nodes: Vec<Multiaddr>) -> Self {
|
pub fn new(boot_nodes: Vec<String>) -> Self {
|
||||||
let mut conf = Config::default();
|
let mut conf = Config::default();
|
||||||
conf.boot_nodes = boot_nodes;
|
conf.boot_nodes = boot_nodes;
|
||||||
|
|
||||||
conf
|
conf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn listen_addresses(&self) -> Result<Vec<Multiaddr>, MultiaddrError> {
|
||||||
|
self.listen_addresses.iter().map(|s| s.parse()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn boot_nodes(&self) -> Result<Vec<Multiaddr>, MultiaddrError> {
|
||||||
|
self.boot_nodes.iter().map(|s| s.parse()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply_cli_args(&mut self, args: &ArgMatches) -> Result<(), &'static str> {
|
||||||
|
if let Some(listen_address_str) = args.value_of("listen-address") {
|
||||||
|
let listen_addresses = listen_address_str.split(",").map(Into::into).collect();
|
||||||
|
self.listen_addresses = listen_addresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(boot_addresses_str) = args.value_of("boot-nodes") {
|
||||||
|
let boot_addresses = boot_addresses_str.split(",").map(Into::into).collect();
|
||||||
|
self.boot_nodes = boot_addresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The configuration parameters for the Identify protocol
|
/// The configuration parameters for the Identify protocol
|
||||||
|
@ -57,7 +57,7 @@ impl Service {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// listen on all addresses
|
// listen on all addresses
|
||||||
for address in &config.listen_addresses {
|
for address in config.listen_addresses().expect("invalid listen multiaddr") {
|
||||||
match Swarm::listen_on(&mut swarm, address.clone()) {
|
match Swarm::listen_on(&mut swarm, address.clone()) {
|
||||||
Ok(mut listen_addr) => {
|
Ok(mut listen_addr) => {
|
||||||
listen_addr.append(Protocol::P2p(local_peer_id.clone().into()));
|
listen_addr.append(Protocol::P2p(local_peer_id.clone().into()));
|
||||||
@ -68,7 +68,7 @@ impl Service {
|
|||||||
}
|
}
|
||||||
// connect to boot nodes - these are currently stored as multiaddrs
|
// connect to boot nodes - these are currently stored as multiaddrs
|
||||||
// Once we have discovery, can set to peerId
|
// Once we have discovery, can set to peerId
|
||||||
for bootnode in config.boot_nodes {
|
for bootnode in config.boot_nodes().expect("invalid boot node multiaddr") {
|
||||||
match Swarm::dial_addr(&mut swarm, bootnode.clone()) {
|
match Swarm::dial_addr(&mut swarm, bootnode.clone()) {
|
||||||
Ok(()) => debug!(log, "Dialing bootnode: {}", bootnode),
|
Ok(()) => debug!(log, "Dialing bootnode: {}", bootnode),
|
||||||
Err(err) => debug!(
|
Err(err) => debug!(
|
||||||
|
@ -3,17 +3,19 @@ mod key;
|
|||||||
mod metrics;
|
mod metrics;
|
||||||
|
|
||||||
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
||||||
|
use clap::ArgMatches;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use iron::prelude::*;
|
use iron::prelude::*;
|
||||||
use network::NetworkMessage;
|
use network::NetworkMessage;
|
||||||
use prometheus::Registry;
|
use prometheus::Registry;
|
||||||
use router::Router;
|
use router::Router;
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use slog::{info, o, warn};
|
use slog::{info, o, warn};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::runtime::TaskExecutor;
|
use tokio::runtime::TaskExecutor;
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct HttpServerConfig {
|
pub struct HttpServerConfig {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub listen_address: String,
|
pub listen_address: String,
|
||||||
@ -30,6 +32,24 @@ impl Default for HttpServerConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HttpServerConfig {
|
||||||
|
pub fn apply_cli_args(&mut self, args: &ArgMatches) -> Result<(), &'static str> {
|
||||||
|
if args.is_present("http") {
|
||||||
|
self.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(listen_address) = args.value_of("http-address") {
|
||||||
|
self.listen_address = listen_address.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(listen_port) = args.value_of("http-port") {
|
||||||
|
self.listen_port = listen_port.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Build the `iron` HTTP server, defining the core routes.
|
/// Build the `iron` HTTP server, defining the core routes.
|
||||||
pub fn create_iron_http_server<T: BeaconChainTypes + 'static>(
|
pub fn create_iron_http_server<T: BeaconChainTypes + 'static>(
|
||||||
beacon_chain: Arc<BeaconChain<T>>,
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
@ -20,6 +20,8 @@ clap = "2.32.0"
|
|||||||
store = { path = "../store" }
|
store = { path = "../store" }
|
||||||
dirs = "1.0.3"
|
dirs = "1.0.3"
|
||||||
futures = "0.1.23"
|
futures = "0.1.23"
|
||||||
|
serde = "1.0"
|
||||||
|
serde_derive = "1.0"
|
||||||
slog = "^2.2.3"
|
slog = "^2.2.3"
|
||||||
slog-term = "^2.4.0"
|
slog-term = "^2.4.0"
|
||||||
slog-async = "^2.3.0"
|
slog-async = "^2.3.0"
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
use clap::ArgMatches;
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
/// RPC Configuration
|
/// RPC Configuration
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// Enable the RPC server.
|
/// Enable the RPC server.
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
@ -20,3 +22,23 @@ impl Default for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
pub fn apply_cli_args(&mut self, args: &ArgMatches) -> Result<(), &'static str> {
|
||||||
|
if args.is_present("rpc") {
|
||||||
|
self.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(rpc_address) = args.value_of("rpc-address") {
|
||||||
|
self.listen_address = rpc_address
|
||||||
|
.parse::<Ipv4Addr>()
|
||||||
|
.map_err(|_| "rpc-address is not IPv4 address")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(rpc_port) = args.value_of("rpc-port") {
|
||||||
|
self.port = rpc_port.parse::<u16>().map_err(|_| "rpc-port is not u16")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,7 +4,7 @@ mod run;
|
|||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use client::ClientConfig;
|
use client::ClientConfig;
|
||||||
use slog::{error, o, Drain};
|
use slog::{crit, o, Drain};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let decorator = slog_term::TermDecorator::new().build();
|
let decorator = slog_term::TermDecorator::new().build();
|
||||||
@ -29,21 +29,14 @@ fn main() {
|
|||||||
Arg::with_name("listen-address")
|
Arg::with_name("listen-address")
|
||||||
.long("listen-address")
|
.long("listen-address")
|
||||||
.value_name("Listen Address")
|
.value_name("Listen Address")
|
||||||
.help("The Network address to listen for p2p connections.")
|
.help("One or more comma-delimited multi-addresses to listen for p2p connections.")
|
||||||
.takes_value(true),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("port")
|
|
||||||
.long("port")
|
|
||||||
.value_name("PORT")
|
|
||||||
.help("Network listen port for p2p connections.")
|
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("boot-nodes")
|
Arg::with_name("boot-nodes")
|
||||||
.long("boot-nodes")
|
.long("boot-nodes")
|
||||||
.value_name("BOOTNODES")
|
.value_name("BOOTNODES")
|
||||||
.help("A list of comma separated multi addresses representing bootnodes to connect to.")
|
.help("One or more comma-delimited multi-addresses to bootstrap the p2p network.")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
// rpc related arguments
|
// rpc related arguments
|
||||||
@ -101,11 +94,18 @@ fn main() {
|
|||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
// invalid arguments, panic
|
let mut config = ClientConfig::default();
|
||||||
let config = ClientConfig::parse_args(matches, &logger).unwrap();
|
|
||||||
|
match config.apply_cli_args(&matches) {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(s) => {
|
||||||
|
crit!(logger, "Failed to parse CLI arguments"; "error" => s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
match run::run_beacon_node(config, &logger) {
|
match run::run_beacon_node(config, &logger) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => error!(logger, "Beacon node failed because {:?}", e),
|
Err(e) => crit!(logger, "Beacon node failed to start"; "reason" => format!("{:}", e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
use client::{
|
use client::{
|
||||||
error, notifier, BeaconChainTypes, Client, ClientConfig, DBType, TestnetDiskBeaconChainTypes,
|
error, notifier, BeaconChainTypes, Client, ClientConfig, InitialiseBeaconChain,
|
||||||
TestnetMemoryBeaconChainTypes,
|
TestnetDiskBeaconChainTypes, TestnetMemoryBeaconChainTypes,
|
||||||
};
|
};
|
||||||
use futures::sync::oneshot;
|
use futures::sync::oneshot;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use slog::info;
|
use slog::{error, info};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
use store::{DiskStore, MemoryStore};
|
use store::{DiskStore, MemoryStore};
|
||||||
use tokio::runtime::Builder;
|
use tokio::runtime::Builder;
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
@ -19,51 +21,58 @@ pub fn run_beacon_node(config: ClientConfig, log: &slog::Logger) -> error::Resul
|
|||||||
.build()
|
.build()
|
||||||
.map_err(|e| format!("{:?}", e))?;
|
.map_err(|e| format!("{:?}", e))?;
|
||||||
|
|
||||||
// Log configuration
|
|
||||||
info!(log, "Listening on {:?}", &config.net_conf.listen_addresses;
|
|
||||||
"data_dir" => &config.data_dir.to_str(),
|
|
||||||
"port" => &config.net_conf.listen_port);
|
|
||||||
|
|
||||||
let executor = runtime.executor();
|
let executor = runtime.executor();
|
||||||
|
|
||||||
match config.db_type {
|
let db_path: PathBuf = config
|
||||||
DBType::Disk => {
|
.db_path()
|
||||||
info!(
|
.ok_or_else::<error::Error, _>(|| "Unable to access database path".into())?;
|
||||||
log,
|
let db_type = &config.db_type;
|
||||||
"BeaconNode starting";
|
let spec = &config.spec;
|
||||||
"type" => "TestnetDiskBeaconChainTypes"
|
|
||||||
);
|
|
||||||
|
|
||||||
let store = DiskStore::open(&config.db_name).expect("Unable to open DB.");
|
let other_config = config.clone();
|
||||||
|
|
||||||
let client: Client<TestnetDiskBeaconChainTypes> =
|
let result = match (db_type.as_str(), spec.as_str()) {
|
||||||
Client::new(config, store, log.clone(), &executor)?;
|
("disk", "testnet") => {
|
||||||
|
run::<TestnetDiskBeaconChainTypes>(&db_path, config, executor, runtime, log)
|
||||||
run(client, executor, runtime, log)
|
|
||||||
}
|
}
|
||||||
DBType::Memory => {
|
("memory", "testnet") => {
|
||||||
info!(
|
run::<TestnetMemoryBeaconChainTypes>(&db_path, config, executor, runtime, log)
|
||||||
log,
|
|
||||||
"BeaconNode starting";
|
|
||||||
"type" => "TestnetMemoryBeaconChainTypes"
|
|
||||||
);
|
|
||||||
|
|
||||||
let store = MemoryStore::open();
|
|
||||||
|
|
||||||
let client: Client<TestnetMemoryBeaconChainTypes> =
|
|
||||||
Client::new(config, store, log.clone(), &executor)?;
|
|
||||||
|
|
||||||
run(client, executor, runtime, log)
|
|
||||||
}
|
}
|
||||||
|
(db_type, spec) => {
|
||||||
|
error!(log, "Unknown runtime configuration"; "spec" => spec, "db_type" => db_type);
|
||||||
|
Err("Unknown specification and/or db_type.".into())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if result.is_ok() {
|
||||||
|
info!(
|
||||||
|
log,
|
||||||
|
"Started beacon node";
|
||||||
|
"p2p_listen_addresses" => format!("{:?}", &other_config.network.listen_addresses()),
|
||||||
|
"data_dir" => format!("{:?}", other_config.data_dir()),
|
||||||
|
"spec" => &other_config.spec,
|
||||||
|
"db_type" => &other_config.db_type,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run<T: BeaconChainTypes + Send + Sync + 'static>(
|
pub fn run<T>(
|
||||||
client: Client<T>,
|
db_path: &Path,
|
||||||
|
config: ClientConfig,
|
||||||
executor: TaskExecutor,
|
executor: TaskExecutor,
|
||||||
mut runtime: Runtime,
|
mut runtime: Runtime,
|
||||||
log: &slog::Logger,
|
log: &slog::Logger,
|
||||||
) -> error::Result<()> {
|
) -> error::Result<()>
|
||||||
|
where
|
||||||
|
T: BeaconChainTypes + InitialiseBeaconChain<T> + Send + Sync + 'static + Clone,
|
||||||
|
T::Store: OpenDatabase,
|
||||||
|
{
|
||||||
|
let store = T::Store::open_database(&db_path)?;
|
||||||
|
|
||||||
|
let client: Client<T> = Client::new(config, store, log.clone(), &executor)?;
|
||||||
|
|
||||||
// run service until ctrl-c
|
// run service until ctrl-c
|
||||||
let (ctrlc_send, ctrlc_oneshot) = oneshot::channel();
|
let (ctrlc_send, ctrlc_oneshot) = oneshot::channel();
|
||||||
let ctrlc_send_c = RefCell::new(Some(ctrlc_send));
|
let ctrlc_send_c = RefCell::new(Some(ctrlc_send));
|
||||||
@ -91,3 +100,22 @@ pub fn run<T: BeaconChainTypes + Send + Sync + 'static>(
|
|||||||
runtime.shutdown_on_idle().wait().unwrap();
|
runtime.shutdown_on_idle().wait().unwrap();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A convenience trait, providing a method to open a database.
|
||||||
|
///
|
||||||
|
/// Panics if unable to open the database.
|
||||||
|
pub trait OpenDatabase: Sized {
|
||||||
|
fn open_database(path: &Path) -> error::Result<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OpenDatabase for MemoryStore {
|
||||||
|
fn open_database(_path: &Path) -> error::Result<Self> {
|
||||||
|
Ok(MemoryStore::open())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OpenDatabase for DiskStore {
|
||||||
|
fn open_database(path: &Path) -> error::Result<Self> {
|
||||||
|
DiskStore::open(path).map_err(|e| format!("Unable to open database: {:?}", e).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
extern crate rocksdb;
|
extern crate rocksdb;
|
||||||
|
|
||||||
// use super::stores::COLUMNS;
|
|
||||||
use super::{ClientDB, DBError, DBValue};
|
use super::{ClientDB, DBError, DBValue};
|
||||||
use rocksdb::Error as RocksError;
|
use rocksdb::Error as RocksError;
|
||||||
use rocksdb::{Options, DB};
|
use rocksdb::{Options, DB};
|
||||||
|
Loading…
Reference in New Issue
Block a user