Automate wallet seed recovery process (#2319)

This commit is contained in:
Yeastplume 2019-01-09 16:13:05 +00:00 committed by GitHub
parent ea38e15a6f
commit 5915580ab3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 82 additions and 2 deletions

View file

@ -74,6 +74,33 @@ fn prompt_password_confirm() -> String {
first
}
fn prompt_replace_seed() -> Result<bool, ParseError> {
let interface = Arc::new(Interface::new("replace_seed")?);
interface.set_report_signal(Signal::Interrupt, true);
interface.set_prompt("Replace seed? (y/n)> ")?;
println!();
println!("Existing wallet.seed file already exists. Continue?");
println!("Continuing will back up your existing 'wallet.seed' file as 'wallet.seed.bak'");
println!();
loop {
let res = interface.read_line()?;
match res {
ReadResult::Eof => return Ok(false),
ReadResult::Signal(sig) => {
if sig == Signal::Interrupt {
interface.cancel_read_line()?;
return Err(ParseError::CancelledError);
}
}
ReadResult::Input(line) => match line.trim() {
"Y" | "y" => return Ok(true),
"N" | "n" => return Ok(false),
_ => println!("Please respond y or n"),
},
}
}
}
fn prompt_recovery_phrase() -> Result<String, ParseError> {
let interface = Arc::new(Interface::new("recover")?);
let mut phrase = String::new();
@ -219,6 +246,7 @@ pub fn parse_init_args(
}
pub fn parse_recover_args(
config: &WalletConfig,
g_args: &command::GlobalArgs,
args: &ArgMatches,
) -> Result<command::RecoverArgs, ParseError> {
@ -226,6 +254,16 @@ pub fn parse_recover_args(
match args.is_present("display") {
true => (prompt_password(&g_args.password), None),
false => {
let cont = {
if command::wallet_seed_exists(config).is_err() {
prompt_replace_seed()?
} else {
true
}
};
if !cont {
return Err(ParseError::CancelledError);
}
let phrase = prompt_recovery_phrase()?;
println!("Please provide a new password for the recovered wallet");
(prompt_password_confirm(), Some(phrase.to_owned()))
@ -482,7 +520,11 @@ pub fn wallet_command(
command::init(&global_wallet_args, a)
}
("recover", Some(args)) => {
let a = arg_parse!(parse_recover_args(&global_wallet_args, &args));
let a = arg_parse!(parse_recover_args(
&wallet_config,
&global_wallet_args,
&args
));
command::recover(&wallet_config, a)
}
("listen", Some(args)) => {

View file

@ -72,6 +72,12 @@ pub struct RecoverArgs {
pub passphrase: String,
}
/// Check whether seed file exists
pub fn wallet_seed_exists(config: &WalletConfig) -> Result<(), Error> {
let res = WalletSeed::seed_file_exists(&config)?;
Ok(res)
}
pub fn recover(config: &WalletConfig, args: RecoverArgs) -> Result<(), Error> {
if args.recovery_phrase.is_none() {
let res = WalletSeed::from_file(config, &args.passphrase);

View file

@ -152,6 +152,36 @@ impl WalletSeed {
Ok(())
}
pub fn backup_seed(wallet_config: &WalletConfig) -> Result<(), Error> {
let seed_file_name = &format!(
"{}{}{}",
wallet_config.data_file_dir, MAIN_SEPARATOR, SEED_FILE,
);
let mut path = Path::new(seed_file_name).to_path_buf();
path.pop();
let mut backup_seed_file_name = format!(
"{}{}{}.bak",
wallet_config.data_file_dir, MAIN_SEPARATOR, SEED_FILE
);
let mut i = 1;
while Path::new(&backup_seed_file_name).exists() {
backup_seed_file_name = format!(
"{}{}{}.bak.{}",
wallet_config.data_file_dir, MAIN_SEPARATOR, SEED_FILE, i
);
i += 1;
}
path.push(backup_seed_file_name.clone());
if let Err(_) = fs::rename(seed_file_name, backup_seed_file_name.as_str()) {
return Err(ErrorKind::GenericError(
"Can't rename wallet seed file".to_owned(),
))?;
}
warn!("{} backed up as {}", seed_file_name, backup_seed_file_name);
Ok(())
}
pub fn recover_from_phrase(
wallet_config: &WalletConfig,
word_list: &str,
@ -161,7 +191,9 @@ impl WalletSeed {
"{}{}{}",
wallet_config.data_file_dir, MAIN_SEPARATOR, SEED_FILE,
);
let _ = WalletSeed::seed_file_exists(wallet_config)?;
if WalletSeed::seed_file_exists(wallet_config).is_err() {
WalletSeed::backup_seed(wallet_config)?;
}
let seed = WalletSeed::from_mnemonic(word_list)?;
let enc_seed = EncryptedWalletSeed::from_seed(&seed, password)?;
let enc_seed_json = serde_json::to_string_pretty(&enc_seed).context(ErrorKind::Format)?;