From 3fe28b0f03b647b1760315a485dc0f5f9f94d384 Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Mon, 24 Apr 2017 18:49:57 -0700 Subject: [PATCH] Server types cleanup and serde for configuration types Moved error and configuration types from server.rs to types.rs where they should have been from the start. Configuration types for the server and p2p modules now derive serde Serialize and Deserialize so we can have a simple JSON configuration file. --- grin/Cargo.toml | 2 + grin/src/lib.rs | 6 ++- grin/src/server.rs | 104 ++++++++++++--------------------------------- grin/src/types.rs | 57 +++++++++++++++++++++++++ p2p/Cargo.toml | 2 + p2p/src/lib.rs | 3 ++ p2p/src/types.rs | 3 +- 7 files changed, 99 insertions(+), 78 deletions(-) diff --git a/grin/Cargo.toml b/grin/Cargo.toml index d4f6bb5b..b4b3a46c 100644 --- a/grin/Cargo.toml +++ b/grin/Cargo.toml @@ -19,6 +19,8 @@ futures-cpupool = "^0.1.3" hyper = { git = "https://github.com/hyperium/hyper" } log = "^0.3" time = "^0.1" +serde = "~0.9.10" +serde_derive = "~0.9.10" tokio-core="^0.1.1" tokio-timer="^0.1.0" rand = "^0.3" diff --git a/grin/src/lib.rs b/grin/src/lib.rs index 18400046..51a6243c 100644 --- a/grin/src/lib.rs +++ b/grin/src/lib.rs @@ -28,6 +28,9 @@ extern crate futures; extern crate futures_cpupool as cpupool; extern crate hyper; extern crate rand; +extern crate serde; +#[macro_use] +extern crate serde_derive; extern crate time; extern crate tokio_core; extern crate tokio_timer; @@ -48,4 +51,5 @@ mod seed; mod sync; mod types; -pub use server::{Server, ServerConfig, Seeding}; +pub use server::Server; +pub use types::{ServerConfig, Seeding}; diff --git a/grin/src/server.rs b/grin/src/server.rs index 70f09f7c..76fbb128 100644 --- a/grin/src/server.rs +++ b/grin/src/server.rs @@ -19,9 +19,11 @@ use std::net::SocketAddr; use std::sync::{Arc, Mutex}; use std::thread; +use std::time; -use futures::{future, Future}; +use futures::{future, Future, Stream}; use tokio_core::reactor; +use tokio_timer::Timer; use adapters::{NetToChainAdapter, ChainToNetAdapter}; use api; @@ -33,71 +35,7 @@ use p2p; use seed; use store; use sync; - -/// Errors than can be reported by a server implementation, mostly wraps -/// underlying components errors. -#[derive(Debug)] -pub enum Error { - /// Error when trying to add a block to the chain - ChainErr(chain::pipe::Error), - /// Peer connection error - PeerErr(core::ser::Error), - /// Data store error - StoreErr(store::Error), -} - -impl From for Error { - fn from(e: store::Error) -> Error { - Error::StoreErr(e) - } -} - -/// Type of seeding the server will use to find other peers on the network. -#[derive(Debug, Clone)] -pub enum Seeding { - /// No seeding, mostly for tests that programmatically connect - None, - /// A list of seed addresses provided to the server - List(Vec), - /// Automatically download a gist with a list of server addresses - Gist, -} - -/// Full server configuration, aggregating configurations required for the -/// different components. -#[derive(Debug, Clone)] -pub struct ServerConfig { - /// Directory under which the rocksdb stores will be created - pub db_root: String, - - /// Network address for the Rest API HTTP server. - pub api_http_addr: String, - - /// Allows overriding the default cuckoo cycle size - pub cuckoo_size: u8, - - /// Capabilities expose by this node, also conditions which other peers this - /// node will have an affinity toward when connection. - pub capabilities: p2p::Capabilities, - - pub seeding_type: Seeding, - - /// Configuration for the peer-to-peer server - pub p2p_config: p2p::P2PConfig, -} - -impl Default for ServerConfig { - fn default() -> ServerConfig { - ServerConfig { - db_root: ".grin".to_string(), - api_http_addr: "127.0.0.1:13415".to_string(), - cuckoo_size: 0, - capabilities: p2p::FULL_NODE, - seeding_type: Seeding::None, - p2p_config: p2p::P2PConfig::default(), - } - } -} +use types::*; /// Grin server holding internal structures. pub struct Server { @@ -118,9 +56,22 @@ impl Server { /// Instantiates and starts a new server. pub fn start(config: ServerConfig) -> Result { let mut evtlp = reactor::Core::new().unwrap(); - let serv = Server::future(config, &evtlp.handle()); - evtlp.run(future::ok::<(), ()>(())).unwrap(); - serv + let enable_mining = config.enable_mining; + let serv = Server::future(config, &evtlp.handle())?; + if enable_mining { + serv.start_miner(); + } + + let forever = Timer::default() + .interval(time::Duration::from_secs(60)) + .for_each(move |_| { + debug!("event loop running"); + Ok(()) + }) + .map_err(|_| ()); + + evtlp.run(forever).unwrap(); + Ok(serv) } /// Instantiates a new server associated with the provided future reactor. @@ -145,8 +96,8 @@ impl Server { Seeding::List(seeds) => { seed.connect_and_monitor(evt_handle.clone(), seed::predefined_seeds(seeds)); } - Seeding::Gist => { - seed.connect_and_monitor(evt_handle.clone(), seed::gist_seeds(evt_handle.clone())); + Seeding::WebStatic => { + seed.connect_and_monitor(evt_handle.clone(), seed::web_seeds(evt_handle.clone())); } } @@ -202,25 +153,26 @@ impl Server { fn store_head(config: &ServerConfig) -> Result<(Arc, chain::Tip), Error> { let chain_store = try!(chain::store::ChainKVStore::new(config.db_root.clone()) - .map_err(&Error::StoreErr)); + .map_err(&Error::Store)); // check if we have a head in store, otherwise the genesis block is it let head = match chain_store.head() { Ok(tip) => tip, Err(store::Error::NotFoundErr) => { - debug!("No genesis block found, creating and saving one."); + info!("No genesis block found, creating and saving one."); let mut gen = core::genesis::genesis(); if config.cuckoo_size > 0 { gen.header.cuckoo_len = config.cuckoo_size; let diff = gen.header.difficulty.clone(); core::pow::pow(&mut gen.header, diff).unwrap(); } - try!(chain_store.save_block(&gen).map_err(&Error::StoreErr)); + try!(chain_store.save_block(&gen).map_err(&Error::Store)); let tip = chain::types::Tip::new(gen.hash()); - try!(chain_store.save_head(&tip).map_err(&Error::StoreErr)); + try!(chain_store.save_head(&tip).map_err(&Error::Store)); + info!("Saved genesis block with hash {}", gen.hash()); tip } - Err(e) => return Err(Error::StoreErr(e)), + Err(e) => return Err(Error::Store(e)), }; Ok((Arc::new(chain_store), head)) } diff --git a/grin/src/types.rs b/grin/src/types.rs index 3a93d97c..f5309a53 100644 --- a/grin/src/types.rs +++ b/grin/src/types.rs @@ -18,9 +18,14 @@ use chain; use p2p; use store; +/// Error type wrapping underlying module errors. +#[derive(Debug)] pub enum Error { + /// Error originating from the db storage. Store(store::Error), + /// Error originating from the blockchain implementation. Chain(chain::Error), + /// Error originating from the peer-to-peer network. P2P(p2p::Error), } @@ -41,3 +46,55 @@ impl From for Error { Error::Store(e) } } + +/// Type of seeding the server will use to find other peers on the network. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum Seeding { + /// No seeding, mostly for tests that programmatically connect + None, + /// A list of seed addresses provided to the server + List(Vec), + /// Automatically download a text file with a list of server addresses + WebStatic, +} + +/// Full server configuration, aggregating configurations required for the +/// different components. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ServerConfig { + /// Directory under which the rocksdb stores will be created + pub db_root: String, + + /// Network address for the Rest API HTTP server. + pub api_http_addr: String, + + /// Allows overriding the default cuckoo cycle size + pub cuckoo_size: u8, + + /// Capabilities expose by this node, also conditions which other peers this + /// node will have an affinity toward when connection. + pub capabilities: p2p::Capabilities, + + /// Method used to get the list of seed nodes for initial bootstrap. + pub seeding_type: Seeding, + + /// Configuration for the peer-to-peer server + pub p2p_config: p2p::P2PConfig, + + /// Whethere to start the miner with the server + pub enable_mining: bool, +} + +impl Default for ServerConfig { + fn default() -> ServerConfig { + ServerConfig { + db_root: ".grin".to_string(), + api_http_addr: "127.0.0.1:13415".to_string(), + cuckoo_size: 0, + capabilities: p2p::FULL_NODE, + seeding_type: Seeding::None, + p2p_config: p2p::P2PConfig::default(), + enable_mining: false, + } + } +} diff --git a/p2p/Cargo.toml b/p2p/Cargo.toml index 97902e9c..1614ba77 100644 --- a/p2p/Cargo.toml +++ b/p2p/Cargo.toml @@ -11,6 +11,8 @@ futures = "^0.1.9" log = "^0.3" net2 = "0.2.0" rand = "^0.3" +serde = "~0.9.10" +serde_derive = "~0.9.10" tokio-core="^0.1.1" tokio-timer="^0.1.0" time = "^0.1" diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs index ddcde0d7..f68d4e96 100644 --- a/p2p/src/lib.rs +++ b/p2p/src/lib.rs @@ -35,6 +35,9 @@ extern crate futures; extern crate tokio_core; extern crate tokio_timer; extern crate rand; +extern crate serde; +#[macro_use] +extern crate serde_derive; extern crate time; extern crate num; diff --git a/p2p/src/types.rs b/p2p/src/types.rs index 971bc9a4..ef2b80e4 100644 --- a/p2p/src/types.rs +++ b/p2p/src/types.rs @@ -63,7 +63,7 @@ impl From for Error { } /// Configuration for the peer-to-peer server. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] pub struct P2PConfig { pub host: IpAddr, pub port: u16, @@ -82,6 +82,7 @@ impl Default for P2PConfig { bitflags! { /// Options for what type of interaction a peer supports + #[derive(Serialize, Deserialize)] pub flags Capabilities: u32 { /// We don't know (yet) what the peer can do. const UNKNOWN = 0b00000000,