mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-20 19:11:08 +03:00
Addition of configuration file (#79)
* addition of configuration file to grin executable, instructions on how it's picked up are in grin.toml * Starting to add a configuration file, and change some elements of configuration structures to make them more consistent
This commit is contained in:
parent
e2ebd854e1
commit
1ede61d2a2
13 changed files with 531 additions and 77 deletions
|
@ -4,11 +4,12 @@ version = "0.1.0"
|
|||
authors = ["Ignotus Peverell <igno.peverell@protonmail.com>"]
|
||||
|
||||
[workspace]
|
||||
members = ["api", "chain", "core", "grin", "p2p", "store", "util", "pool", "wallet"]
|
||||
members = ["api", "chain", "config", "core", "grin", "p2p", "store", "util", "pool", "wallet"]
|
||||
|
||||
[dependencies]
|
||||
grin_api = { path = "./api" }
|
||||
grin_wallet = { path = "./wallet" }
|
||||
grin_config = { path = "./config" }
|
||||
secp256k1zkp = { path = "./secp256k1zkp" }
|
||||
|
||||
clap = "^2.23.3"
|
||||
|
|
14
config/Cargo.toml
Normal file
14
config/Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "grin_config"
|
||||
version = "0.1.0"
|
||||
authors = [" yeastplume"]
|
||||
workspace = ".."
|
||||
|
||||
[dependencies]
|
||||
serde = "~1.0.8"
|
||||
serde_derive = "~1.0.8"
|
||||
toml = "0.4"
|
||||
|
||||
grin_grin = { path = "../grin" }
|
||||
grin_p2p = { path = "../p2p" }
|
||||
grin_wallet = { path = "../wallet"}
|
212
config/src/config.rs
Normal file
212
config/src/config.rs
Normal file
|
@ -0,0 +1,212 @@
|
|||
// Copyright 2017 The Grin Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Configuration file management
|
||||
|
||||
use std::env;
|
||||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
use std::fs::File;
|
||||
|
||||
use toml;
|
||||
use grin::{ServerConfig,
|
||||
MinerConfig};
|
||||
use wallet::WalletConfig;
|
||||
|
||||
use types::{ConfigMembers,
|
||||
GlobalConfig,
|
||||
ConfigError};
|
||||
|
||||
/// The default file name to use when trying to derive
|
||||
/// the config file location
|
||||
|
||||
const CONFIG_FILE_NAME: &'static str = "grin.toml";
|
||||
const GRIN_HOME: &'static str = ".grin";
|
||||
|
||||
/// Returns the defaults, as strewn throughout the code
|
||||
|
||||
impl Default for ConfigMembers {
|
||||
fn default() -> ConfigMembers {
|
||||
ConfigMembers {
|
||||
server: ServerConfig::default(),
|
||||
mining: Some(MinerConfig::default()),
|
||||
//wallet: Some(WalletConfig::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for GlobalConfig {
|
||||
fn default() -> GlobalConfig{
|
||||
GlobalConfig {
|
||||
config_file_path: None,
|
||||
using_config_file: false,
|
||||
members: Some(ConfigMembers::default())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GlobalConfig {
|
||||
|
||||
/// Need to decide on rules where to read the config file from,
|
||||
/// but will take a stab at logic for now
|
||||
|
||||
fn derive_config_location(&mut self) -> Result<(), ConfigError> {
|
||||
//First, check working directory
|
||||
let mut config_path = env::current_dir().unwrap();
|
||||
config_path.push(CONFIG_FILE_NAME);
|
||||
if config_path.exists() {
|
||||
self.config_file_path = Some(config_path);
|
||||
return Ok(())
|
||||
}
|
||||
//Next, look in directory of executable
|
||||
let mut config_path=env::current_exe().unwrap();
|
||||
config_path.pop();
|
||||
config_path.push(CONFIG_FILE_NAME);
|
||||
if config_path.exists() {
|
||||
self.config_file_path = Some(config_path);
|
||||
return Ok(())
|
||||
}
|
||||
//Then look in {user_home}/.grin
|
||||
let config_path = env::home_dir();
|
||||
if let Some(mut p) = config_path {
|
||||
p.push(GRIN_HOME);
|
||||
p.push(CONFIG_FILE_NAME);
|
||||
if p.exists() {
|
||||
self.config_file_path = Some(p);
|
||||
return Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Give up
|
||||
Err(ConfigError::FileNotFoundError(String::from("")))
|
||||
|
||||
}
|
||||
|
||||
/// Takes the path to a config file, or if NONE, tries
|
||||
/// to determine a config file based on rules in
|
||||
/// derive_config_location
|
||||
|
||||
pub fn new(file_path:Option<&str>) -> Result<GlobalConfig, ConfigError> {
|
||||
let mut return_value = GlobalConfig::default();
|
||||
if let Some(fp) = file_path {
|
||||
return_value.config_file_path = Some(PathBuf::from(&fp));
|
||||
} else {
|
||||
return_value.derive_config_location();
|
||||
}
|
||||
|
||||
//No attempt at a config file, just return defaults
|
||||
if let None = return_value.config_file_path {
|
||||
return Ok(return_value);
|
||||
}
|
||||
|
||||
//Config file path is given but not valid
|
||||
if !return_value.config_file_path.as_mut().unwrap().exists() {
|
||||
return Err(
|
||||
ConfigError::FileNotFoundError(String::from(return_value.config_file_path.as_mut()
|
||||
.unwrap().to_str().unwrap().clone()))
|
||||
);
|
||||
}
|
||||
|
||||
//Try to parse the config file if it exists
|
||||
//explode if it does exist but something's wrong
|
||||
//with it
|
||||
return_value.read_config()
|
||||
}
|
||||
|
||||
pub fn read_config(mut self) -> Result<GlobalConfig, ConfigError> {
|
||||
let mut file = File::open(self.config_file_path.as_mut().unwrap())?;
|
||||
let mut contents = String::new();
|
||||
file.read_to_string(&mut contents)?;
|
||||
let decoded:Result<ConfigMembers, toml::de::Error> = toml::from_str(&contents);
|
||||
match decoded {
|
||||
Ok(mut gc) => {
|
||||
//Put the struct back together, because the config
|
||||
//file was flattened a bit
|
||||
gc.server.mining_config = gc.mining.clone();
|
||||
self.using_config_file = true;
|
||||
self.members = Some(gc);
|
||||
return Ok(self)
|
||||
},
|
||||
Err (e) => {
|
||||
return Err(
|
||||
ConfigError::ParseError(String::from(self.config_file_path.as_mut()
|
||||
.unwrap().to_str().unwrap().clone()),
|
||||
String::from(format!("{}", e))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ser_config(&mut self) -> Result<String, ConfigError> {
|
||||
let encoded:Result<String, toml::ser::Error> = toml::to_string(self.members.as_mut().unwrap());
|
||||
match encoded {
|
||||
Ok(enc) => {
|
||||
return Ok(enc)
|
||||
},
|
||||
Err (e) => {
|
||||
return Err(
|
||||
ConfigError::SerializationError(
|
||||
String::from(format!("{}", e))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*pub fn wallet_enabled(&mut self) -> bool {
|
||||
return self.members.as_mut().unwrap().wallet.as_mut().unwrap().enable_wallet;
|
||||
}*/
|
||||
|
||||
pub fn mining_enabled(&mut self) -> bool {
|
||||
return self.members.as_mut().unwrap().mining.as_mut().unwrap().enable_mining;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_config() {
|
||||
let toml_str = r#"
|
||||
#Section is optional, if not here or enable_server is false, will only run wallet
|
||||
[server]
|
||||
enable_server = true
|
||||
api_http_addr = "127.0.0.1"
|
||||
db_root = "."
|
||||
seeding_type = "None"
|
||||
test_mode = false
|
||||
#7 = FULL_NODE, not sure how to serialise this properly to use constants
|
||||
capabilities = [7]
|
||||
|
||||
[server.p2p_config]
|
||||
host = "127.0.0.1"
|
||||
port = 13414
|
||||
|
||||
#Mining section is optional, if it's not here it will default to not mining
|
||||
[mining]
|
||||
enable_mining = true
|
||||
wallet_receiver_url = "http://127.0.0.1:13415"
|
||||
burn_reward = false
|
||||
#testing value, optional
|
||||
#slow_down_in_millis = 30
|
||||
#testing value, should really be removed and read from consensus instead, optional
|
||||
#cuckoo_size = 12
|
||||
|
||||
|
||||
"#;
|
||||
|
||||
let mut decoded: GlobalConfig = toml::from_str(toml_str).unwrap();
|
||||
decoded.server.as_mut().unwrap().mining_config = decoded.mining;
|
||||
println!("Decoded.server: {:?}", decoded.server);
|
||||
println!("Decoded wallet: {:?}", decoded.wallet);
|
||||
panic!("panic");
|
||||
}
|
36
config/src/lib.rs
Normal file
36
config/src/lib.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
// Copyright 2017 The Grin Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Crate wrapping up the Grin binary and configuration file
|
||||
|
||||
#![deny(non_upper_case_globals)]
|
||||
#![deny(non_camel_case_types)]
|
||||
#![deny(non_snake_case)]
|
||||
#![deny(unused_mut)]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate toml;
|
||||
|
||||
extern crate grin_grin as grin;
|
||||
extern crate grin_p2p as p2p;
|
||||
extern crate grin_wallet as wallet;
|
||||
|
||||
pub mod config;
|
||||
pub mod types;
|
||||
|
||||
pub use types::{GlobalConfig, ConfigMembers, ConfigError};
|
103
config/src/types.rs
Normal file
103
config/src/types.rs
Normal file
|
@ -0,0 +1,103 @@
|
|||
// Copyright 2017 The Grin Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Public types for config modules
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::io;
|
||||
use std::fmt;
|
||||
|
||||
use grin::{ServerConfig,
|
||||
MinerConfig};
|
||||
use wallet::WalletConfig;
|
||||
|
||||
|
||||
/// Error type wrapping config errors.
|
||||
#[derive(Debug)]
|
||||
pub enum ConfigError {
|
||||
/// Error with parsing of config file
|
||||
ParseError (String, String),
|
||||
|
||||
/// Error with fileIO while reading config file
|
||||
FileIOError (String, String),
|
||||
|
||||
/// No file found
|
||||
FileNotFoundError (String),
|
||||
|
||||
/// Error serializing config values
|
||||
SerializationError (String),
|
||||
}
|
||||
|
||||
impl fmt::Display for ConfigError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
ConfigError::ParseError(ref file_name, ref message) => {
|
||||
write!(f, "Error parsing configuration file at {} - {}",file_name, message)
|
||||
}
|
||||
ConfigError::FileIOError(ref file_name, ref message) => {
|
||||
write!(f, "{} {}", message, file_name)
|
||||
}
|
||||
ConfigError::FileNotFoundError(ref file_name) => {
|
||||
write!(f, "Configuration file not found: {}", file_name)
|
||||
}
|
||||
ConfigError::SerializationError(ref message) => {
|
||||
write!(f, "Error serializing configuration: {}", message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for ConfigError {
|
||||
fn from(error: io::Error) -> ConfigError {
|
||||
ConfigError::FileIOError(
|
||||
String::from(""),
|
||||
String::from(format!("Error loading config file: {}",error)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Going to hold all of the various configuration types
|
||||
/// separately for now, then put them together as a single
|
||||
/// ServerConfig object afterwards. This is to flatten
|
||||
/// out the configuration file into logical sections,
|
||||
/// as they tend to be quite nested in the code
|
||||
/// Most structs optional, as they may or may not
|
||||
/// be needed depending on what's being run
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GlobalConfig {
|
||||
//Keep track of the file we've read
|
||||
pub config_file_path: Option<PathBuf>,
|
||||
//keep track of whether we're using
|
||||
//a config file or just the defaults
|
||||
//for each member
|
||||
pub using_config_file: bool,
|
||||
pub members: Option<ConfigMembers>,
|
||||
}
|
||||
|
||||
/// Keeping an 'inner' structure here, as the top
|
||||
/// level GlobalConfigContainer options might want to keep
|
||||
/// internal state that we don't necessarily
|
||||
/// want serialised or deserialised
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ConfigMembers {
|
||||
pub server: ServerConfig,
|
||||
pub mining: Option<MinerConfig>,
|
||||
//removing wallet from here for now,
|
||||
//as its concerns are separate from the server's, really
|
||||
//given it needs to manage keys. It should probably
|
||||
//stay command line only for the time being
|
||||
//pub wallet: Option<WalletConfig>
|
||||
}
|
60
grin.toml
Normal file
60
grin.toml
Normal file
|
@ -0,0 +1,60 @@
|
|||
# Sample Server Configuration File for Grin
|
||||
#
|
||||
# When running the grin executable without specifying any command line
|
||||
# arguments, it will look for this file in three places, in the following
|
||||
# order:
|
||||
#
|
||||
# -The working directory
|
||||
# -The directory in which the executable resides
|
||||
# -[user home]/.grin
|
||||
#
|
||||
|
||||
#Server connection details
|
||||
[server]
|
||||
|
||||
#the address on which services will listen, e.g. Transaction Pool
|
||||
api_http_addr = "127.0.0.1:13413"
|
||||
|
||||
#the directory, relative to current, in which the grin blockchain
|
||||
#is stored
|
||||
db_root = ".grin"
|
||||
|
||||
#How to seed this server, can be None, List or WebStatic
|
||||
seeding_type = "None"
|
||||
|
||||
#if seeding_type = List, the list of peers to connect to.
|
||||
#seeds = ["192.168.0.1:8080","192.168.0.2:8080"]
|
||||
|
||||
#Whether to run in test mode, which at the moment affects cuckoo_size
|
||||
#if this is false tries to use a slow cuckoo30 at the moment, not
|
||||
#recommended
|
||||
test_mode = true
|
||||
|
||||
#7 = Bit flags for FULL_NODE, this structure needs to be changed
|
||||
#internally to make it more configurable
|
||||
capabilities = [7]
|
||||
|
||||
#The P2P server details (i.e. the server that communicates with other
|
||||
#grin server nodes
|
||||
[server.p2p_config]
|
||||
host = "127.0.0.1"
|
||||
port = 13414
|
||||
|
||||
#Mining details. This section is optional. If it's not here, the server
|
||||
#will default to not mining.
|
||||
|
||||
[mining]
|
||||
#flag whether mining is enabled
|
||||
enable_mining = true
|
||||
|
||||
#the wallet reciever to which coinbase rewards will be sent
|
||||
wallet_receiver_url = "http://127.0.0.1:13415"
|
||||
|
||||
#whether to ignore the reward (mostly for testing)
|
||||
burn_reward = true
|
||||
|
||||
#testing value, optional
|
||||
#slow_down_in_millis = 30
|
||||
|
||||
#testing value, should really be removed and read from consensus instead, optional
|
||||
#cuckoo_size = 12
|
|
@ -95,14 +95,15 @@ impl Miner {
|
|||
let mut sol = None;
|
||||
debug!("(Server ID: {}) Mining at Cuckoo{} for at most 2 secs on block {} at difficulty {}.",
|
||||
self.debug_output_id,
|
||||
self.config.cuckoo_size,
|
||||
self.config.cuckoo_size.unwrap(),
|
||||
latest_hash,
|
||||
b.header.difficulty);
|
||||
let mut iter_count = 0;
|
||||
if self.config.slow_down_in_millis > 0 {
|
||||
|
||||
if self.config.slow_down_in_millis != None && self.config.slow_down_in_millis.unwrap() > 0 {
|
||||
debug!("(Server ID: {}) Artificially slowing down loop by {}ms per iteration.",
|
||||
self.debug_output_id,
|
||||
self.config.slow_down_in_millis);
|
||||
self.config.slow_down_in_millis.unwrap());
|
||||
}
|
||||
while head.hash() == latest_hash && time::get_time().sec < deadline {
|
||||
let pow_hash = b.hash();
|
||||
|
@ -123,8 +124,8 @@ impl Miner {
|
|||
iter_count += 1;
|
||||
|
||||
//Artificial slow down
|
||||
if self.config.slow_down_in_millis > 0 {
|
||||
thread::sleep(std::time::Duration::from_millis(self.config.slow_down_in_millis));
|
||||
if self.config.slow_down_in_millis != None && self.config.slow_down_in_millis.unwrap() > 0 {
|
||||
thread::sleep(std::time::Duration::from_millis(self.config.slow_down_in_millis.unwrap()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,7 +134,7 @@ impl Miner {
|
|||
info!("(Server ID: {}) Found valid proof of work, adding block {}.",
|
||||
self.debug_output_id, b.hash());
|
||||
b.header.pow = proof;
|
||||
let opts = if self.config.cuckoo_size < consensus::DEFAULT_SIZESHIFT as u32 {
|
||||
let opts = if self.config.cuckoo_size.unwrap() < consensus::DEFAULT_SIZESHIFT as u32 {
|
||||
chain::EASY_POW
|
||||
} else {
|
||||
chain::NONE
|
||||
|
|
|
@ -62,10 +62,10 @@ impl Server {
|
|||
check_config(&mut config);
|
||||
let mut evtlp = reactor::Core::new().unwrap();
|
||||
|
||||
let mining_config = config.mining_config.clone();
|
||||
let mut mining_config = config.mining_config.clone();
|
||||
let serv = Server::future(config, &evtlp.handle())?;
|
||||
if mining_config.enable_mining {
|
||||
serv.start_miner(mining_config);
|
||||
if mining_config.as_mut().unwrap().enable_mining {
|
||||
serv.start_miner(mining_config.unwrap());
|
||||
}
|
||||
|
||||
let forever = Timer::default()
|
||||
|
@ -99,14 +99,14 @@ impl Server {
|
|||
tx_pool.clone(),
|
||||
peer_store.clone()));
|
||||
let p2p_server =
|
||||
Arc::new(p2p::Server::new(config.capabilities, config.p2p_config, net_adapter.clone()));
|
||||
Arc::new(p2p::Server::new(config.capabilities, config.p2p_config.unwrap(), net_adapter.clone()));
|
||||
chain_adapter.init(p2p_server.clone());
|
||||
|
||||
let seed = seed::Seeder::new(config.capabilities, peer_store.clone(), p2p_server.clone());
|
||||
match config.seeding_type.clone() {
|
||||
Seeding::None => {}
|
||||
Seeding::List(seeds) => {
|
||||
seed.connect_and_monitor(evt_handle.clone(), seed::predefined_seeds(seeds));
|
||||
Seeding::List => {
|
||||
seed.connect_and_monitor(evt_handle.clone(), seed::predefined_seeds(config.seeds.as_mut().unwrap().clone()));
|
||||
}
|
||||
Seeding::WebStatic => {
|
||||
seed.connect_and_monitor(evt_handle.clone(), seed::web_seeds(evt_handle.clone()));
|
||||
|
@ -150,9 +150,9 @@ impl Server {
|
|||
#[cfg(not(feature = "use-cuckoo-miner"))]
|
||||
pub fn start_miner(&self, config: MinerConfig) {
|
||||
let mut miner = miner::Miner::new(config.clone(), self.chain.clone(), self.tx_pool.clone());
|
||||
miner.set_debug_output_id(format!("Port {}",self.config.p2p_config.port));
|
||||
miner.set_debug_output_id(format!("Port {}",self.config.p2p_config.unwrap().port));
|
||||
thread::spawn(move || {
|
||||
let test_cuckoo_miner = cuckoo::Miner::new(consensus::EASINESS, config.cuckoo_size.clone());
|
||||
let test_cuckoo_miner = cuckoo::Miner::new(consensus::EASINESS, config.cuckoo_size.unwrap().clone());
|
||||
miner.run_loop(test_cuckoo_miner);
|
||||
});
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ impl Server {
|
|||
let mut miner = miner::Miner::new(config.clone(), self.chain.clone(), self.tx_pool.clone());
|
||||
miner.set_debug_output_id(format!("Port {}",self.config.p2p_config.port));
|
||||
thread::spawn(move || {
|
||||
let test_cuckoo_miner = PluginMiner::new(consensus::EASINESS, config.cuckoo_size.clone());
|
||||
let test_cuckoo_miner = PluginMiner::new(consensus::EASINESS, config.cuckoo_size.unwrap().clone());
|
||||
miner.run_loop(test_cuckoo_miner);
|
||||
});
|
||||
}
|
||||
|
@ -186,9 +186,9 @@ impl Server {
|
|||
|
||||
fn check_config(config: &mut ServerConfig) {
|
||||
// applying test/normal config
|
||||
config.mining_config.cuckoo_size = if config.test_mode {
|
||||
consensus::TEST_SIZESHIFT as u32
|
||||
config.mining_config.as_mut().unwrap().cuckoo_size = if config.test_mode {
|
||||
Some(consensus::TEST_SIZESHIFT as u32)
|
||||
} else {
|
||||
consensus::DEFAULT_SIZESHIFT as u32
|
||||
Some(consensus::DEFAULT_SIZESHIFT as u32)
|
||||
};
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ pub enum Seeding {
|
|||
/// No seeding, mostly for tests that programmatically connect
|
||||
None,
|
||||
/// A list of seed addresses provided to the server
|
||||
List(Vec<String>),
|
||||
List,
|
||||
/// Automatically download a text file with a list of server addresses
|
||||
WebStatic,
|
||||
}
|
||||
|
@ -77,21 +77,24 @@ pub struct ServerConfig {
|
|||
/// Network address for the Rest API HTTP server.
|
||||
pub api_http_addr: String,
|
||||
|
||||
/// Setup the server for tests and testnet
|
||||
pub test_mode: bool,
|
||||
|
||||
/// Method used to get the list of seed nodes for initial bootstrap.
|
||||
pub seeding_type: Seeding,
|
||||
|
||||
/// The list of seed nodes, if using Seeding as a seed type
|
||||
pub seeds: Option<Vec<String>>,
|
||||
|
||||
/// 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,
|
||||
pub p2p_config: Option<p2p::P2PConfig>,
|
||||
|
||||
/// Configuration for the mining daemon
|
||||
pub mining_config: MinerConfig,
|
||||
|
||||
/// Setup the server for tests and testnet
|
||||
pub test_mode: bool,
|
||||
pub mining_config: Option<MinerConfig>,
|
||||
}
|
||||
|
||||
/// Mining configuration
|
||||
|
@ -109,10 +112,10 @@ pub struct MinerConfig {
|
|||
|
||||
/// a testing attribute for the time being that artifically slows down the
|
||||
/// mining loop by adding a sleep to the thread
|
||||
pub slow_down_in_millis: u64,
|
||||
pub slow_down_in_millis: Option<u64>,
|
||||
|
||||
/// Size of Cuckoo Cycle to mine on
|
||||
pub cuckoo_size: u32,
|
||||
pub cuckoo_size: Option<u32>,
|
||||
|
||||
|
||||
}
|
||||
|
@ -124,8 +127,9 @@ impl Default for ServerConfig {
|
|||
api_http_addr: "127.0.0.1:13415".to_string(),
|
||||
capabilities: p2p::FULL_NODE,
|
||||
seeding_type: Seeding::None,
|
||||
p2p_config: p2p::P2PConfig::default(),
|
||||
mining_config: MinerConfig::default(),
|
||||
seeds: None,
|
||||
p2p_config: Some(p2p::P2PConfig::default()),
|
||||
mining_config: Some(MinerConfig::default()),
|
||||
test_mode: true,
|
||||
}
|
||||
}
|
||||
|
@ -137,8 +141,8 @@ impl Default for MinerConfig {
|
|||
enable_mining: false,
|
||||
wallet_receiver_url: "http://localhost:13416".to_string(),
|
||||
burn_reward: false,
|
||||
slow_down_in_millis: 0,
|
||||
cuckoo_size: 0
|
||||
slow_down_in_millis: Some(0),
|
||||
cuckoo_size: Some(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -203,9 +203,11 @@ impl LocalServerContainer {
|
|||
let api_addr = format!("{}:{}", self.config.base_addr, self.config.api_server_port);
|
||||
|
||||
let mut seeding_type=grin::Seeding::None;
|
||||
let mut seeds=Vec::new();
|
||||
|
||||
if self.config.seed_addr.len()>0{
|
||||
seeding_type=grin::Seeding::List(vec![self.config.seed_addr.to_string()]);
|
||||
seeding_type=grin::Seeding::List;
|
||||
seeds=vec![self.config.seed_addr.to_string()];
|
||||
}
|
||||
|
||||
|
||||
|
@ -213,7 +215,8 @@ impl LocalServerContainer {
|
|||
grin::ServerConfig{
|
||||
api_http_addr: api_addr,
|
||||
db_root: format!("{}/.grin", self.working_dir),
|
||||
p2p_config: p2p::P2PConfig{port: self.config.p2p_server_port, ..p2p::P2PConfig::default()},
|
||||
p2p_config: Some(p2p::P2PConfig{port: self.config.p2p_server_port, ..p2p::P2PConfig::default()}),
|
||||
seeds: Some(seeds),
|
||||
seeding_type: seeding_type,
|
||||
..Default::default()
|
||||
}, &event_loop.handle()).unwrap();
|
||||
|
@ -229,9 +232,9 @@ impl LocalServerContainer {
|
|||
let mut miner_config = grin::MinerConfig {
|
||||
enable_mining: self.config.start_miner,
|
||||
burn_reward: self.config.burn_mining_rewards,
|
||||
cuckoo_size: self.config.cuckoo_size,
|
||||
cuckoo_size: Some(self.config.cuckoo_size),
|
||||
wallet_receiver_url : self.config.coinbase_wallet_address.clone(),
|
||||
slow_down_in_millis: self.config.miner_slowdown_in_millis.clone(),
|
||||
slow_down_in_millis: Some(self.config.miner_slowdown_in_millis.clone()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
|
|
@ -199,7 +199,7 @@ fn simulate_block_propagation() {
|
|||
let miner_config = grin::MinerConfig{
|
||||
enable_mining: true,
|
||||
burn_reward: true,
|
||||
cuckoo_size: consensus::TEST_SIZESHIFT as u32,
|
||||
cuckoo_size: Some(consensus::TEST_SIZESHIFT as u32),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -210,7 +210,7 @@ fn simulate_block_propagation() {
|
|||
grin::ServerConfig{
|
||||
api_http_addr: format!("127.0.0.1:{}", 20000+n),
|
||||
db_root: format!("target/{}/grin-prop-{}", test_name_dir, n),
|
||||
p2p_config: p2p::P2PConfig{port: 10000+n, ..p2p::P2PConfig::default()},
|
||||
p2p_config: Some(p2p::P2PConfig{port: 10000+n, ..p2p::P2PConfig::default()}),
|
||||
..Default::default()
|
||||
}, &handle).unwrap();
|
||||
servers.push(s);
|
||||
|
@ -256,7 +256,7 @@ fn simulate_full_sync() {
|
|||
let miner_config = grin::MinerConfig{
|
||||
enable_mining: true,
|
||||
burn_reward: true,
|
||||
cuckoo_size: consensus::TEST_SIZESHIFT as u32,
|
||||
cuckoo_size: Some(consensus::TEST_SIZESHIFT as u32),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -266,7 +266,7 @@ fn simulate_full_sync() {
|
|||
let s = grin::Server::future(
|
||||
grin::ServerConfig{
|
||||
db_root: format!("target/{}/grin-sync-{}", test_name_dir, n),
|
||||
p2p_config: p2p::P2PConfig{port: 11000+n, ..p2p::P2PConfig::default()},
|
||||
p2p_config: Some(p2p::P2PConfig{port: 11000+n, ..p2p::P2PConfig::default()}),
|
||||
..Default::default()
|
||||
}, &handle).unwrap();
|
||||
servers.push(s);
|
||||
|
|
|
@ -26,10 +26,9 @@ extern crate tiny_keccak;
|
|||
extern crate grin_api as api;
|
||||
extern crate grin_grin as grin;
|
||||
extern crate grin_wallet as wallet;
|
||||
extern crate grin_config as config;
|
||||
extern crate secp256k1zkp as secp;
|
||||
|
||||
const GRIN_HOME: &'static str = ".grin";
|
||||
|
||||
use std::env;
|
||||
use std::thread;
|
||||
use std::io::Read;
|
||||
|
@ -44,6 +43,16 @@ use secp::Secp256k1;
|
|||
|
||||
use wallet::WalletConfig;
|
||||
|
||||
use config::{GlobalConfig, ConfigError};
|
||||
|
||||
fn start_from_config_file(mut global_config:GlobalConfig){
|
||||
info!("Starting the Grin server from configuration file at {}", global_config.config_file_path.unwrap().to_str().unwrap());
|
||||
grin::Server::start(global_config.members.as_mut().unwrap().server.clone()).unwrap();
|
||||
loop {
|
||||
thread::sleep(Duration::from_secs(60));
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
env_logger::init().unwrap();
|
||||
|
||||
|
@ -80,12 +89,6 @@ fn main() {
|
|||
.long("wallet_url")
|
||||
.help("A listening wallet receiver to which mining rewards will be sent")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("config")
|
||||
.short("c")
|
||||
.long("config")
|
||||
.value_name("FILE.json")
|
||||
.help("Sets a custom json configuration file")
|
||||
.takes_value(true))
|
||||
.subcommand(SubCommand::with_name("start")
|
||||
.about("Start the Grin server as a daemon"))
|
||||
.subcommand(SubCommand::with_name("stop")
|
||||
|
@ -162,7 +165,34 @@ fn main() {
|
|||
wallet_command(wallet_args);
|
||||
}
|
||||
|
||||
_ => println!("Unknown command, use 'grin help' for a list of all commands"),
|
||||
//If nothing is specified, try to load up and use a config file instead
|
||||
//this should possibly become the way to configure most things
|
||||
//with most command line options being phased out
|
||||
_ => {
|
||||
//This will return a global config object,
|
||||
//which will either contain defaults for all
|
||||
//of the config structures or a configuration
|
||||
//read from a config file
|
||||
|
||||
let mut global_config = GlobalConfig::new(None);
|
||||
match global_config {
|
||||
Ok(gc) => {
|
||||
if (gc.using_config_file){
|
||||
start_from_config_file(gc);
|
||||
} else {
|
||||
//won't attempt to just start with defaults,
|
||||
//and will reject
|
||||
println!("Unknown command, and no configuration file was found.");
|
||||
println!("Use 'grin help' for a list of all commands.");
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,10 +203,11 @@ fn main() {
|
|||
fn server_command(server_args: &ArgMatches) {
|
||||
info!("Starting the Grin server...");
|
||||
|
||||
// configuration wrangling
|
||||
let mut server_config = read_config();
|
||||
// just get defaults from the global config
|
||||
let mut server_config = GlobalConfig::default().members.unwrap().server;
|
||||
|
||||
if let Some(port) = server_args.value_of("port") {
|
||||
server_config.p2p_config.port = port.parse().unwrap();
|
||||
server_config.p2p_config.as_mut().unwrap().port = port.parse().unwrap();
|
||||
}
|
||||
|
||||
if let Some(api_port) = server_args.value_of("api_port") {
|
||||
|
@ -185,17 +216,22 @@ fn server_command(server_args: &ArgMatches) {
|
|||
}
|
||||
|
||||
if server_args.is_present("mine") {
|
||||
server_config.mining_config.enable_mining = true;
|
||||
server_config.mining_config.as_mut().unwrap().enable_mining = true;
|
||||
}
|
||||
|
||||
if let Some(wallet_url) = server_args.value_of("wallet_url") {
|
||||
server_config.mining_config.wallet_receiver_url = wallet_url.to_string();
|
||||
server_config.mining_config.as_mut().unwrap().wallet_receiver_url = wallet_url.to_string();
|
||||
}
|
||||
|
||||
if let Some(seeds) = server_args.values_of("seed") {
|
||||
server_config.seeding_type = grin::Seeding::List(seeds.map(|s| s.to_string()).collect());
|
||||
server_config.seeding_type = grin::Seeding::List;
|
||||
server_config.seeds = Some(seeds.map(|s| s.to_string()).collect());
|
||||
}
|
||||
|
||||
/*let mut sc = GlobalConfig::default();
|
||||
sc.members.as_mut().unwrap().server = server_config.clone();
|
||||
println!("{}", sc.ser_config().unwrap());*/
|
||||
|
||||
// start the server in the different run modes (interactive or daemon)
|
||||
match server_args.subcommand() {
|
||||
("run", _) => {
|
||||
|
@ -291,22 +327,3 @@ fn wallet_command(wallet_args: &ArgMatches) {
|
|||
}
|
||||
}
|
||||
|
||||
fn read_config() -> grin::ServerConfig {
|
||||
let mut config_path = env::home_dir().ok_or("Failed to detect home directory!").unwrap();
|
||||
config_path.push(GRIN_HOME);
|
||||
if !config_path.exists() {
|
||||
return default_config();
|
||||
}
|
||||
let mut config_file = File::open(config_path).unwrap();
|
||||
let mut config_content = String::new();
|
||||
config_file.read_to_string(&mut config_content).unwrap();
|
||||
serde_json::from_str(config_content.as_str()).unwrap()
|
||||
}
|
||||
|
||||
fn default_config() -> grin::ServerConfig {
|
||||
grin::ServerConfig {
|
||||
test_mode: true,
|
||||
seeding_type: grin::Seeding::WebStatic,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,8 +76,10 @@ impl From<api::Error> for Error {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct WalletConfig {
|
||||
//Whether to run a wallet
|
||||
pub enable_wallet: bool,
|
||||
//The api address that this api server (i.e. this wallet) will run
|
||||
pub api_http_addr: String,
|
||||
//The api address of a running server node, against which transaction inputs will be checked
|
||||
|
@ -90,6 +92,7 @@ pub struct WalletConfig {
|
|||
impl Default for WalletConfig {
|
||||
fn default() -> WalletConfig {
|
||||
WalletConfig {
|
||||
enable_wallet: false,
|
||||
api_http_addr: "http://127.0.0.1:13415".to_string(),
|
||||
check_node_api_http_addr: "http://127.0.0.1:13415".to_string(),
|
||||
data_file_dir: ".".to_string(),
|
||||
|
|
Loading…
Reference in a new issue