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.
This commit is contained in:
Ignotus Peverell 2017-04-24 18:49:57 -07:00
parent a37e2b99fb
commit 3fe28b0f03
No known key found for this signature in database
GPG key ID: 99CD25F39F8F8211
7 changed files with 99 additions and 78 deletions

View file

@ -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"

View file

@ -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};

View file

@ -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<store::Error> 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<String>),
/// 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<Server, Error> {
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::store::ChainKVStore>, 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))
}

View file

@ -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<store::Error> 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<String>),
/// 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,
}
}
}

View file

@ -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"

View file

@ -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;

View file

@ -63,7 +63,7 @@ impl From<TimerError> 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,