diff --git a/config/src/config.rs b/config/src/config.rs index d334b41b6..3ec8e78f7 100644 --- a/config/src/config.rs +++ b/config/src/config.rs @@ -44,7 +44,8 @@ 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"; +/// Wallet data directory +pub const GRIN_WALLET_DIR: &'static str = "wallet_data"; const API_SECRET_FILE_NAME: &'static str = ".api_secret"; fn get_grin_path(chain_type: &global::ChainTypes) -> Result { diff --git a/config/src/lib.rs b/config/src/lib.rs index aec60bc5e..81bc671c7 100644 --- a/config/src/lib.rs +++ b/config/src/lib.rs @@ -36,5 +36,5 @@ mod comments; pub mod config; pub mod types; -pub use crate::config::{initial_setup_server, initial_setup_wallet}; +pub use crate::config::{initial_setup_server, initial_setup_wallet, GRIN_WALLET_DIR}; pub use crate::types::{ConfigError, ConfigMembers, GlobalConfig, GlobalWalletConfig}; diff --git a/servers/tests/framework.rs b/servers/tests/framework.rs index b4c339220..a32cae692 100644 --- a/servers/tests/framework.rs +++ b/servers/tests/framework.rs @@ -272,7 +272,7 @@ impl LocalServerContainer { self.wallet_config.owner_api_include_foreign = Some(self.config.owner_api_include_foreign); let _ = fs::create_dir_all(self.wallet_config.clone().data_file_dir); - let r = wallet::WalletSeed::init_file(&self.wallet_config, 32, ""); + let r = wallet::WalletSeed::init_file(&self.wallet_config, 32, None, ""); let client_n = HTTPNodeClient::new(&self.wallet_config.check_node_api_http_addr, None); @@ -331,7 +331,7 @@ impl LocalServerContainer { pub fn get_wallet_seed(config: &WalletConfig) -> wallet::WalletSeed { let _ = fs::create_dir_all(config.clone().data_file_dir); - wallet::WalletSeed::init_file(config, 32, "").unwrap(); + wallet::WalletSeed::init_file(config, 32, None, "").unwrap(); let wallet_seed = wallet::WalletSeed::from_file(config, "").expect("Failed to read wallet seed file."); wallet_seed diff --git a/servers/tests/simulnet.rs b/servers/tests/simulnet.rs index a91157221..c04cde17c 100644 --- a/servers/tests/simulnet.rs +++ b/servers/tests/simulnet.rs @@ -879,7 +879,7 @@ pub fn create_wallet( ) -> Arc>> { let mut wallet_config = WalletConfig::default(); wallet_config.data_file_dir = String::from(dir); - let _ = wallet::WalletSeed::init_file(&wallet_config, 32, ""); + let _ = wallet::WalletSeed::init_file(&wallet_config, 32, None, ""); let mut wallet: LMDBBackend = LMDBBackend::new(wallet_config.clone(), "", client_n).unwrap_or_else(|e| { panic!("Error creating wallet: {:?} Config: {:?}", e, wallet_config) diff --git a/src/bin/cmd/config.rs b/src/bin/cmd/config.rs index 16b7b38c3..8405fb510 100644 --- a/src/bin/cmd/config.rs +++ b/src/bin/cmd/config.rs @@ -13,7 +13,7 @@ // limitations under the License. /// Grin configuration file output command -use crate::config::{GlobalConfig, GlobalWalletConfig}; +use crate::config::{GlobalConfig, GlobalWalletConfig, GRIN_WALLET_DIR}; use crate::core::global; use std::env; @@ -52,12 +52,22 @@ pub fn config_command_wallet(chain_type: &global::ChainTypes, file_name: &str) { }); let mut config_file_name = current_dir.clone(); config_file_name.push(file_name); - if config_file_name.exists() { + + let mut data_dir_name = current_dir.clone(); + data_dir_name.push(GRIN_WALLET_DIR); + + if config_file_name.exists() && data_dir_name.exists() { panic!( "{} already exists in the target directory. Please remove it first", file_name ); } + + // just leave as is if file exists but there's no data dir + if config_file_name.exists() { + return; + } + default_config.update_paths(¤t_dir); default_config .write_to_file(config_file_name.to_str().unwrap()) diff --git a/src/bin/cmd/wallet.rs b/src/bin/cmd/wallet.rs index 069ae817a..31328ec75 100644 --- a/src/bin/cmd/wallet.rs +++ b/src/bin/cmd/wallet.rs @@ -22,7 +22,7 @@ use std::time::Duration; pub fn _init_wallet_seed(wallet_config: WalletConfig, password: &str) { if let Err(_) = WalletSeed::from_file(&wallet_config, password) { - WalletSeed::init_file(&wallet_config, 32, password) + WalletSeed::init_file(&wallet_config, 32, None, password) .expect("Failed to create wallet seed file."); }; } diff --git a/src/bin/cmd/wallet_args.rs b/src/bin/cmd/wallet_args.rs index b4528422f..54bab998f 100644 --- a/src/bin/cmd/wallet_args.rs +++ b/src/bin/cmd/wallet_args.rs @@ -233,15 +233,28 @@ pub fn parse_init_args( false => 32, true => 16, }; - println!("Please enter a password for your new wallet"); + let recovery_phrase = match args.is_present("recover") { + true => Some(prompt_recovery_phrase()?), + false => None, + }; + + if recovery_phrase.is_some() { + println!("Please provide a new password for the recovered wallet"); + } else { + println!("Please enter a password for your new wallet"); + } + let password = match g_args.password.clone() { Some(p) => p, None => prompt_password_confirm(), }; + Ok(command::InitArgs { list_length: list_length, password: password, config: config.clone(), + recovery_phrase: recovery_phrase, + restore: false, }) } diff --git a/src/bin/grin.yml b/src/bin/grin.yml index 772ab41a2..74e4d1b05 100644 --- a/src/bin/grin.yml +++ b/src/bin/grin.yml @@ -284,6 +284,11 @@ subcommands: short: s long: short_wordlist takes_value: false + - recover: + help: Initialize new wallet using a recovery phrase + short: r + long: recover + takes_value: false - recover: about: Recover a wallet.seed file from a recovery phrase (default) or displays a recovery phrase for an existing seed file args: diff --git a/wallet/src/command.rs b/wallet/src/command.rs index 2a4412998..175308fcd 100644 --- a/wallet/src/command.rs +++ b/wallet/src/command.rs @@ -51,10 +51,17 @@ pub struct InitArgs { pub list_length: usize, pub password: String, pub config: WalletConfig, + pub recovery_phrase: Option, + pub restore: bool, } pub fn init(g_args: &GlobalArgs, args: InitArgs) -> Result<(), Error> { - WalletSeed::init_file(&args.config, args.list_length, &args.password)?; + WalletSeed::init_file( + &args.config, + args.list_length, + args.recovery_phrase, + &args.password, + )?; info!("Wallet seed file created"); let client_n = HTTPNodeClient::new( &args.config.check_node_api_http_addr, diff --git a/wallet/src/test_framework/mod.rs b/wallet/src/test_framework/mod.rs index 98f2b4a0b..bbb8e8bfd 100644 --- a/wallet/src/test_framework/mod.rs +++ b/wallet/src/test_framework/mod.rs @@ -160,7 +160,7 @@ where { let mut wallet_config = WalletConfig::default(); wallet_config.data_file_dir = String::from(dir); - let _ = WalletSeed::init_file(&wallet_config, 32, ""); + let _ = WalletSeed::init_file(&wallet_config, 32, None, ""); let mut wallet = LMDBBackend::new(wallet_config.clone(), "", n_client) .unwrap_or_else(|e| panic!("Error creating wallet: {:?} Config: {:?}", e, wallet_config)); wallet.open_with_credentials().unwrap_or_else(|e| { diff --git a/wallet/src/types.rs b/wallet/src/types.rs index d0090ebba..4831a4230 100644 --- a/wallet/src/types.rs +++ b/wallet/src/types.rs @@ -216,6 +216,7 @@ impl WalletSeed { pub fn init_file( wallet_config: &WalletConfig, seed_length: usize, + recovery_phrase: Option, password: &str, ) -> Result { // create directory if it doesn't exist @@ -229,7 +230,11 @@ impl WalletSeed { warn!("Generating wallet seed file at: {}", seed_file_path); let _ = WalletSeed::seed_file_exists(wallet_config)?; - let seed = WalletSeed::init_new(seed_length); + let seed = match recovery_phrase { + Some(p) => WalletSeed::from_mnemonic(&p)?, + None => WalletSeed::init_new(seed_length), + }; + let enc_seed = EncryptedWalletSeed::from_seed(&seed, password)?; let enc_seed_json = serde_json::to_string_pretty(&enc_seed).context(ErrorKind::Format)?; let mut file = File::create(seed_file_path).context(ErrorKind::IO)?;