diff --git a/.gitignore b/.gitignore index 78d8a7c..a662463 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ grin.log wallet.seed test_output .idea/ +*.vs +.gitattributes diff --git a/.hooks/pre-commit b/.hooks/pre-commit old mode 100755 new mode 100644 diff --git a/Cargo.lock b/Cargo.lock index d7fb3ba..73e3962 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1487,6 +1487,7 @@ dependencies = [ "grin_core", "grin_util", "grin_wallet_util", + "log", "pretty_assertions", "rand 0.6.5", "serde", diff --git a/config/src/comments.rs b/config/src/comments.rs index 4ae9f1b..c027042 100644 --- a/config/src/comments.rs +++ b/config/src/comments.rs @@ -333,10 +333,9 @@ pub fn migrate_comments( None } false => { - let comments: String = - vec_old_conf.iter().map(|s| s.chars()).flatten().collect(); + let comments: String = vec_old_conf.iter().flat_map(|s| s.chars()).collect(); let key = get_key(line_nospace); - match !(key == "NOT_FOUND") { + match key != "NOT_FOUND" { true => { vec_old_conf.clear(); hm_key_cmt_old.insert(key.clone(), comments); @@ -356,10 +355,10 @@ pub fn migrate_comments( .filter_map(|line| { let line_nospace = line.trim(); let is_ascii_control = line_nospace.chars().all(|x| x.is_ascii_control()); - match !(line.contains("#") || is_ascii_control) { + match !line.contains("#") && !is_ascii_control { true => { let key = get_key(line_nospace); - match !(key == "NOT_FOUND") { + match key != "NOT_FOUND" { true => Some((key, line_nospace.to_string())), false => None, } diff --git a/config/src/config.rs b/config/src/config.rs index d112980..cf87704 100644 --- a/config/src/config.rs +++ b/config/src/config.rs @@ -14,16 +14,6 @@ //! Configuration file management -use dirs; -use rand::distributions::{Alphanumeric, Distribution}; -use rand::thread_rng; -use std::env; -use std::fs::{self, File}; -use std::io::prelude::*; -use std::io::BufReader; -use std::path::PathBuf; -use toml; - use crate::comments::{insert_comments, migrate_comments}; use crate::core::global; use crate::types::{ @@ -31,11 +21,20 @@ use crate::types::{ }; use crate::types::{TorConfig, WalletConfig}; use crate::util::logger::LoggingConfig; +use rand::distributions::{Alphanumeric, Distribution}; +use rand::thread_rng; +use std::env; +use std::fs::{self, File}; +use std::io::prelude::*; +use std::io::BufReader; +use std::path::{Path, PathBuf}; +use toml; /// Wallet configuration file name pub const WALLET_CONFIG_FILE_NAME: &str = "grin-wallet.toml"; const WALLET_LOG_FILE_NAME: &str = "grin-wallet.log"; -const GRIN_HOME: &str = ".grin"; +/// .grin folder, usually in home/.grin +pub const GRIN_HOME: &str = ".grin"; /// Wallet data directory pub const GRIN_WALLET_DIR: &str = "wallet_data"; /// Node API secret @@ -43,31 +42,85 @@ pub const API_SECRET_FILE_NAME: &str = ".foreign_api_secret"; /// Owner API secret pub const OWNER_API_SECRET_FILE_NAME: &str = ".owner_api_secret"; -fn get_grin_path( +/// Function to locate the wallet dir and grin-wallet.toml in the order +/// a) config in top-dir if provided, b) in working dir, c) default dir +/// Function to get wallet dir and create dirs if not existing +pub fn get_wallet_path( chain_type: &global::ChainTypes, create_path: bool, ) -> Result { - // Check if grin dir exists - let mut grin_path = match dirs::home_dir() { + // A - Detect grin-wallet.toml in working dir + let mut config_path = std::env::current_dir()?; + config_path.push(WALLET_CONFIG_FILE_NAME); + if create_path == false && config_path.exists() { + config_path.pop(); + println!("Detected 'grin-wallet.toml' in working dir - opening associated wallet"); + return Ok(config_path); + }; + // B - Select home directory + let mut wallet_path = match dirs::home_dir() { Some(p) => p, None => PathBuf::new(), }; - grin_path.push(GRIN_HOME); - grin_path.push(chain_type.shortname()); + wallet_path.push(GRIN_HOME); + wallet_path.push(chain_type.shortname()); // Create if the default path doesn't exist - if !grin_path.exists() && create_path { - fs::create_dir_all(grin_path.clone())?; + if !wallet_path.exists() && create_path { + fs::create_dir_all(wallet_path.clone())?; } - - if !grin_path.exists() { + // Throw an error if the path still does not exist + if !wallet_path.exists() { Err(ConfigError::PathNotFoundError(String::from( - grin_path.to_str().unwrap(), + wallet_path.to_str().unwrap(), ))) } else { - Ok(grin_path) + Ok(wallet_path) } } +/// Smart function to detect the nodes .foreign_api_secret file in the order +/// a) top-dir, b) home directory - create directory if needed +pub fn get_node_path( + data_path: Option, + chain_type: &global::ChainTypes, +) -> Result { + let node_path = match data_path { + // 1) A If top dir provided and api_secret exist, return top dir + Some(path) => { + let mut node_path = path; + node_path.push(GRIN_HOME); + node_path.push(chain_type.shortname()); + node_path.push(API_SECRET_FILE_NAME); + if node_path.exists() { + node_path.pop(); + Ok(node_path) + // 1) B If top dir exists, but no api_secret, return home dir + } else { + let mut node_path = match dirs::home_dir() { + Some(p) => p, + None => PathBuf::new(), + }; + node_path.push(GRIN_HOME); + node_path.push(chain_type.shortname()); + Ok(node_path) + } + } + // 2) If there is no top_dir provided, always return home dir + None => { + let mut node_path = match dirs::home_dir() { + Some(p) => p, + None => PathBuf::new(), + }; + node_path.push(GRIN_HOME); + node_path.push(chain_type.shortname()); + Ok(node_path) + } + }; + node_path +} + +/// Checks if config in current working dir +#[allow(dead_code)] fn check_config_current_dir(path: &str) -> Option { let p = env::current_dir(); let mut c = match p { @@ -122,7 +175,7 @@ fn check_api_secret_file( ) -> Result<(), ConfigError> { let grin_path = match data_path { Some(p) => p, - None => get_grin_path(chain_type, false)?, + None => get_node_path(data_path, chain_type)?, }; let mut api_secret_path = grin_path; api_secret_path.push(file_name); @@ -133,55 +186,99 @@ fn check_api_secret_file( } } -/// Handles setup and detection of paths for wallet +/// Initial wallet setup does the following +/// 1) Load wallet config if run without 'init' 2) create wallet if run with 'init'' +/// Try in thiss order a) current dir as template, b) in top path, or c) .grin home +/// - load default config values +/// - update the wallet and node dir to the correct paths +/// - if grin-wallet.toml exists, but the wallet data dir does not, load config and continue wallet generation +/// - Automatically detect grin-wallet.toml in current directory pub fn initial_setup_wallet( chain_type: &global::ChainTypes, - data_path: Option, + mut data_path: Option, create_path: bool, ) -> Result { - if create_path { - if let Some(p) = data_path.clone() { - fs::create_dir_all(p)?; + // Fixing the input path when run with -here or -t (top-dir) + // - Fix top-dir path to compensate for bug on Linux to handle "\" + // - Convert top-dir path to be always absolute for config generation + // - Fix for Windows 10/11 to strip the '\\?\' prefix added to the path + if let Some(p) = &data_path { + if let Some(p_str) = p.to_str() { + let fixed_str = p_str.replace("\\", "/"); + let fixed_path = PathBuf::from(fixed_str); + if create_path { + fs::create_dir_all(&fixed_path)?; + } + let absolute_path = if fixed_path.is_absolute() { + fixed_path.canonicalize()? + } else { + env::current_dir()?.join(&fixed_path).canonicalize()? + }; + let absolute_path = + std::path::PathBuf::from(absolute_path.to_str().unwrap().replace(r"\\?\", "")); + data_path = Some(absolute_path); // Store the updated path } } - // Use config file if current directory if it exists, .grin home otherwise - let (path, config) = if let Some(p) = check_config_current_dir(WALLET_CONFIG_FILE_NAME) { - let mut path = p.clone(); - path.pop(); - (path, GlobalWalletConfig::new(p.to_str().unwrap())?) - } else { - // Check if grin dir exists - let grin_path = match data_path { - Some(p) => p, - None => get_grin_path(chain_type, create_path)?, - }; - // Get path to default config file - let mut config_path = grin_path.clone(); - config_path.push(WALLET_CONFIG_FILE_NAME); + // Get wallet data_dir path if none provided + let wallet_path = match data_path { + Some(p) => p, + None => get_wallet_path(chain_type, create_path)?, + }; + println!("Wallet path: {}", wallet_path.display()); + // Get path to the node directory, + let node_path = get_node_path(Some(wallet_path.clone()), chain_type)?; - // Return defaults if file doesn't exist - match config_path.clone().exists() { - false => { - let mut default_config = GlobalWalletConfig::for_chain(chain_type); - default_config.config_file_path = Some(config_path); - // update paths relative to current dir - default_config.update_paths(&grin_path); - (grin_path, default_config) + // Get config path and data path + let mut config_path = wallet_path.clone(); + config_path.push(WALLET_CONFIG_FILE_NAME); + let mut data_dir = wallet_path.clone(); + data_dir.push(GRIN_WALLET_DIR); + // Check if a config exists in theworking dir, if so load it + let (path, config) = match config_path.clone().exists() { + // If the config does not exist, load default and updated node and wallet dir + false => { + let mut default_config = GlobalWalletConfig::for_chain(chain_type); + default_config.config_file_path = Some(config_path.clone()); + default_config.update_paths(&wallet_path, &node_path); + + // Write config file + let res = + default_config.write_to_file(config_path.to_str().unwrap(), false, None, None); + + if let Err(e) = res { + let msg = format!( + "Error creating config file as ({}): {}", + config_path.to_str().unwrap(), + e + ); + return Err(ConfigError::SerializationError(msg)); } - true => { - let mut path = config_path.clone(); - path.pop(); - ( - path, - GlobalWalletConfig::new(config_path.to_str().unwrap())?, - ) + + (wallet_path, default_config) + } + + // Return config if not run with init + true => { + // If run with init and seed does not yet exists, continue, else throw error + if data_dir.exists() && create_path == true { + let msg = format!( + "{} already exists in the target directory ({}). Please remove it first", + config_path.to_str().unwrap(), + data_dir.to_str().unwrap(), + ); + return Err(ConfigError::SerializationError(msg)); + } else { + let config = GlobalWalletConfig::new(config_path.to_str().unwrap())?; + (wallet_path, config) } } }; + // Check API secrets, if ok, return config check_api_secret_file(chain_type, Some(path.clone()), OWNER_API_SECRET_FILE_NAME)?; check_api_secret_file(chain_type, Some(path), API_SECRET_FILE_NAME)?; + Ok(config) } @@ -211,7 +308,7 @@ impl GlobalWalletConfig { pub fn for_chain(chain_type: &global::ChainTypes) -> GlobalWalletConfig { let mut defaults_conf = GlobalWalletConfig::default(); let defaults = &mut defaults_conf.members.as_mut().unwrap().wallet; - defaults.chain_type = Some(chain_type.clone()); + defaults.chain_type = Some(*chain_type); match *chain_type { global::ChainTypes::Mainnet => {} @@ -268,21 +365,22 @@ impl GlobalWalletConfig { } /// 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 secret_path = wallet_home.clone(); - secret_path.push(OWNER_API_SECRET_FILE_NAME); - self.members.as_mut().unwrap().wallet.api_secret_path = - Some(secret_path.to_str().unwrap().to_owned()); - let mut node_secret_path = wallet_home.clone(); + pub fn update_paths(&mut self, wallet_home: &PathBuf, node_home: &Path) { + let mut data_file_dir = wallet_home.to_path_buf(); + let mut node_secret_path = node_home.to_path_buf(); + let mut secret_path = wallet_home.to_path_buf(); + let mut log_path = wallet_home.to_path_buf(); + let tor_path = wallet_home.to_path_buf(); node_secret_path.push(API_SECRET_FILE_NAME); + data_file_dir.push(GRIN_WALLET_DIR); + secret_path.push(OWNER_API_SECRET_FILE_NAME); + log_path.push(WALLET_LOG_FILE_NAME); + self.members.as_mut().unwrap().wallet.data_file_dir = + data_file_dir.to_str().unwrap().to_owned(); self.members.as_mut().unwrap().wallet.node_api_secret_path = Some(node_secret_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().wallet.api_secret_path = + Some(secret_path.to_str().unwrap().to_owned()); self.members .as_mut() .unwrap() @@ -290,7 +388,6 @@ impl GlobalWalletConfig { .as_mut() .unwrap() .log_file_path = log_path.to_str().unwrap().to_owned(); - let tor_path = wallet_home.clone(); self.members .as_mut() .unwrap() @@ -339,7 +436,7 @@ impl GlobalWalletConfig { ) -> Result { let config: GlobalWalletConfigMembers = toml::from_str(&GlobalWalletConfig::fix_warning_level(config_str.clone())).unwrap(); - if config.config_file_version != None { + if config.config_file_version.is_some() { return Ok(config_str); } let adjusted_config = GlobalWalletConfigMembers { @@ -347,7 +444,7 @@ impl GlobalWalletConfig { tor: Some(TorConfig { bridge: TorBridgeConfig::default(), proxy: TorProxyConfig::default(), - ..config.tor.unwrap_or(TorConfig::default()) + ..config.tor.unwrap_or_default() }), ..config }; @@ -379,4 +476,4 @@ impl GlobalWalletConfig { .replace("WARN", "Warning") .replace("ERROR", "Error") } -} +} \ No newline at end of file diff --git a/controller/src/command.rs b/controller/src/command.rs index 938eb82..536a3f3 100644 --- a/controller/src/command.rs +++ b/controller/src/command.rs @@ -70,6 +70,7 @@ pub struct InitArgs { pub restore: bool, } +/// Write config (default if None), initiate the wallet pub fn init( owner_api: &mut Owner, _g_args: &GlobalArgs, @@ -81,7 +82,7 @@ where C: NodeClient + 'static, K: keychain::Keychain + 'static, { - // Assume global chain type has already been initialized. +// Assume global chain type has already been initialized. let chain_type = global::get_chain_type(); let mut w_lock = owner_api.wallet_inst.lock(); diff --git a/controller/tests/transaction.rs b/controller/tests/transaction.rs index fa34014..33db4c9 100644 --- a/controller/tests/transaction.rs +++ b/controller/tests/transaction.rs @@ -442,7 +442,7 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> { // few values to keep things shorter let reward = core::consensus::REWARD; let cm = global::coinbase_maturity(); // assume all testing precedes soft fork height - // mine a few blocks + // mine a few blocks let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 5, false); let amount = 30_000_000_000; diff --git a/impls/src/lifecycle/default.rs b/impls/src/lifecycle/default.rs index d0cc606..0b24b68 100644 --- a/impls/src/lifecycle/default.rs +++ b/impls/src/lifecycle/default.rs @@ -27,6 +27,15 @@ use crate::LMDBBackend; use grin_util::logger::LoggingConfig; use std::fs; use std::path::PathBuf; +use std::path::MAIN_SEPARATOR; + +// Helper fuction to format paths according to OS, avoids bugs on Linux +pub fn fmt_path(path: String) -> String { + let sep = &MAIN_SEPARATOR.to_string(); + let path = path.replace("/", &sep); + let path = path.replace("\\", &sep); + path +} pub struct DefaultLCProvider<'a, C, K> where @@ -64,7 +73,13 @@ where } fn get_top_level_directory(&self) -> Result { - Ok(self.data_dir.to_owned()) + let sep = &MAIN_SEPARATOR.to_string(); + let data_dir = self + .data_dir + .to_owned() + .replace("/", &sep) + .replace("\\", &sep); + Ok(data_dir) } fn create_config( @@ -87,11 +102,12 @@ where None => None, }, }; - let wallet = match wallet_config { - Some(w) => w, + // Check if config was provided, if not load default and set update to "true" + let (wallet, update) = match wallet_config { + Some(w) => (w, false), None => match default_config.members.as_ref() { - Some(m) => m.clone().wallet, - None => WalletConfig::default(), + Some(m) => (m.clone().wallet, true), + None => (WalletConfig::default(), true), }, }; let tor = match tor_config { @@ -113,13 +129,6 @@ where let mut config_file_name = PathBuf::from(self.data_dir.clone()); config_file_name.push(file_name); - // create top level dir if it doesn't exist - let dd = PathBuf::from(self.data_dir.clone()); - if !dd.exists() { - // try create - fs::create_dir_all(dd)?; - } - let mut data_dir_name = PathBuf::from(self.data_dir.clone()); data_dir_name.push(GRIN_WALLET_DIR); @@ -132,15 +141,26 @@ where return Err(Error::Lifecycle(msg)); } - // just leave as is if file exists but there's no data dir + // If config exists but the datadir return ok if config_file_name.exists() { return Ok(()); } + // default settings are updated if no config was provided, no support for top_dir/here + let mut abs_path_node = std::env::current_dir()?; + abs_path_node.push(self.data_dir.clone()); + let mut absolute_path_wallet = std::env::current_dir()?; + absolute_path_wallet.push(self.data_dir.clone()); - let mut abs_path = std::env::current_dir()?; - abs_path.push(self.data_dir.clone()); - - default_config.update_paths(&abs_path); + // if no config provided, update defaults + if update == true { + // create top level dir if it doesn't exist + let dd = PathBuf::from(self.data_dir.clone()); + if !dd.exists() { + // try create + fs::create_dir_all(dd)?; + default_config.update_paths(&abs_path_node, &absolute_path_wallet); + } + }; let res = default_config.write_to_file(config_file_name.to_str().unwrap(), false, None, None); if let Err(e) = res { @@ -178,7 +198,7 @@ where ) -> Result<(), Error> { let mut data_dir_name = PathBuf::from(self.data_dir.clone()); data_dir_name.push(GRIN_WALLET_DIR); - let data_dir_name = data_dir_name.to_str().unwrap(); + let data_dir_name = fmt_path((data_dir_name.to_str().unwrap()).to_string()); let exists = WalletSeed::seed_file_exists(&data_dir_name); if !test_mode { if let Ok(true) = exists { @@ -226,7 +246,7 @@ where ) -> Result, Error> { let mut data_dir_name = PathBuf::from(self.data_dir.clone()); data_dir_name.push(GRIN_WALLET_DIR); - let data_dir_name = data_dir_name.to_str().unwrap(); + let data_dir_name = fmt_path(data_dir_name.to_str().unwrap().to_string()); let mut wallet: LMDBBackend<'a, C, K> = match LMDBBackend::new(&data_dir_name, self.node_client.clone()) { Err(e) => { @@ -271,7 +291,7 @@ where ) -> Result { let mut data_dir_name = PathBuf::from(self.data_dir.clone()); data_dir_name.push(GRIN_WALLET_DIR); - let data_dir_name = data_dir_name.to_str().unwrap(); + let data_dir_name = fmt_path(data_dir_name.display().to_string()); let wallet_seed = WalletSeed::from_file(&data_dir_name, password) .map_err(|_| Error::Lifecycle("Error opening wallet seed file".into()))?; let res = wallet_seed diff --git a/impls/src/lifecycle/seed.rs b/impls/src/lifecycle/seed.rs index e7b6b46..59dcd34 100644 --- a/impls/src/lifecycle/seed.rs +++ b/impls/src/lifecycle/seed.rs @@ -12,16 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +use crate::blake2; use core::num::NonZeroU32; +use rand::{thread_rng, Rng}; +use serde_json; use std::fs::{self, File}; use std::io::{Read, Write}; use std::path::Path; use std::path::MAIN_SEPARATOR; -use crate::blake2; -use rand::{thread_rng, Rng}; -use serde_json; - use ring::aead; use ring::pbkdf2; @@ -57,6 +56,13 @@ impl WalletSeed { self.0.to_vec().to_hex() } + // Helper fuction to format paths according to OS, avoids bugs on Linux + pub fn fmt_path(path: String) -> String { + let sep = &MAIN_SEPARATOR.to_string(); + let path = path.replace("/", &sep); + let path = path.replace("\\", &sep); + path + } pub fn to_mnemonic(&self) -> Result { let result = mnemonic::from_entropy(&self.0); match result { @@ -97,7 +103,12 @@ impl WalletSeed { } pub fn seed_file_exists(data_file_dir: &str) -> Result { - let seed_file_path = &format!("{}{}{}", data_file_dir, MAIN_SEPARATOR, SEED_FILE,); + let seed_file_path = &format!( + "{}{}{}", + Self::fmt_path(data_file_dir.to_string()), + MAIN_SEPARATOR, + SEED_FILE, + ); debug!("Seed file path: {}", seed_file_path); if Path::new(seed_file_path).exists() { Ok(true) @@ -132,7 +143,12 @@ impl WalletSeed { word_list: util::ZeroingString, password: util::ZeroingString, ) -> Result<(), Error> { - let seed_file_path = &format!("{}{}{}", data_file_dir, MAIN_SEPARATOR, SEED_FILE,); + let seed_file_path = &format!( + "{}{}{}", + Self::fmt_path(data_file_dir.to_string()), + MAIN_SEPARATOR, + SEED_FILE, + ); debug!("data file dir: {}", data_file_dir); if let Ok(true) = WalletSeed::seed_file_exists(data_file_dir) { debug!("seed file exists"); @@ -166,10 +182,15 @@ impl WalletSeed { // create directory if it doesn't exist fs::create_dir_all(data_file_dir).map_err(|_| Error::IO)?; - let seed_file_path = &format!("{}{}{}", data_file_dir, MAIN_SEPARATOR, SEED_FILE,); - + let seed_file_path = &format!( + "{}{}{}", + Self::fmt_path(data_file_dir.to_string()), + MAIN_SEPARATOR, + SEED_FILE, + ); + let data_file_dir = Self::fmt_path(data_file_dir.to_string()); warn!("Generating wallet seed file at: {}", seed_file_path); - let exists = WalletSeed::seed_file_exists(data_file_dir)?; + let exists = WalletSeed::seed_file_exists(&data_file_dir)?; if exists && !test_mode { let msg = format!("Wallet seed already exists at: {}", data_file_dir); error!("{}", msg); @@ -196,7 +217,12 @@ impl WalletSeed { // create directory if it doesn't exist fs::create_dir_all(data_file_dir).map_err(|_| Error::IO)?; - let seed_file_path = &format!("{}{}{}", data_file_dir, MAIN_SEPARATOR, SEED_FILE,); + let seed_file_path = &format!( + "{}{}{}", + Self::fmt_path(data_file_dir.to_string()), + MAIN_SEPARATOR, + SEED_FILE, + ); debug!("Using wallet seed file at: {}", seed_file_path); @@ -219,7 +245,12 @@ impl WalletSeed { } pub fn delete_seed_file(data_file_dir: &str) -> Result<(), Error> { - let seed_file_path = &format!("{}{}{}", data_file_dir, MAIN_SEPARATOR, SEED_FILE,); + let seed_file_path = &format!( + "{}{}{}", + Self::fmt_path(data_file_dir.to_string()), + MAIN_SEPARATOR, + SEED_FILE, + ); if Path::new(seed_file_path).exists() { debug!("Deleting wallet seed file at: {}", seed_file_path); fs::remove_file(seed_file_path).map_err(|_| Error::IO)?; diff --git a/impls/src/node_clients/http.rs b/impls/src/node_clients/http.rs index 66efeb7..6b80b49 100644 --- a/impls/src/node_clients/http.rs +++ b/impls/src/node_clients/http.rs @@ -142,7 +142,8 @@ impl NodeClient for HTTPNodeClient { verified: Some(false), }); } else { - error!("Unable to contact Node to get version info: {}", e); + error!("Unable to contact Node to get version info: {}, check your node is running", e); + warn!("Warning: a) Node is offline, or b) 'node_api_secret_path' in 'grin-wallet.toml' is set incorrectly"); return None; } } diff --git a/src/bin/grin-wallet.rs b/src/bin/grin-wallet.rs index 3a192fd..9189f02 100644 --- a/src/bin/grin-wallet.rs +++ b/src/bin/grin-wallet.rs @@ -24,12 +24,12 @@ use crate::util::init_logger; use clap::App; use grin_core as core; use grin_util as util; +use grin_wallet::cmd; use grin_wallet_config as config; use grin_wallet_impls::HTTPNodeClient; use std::env; use std::path::PathBuf; - -use grin_wallet::cmd; +use std::path::MAIN_SEPARATOR; // include build information pub mod built_info { @@ -55,6 +55,13 @@ pub fn info_strings() -> (String, String) { ) } +// Helper fuction to format paths according to OS, avoids bugs on Linux +pub fn fmt_path(path: String) -> String { + let sep = &MAIN_SEPARATOR.to_string(); + let path = path.replace("/", &sep).replace("\\", &sep); + path +} + fn log_build_info() { let (basic_info, detailed_info) = info_strings(); info!("{}", basic_info); @@ -82,11 +89,11 @@ fn real_main() -> i32 { let mut current_dir = None; let mut create_path = false; - if args.is_present("top_level_dir") { let res = args.value_of("top_level_dir"); match res { Some(d) => { + let d = fmt_path(d.to_owned().to_string()); // Fix for fs to work with paths on Linux current_dir = Some(PathBuf::from(d)); } None => { @@ -138,7 +145,6 @@ fn real_main() -> i32 { "Using wallet configuration file at {}", config.config_file_path.as_ref().unwrap().to_str().unwrap() ); - log_build_info(); global::init_global_chain_type( @@ -154,9 +160,7 @@ fn real_main() -> i32 { ); global::init_global_accept_fee_base(config.members.as_ref().unwrap().wallet.accept_fee_base()); - let wallet_config = config.clone().members.unwrap().wallet; let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None).unwrap(); - cmd::wallet_command(&args, config, node_client) } diff --git a/src/cmd/wallet_args.rs b/src/cmd/wallet_args.rs index 866db6c..205cc0e 100644 --- a/src/cmd/wallet_args.rs +++ b/src/cmd/wallet_args.rs @@ -24,7 +24,7 @@ use grin_core as core; use grin_core::core::amount_to_hr_string; use grin_keychain as keychain; use grin_wallet_api::Owner; -use grin_wallet_config::{config_file_exists, TorConfig, WalletConfig}; +use grin_wallet_config::{TorConfig, WalletConfig}; use grin_wallet_controller::{command, Error}; use grin_wallet_impls::{DefaultLCProvider, DefaultWalletImpl}; use grin_wallet_libwallet::{self, Slate, SlatepackAddress, SlatepackArmor}; @@ -332,7 +332,7 @@ pub fn parse_init_args( config: &WalletConfig, g_args: &command::GlobalArgs, args: &ArgMatches, - test_mode: bool, + _test_mode: bool, ) -> Result where DefaultWalletImpl<'static, C>: WalletInst<'static, L, C, K>, @@ -340,10 +340,6 @@ where C: NodeClient + 'static, K: keychain::Keychain + 'static, { - if config_file_exists(&config.data_file_dir) && !test_mode { - return Err(ParseError::WalletExists(config.data_file_dir.clone())); - } - let list_length = match args.is_present("short_wordlist") { false => 32, true => 16, @@ -1004,7 +1000,7 @@ where node_client.set_node_api_secret(global_wallet_args.node_api_secret.clone()); // legacy hack to avoid the need for changes in existing grin-wallet.toml files - // remove `wallet_data` from end of path as + // remove `wallet_data` from end of path // new lifecycle provider assumes grin_wallet.toml is in root of data directory let mut top_level_wallet_dir = PathBuf::from(wallet_config.clone().data_file_dir); if top_level_wallet_dir.ends_with(GRIN_WALLET_DIR) { diff --git a/tests/common/mod.rs b/tests/common/mod.rs index de71fc9..569fd33 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -165,7 +165,7 @@ pub fn config_command_wallet( .to_owned(), ))?; } - default_config.update_paths(¤t_dir); + default_config.update_paths(¤t_dir, ¤t_dir); default_config .write_to_file(config_file_name.to_str().unwrap(), false, None, None) .unwrap_or_else(|e| {