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" } | ||||
| store = { path = "./store" } | ||||
| client = { path = "client" } | ||||
| fork_choice = { path = "../eth2/fork_choice" } | ||||
| version = { path = "version" } | ||||
| clap = "2.32.0" | ||||
| slog = { version = "^2.2.3" , features = ["max_level_trace", "release_max_level_debug"] } | ||||
|  | ||||
| @ -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) | ||||
|             }; | ||||
|  | ||||
| @ -6,9 +6,12 @@ edition = "2018" | ||||
| 
 | ||||
| [dependencies] | ||||
| beacon_chain =  { path = "../beacon_chain" } | ||||
| clap = "2.32.0" | ||||
| # SigP repository until PR is merged | ||||
| libp2p =  { git = "https://github.com/SigP/rust-libp2p", rev = "b3c32d9a821ae6cc89079499cc6e8a6bab0bffc3" } | ||||
| types = { path =  "../../eth2/types" } | ||||
| serde = "1.0" | ||||
| serde_derive = "1.0" | ||||
| ssz = { path = "../../eth2/utils/ssz" } | ||||
| ssz_derive = { path = "../../eth2/utils/ssz_derive" } | ||||
| slog = "2.4.1" | ||||
|  | ||||
| @ -1,20 +1,22 @@ | ||||
| use crate::Multiaddr; | ||||
| use clap::ArgMatches; | ||||
| 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.
 | ||||
| pub struct Config { | ||||
|     //TODO: stubbing networking initial params, change in the future
 | ||||
|     /// IP address to listen on.
 | ||||
|     pub listen_addresses: Vec<Multiaddr>, | ||||
|     /// Listen port UDP/TCP.
 | ||||
|     pub listen_port: u16, | ||||
|     listen_addresses: Vec<String>, | ||||
|     /// Gossipsub configuration parameters.
 | ||||
|     #[serde(skip)] | ||||
|     pub gs_config: GossipsubConfig, | ||||
|     /// Configuration parameters for node identification protocol.
 | ||||
|     #[serde(skip)] | ||||
|     pub identify_config: IdentifyConfig, | ||||
|     /// List of nodes to initially connect to.
 | ||||
|     pub boot_nodes: Vec<Multiaddr>, | ||||
|     boot_nodes: Vec<String>, | ||||
|     /// Client version
 | ||||
|     pub client_version: String, | ||||
|     /// List of topics to subscribe to as strings
 | ||||
| @ -25,15 +27,12 @@ impl Default for Config { | ||||
|     /// Generate a default network configuration.
 | ||||
|     fn default() -> Self { | ||||
|         Config { | ||||
|             listen_addresses: vec!["/ip4/127.0.0.1/tcp/9000" | ||||
|                 .parse() | ||||
|                 .expect("is a correct multi-address")], | ||||
|             listen_port: 9000, | ||||
|             listen_addresses: vec!["/ip4/127.0.0.1/tcp/9000".to_string()], | ||||
|             gs_config: GossipsubConfigBuilder::new() | ||||
|                 .max_gossip_size(4_000_000) | ||||
|                 .build(), | ||||
|             identify_config: IdentifyConfig::default(), | ||||
|             boot_nodes: Vec::new(), | ||||
|             boot_nodes: vec![], | ||||
|             client_version: version::version(), | ||||
|             topics: vec![String::from("beacon_chain")], | ||||
|         } | ||||
| @ -41,12 +40,34 @@ impl Default for Config { | ||||
| } | ||||
| 
 | ||||
| impl Config { | ||||
|     pub fn new(boot_nodes: Vec<Multiaddr>) -> Self { | ||||
|     pub fn new(boot_nodes: Vec<String>) -> Self { | ||||
|         let mut conf = Config::default(); | ||||
|         conf.boot_nodes = boot_nodes; | ||||
| 
 | ||||
|         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
 | ||||
|  | ||||
| @ -57,7 +57,7 @@ impl Service { | ||||
|         }; | ||||
| 
 | ||||
|         // 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()) { | ||||
|                 Ok(mut listen_addr) => { | ||||
|                     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
 | ||||
|         // 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()) { | ||||
|                 Ok(()) => debug!(log, "Dialing bootnode: {}", bootnode), | ||||
|                 Err(err) => debug!( | ||||
|  | ||||
| @ -3,17 +3,19 @@ mod key; | ||||
| mod metrics; | ||||
| 
 | ||||
| use beacon_chain::{BeaconChain, BeaconChainTypes}; | ||||
| use clap::ArgMatches; | ||||
| use futures::Future; | ||||
| use iron::prelude::*; | ||||
| use network::NetworkMessage; | ||||
| use prometheus::Registry; | ||||
| use router::Router; | ||||
| use serde_derive::{Deserialize, Serialize}; | ||||
| use slog::{info, o, warn}; | ||||
| use std::path::PathBuf; | ||||
| use std::sync::Arc; | ||||
| use tokio::runtime::TaskExecutor; | ||||
| 
 | ||||
| #[derive(PartialEq, Clone, Debug)] | ||||
| #[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] | ||||
| pub struct HttpServerConfig { | ||||
|     pub enabled: bool, | ||||
|     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.
 | ||||
| pub fn create_iron_http_server<T: BeaconChainTypes + 'static>( | ||||
|     beacon_chain: Arc<BeaconChain<T>>, | ||||
|  | ||||
| @ -20,6 +20,8 @@ clap = "2.32.0" | ||||
| store = { path = "../store" } | ||||
| dirs = "1.0.3" | ||||
| futures = "0.1.23" | ||||
| serde = "1.0" | ||||
| serde_derive = "1.0" | ||||
| slog = "^2.2.3" | ||||
| slog-term = "^2.4.0" | ||||
| slog-async = "^2.3.0" | ||||
|  | ||||
| @ -1,7 +1,9 @@ | ||||
| use clap::ArgMatches; | ||||
| use serde_derive::{Deserialize, Serialize}; | ||||
| use std::net::Ipv4Addr; | ||||
| 
 | ||||
| /// RPC Configuration
 | ||||
| #[derive(Debug, Clone)] | ||||
| #[derive(Debug, Clone, Serialize, Deserialize)] | ||||
| pub struct Config { | ||||
|     /// Enable the RPC server.
 | ||||
|     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 client::ClientConfig; | ||||
| use slog::{error, o, Drain}; | ||||
| use slog::{crit, o, Drain}; | ||||
| 
 | ||||
| fn main() { | ||||
|     let decorator = slog_term::TermDecorator::new().build(); | ||||
| @ -29,21 +29,14 @@ fn main() { | ||||
|             Arg::with_name("listen-address") | ||||
|                 .long("listen-address") | ||||
|                 .value_name("Listen Address") | ||||
|                 .help("The Network address 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.") | ||||
|                 .help("One or more comma-delimited multi-addresses to listen for p2p connections.") | ||||
|                 .takes_value(true), | ||||
|         ) | ||||
|         .arg( | ||||
|             Arg::with_name("boot-nodes") | ||||
|                 .long("boot-nodes") | ||||
|                 .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), | ||||
|         ) | ||||
|         // rpc related arguments
 | ||||
| @ -101,11 +94,18 @@ fn main() { | ||||
|         ) | ||||
|         .get_matches(); | ||||
| 
 | ||||
|     // invalid arguments, panic
 | ||||
|     let config = ClientConfig::parse_args(matches, &logger).unwrap(); | ||||
|     let mut config = ClientConfig::default(); | ||||
| 
 | ||||
|     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) { | ||||
|         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::{ | ||||
|     error, notifier, BeaconChainTypes, Client, ClientConfig, DBType, TestnetDiskBeaconChainTypes, | ||||
|     TestnetMemoryBeaconChainTypes, | ||||
|     error, notifier, BeaconChainTypes, Client, ClientConfig, InitialiseBeaconChain, | ||||
|     TestnetDiskBeaconChainTypes, TestnetMemoryBeaconChainTypes, | ||||
| }; | ||||
| use futures::sync::oneshot; | ||||
| use futures::Future; | ||||
| use slog::info; | ||||
| use slog::{error, info}; | ||||
| use std::cell::RefCell; | ||||
| use std::path::Path; | ||||
| use std::path::PathBuf; | ||||
| use store::{DiskStore, MemoryStore}; | ||||
| use tokio::runtime::Builder; | ||||
| use tokio::runtime::Runtime; | ||||
| @ -19,51 +21,58 @@ pub fn run_beacon_node(config: ClientConfig, log: &slog::Logger) -> error::Resul | ||||
|         .build() | ||||
|         .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(); | ||||
| 
 | ||||
|     match config.db_type { | ||||
|         DBType::Disk => { | ||||
|             info!( | ||||
|                 log, | ||||
|                 "BeaconNode starting"; | ||||
|                 "type" => "TestnetDiskBeaconChainTypes" | ||||
|             ); | ||||
|     let db_path: PathBuf = config | ||||
|         .db_path() | ||||
|         .ok_or_else::<error::Error, _>(|| "Unable to access database path".into())?; | ||||
|     let db_type = &config.db_type; | ||||
|     let spec = &config.spec; | ||||
| 
 | ||||
|             let store = DiskStore::open(&config.db_name).expect("Unable to open DB."); | ||||
|     let other_config = config.clone(); | ||||
| 
 | ||||
|             let client: Client<TestnetDiskBeaconChainTypes> = | ||||
|                 Client::new(config, store, log.clone(), &executor)?; | ||||
| 
 | ||||
|             run(client, executor, runtime, log) | ||||
|     let result = match (db_type.as_str(), spec.as_str()) { | ||||
|         ("disk", "testnet") => { | ||||
|             run::<TestnetDiskBeaconChainTypes>(&db_path, config, executor, runtime, log) | ||||
|         } | ||||
|         DBType::Memory => { | ||||
|             info!( | ||||
|                 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) | ||||
|         ("memory", "testnet") => { | ||||
|             run::<TestnetMemoryBeaconChainTypes>(&db_path, config, 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>( | ||||
|     client: Client<T>, | ||||
| pub fn run<T>( | ||||
|     db_path: &Path, | ||||
|     config: ClientConfig, | ||||
|     executor: TaskExecutor, | ||||
|     mut runtime: Runtime, | ||||
|     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
 | ||||
|     let (ctrlc_send, ctrlc_oneshot) = oneshot::channel(); | ||||
|     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(); | ||||
|     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; | ||||
| 
 | ||||
| // use super::stores::COLUMNS;
 | ||||
| use super::{ClientDB, DBError, DBValue}; | ||||
| use rocksdb::Error as RocksError; | ||||
| use rocksdb::{Options, DB}; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user