mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-21 03:21:08 +03:00
Automate wallet seed recovery process (#2319)
This commit is contained in:
parent
ea38e15a6f
commit
5915580ab3
3 changed files with 82 additions and 2 deletions
|
@ -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)) => {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)?;
|
||||
|
|
Loading…
Reference in a new issue