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
|
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> {
|
fn prompt_recovery_phrase() -> Result<String, ParseError> {
|
||||||
let interface = Arc::new(Interface::new("recover")?);
|
let interface = Arc::new(Interface::new("recover")?);
|
||||||
let mut phrase = String::new();
|
let mut phrase = String::new();
|
||||||
|
@ -219,6 +246,7 @@ pub fn parse_init_args(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_recover_args(
|
pub fn parse_recover_args(
|
||||||
|
config: &WalletConfig,
|
||||||
g_args: &command::GlobalArgs,
|
g_args: &command::GlobalArgs,
|
||||||
args: &ArgMatches,
|
args: &ArgMatches,
|
||||||
) -> Result<command::RecoverArgs, ParseError> {
|
) -> Result<command::RecoverArgs, ParseError> {
|
||||||
|
@ -226,6 +254,16 @@ pub fn parse_recover_args(
|
||||||
match args.is_present("display") {
|
match args.is_present("display") {
|
||||||
true => (prompt_password(&g_args.password), None),
|
true => (prompt_password(&g_args.password), None),
|
||||||
false => {
|
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()?;
|
let phrase = prompt_recovery_phrase()?;
|
||||||
println!("Please provide a new password for the recovered wallet");
|
println!("Please provide a new password for the recovered wallet");
|
||||||
(prompt_password_confirm(), Some(phrase.to_owned()))
|
(prompt_password_confirm(), Some(phrase.to_owned()))
|
||||||
|
@ -482,7 +520,11 @@ pub fn wallet_command(
|
||||||
command::init(&global_wallet_args, a)
|
command::init(&global_wallet_args, a)
|
||||||
}
|
}
|
||||||
("recover", Some(args)) => {
|
("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)
|
command::recover(&wallet_config, a)
|
||||||
}
|
}
|
||||||
("listen", Some(args)) => {
|
("listen", Some(args)) => {
|
||||||
|
|
|
@ -72,6 +72,12 @@ pub struct RecoverArgs {
|
||||||
pub passphrase: String,
|
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> {
|
pub fn recover(config: &WalletConfig, args: RecoverArgs) -> Result<(), Error> {
|
||||||
if args.recovery_phrase.is_none() {
|
if args.recovery_phrase.is_none() {
|
||||||
let res = WalletSeed::from_file(config, &args.passphrase);
|
let res = WalletSeed::from_file(config, &args.passphrase);
|
||||||
|
|
|
@ -152,6 +152,36 @@ impl WalletSeed {
|
||||||
Ok(())
|
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(
|
pub fn recover_from_phrase(
|
||||||
wallet_config: &WalletConfig,
|
wallet_config: &WalletConfig,
|
||||||
word_list: &str,
|
word_list: &str,
|
||||||
|
@ -161,7 +191,9 @@ impl WalletSeed {
|
||||||
"{}{}{}",
|
"{}{}{}",
|
||||||
wallet_config.data_file_dir, MAIN_SEPARATOR, SEED_FILE,
|
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 seed = WalletSeed::from_mnemonic(word_list)?;
|
||||||
let enc_seed = EncryptedWalletSeed::from_seed(&seed, password)?;
|
let enc_seed = EncryptedWalletSeed::from_seed(&seed, password)?;
|
||||||
let enc_seed_json = serde_json::to_string_pretty(&enc_seed).context(ErrorKind::Format)?;
|
let enc_seed_json = serde_json::to_string_pretty(&enc_seed).context(ErrorKind::Format)?;
|
||||||
|
|
Loading…
Reference in a new issue