mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 08:51:08 +03:00
Config + Default directories (#1433)
* config file can now be generated by executable * rustfmt * remove now-unnecessary config defaults test * set up paths and config file creation in user's home directory * rustfmt * remove default grin.toml * add grin configuration command to spit out config file * Split configuration into wallet and server * rustfmt * Restore logging to wallet configurations * rustfmt
This commit is contained in:
parent
471e80e69e
commit
1ded3f3972
19 changed files with 955 additions and 381 deletions
469
config/src/comments.rs
Normal file
469
config/src/comments.rs
Normal file
|
@ -0,0 +1,469 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
//! Comments for configuration + injection into output .toml
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// maps entries to Comments that should preceed them
|
||||
fn comments() -> HashMap<String, String> {
|
||||
let mut retval = HashMap::new();
|
||||
retval.insert(
|
||||
"[server]".to_string(),
|
||||
"
|
||||
# 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 CONFIGURATION ###
|
||||
#########################################
|
||||
|
||||
#Server connection details
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"api_http_addr".to_string(),
|
||||
"
|
||||
#the address on which services will listen, e.g. Transaction Pool
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"db_root".to_string(),
|
||||
"
|
||||
#the directory, relative to current, in which the grin blockchain
|
||||
#is stored
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"chain_type".to_string(),
|
||||
"
|
||||
#The chain type, which defines the genesis block and the set of cuckoo
|
||||
#parameters used for mining. Can be:
|
||||
#AutomatedTesting - For CI builds and instant blockchain creation
|
||||
#UserTesting - For regular user testing (cuckoo 16)
|
||||
#Testnet1 - Testnet1 genesis block (cuckoo 16)
|
||||
#Testnet2 - Testnet2 genesis block (cuckoo 30)
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"chain_validation_mode".to_string(),
|
||||
"
|
||||
#The chain validation mode, defines how often (if at all) we
|
||||
#want to run a full chain validation. Can be:
|
||||
#\"EveryBlock\" - run full chain validation when processing each block (except during sync)
|
||||
#\"Disabled\" - disable full chain validation (just run regular block validation)
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"archive_mode".to_string(),
|
||||
"
|
||||
#run the node in \"full archive\" mode (default is fast-sync, pruned node)
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"skip_sync_wait".to_string(),
|
||||
"
|
||||
#skip waiting for sync on startup, (optional param, mostly for testing)
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"run_tui".to_string(),
|
||||
"
|
||||
#whether to run the ncurses TUI. Ncurses must be installed and this
|
||||
#will also disable logging to stdout
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"run_wallet_listener".to_string(),
|
||||
"
|
||||
#Whether to run the wallet listener with the server by default
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"run_wallet_owner_api".to_string(),
|
||||
"
|
||||
# Whether to run the web-wallet API (will only run on localhost)
|
||||
# grin wallet web will run this automatically, so this should
|
||||
# only be set to true for test/development purposes
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"run_test_miner".to_string(),
|
||||
"
|
||||
#Whether to run a test miner. This is only for developer testing (chaintype
|
||||
#usertesting) at cuckoo 16, and will only mine into the default wallet port.
|
||||
#real mining should use the standalone grin-miner
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"[server.dandelion_config]".to_string(),
|
||||
"
|
||||
#########################################
|
||||
### DANDELION CONFIGURATION ###
|
||||
#########################################
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"relay_secs".to_string(),
|
||||
"
|
||||
#dandelion relay time (choose new relay peer every n secs)
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"embargo_secs".to_string(),
|
||||
"
|
||||
#fluff and broadcast after embargo expires if tx not seen on network
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"patience_secs".to_string(),
|
||||
"
|
||||
#run dandelion stem/fluff processing every n secs (stem tx aggregation in this window)
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
retval.insert(
|
||||
"stem_probability".to_string(),
|
||||
"
|
||||
#dandelion stem probability (stem 90% of the time, fluff 10% of the time)
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"[server.p2p_config]".to_string(),
|
||||
"#test miner wallet URL (burns if this doesn't exist)
|
||||
#test_miner_wallet_url = \"http://127.0.0.1:13415\"
|
||||
|
||||
#########################################
|
||||
### SERVER P2P CONFIGURATION ###
|
||||
#########################################
|
||||
#The P2P server details (i.e. the server that communicates with other
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"host".to_string(),
|
||||
"
|
||||
#The interface on which to listen.
|
||||
#0.0.0.0 will listen on all interfaces, alowing others to interact
|
||||
#127.0.0.1 will listen on the local machine only
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"port".to_string(),
|
||||
"
|
||||
#The port on which to listen.
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"seeding_type".to_string(),
|
||||
"
|
||||
#How to seed this server, can be None, List, WebStatic or DNSSeed
|
||||
#If the seeding type is List, the list of peers to connect to can
|
||||
#be specified as follows:
|
||||
#seeds = [\"192.168.0.1:13414\",\"192.168.0.2:13414\"]
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"seeds".to_string(),
|
||||
"
|
||||
#If seeding_type = List, the list of peers to connect to.
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"[server.p2p_config.capabilities]".to_string(),
|
||||
"#7 = Bit flags for FULL_NODE, this structure needs to be changed
|
||||
#internally to make it more configurable
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"[server.pool_config]".to_string(),
|
||||
"#hardcoded peer lists for allow/deny
|
||||
#will *only* connect to peers in allow list
|
||||
#peers_allow = [\"192.168.0.1:13414\", \"192.168.0.2:13414\"]
|
||||
#will *never* connect to peers in deny list
|
||||
#peers_deny = [\"192.168.0.3:13414\", \"192.168.0.4:13414\"]
|
||||
#a list of preferred peers to connect to
|
||||
#peers_preferred = [\"192.168.0.1:13414\",\"192.168.0.2:13414\"]
|
||||
|
||||
#how long a banned peer should stay banned
|
||||
#ban_window = 10800
|
||||
|
||||
#maximum number of peers
|
||||
#peer_max_count = 25
|
||||
|
||||
#preferred minimum number of peers (we'll actively keep trying to add peers
|
||||
#until we get to at least this number
|
||||
#peer_min_preferred_count = 8
|
||||
|
||||
#########################################
|
||||
### MEMPOOL CONFIGURATION ###
|
||||
#########################################
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"accept_fee_base".to_string(),
|
||||
"
|
||||
#Base fee that's accepted into the pool
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"max_pool_size".to_string(),
|
||||
"
|
||||
#Maximum number of transactions allowed in the pool
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"[server.stratum_mining_config]".to_string(),
|
||||
"
|
||||
################################################
|
||||
### STRATUM MINING SERVER CONFIGURATION ###
|
||||
################################################
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"enable_stratum_server".to_string(),
|
||||
"
|
||||
#whether stratum server is enabled
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"stratum_server_addr".to_string(),
|
||||
"
|
||||
#what port and address for the stratum server to listen on
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"attempt_time_per_block".to_string(),
|
||||
"
|
||||
#The amount of time, in seconds, to attempt to mine on a particular
|
||||
#header before stopping and re-collecting transactions from the pool
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"minimum_share_difficulty".to_string(),
|
||||
"
|
||||
#The minimum acceptable share difficulty to request from miners
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"wallet_listener_url".to_string(),
|
||||
"
|
||||
#the wallet receiver to which coinbase rewards will be sent
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"burn_reward".to_string(),
|
||||
"
|
||||
#whether to ignore the reward (mostly for testing)
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"[wallet]".to_string(),
|
||||
"
|
||||
#########################################
|
||||
### WALLET CONFIGURATION ###
|
||||
#########################################
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"api_listen_interface".to_string(),
|
||||
"
|
||||
# Host IP for wallet listener, change to \"0.0.0.0\" to receive grins
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"api_listen_port".to_string(),
|
||||
"
|
||||
# Port for wallet listener
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"check_node_api_http_addr".to_string(),
|
||||
"
|
||||
# Where the wallet should find a running node
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"data_file_dir".to_string(),
|
||||
"
|
||||
# Where to find wallet files (seed, data, etc)
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"[logging]".to_string(),
|
||||
"
|
||||
#########################################
|
||||
### LOGGING CONFIGURATION ###
|
||||
#########################################
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"log_to_stdout".to_string(),
|
||||
"
|
||||
# Whether to log to stdout
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"stdout_log_level".to_string(),
|
||||
"
|
||||
# Log level for stdout: Critical, Error, Warning, Info, Debug, Trace
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"log_to_file".to_string(),
|
||||
"
|
||||
# Whether to log to a file
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"file_log_level".to_string(),
|
||||
"
|
||||
# Log level for file: Critical, Error, Warning, Info, Debug, Trace
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"log_file_path".to_string(),
|
||||
"
|
||||
# Log file path
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval.insert(
|
||||
"log_file_append".to_string(),
|
||||
"
|
||||
# Whether to append to the log file (true), or replace it on every run (false)
|
||||
"
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
retval
|
||||
}
|
||||
|
||||
fn get_key(line: &str) -> String {
|
||||
if line.contains("[") && line.contains("]") {
|
||||
return line.to_owned();
|
||||
} else if line.contains("=") {
|
||||
return line.split("=").collect::<Vec<&str>>()[0].trim().to_owned();
|
||||
} else {
|
||||
return "NOT_FOUND".to_owned();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_comments(orig: String) -> String {
|
||||
let comments = comments();
|
||||
let lines: Vec<&str> = orig.split("\n").collect();
|
||||
let mut out_lines = vec![];
|
||||
for l in lines {
|
||||
let key = get_key(l);
|
||||
if let Some(v) = comments.get(&key) {
|
||||
out_lines.push(v.to_owned());
|
||||
}
|
||||
out_lines.push(l.to_owned());
|
||||
out_lines.push("\n".to_owned());
|
||||
}
|
||||
let mut ret_val = String::from("");
|
||||
for l in out_lines {
|
||||
ret_val.push_str(&l);
|
||||
}
|
||||
ret_val.to_owned()
|
||||
}
|
|
@ -14,33 +14,123 @@
|
|||
|
||||
//! Configuration file management
|
||||
|
||||
use dirs;
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::fs::{self, File};
|
||||
use std::io::prelude::*;
|
||||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
use toml;
|
||||
|
||||
use servers::{ServerConfig, StratumServerConfig};
|
||||
use types::{ConfigError, ConfigMembers, GlobalConfig};
|
||||
use comments::insert_comments;
|
||||
use servers::ServerConfig;
|
||||
use types::{
|
||||
ConfigError, ConfigMembers, GlobalConfig, GlobalWalletConfig, GlobalWalletConfigMembers,
|
||||
};
|
||||
use util::LoggingConfig;
|
||||
use wallet::WalletConfig;
|
||||
|
||||
/// The default file name to use when trying to derive
|
||||
/// the config file location
|
||||
|
||||
const CONFIG_FILE_NAME: &'static str = "grin.toml";
|
||||
/// the node config file location
|
||||
pub const SERVER_CONFIG_FILE_NAME: &'static str = "grin-server.toml";
|
||||
/// And a wallet configuration file name
|
||||
pub const WALLET_CONFIG_FILE_NAME: &'static str = "grin-wallet.toml";
|
||||
const SERVER_LOG_FILE_NAME: &'static str = "grin-server.log";
|
||||
const WALLET_LOG_FILE_NAME: &'static str = "grin-wallet.log";
|
||||
const GRIN_HOME: &'static str = ".grin";
|
||||
const GRIN_CHAIN_DIR: &'static str = "chain_data";
|
||||
const GRIN_WALLET_DIR: &'static str = "wallet_data";
|
||||
|
||||
fn get_grin_path() -> Result<PathBuf, ConfigError> {
|
||||
// Check if grin dir exists
|
||||
let grin_path = {
|
||||
match env::home_dir() {
|
||||
Some(mut p) => {
|
||||
p.push(GRIN_HOME);
|
||||
p
|
||||
}
|
||||
None => {
|
||||
let mut pb = PathBuf::new();
|
||||
pb.push(GRIN_HOME);
|
||||
pb
|
||||
}
|
||||
}
|
||||
};
|
||||
// Create if the default path doesn't exist
|
||||
if !grin_path.exists() {
|
||||
fs::create_dir_all(grin_path.clone())?;
|
||||
}
|
||||
Ok(grin_path)
|
||||
}
|
||||
|
||||
fn check_config_current_dir(path: &str) -> Option<PathBuf> {
|
||||
let p = env::current_dir();
|
||||
let mut c = match p {
|
||||
Ok(c) => c,
|
||||
Err(_) => {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
c.push(path);
|
||||
if c.exists() {
|
||||
return Some(c);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Handles setup and detection of paths for node
|
||||
pub fn initial_setup_server() -> Result<GlobalConfig, ConfigError> {
|
||||
// Use config file if current directory if it exists, .grin home otherwise
|
||||
if let Some(p) = check_config_current_dir(SERVER_CONFIG_FILE_NAME) {
|
||||
GlobalConfig::new(p.to_str().unwrap())
|
||||
} else {
|
||||
// Check if grin dir exists
|
||||
let grin_path = get_grin_path()?;
|
||||
|
||||
// Get path to default config file
|
||||
let mut config_path = grin_path.clone();
|
||||
config_path.push(SERVER_CONFIG_FILE_NAME);
|
||||
|
||||
// Spit it out if it doesn't exist
|
||||
if !config_path.exists() {
|
||||
let mut default_config = GlobalConfig::default();
|
||||
// update paths relative to current dir
|
||||
default_config.update_paths(&grin_path);
|
||||
default_config.write_to_file(config_path.to_str().unwrap())?;
|
||||
}
|
||||
GlobalConfig::new(config_path.to_str().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles setup and detection of paths for wallet
|
||||
pub fn initial_setup_wallet() -> Result<GlobalWalletConfig, ConfigError> {
|
||||
// Use config file if current directory if it exists, .grin home otherwise
|
||||
if let Some(p) = check_config_current_dir(WALLET_CONFIG_FILE_NAME) {
|
||||
GlobalWalletConfig::new(p.to_str().unwrap())
|
||||
} else {
|
||||
// Check if grin dir exists
|
||||
let grin_path = get_grin_path()?;
|
||||
|
||||
// Get path to default config file
|
||||
let mut config_path = grin_path.clone();
|
||||
config_path.push(WALLET_CONFIG_FILE_NAME);
|
||||
|
||||
// Spit it out if it doesn't exist
|
||||
if !config_path.exists() {
|
||||
let mut default_config = GlobalWalletConfig::default();
|
||||
// update paths relative to current dir
|
||||
default_config.update_paths(&grin_path);
|
||||
default_config.write_to_file(config_path.to_str().unwrap())?;
|
||||
}
|
||||
GlobalWalletConfig::new(config_path.to_str().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the defaults, as strewn throughout the code
|
||||
|
||||
impl Default for ConfigMembers {
|
||||
fn default() -> ConfigMembers {
|
||||
ConfigMembers {
|
||||
server: ServerConfig::default(),
|
||||
mining_server: Some(StratumServerConfig::default()),
|
||||
logging: Some(LoggingConfig::default()),
|
||||
wallet: WalletConfig::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,55 +144,29 @@ impl Default for GlobalConfig {
|
|||
}
|
||||
}
|
||||
|
||||
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(());
|
||||
impl Default for GlobalWalletConfigMembers {
|
||||
fn default() -> GlobalWalletConfigMembers {
|
||||
GlobalWalletConfigMembers {
|
||||
logging: Some(LoggingConfig::default()),
|
||||
wallet: WalletConfig::default(),
|
||||
}
|
||||
// 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 = dirs::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> {
|
||||
impl Default for GlobalWalletConfig {
|
||||
fn default() -> GlobalWalletConfig {
|
||||
GlobalWalletConfig {
|
||||
config_file_path: None,
|
||||
members: Some(GlobalWalletConfigMembers::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GlobalConfig {
|
||||
/// Requires the path to a config file
|
||||
pub fn new(file_path: &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 {
|
||||
let _result = 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);
|
||||
}
|
||||
return_value.config_file_path = Some(PathBuf::from(&file_path));
|
||||
|
||||
// Config file path is given but not valid
|
||||
let config_file = return_value.config_file_path.clone().unwrap();
|
||||
|
@ -124,10 +188,7 @@ impl GlobalConfig {
|
|||
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.stratum_mining_config = gc.mining_server.clone();
|
||||
Ok(gc) => {
|
||||
self.members = Some(gc);
|
||||
return Ok(self);
|
||||
}
|
||||
|
@ -147,6 +208,37 @@ impl GlobalConfig {
|
|||
}
|
||||
}
|
||||
|
||||
/// Update paths
|
||||
pub fn update_paths(&mut self, grin_home: &PathBuf) {
|
||||
// need to update server chain path
|
||||
let mut chain_path = grin_home.clone();
|
||||
chain_path.push(GRIN_CHAIN_DIR);
|
||||
self.members.as_mut().unwrap().server.db_root = chain_path.to_str().unwrap().to_owned();
|
||||
let mut log_path = grin_home.clone();
|
||||
log_path.push(SERVER_LOG_FILE_NAME);
|
||||
self.members
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.logging
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.log_file_path = log_path.to_str().unwrap().to_owned();
|
||||
}
|
||||
|
||||
/// Enable mining
|
||||
pub fn stratum_enabled(&mut self) -> bool {
|
||||
return self
|
||||
.members
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.server
|
||||
.stratum_mining_config
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.enable_stratum_server
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/// Serialize config
|
||||
pub fn ser_config(&mut self) -> Result<String, ConfigError> {
|
||||
let encoded: Result<String, toml::ser::Error> =
|
||||
|
@ -162,20 +254,101 @@ impl GlobalConfig {
|
|||
}
|
||||
}
|
||||
|
||||
/*pub fn wallet_enabled(&mut self) -> bool {
|
||||
return self.members.as_mut().unwrap().wallet.as_mut().unwrap().enable_wallet;
|
||||
}*/
|
||||
|
||||
/// Enable mining
|
||||
pub fn stratum_enabled(&mut self) -> bool {
|
||||
return self
|
||||
.members
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.mining_server
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.enable_stratum_server
|
||||
.unwrap();
|
||||
/// Write configuration to a file
|
||||
pub fn write_to_file(&mut self, name: &str) -> Result<(), ConfigError> {
|
||||
let conf_out = self.ser_config()?;
|
||||
let conf_out = insert_comments(conf_out);
|
||||
let mut file = File::create(name)?;
|
||||
file.write_all(conf_out.as_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: Properly templatize these structs (if it's worth the effort)
|
||||
impl GlobalWalletConfig {
|
||||
/// Requires the path to a config file
|
||||
pub fn new(file_path: &str) -> Result<GlobalWalletConfig, ConfigError> {
|
||||
let mut return_value = GlobalWalletConfig::default();
|
||||
return_value.config_file_path = Some(PathBuf::from(&file_path));
|
||||
|
||||
// Config file path is given but not valid
|
||||
let config_file = return_value.config_file_path.clone().unwrap();
|
||||
if !config_file.exists() {
|
||||
return Err(ConfigError::FileNotFoundError(String::from(
|
||||
config_file.to_str().unwrap(),
|
||||
)));
|
||||
}
|
||||
|
||||
// Try to parse the config file if it exists, explode if it does exist but
|
||||
// something's wrong with it
|
||||
return_value.read_config()
|
||||
}
|
||||
|
||||
/// Read config
|
||||
fn read_config(mut self) -> Result<GlobalWalletConfig, 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<GlobalWalletConfigMembers, toml::de::Error> = toml::from_str(&contents);
|
||||
match decoded {
|
||||
Ok(gc) => {
|
||||
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)),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Update paths
|
||||
pub fn update_paths(&mut self, wallet_home: &PathBuf) {
|
||||
let mut wallet_path = wallet_home.clone();
|
||||
wallet_path.push(GRIN_WALLET_DIR);
|
||||
self.members.as_mut().unwrap().wallet.data_file_dir =
|
||||
wallet_path.to_str().unwrap().to_owned();
|
||||
let mut log_path = wallet_home.clone();
|
||||
log_path.push(WALLET_LOG_FILE_NAME);
|
||||
self.members
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.logging
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.log_file_path = log_path.to_str().unwrap().to_owned();
|
||||
}
|
||||
|
||||
/// Serialize config
|
||||
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
|
||||
))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Write configuration to a file
|
||||
pub fn write_to_file(&mut self, name: &str) -> Result<(), ConfigError> {
|
||||
let conf_out = self.ser_config()?;
|
||||
let conf_out = insert_comments(conf_out);
|
||||
let mut file = File::create(name)?;
|
||||
file.write_all(conf_out.as_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#![deny(unused_mut)]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate dirs;
|
||||
|
@ -31,7 +30,9 @@ extern crate grin_servers as servers;
|
|||
extern crate grin_util as util;
|
||||
extern crate grin_wallet as wallet;
|
||||
|
||||
mod comments;
|
||||
pub mod config;
|
||||
pub mod types;
|
||||
|
||||
pub use types::{ConfigError, ConfigMembers, GlobalConfig};
|
||||
pub use config::{initial_setup_server, initial_setup_wallet};
|
||||
pub use types::{ConfigError, ConfigMembers, GlobalConfig, GlobalWalletConfig};
|
||||
|
|
|
@ -18,7 +18,7 @@ use std::fmt;
|
|||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use servers::{ServerConfig, StratumServerConfig};
|
||||
use servers::ServerConfig;
|
||||
use util::LoggingConfig;
|
||||
use wallet::WalletConfig;
|
||||
|
||||
|
@ -92,14 +92,25 @@ pub struct ConfigMembers {
|
|||
/// Server config
|
||||
#[serde(default)]
|
||||
pub server: ServerConfig,
|
||||
/// Mining config
|
||||
pub mining_server: Option<StratumServerConfig>,
|
||||
/// Logging config
|
||||
pub logging: Option<LoggingConfig>,
|
||||
}
|
||||
|
||||
/// Wallet config. May eventually need to be moved to its own thing. Or not.
|
||||
/// Depends on whether we end up starting the wallet in its own process but
|
||||
/// with the same lifecycle as the server.
|
||||
/// Wallet should be split into a separate configuration file
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub struct GlobalWalletConfig {
|
||||
/// Keep track of the file we've read
|
||||
pub config_file_path: Option<PathBuf>,
|
||||
/// Wallet members
|
||||
pub members: Option<GlobalWalletConfigMembers>,
|
||||
}
|
||||
|
||||
/// Wallet internal members
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub struct GlobalWalletConfigMembers {
|
||||
/// Wallet configuration
|
||||
#[serde(default)]
|
||||
pub wallet: WalletConfig,
|
||||
/// Logging config
|
||||
pub logging: Option<LoggingConfig>,
|
||||
}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
#[macro_use]
|
||||
extern crate pretty_assertions;
|
||||
extern crate grin_config as config;
|
||||
|
||||
use config::GlobalConfig;
|
||||
|
||||
#[test]
|
||||
fn file_config_equal_to_defaults() {
|
||||
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
|
||||
);
|
||||
}
|
183
grin.toml
183
grin.toml
|
@ -1,183 +0,0 @@
|
|||
# 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 CONFIGURATION ###
|
||||
#########################################
|
||||
|
||||
#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"
|
||||
|
||||
#The chain type, which defines the genesis block and the set of cuckoo
|
||||
#parameters used for mining. Can be:
|
||||
#AutomatedTesting - For CI builds and instant blockchain creation
|
||||
#UserTesting - For regular user testing (cuckoo 16)
|
||||
#Testnet1 - Testnet1 genesis block (cuckoo 16)
|
||||
#Testnet2 - Testnet2 genesis block (cuckoo 30)
|
||||
|
||||
chain_type = "Testnet3"
|
||||
|
||||
#The chain validation mode, defines how often (if at all) we
|
||||
#want to run a full chain validation. Can be:
|
||||
#"EveryBlock" - run full chain validation when processing each block (except during sync)
|
||||
#"Disabled" - disable full chain validation (just run regular block validation)
|
||||
#chain_validation_mode = "Disabled"
|
||||
|
||||
#run the node in "full archive" mode (default is fast-sync, pruned node)
|
||||
#archive_mode = false
|
||||
|
||||
#skip waiting for sync on startup, (optional param, mostly for testing)
|
||||
skip_sync_wait = false
|
||||
|
||||
#whether to run the ncurses TUI. Ncurses must be installed and this
|
||||
#will also disable logging to stdout
|
||||
run_tui = true
|
||||
|
||||
#Whether to run the wallet listener with the server by default
|
||||
run_wallet_listener = true
|
||||
|
||||
# Whether to run the web-wallet API (will only run on localhost)
|
||||
# grin wallet web will run this automatically, so this should
|
||||
# only be set to true for test/development purposes
|
||||
run_wallet_owner_api = false
|
||||
|
||||
#Whether to run a test miner. This is only for developer testing (chaintype
|
||||
#usertesting) at cuckoo 16, and will only mine into the default wallet port.
|
||||
#real mining should use the standalone grin-miner
|
||||
run_test_miner = false
|
||||
|
||||
#test miner wallet URL (burns if this doesn't exist)
|
||||
#test_miner_wallet_url = "http://127.0.0.1:13415"
|
||||
|
||||
[server.dandelion_config]
|
||||
#dandelion relay time (choose new relay peer every n secs)
|
||||
relay_secs = 600
|
||||
|
||||
#fluff and broadcast after embargo expires if tx not seen on network
|
||||
embargo_secs = 180
|
||||
|
||||
#run dandelion stem/fluff processing every n secs (stem tx aggregation in this window)
|
||||
patience_secs = 10
|
||||
|
||||
#dandelion stem probability (stem 90% of the time, fluff 10% of the time)
|
||||
stem_probability = 90
|
||||
|
||||
#The P2P server details (i.e. the server that communicates with other
|
||||
#grin server nodes
|
||||
[server.p2p_config]
|
||||
|
||||
host = "0.0.0.0"
|
||||
port = 13414
|
||||
|
||||
#How to seed this server, can be None, List, WebStatic or DNSSeed
|
||||
#
|
||||
#seeding_type = "None"
|
||||
|
||||
#If seeding_type = List, the list of peers to connect to.
|
||||
#
|
||||
#seeds = ["192.168.0.1:13414","192.168.0.2:13414"]
|
||||
|
||||
#7 = Bit flags for FULL_NODE, this structure needs to be changed
|
||||
#internally to make it more configurable
|
||||
capabilities = [7]
|
||||
|
||||
#hardcoded peer lists for allow/deny
|
||||
#will *only* connect to peers in allow list
|
||||
#peers_allow = ["192.168.0.1:13414", "192.168.0.2:13414"]
|
||||
#will *never* connect to peers in deny list
|
||||
#peers_deny = ["192.168.0.3:13414", "192.168.0.4:13414"]
|
||||
#a list of preferred peers to connect to
|
||||
#peers_preferred = ["192.168.0.1:13414","192.168.0.2:13414"]
|
||||
|
||||
#how long a banned peer should stay banned
|
||||
#ban_window = 10800
|
||||
|
||||
#maximum number of peers
|
||||
#peer_max_count = 25
|
||||
|
||||
#preferred minimum number of peers (we'll actively keep trying to add peers
|
||||
#until we get to at least this number
|
||||
#peer_min_preferred_count = 8
|
||||
|
||||
###########################################
|
||||
### STRATUM MINING SERVER CONFIGURATION ###
|
||||
###########################################
|
||||
[mining_server]
|
||||
|
||||
#flag whether stratum server is enabled
|
||||
enable_stratum_server = true
|
||||
|
||||
#what port and address for the stratum server to listen on
|
||||
stratum_server_addr = "127.0.0.1:13416"
|
||||
|
||||
#The amount of time, in seconds, to attempt to mine on a particular
|
||||
#header before stopping and re-collecting transactions from the pool
|
||||
attempt_time_per_block = 15
|
||||
|
||||
#The minimum acceptable share difficulty to request from miners
|
||||
minimum_share_difficulty = 1
|
||||
|
||||
#the wallet receiver to which coinbase rewards will be sent
|
||||
wallet_listener_url = "http://127.0.0.1:13415"
|
||||
|
||||
#whether to ignore the reward (mostly for testing)
|
||||
burn_reward = false
|
||||
|
||||
#########################################
|
||||
### WALLET CONFIGURATION ###
|
||||
#########################################
|
||||
|
||||
[wallet]
|
||||
|
||||
# Host IP for wallet listener, change to "0.0.0.0" to receive grins
|
||||
api_listen_interface = "127.0.0.1"
|
||||
|
||||
# Port for wallet listener
|
||||
api_listen_port = 13415
|
||||
|
||||
# Where the wallet should find a running node
|
||||
check_node_api_http_addr = "http://127.0.0.1:13413"
|
||||
|
||||
# Where to find wallet files (seed, data, etc)
|
||||
data_file_dir = "."
|
||||
|
||||
#########################################
|
||||
### LOGGING CONFIGURATION ###
|
||||
#########################################
|
||||
|
||||
[logging]
|
||||
|
||||
# Whether to log to stdout
|
||||
log_to_stdout = true
|
||||
|
||||
# Log level for stdout: Critical, Error, Warning, Info, Debug, Trace
|
||||
stdout_log_level = "Warning"
|
||||
|
||||
# Whether to log to a file
|
||||
log_to_file = true
|
||||
|
||||
# Log level for file: Critical, Error, Warning, Info, Debug, Trace
|
||||
file_log_level = "Debug"
|
||||
|
||||
# Log file path
|
||||
log_file_path = "grin.log"
|
||||
|
||||
# Whether to append to the log file (true), or replace it on every run (false)
|
||||
log_file_append = true
|
|
@ -142,7 +142,7 @@ impl Default for P2PConfig {
|
|||
}
|
||||
|
||||
/// Note certain fields are options just so they don't have to be
|
||||
/// included in grin.toml, but we don't want them to ever return none
|
||||
/// included in grin-server.toml, but we don't want them to ever return none
|
||||
impl P2PConfig {
|
||||
/// return ban window
|
||||
pub fn ban_window(&self) -> i64 {
|
||||
|
|
|
@ -201,8 +201,8 @@ impl Default for StratumStats {
|
|||
is_running: false,
|
||||
num_workers: 0,
|
||||
block_height: 0,
|
||||
network_difficulty: 0,
|
||||
cuckoo_size: 0,
|
||||
network_difficulty: 1000,
|
||||
cuckoo_size: 30,
|
||||
worker_stats: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,26 +117,12 @@ pub struct ServerConfig {
|
|||
#[serde(default)]
|
||||
pub chain_type: ChainTypes,
|
||||
|
||||
/// Whether this node is a full archival node or a fast-sync, pruned node
|
||||
pub archive_mode: Option<bool>,
|
||||
|
||||
/// Automatically run full chain validation during normal block processing?
|
||||
#[serde(default)]
|
||||
pub chain_validation_mode: ChainValidationMode,
|
||||
|
||||
/// Configuration for the peer-to-peer server
|
||||
pub p2p_config: p2p::P2PConfig,
|
||||
|
||||
/// Configuration for the mining daemon
|
||||
pub stratum_mining_config: Option<StratumServerConfig>,
|
||||
|
||||
/// Transaction pool configuration
|
||||
#[serde(default)]
|
||||
pub pool_config: pool::PoolConfig,
|
||||
|
||||
/// Dandelion configuration
|
||||
#[serde(default)]
|
||||
pub dandelion_config: pool::DandelionConfig,
|
||||
/// Whether this node is a full archival node or a fast-sync, pruned node
|
||||
pub archive_mode: Option<bool>,
|
||||
|
||||
/// Whether to skip the sync timeout on startup
|
||||
/// (To assist testing on solo chains)
|
||||
|
@ -160,23 +146,38 @@ pub struct ServerConfig {
|
|||
|
||||
/// Test miner wallet URL
|
||||
pub test_miner_wallet_url: Option<String>,
|
||||
|
||||
/// Configuration for the peer-to-peer server
|
||||
pub p2p_config: p2p::P2PConfig,
|
||||
|
||||
/// Transaction pool configuration
|
||||
#[serde(default)]
|
||||
pub pool_config: pool::PoolConfig,
|
||||
|
||||
/// Dandelion configuration
|
||||
#[serde(default)]
|
||||
pub dandelion_config: pool::DandelionConfig,
|
||||
|
||||
/// Configuration for the mining daemon
|
||||
#[serde(default)]
|
||||
pub stratum_mining_config: Option<StratumServerConfig>,
|
||||
}
|
||||
|
||||
impl Default for ServerConfig {
|
||||
fn default() -> ServerConfig {
|
||||
ServerConfig {
|
||||
db_root: ".grin".to_string(),
|
||||
db_root: "grin_chain".to_string(),
|
||||
api_http_addr: "127.0.0.1:13413".to_string(),
|
||||
p2p_config: p2p::P2PConfig::default(),
|
||||
dandelion_config: pool::DandelionConfig::default(),
|
||||
stratum_mining_config: Some(StratumServerConfig::default()),
|
||||
chain_type: ChainTypes::default(),
|
||||
archive_mode: None,
|
||||
archive_mode: Some(false),
|
||||
chain_validation_mode: ChainValidationMode::default(),
|
||||
pool_config: pool::PoolConfig::default(),
|
||||
skip_sync_wait: Some(false),
|
||||
run_tui: Some(true),
|
||||
run_wallet_listener: Some(true),
|
||||
run_wallet_listener: Some(false),
|
||||
run_wallet_owner_api: Some(false),
|
||||
use_db_wallet: None,
|
||||
run_test_miner: Some(false),
|
||||
|
@ -217,7 +218,7 @@ impl Default for StratumServerConfig {
|
|||
burn_reward: false,
|
||||
attempt_time_per_block: 15,
|
||||
minimum_share_difficulty: 1,
|
||||
enable_stratum_server: Some(true),
|
||||
enable_stratum_server: Some(false),
|
||||
stratum_server_addr: Some("127.0.0.1:13416".to_string()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,19 +65,21 @@ impl Server {
|
|||
where
|
||||
F: FnMut(Arc<Server>),
|
||||
{
|
||||
let mut mining_config = config.stratum_mining_config.clone();
|
||||
let mining_config = config.stratum_mining_config.clone();
|
||||
let enable_test_miner = config.run_test_miner;
|
||||
let test_miner_wallet_url = config.test_miner_wallet_url.clone();
|
||||
let serv = Arc::new(Server::new(config)?);
|
||||
|
||||
let enable_stratum_server = mining_config.as_mut().unwrap().enable_stratum_server;
|
||||
if let Some(s) = enable_stratum_server {
|
||||
if s {
|
||||
{
|
||||
let mut stratum_stats = serv.state_info.stratum_stats.write().unwrap();
|
||||
stratum_stats.is_enabled = true;
|
||||
if let Some(c) = mining_config {
|
||||
let enable_stratum_server = c.enable_stratum_server;
|
||||
if let Some(s) = enable_stratum_server {
|
||||
if s {
|
||||
{
|
||||
let mut stratum_stats = serv.state_info.stratum_stats.write().unwrap();
|
||||
stratum_stats.is_enabled = true;
|
||||
}
|
||||
serv.start_stratum_server(c.clone());
|
||||
}
|
||||
serv.start_stratum_server(mining_config.clone().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
71
src/bin/cmd/config.rs
Normal file
71
src/bin/cmd/config.rs
Normal file
|
@ -0,0 +1,71 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
/// Grin configuation file output command
|
||||
use config::{GlobalConfig, GlobalWalletConfig};
|
||||
use std::env;
|
||||
|
||||
/// Create a config file in the current directory
|
||||
pub fn config_command_server(file_name: &str) {
|
||||
let mut default_config = GlobalConfig::default();
|
||||
let current_dir = env::current_dir().unwrap_or_else(|e| {
|
||||
panic!("Error creating config file: {}", e);
|
||||
});
|
||||
let mut config_file_name = current_dir.clone();
|
||||
config_file_name.push(file_name);
|
||||
if config_file_name.exists() {
|
||||
panic!(
|
||||
"{} already exists in the current directory. Please remove it first",
|
||||
file_name
|
||||
);
|
||||
}
|
||||
default_config.update_paths(¤t_dir);
|
||||
default_config
|
||||
.write_to_file(config_file_name.to_str().unwrap())
|
||||
.unwrap_or_else(|e| {
|
||||
panic!("Error creating config file: {}", e);
|
||||
});
|
||||
|
||||
println!(
|
||||
"{} file configured and created in current directory",
|
||||
file_name
|
||||
);
|
||||
}
|
||||
|
||||
/// Create a config file in the current directory
|
||||
pub fn config_command_wallet(file_name: &str) {
|
||||
let mut default_config = GlobalWalletConfig::default();
|
||||
let current_dir = env::current_dir().unwrap_or_else(|e| {
|
||||
panic!("Error creating config file: {}", e);
|
||||
});
|
||||
let mut config_file_name = current_dir.clone();
|
||||
config_file_name.push(file_name);
|
||||
if config_file_name.exists() {
|
||||
panic!(
|
||||
"{} already exists in the target directory. Please remove it first",
|
||||
file_name
|
||||
);
|
||||
}
|
||||
default_config.update_paths(¤t_dir);
|
||||
default_config
|
||||
.write_to_file(config_file_name.to_str().unwrap())
|
||||
.unwrap_or_else(|e| {
|
||||
panic!("Error creating config file: {}", e);
|
||||
});
|
||||
|
||||
println!(
|
||||
"File {} configured and created",
|
||||
config_file_name.to_str().unwrap(),
|
||||
);
|
||||
}
|
|
@ -13,9 +13,11 @@
|
|||
// limitations under the License.
|
||||
|
||||
mod client;
|
||||
mod config;
|
||||
mod server;
|
||||
mod wallet;
|
||||
|
||||
pub use self::client::client_command;
|
||||
pub use self::config::{config_command_server, config_command_wallet};
|
||||
pub use self::server::server_command;
|
||||
pub use self::wallet::wallet_command;
|
||||
pub use self::wallet::{seed_exists, wallet_command};
|
||||
|
|
|
@ -123,7 +123,7 @@ pub fn server_command(server_args: Option<&ArgMatches>, mut global_config: Globa
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(true) = server_config.run_wallet_listener {
|
||||
/*if let Some(true) = server_config.run_wallet_listener {
|
||||
let mut wallet_config = global_config.members.as_ref().unwrap().wallet.clone();
|
||||
wallet::init_wallet_seed(wallet_config.clone());
|
||||
let wallet = wallet::instantiate_wallet(wallet_config.clone(), "");
|
||||
|
@ -155,7 +155,7 @@ pub fn server_command(server_args: Option<&ArgMatches>, mut global_config: Globa
|
|||
)
|
||||
});
|
||||
});
|
||||
}
|
||||
}*/
|
||||
|
||||
// start the server in the different run modes (interactive or daemon)
|
||||
if let Some(a) = server_args {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::path::PathBuf;
|
||||
/// Wallet commands processing
|
||||
use std::process::exit;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
@ -20,7 +21,7 @@ use std::time::Duration;
|
|||
|
||||
use clap::ArgMatches;
|
||||
|
||||
use config::GlobalConfig;
|
||||
use config::GlobalWalletConfig;
|
||||
use core::core;
|
||||
use grin_wallet::{self, controller, display, libwallet};
|
||||
use grin_wallet::{HTTPWalletClient, LMDBBackend, WalletConfig, WalletInst, WalletSeed};
|
||||
|
@ -28,12 +29,22 @@ use keychain;
|
|||
use servers::start_webwallet_server;
|
||||
use util::LOGGER;
|
||||
|
||||
pub fn init_wallet_seed(wallet_config: WalletConfig) {
|
||||
pub fn _init_wallet_seed(wallet_config: WalletConfig) {
|
||||
if let Err(_) = WalletSeed::from_file(&wallet_config) {
|
||||
WalletSeed::init_file(&wallet_config).expect("Failed to create wallet seed file.");
|
||||
};
|
||||
}
|
||||
|
||||
pub fn seed_exists(wallet_config: WalletConfig) -> bool {
|
||||
let mut data_file_dir = PathBuf::new();
|
||||
data_file_dir.push(wallet_config.data_file_dir);
|
||||
data_file_dir.push(grin_wallet::SEED_FILE);
|
||||
if data_file_dir.exists() {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
pub fn instantiate_wallet(
|
||||
wallet_config: WalletConfig,
|
||||
passphrase: &str,
|
||||
|
@ -49,7 +60,7 @@ pub fn instantiate_wallet(
|
|||
warn!(LOGGER, "Migration successful. Using LMDB Wallet backend");
|
||||
}
|
||||
warn!(LOGGER, "Please check the results of the migration process using `grin wallet info` and `grin wallet outputs`");
|
||||
warn!(LOGGER, "If anything went wrong, you can try again by deleting the `wallet_data` directory and running a wallet command");
|
||||
warn!(LOGGER, "If anything went wrong, you can try again by deleting the `db` directory and running a wallet command");
|
||||
warn!(LOGGER, "If all is okay, you can move/backup/delete all files in the wallet directory EXCEPT FOR wallet.seed");
|
||||
}
|
||||
let client = HTTPWalletClient::new(&wallet_config.check_node_api_http_addr);
|
||||
|
@ -63,9 +74,9 @@ pub fn instantiate_wallet(
|
|||
Box::new(db_wallet)
|
||||
}
|
||||
|
||||
pub fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) {
|
||||
pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) {
|
||||
// just get defaults from the global config
|
||||
let mut wallet_config = global_config.members.unwrap().wallet;
|
||||
let mut wallet_config = config.members.unwrap().wallet;
|
||||
|
||||
if wallet_args.is_present("external") {
|
||||
wallet_config.api_listen_interface = "0.0.0.0".to_string();
|
||||
|
|
143
src/bin/grin.rs
143
src/bin/grin.rs
|
@ -41,7 +41,7 @@ pub mod tui;
|
|||
|
||||
use clap::{App, Arg, SubCommand};
|
||||
|
||||
use config::GlobalConfig;
|
||||
use config::config::{SERVER_CONFIG_FILE_NAME, WALLET_CONFIG_FILE_NAME};
|
||||
use core::global;
|
||||
use util::{init_logger, LOGGER};
|
||||
|
||||
|
@ -81,10 +81,14 @@ fn main() {
|
|||
.version(crate_version!())
|
||||
.author("The Grin Team")
|
||||
.about("Lightweight implementation of the MimbleWimble protocol.")
|
||||
|
||||
// specification of all the server commands and options
|
||||
.subcommand(SubCommand::with_name("server")
|
||||
.about("Control the Grin server")
|
||||
.arg(Arg::with_name("config_file")
|
||||
.short("c")
|
||||
.long("config_file")
|
||||
.help("Path to a grin-server.toml configuration file")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("port")
|
||||
.short("p")
|
||||
.long("port")
|
||||
|
@ -104,7 +108,9 @@ fn main() {
|
|||
.short("w")
|
||||
.long("wallet_url")
|
||||
.help("The wallet listener to which mining rewards will be sent")
|
||||
.takes_value(true))
|
||||
.takes_value(true))
|
||||
.subcommand(SubCommand::with_name("config")
|
||||
.about("Generate a configuration grin-server.toml file in the current directory"))
|
||||
.subcommand(SubCommand::with_name("start")
|
||||
.about("Start the Grin server as a daemon"))
|
||||
.subcommand(SubCommand::with_name("stop")
|
||||
|
@ -274,85 +280,114 @@ fn main() {
|
|||
.about("basic wallet contents summary"))
|
||||
|
||||
.subcommand(SubCommand::with_name("init")
|
||||
.about("Initialize a new wallet seed file and database."))
|
||||
.about("Initialize a new wallet seed file and database.")
|
||||
.arg(Arg::with_name("here")
|
||||
.short("h")
|
||||
.long("here")
|
||||
.help("Create wallet files in the current directory instead of the default ~/.grin directory")
|
||||
.takes_value(false)))
|
||||
|
||||
.subcommand(SubCommand::with_name("restore")
|
||||
.about("Attempt to restore wallet contents from the chain using seed and password. \
|
||||
NOTE: Backup wallet.* and run `wallet listen` before running restore.")))
|
||||
|
||||
.get_matches();
|
||||
let mut wallet_config = None;
|
||||
let mut node_config = None;
|
||||
|
||||
// load a global config object,
|
||||
// then modify that object with any switches
|
||||
// found so that the switches override the
|
||||
// global config file
|
||||
|
||||
// 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).unwrap_or_else(|e| {
|
||||
panic!("Error parsing config file: {}", e);
|
||||
});
|
||||
|
||||
// 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);
|
||||
// Deal with configuration file creation
|
||||
match args.subcommand() {
|
||||
("server", Some(server_args)) => {
|
||||
// If it's just a server config command, do it and exit
|
||||
if let ("config", Some(_)) = server_args.subcommand() {
|
||||
cmd::config_command_server(SERVER_CONFIG_FILE_NAME);
|
||||
return;
|
||||
}
|
||||
}
|
||||
("wallet", Some(wallet_args)) => {
|
||||
// wallet init command should spit out its config file then continue
|
||||
// (if desired)
|
||||
if let ("init", Some(init_args)) = wallet_args.subcommand() {
|
||||
if init_args.is_present("here") {
|
||||
cmd::config_command_wallet(WALLET_CONFIG_FILE_NAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match args.subcommand() {
|
||||
// If it's a wallet command, try and load a wallet config file
|
||||
("wallet", Some(wallet_args)) => {
|
||||
let mut w = config::initial_setup_wallet().unwrap_or_else(|e| {
|
||||
panic!("Error loading wallet configuration: {}", e);
|
||||
});
|
||||
if !cmd::seed_exists(w.members.as_ref().unwrap().wallet.clone()) {
|
||||
if let ("init", Some(_)) = wallet_args.subcommand() {
|
||||
} else {
|
||||
println!("Wallet seed file doesn't exist. Run `grin wallet -p [password] init` first");
|
||||
return;
|
||||
}
|
||||
}
|
||||
let mut l = w.members.as_mut().unwrap().logging.clone().unwrap();
|
||||
l.tui_running = Some(false);
|
||||
init_logger(Some(l));
|
||||
warn!(
|
||||
LOGGER,
|
||||
"Using wallet configuration file at {}",
|
||||
w.config_file_path.as_ref().unwrap().to_str().unwrap()
|
||||
);
|
||||
wallet_config = Some(w);
|
||||
}
|
||||
// Otherwise load up the node config as usual
|
||||
_ => {
|
||||
let mut s = config::initial_setup_server().unwrap_or_else(|e| {
|
||||
panic!("Error loading server configuration: {}", e);
|
||||
});
|
||||
let mut l = s.members.as_mut().unwrap().logging.clone().unwrap();
|
||||
let run_tui = s.members.as_mut().unwrap().server.run_tui;
|
||||
if let Some(true) = run_tui {
|
||||
l.log_to_stdout = false;
|
||||
l.tui_running = Some(true);
|
||||
}
|
||||
init_logger(Some(l));
|
||||
global::set_mining_mode(s.members.as_mut().unwrap().server.clone().chain_type);
|
||||
if let Some(file_path) = &s.config_file_path {
|
||||
info!(
|
||||
LOGGER,
|
||||
"Using configuration file at {}",
|
||||
file_path.to_str().unwrap()
|
||||
);
|
||||
} else {
|
||||
info!(LOGGER, "Node configuration file not found, using default");
|
||||
}
|
||||
node_config = Some(s);
|
||||
}
|
||||
}
|
||||
init_logger(Some(log_conf));
|
||||
global::set_mining_mode(
|
||||
global_config
|
||||
.members
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.server
|
||||
.clone()
|
||||
.chain_type,
|
||||
);
|
||||
|
||||
log_build_info();
|
||||
|
||||
if let Some(file_path) = &global_config.config_file_path {
|
||||
info!(
|
||||
LOGGER,
|
||||
"Found configuration file at {}",
|
||||
file_path.to_str().unwrap()
|
||||
);
|
||||
} else {
|
||||
info!(LOGGER, "configuration file not found, using default");
|
||||
}
|
||||
|
||||
match args.subcommand() {
|
||||
// server commands and options
|
||||
("server", Some(server_args)) => {
|
||||
cmd::server_command(Some(server_args), global_config);
|
||||
cmd::server_command(Some(server_args), node_config.unwrap());
|
||||
}
|
||||
|
||||
// client commands and options
|
||||
("client", Some(client_args)) => {
|
||||
cmd::client_command(client_args, global_config);
|
||||
cmd::client_command(client_args, node_config.unwrap());
|
||||
}
|
||||
|
||||
// client commands and options
|
||||
("wallet", Some(wallet_args)) => {
|
||||
cmd::wallet_command(wallet_args, global_config);
|
||||
cmd::wallet_command(wallet_args, wallet_config.unwrap());
|
||||
}
|
||||
|
||||
// If nothing is specified, try to just use the config file instead
|
||||
// this could possibly become the way to configure most things
|
||||
// with most command line options being phased out
|
||||
_ => {
|
||||
cmd::server_command(None, global_config);
|
||||
cmd::server_command(None, node_config.unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ use store::{self, to_key};
|
|||
const DETAIL_FILE: &'static str = "wallet.det";
|
||||
const DAT_FILE: &'static str = "wallet.dat";
|
||||
const SEED_FILE: &'static str = "wallet.seed";
|
||||
const DB_DIR: &'static str = "wallet_data";
|
||||
const DB_DIR: &'static str = "db";
|
||||
const OUTPUT_PREFIX: u8 = 'o' as u8;
|
||||
const DERIV_PREFIX: u8 = 'd' as u8;
|
||||
const CONFIRMED_HEIGHT_PREFIX: u8 = 'c' as u8;
|
||||
|
|
|
@ -63,7 +63,7 @@ pub use libwallet::types::{
|
|||
BlockFees, CbData, WalletBackend, WalletClient, WalletInfo, WalletInst,
|
||||
};
|
||||
pub use lmdb_wallet::{wallet_db_exists, LMDBBackend};
|
||||
pub use types::{WalletConfig, WalletSeed};
|
||||
pub use types::{WalletConfig, WalletSeed, SEED_FILE};
|
||||
|
||||
// temporary
|
||||
pub use db_migrate::{migrate, needs_migrate};
|
||||
|
|
|
@ -159,7 +159,7 @@ where
|
|||
if !is_empty {
|
||||
error!(
|
||||
LOGGER,
|
||||
"Not restoring. Please back up and remove existing wallet_data directory first."
|
||||
"Not restoring. Please back up and remove existing db directory first."
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ use libwallet::{internal, Error, ErrorKind};
|
|||
use types::{WalletConfig, WalletSeed};
|
||||
use util::secp::pedersen;
|
||||
|
||||
pub const DB_DIR: &'static str = "wallet_data";
|
||||
pub const DB_DIR: &'static str = "db";
|
||||
|
||||
const COMMITMENT_PREFIX: u8 = 'C' as u8;
|
||||
const OUTPUT_PREFIX: u8 = 'o' as u8;
|
||||
|
|
Loading…
Reference in a new issue