Make grin.toml config optional (#1278)

* Make grin.toml config optional. Mirror exisiting config parameters in grin.toml to source code, so binary can run without a config file. Add test for it.
* fixup! Make grin.toml config optional
This commit is contained in:
Ivan Sorokin 2018-07-30 02:48:24 +02:00 committed by Ignotus Peverell
parent 61506a8064
commit 5c029e3f87
14 changed files with 114 additions and 99 deletions

View file

@ -38,5 +38,6 @@ env:
- TEST_DIR=keychain - TEST_DIR=keychain
- TEST_DIR=core - TEST_DIR=core
- TEST_DIR=util - TEST_DIR=util
- TEST_DIR=config
script: cd $TEST_DIR && cargo test --release script: cd $TEST_DIR && cargo test --release

17
Cargo.lock generated
View file

@ -381,6 +381,11 @@ dependencies = [
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "difference"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "dtoa" name = "dtoa"
version = "0.2.2" version = "0.2.2"
@ -619,6 +624,7 @@ dependencies = [
"grin_servers 0.3.0", "grin_servers 0.3.0",
"grin_util 0.3.0", "grin_util 0.3.0",
"grin_wallet 0.3.0", "grin_wallet 0.3.0",
"pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.69 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1426,6 +1432,15 @@ name = "podio"
version = "0.1.6" version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "pretty_assertions"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "prettytable-rs" name = "prettytable-rs"
version = "0.7.0" version = "0.7.0"
@ -2303,6 +2318,7 @@ dependencies = [
"checksum ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "630391922b1b893692c6334369ff528dcc3a9d8061ccf4c803aa8f83cb13db5e" "checksum ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "630391922b1b893692c6334369ff528dcc3a9d8061ccf4c803aa8f83cb13db5e"
"checksum cursive 0.8.2-alpha.0 (git+https://github.com/yeastplume/Cursive?tag=grin_integration_1)" = "<none>" "checksum cursive 0.8.2-alpha.0 (git+https://github.com/yeastplume/Cursive?tag=grin_integration_1)" = "<none>"
"checksum daemonize 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4093d27eb267d617f03c2ee25d4c3ca525b89a76154001954a11984508ffbde5" "checksum daemonize 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4093d27eb267d617f03c2ee25d4c3ca525b89a76154001954a11984508ffbde5"
"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
"checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d" "checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d"
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
@ -2394,6 +2410,7 @@ dependencies = [
"checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f" "checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f"
"checksum plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a6a0dc3910bc8db877ffed8e457763b317cf880df4ae19109b9f77d277cf6e0" "checksum plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a6a0dc3910bc8db877ffed8e457763b317cf880df4ae19109b9f77d277cf6e0"
"checksum podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd" "checksum podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd"
"checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6"
"checksum prettytable-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5511ca4c805aa35f0abff6be7923231d664408b60c09f44ef715f2bce106cd9e" "checksum prettytable-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5511ca4c805aa35f0abff6be7923231d664408b60c09f44ef715f2bce106cd9e"
"checksum proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4" "checksum proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4"
"checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6" "checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6"

View file

@ -14,3 +14,6 @@ grin_servers = { path = "../servers" }
grin_p2p = { path = "../p2p" } grin_p2p = { path = "../p2p" }
grin_util = { path = "../util" } grin_util = { path = "../util" }
grin_wallet = { path = "../wallet"} grin_wallet = { path = "../wallet"}
[dev-dependencies]
pretty_assertions = "0.5.1"

View file

@ -48,7 +48,6 @@ impl Default for GlobalConfig {
fn default() -> GlobalConfig { fn default() -> GlobalConfig {
GlobalConfig { GlobalConfig {
config_file_path: None, config_file_path: None,
using_config_file: false,
members: Some(ConfigMembers::default()), members: Some(ConfigMembers::default()),
} }
} }
@ -112,7 +111,7 @@ impl GlobalConfig {
))); )));
} }
// Try to parse the config file if it exists explode if it does exist but // Try to parse the config file if it exists, explode if it does exist but
// something's wrong with it // something's wrong with it
return_value.read_config() return_value.read_config()
} }
@ -128,7 +127,6 @@ impl GlobalConfig {
// Put the struct back together, because the config // Put the struct back together, because the config
// file was flattened a bit // file was flattened a bit
gc.server.stratum_mining_config = gc.mining_server.clone(); gc.server.stratum_mining_config = gc.mining_server.clone();
self.using_config_file = true;
self.members = Some(gc); self.members = Some(gc);
return Ok(self); return Ok(self);
} }

View file

@ -75,14 +75,10 @@ impl From<io::Error> for ConfigError {
/// as they tend to be quite nested in the code /// as they tend to be quite nested in the code
/// Most structs optional, as they may or may not /// Most structs optional, as they may or may not
/// be needed depending on what's being run /// be needed depending on what's being run
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct GlobalConfig { pub struct GlobalConfig {
/// Keep track of the file we've read /// Keep track of the file we've read
pub config_file_path: Option<PathBuf>, 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,
/// Global member config /// Global member config
pub members: Option<ConfigMembers>, pub members: Option<ConfigMembers>,
} }
@ -91,7 +87,7 @@ pub struct GlobalConfig {
/// level GlobalConfigContainer options might want to keep /// level GlobalConfigContainer options might want to keep
/// internal state that we don't necessarily /// internal state that we don't necessarily
/// want serialised or deserialised /// want serialised or deserialised
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct ConfigMembers { pub struct ConfigMembers {
/// Server config /// Server config
#[serde(default)] #[serde(default)]

20
config/tests/config.rs Normal file
View file

@ -0,0 +1,20 @@
#[macro_use]
extern crate pretty_assertions;
extern crate grin_config as config;
use config::GlobalConfig;
#[test]
fn file_config_equal_to_defaults() {
let x = true;
let global_config_without_file = GlobalConfig::default();
let global_config_with_file = GlobalConfig::new(Some("../grin.toml")).unwrap_or_else(|e| {
panic!("Error parsing config file: {}", e);
});
assert_eq!(
global_config_without_file.members,
global_config_with_file.members
);
}

View file

@ -83,7 +83,7 @@ pub enum ChainTypes {
impl Default for ChainTypes { impl Default for ChainTypes {
fn default() -> ChainTypes { fn default() -> ChainTypes {
ChainTypes::UserTesting ChainTypes::Testnet3
} }
} }
@ -245,11 +245,11 @@ where
} }
let mut interval_index = live_intervals.len() - 1; let mut interval_index = live_intervals.len() - 1;
let mut last_ts = last_n.first().as_ref().unwrap().as_ref().unwrap().0; let mut last_ts = last_n.first().as_ref().unwrap().as_ref().unwrap().0;
let last_diff = live_intervals[live_intervals.len()-1].1; let last_diff = live_intervals[live_intervals.len() - 1].1;
// fill in simulated blocks with values from the previous real block // fill in simulated blocks with values from the previous real block
for _ in 0..block_count_difference { for _ in 0..block_count_difference {
last_ts = last_ts.saturating_sub(live_intervals[live_intervals.len()-1].0); last_ts = last_ts.saturating_sub(live_intervals[live_intervals.len() - 1].0);
last_n.insert(0, Ok((last_ts, last_diff.clone()))); last_n.insert(0, Ok((last_ts, last_diff.clone())));
interval_index = match interval_index { interval_index = match interval_index {
0 => live_intervals.len() - 1, 0 => live_intervals.len() - 1,

View file

@ -149,7 +149,7 @@ api_listen_interface = "127.0.0.1"
api_listen_port = 13415 api_listen_port = 13415
# Where the wallet should find a running node # Where the wallet should find a running node
check_node_api_http_addr = "http://localhost:13413" check_node_api_http_addr = "http://127.0.0.1:13413"
# Where to find wallet files (seed, data, etc) # Where to find wallet files (seed, data, etc)
data_file_dir = "." data_file_dir = "."

View file

@ -90,7 +90,7 @@ impl<T> From<mpsc::TrySendError<T>> for Error {
} }
/// Configuration for the peer-to-peer server. /// Configuration for the peer-to-peer server.
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct P2PConfig { pub struct P2PConfig {
pub host: IpAddr, pub host: IpAddr,
pub port: u16, pub port: u16,
@ -115,9 +115,9 @@ impl Default for P2PConfig {
port: 13414, port: 13414,
peers_allow: None, peers_allow: None,
peers_deny: None, peers_deny: None,
ban_window: Some(BAN_WINDOW), ban_window: None,
peer_max_count: Some(PEER_MAX_COUNT), peer_max_count: None,
peer_min_preferred_count: Some(PEER_MIN_PREFERRED_COUNT), peer_min_preferred_count: None,
} }
} }
} }
@ -266,12 +266,7 @@ pub trait ChainAdapter: Sync + Send {
/// If we're willing to accept that new state, the data stream will be /// If we're willing to accept that new state, the data stream will be
/// read as a zip file, unzipped and the resulting state files should be /// read as a zip file, unzipped and the resulting state files should be
/// rewound to the provided indexes. /// rewound to the provided indexes.
fn txhashset_write( fn txhashset_write(&self, h: Hash, txhashset_data: File, peer_addr: SocketAddr) -> bool;
&self,
h: Hash,
txhashset_data: File,
peer_addr: SocketAddr,
) -> bool;
} }
/// Additional methods required by the protocol that don't need to be /// Additional methods required by the protocol that don't need to be

View file

@ -35,7 +35,7 @@ const DANDELION_STEM_PROBABILITY: usize = 90;
/// Configuration for "Dandelion". /// Configuration for "Dandelion".
/// Note: shared between p2p and pool. /// Note: shared between p2p and pool.
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct DandelionConfig { pub struct DandelionConfig {
/// Choose new Dandelion relay peer every n secs. /// Choose new Dandelion relay peer every n secs.
#[serde = "default_dandelion_relay_secs"] #[serde = "default_dandelion_relay_secs"]
@ -81,7 +81,7 @@ fn default_dandelion_stem_probability() -> Option<usize> {
} }
/// Transaction pool configuration /// Transaction pool configuration
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct PoolConfig { pub struct PoolConfig {
/// Base fee for a transaction to be accepted by the pool. The transaction /// Base fee for a transaction to be accepted by the pool. The transaction
/// weight is computed from its number of inputs, outputs and kernels and /// weight is computed from its number of inputs, outputs and kernels and

View file

@ -126,7 +126,7 @@ impl Default for Seeding {
/// Full server configuration, aggregating configurations required for the /// Full server configuration, aggregating configurations required for the
/// different components. /// different components.
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ServerConfig { pub struct ServerConfig {
/// Directory under which the rocksdb stores will be created /// Directory under which the rocksdb stores will be created
pub db_root: String, pub db_root: String,
@ -200,7 +200,7 @@ impl Default for ServerConfig {
fn default() -> ServerConfig { fn default() -> ServerConfig {
ServerConfig { ServerConfig {
db_root: ".grin".to_string(), db_root: ".grin".to_string(),
api_http_addr: "0.0.0.0:13413".to_string(), api_http_addr: "127.0.0.1:13413".to_string(),
capabilities: p2p::Capabilities::FULL_NODE, capabilities: p2p::Capabilities::FULL_NODE,
seeding_type: Seeding::default(), seeding_type: Seeding::default(),
seeds: None, seeds: None,
@ -211,11 +211,11 @@ impl Default for ServerConfig {
archive_mode: None, archive_mode: None,
chain_validation_mode: ChainValidationMode::default(), chain_validation_mode: ChainValidationMode::default(),
pool_config: pool::PoolConfig::default(), pool_config: pool::PoolConfig::default(),
skip_sync_wait: None, skip_sync_wait: Some(false),
run_tui: None, run_tui: Some(true),
run_wallet_listener: Some(false), run_wallet_listener: Some(true),
run_wallet_owner_api: Some(false), run_wallet_owner_api: Some(true),
use_db_wallet: Some(false), use_db_wallet: None,
run_test_miner: Some(false), run_test_miner: Some(false),
test_miner_wallet_url: None, test_miner_wallet_url: None,
} }
@ -223,7 +223,7 @@ impl Default for ServerConfig {
} }
/// Stratum (Mining server) configuration /// Stratum (Mining server) configuration
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct StratumServerConfig { pub struct StratumServerConfig {
/// Run a stratum mining server (the only way to communicate to mine this /// Run a stratum mining server (the only way to communicate to mine this
/// node via grin-miner /// node via grin-miner
@ -250,12 +250,12 @@ pub struct StratumServerConfig {
impl Default for StratumServerConfig { impl Default for StratumServerConfig {
fn default() -> StratumServerConfig { fn default() -> StratumServerConfig {
StratumServerConfig { StratumServerConfig {
wallet_listener_url: "http://localhost:13415".to_string(), wallet_listener_url: "http://127.0.0.1:13415".to_string(),
burn_reward: false, burn_reward: false,
attempt_time_per_block: <u32>::max_value(), attempt_time_per_block: 15,
minimum_share_difficulty: 1, minimum_share_difficulty: 1,
enable_stratum_server: None, enable_stratum_server: Some(true),
stratum_server_addr: None, stratum_server_addr: Some("127.0.0.1:13416".to_string()),
} }
} }
} }

View file

@ -52,7 +52,7 @@ use config::GlobalConfig;
use core::core::amount_to_hr_string; use core::core::amount_to_hr_string;
use core::global; use core::global;
use tui::ui; use tui::ui;
use util::{init_logger, LoggingConfig, LOGGER}; use util::{init_logger, LOGGER};
use wallet::{libwallet, HTTPWalletClient, LMDBBackend, WalletConfig, WalletInst}; use wallet::{libwallet, HTTPWalletClient, LMDBBackend, WalletConfig, WalletInst};
// include build information // include build information
@ -333,33 +333,39 @@ fn main() {
panic!("Error parsing config file: {}", e); panic!("Error parsing config file: {}", e);
}); });
if global_config.using_config_file { if let Some(file_path) = &global_config.config_file_path {
// initialize the logger info!(
let mut log_conf = global_config LOGGER,
"Found configuration file at {}",
file_path.to_str().unwrap()
);
} else {
info!(LOGGER, "configuration file not found, using default");
}
// initialize the logger
let mut log_conf = global_config
.members
.as_mut()
.unwrap()
.logging
.clone()
.unwrap();
let run_tui = global_config.members.as_mut().unwrap().server.run_tui;
if run_tui.is_some() && run_tui.unwrap() && args.subcommand().0 != "wallet" {
log_conf.log_to_stdout = false;
log_conf.tui_running = Some(true);
}
init_logger(Some(log_conf));
global::set_mining_mode(
global_config
.members .members
.as_mut() .as_mut()
.unwrap() .unwrap()
.logging .server
.clone() .clone()
.unwrap(); .chain_type,
let run_tui = global_config.members.as_mut().unwrap().server.run_tui; );
if run_tui.is_some() && run_tui.unwrap() && args.subcommand().0 != "wallet" {
log_conf.log_to_stdout = false;
log_conf.tui_running = Some(true);
}
init_logger(Some(log_conf));
global::set_mining_mode(
global_config
.members
.as_mut()
.unwrap()
.server
.clone()
.chain_type,
);
} else {
init_logger(Some(LoggingConfig::default()));
}
log_build_info(); log_build_info();
@ -383,14 +389,7 @@ fn main() {
// this could possibly become the way to configure most things // this could possibly become the way to configure most things
// with most command line options being phased out // with most command line options being phased out
_ => { _ => {
if global_config.using_config_file { server_command(None, global_config);
server_command(None, global_config);
} 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.");
}
} }
} }
} }
@ -400,29 +399,15 @@ fn main() {
/// arguments /// arguments
/// to build a proper configuration and runs Grin with that configuration. /// to build a proper configuration and runs Grin with that configuration.
fn server_command(server_args: Option<&ArgMatches>, mut global_config: GlobalConfig) { fn server_command(server_args: Option<&ArgMatches>, mut global_config: GlobalConfig) {
if global_config.using_config_file { global::set_mining_mode(
info!( global_config
LOGGER, .members
"Starting the Grin server from configuration file at {}", .as_mut()
global_config .unwrap()
.config_file_path .server
.as_ref() .clone()
.unwrap() .chain_type,
.to_str() );
.unwrap()
);
global::set_mining_mode(
global_config
.members
.as_mut()
.unwrap()
.server
.clone()
.chain_type,
);
} else {
panic!("No configuration found.");
}
// just get defaults from the global config // just get defaults from the global config
let mut server_config = global_config.members.as_ref().unwrap().server.clone(); let mut server_config = global_config.members.as_ref().unwrap().server.clone();

View file

@ -15,7 +15,7 @@
//! Logging configuration types //! Logging configuration types
/// Log level types, as slog's don't implement serialize /// Log level types, as slog's don't implement serialize
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum LogLevel { pub enum LogLevel {
/// Critical /// Critical
Critical, Critical,
@ -32,7 +32,7 @@ pub enum LogLevel {
} }
/// Logging config /// Logging config
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct LoggingConfig { pub struct LoggingConfig {
/// whether to log to stdout /// whether to log to stdout
pub log_to_stdout: bool, pub log_to_stdout: bool,
@ -54,11 +54,11 @@ impl Default for LoggingConfig {
fn default() -> LoggingConfig { fn default() -> LoggingConfig {
LoggingConfig { LoggingConfig {
log_to_stdout: true, log_to_stdout: true,
stdout_log_level: LogLevel::Debug, stdout_log_level: LogLevel::Warning,
log_to_file: false, log_to_file: true,
file_log_level: LogLevel::Trace, file_log_level: LogLevel::Debug,
log_file_path: String::from("grin.log"), log_file_path: String::from("grin.log"),
log_file_append: false, log_file_append: true,
tui_running: None, tui_running: None,
} }
} }

View file

@ -29,7 +29,7 @@ use util::LOGGER;
pub const SEED_FILE: &'static str = "wallet.seed"; pub const SEED_FILE: &'static str = "wallet.seed";
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct WalletConfig { pub struct WalletConfig {
// Right now the decision to run or not a wallet is based on the command. // Right now the decision to run or not a wallet is based on the command.
// This may change in the near-future. // This may change in the near-future.