mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-05-06 08:09:34 +00:00
The mnemonic/wallet generation was using a constant zero-byte array for entropy ([0u8; 32]), making all wallets deterministic based solely on the password. This commit introduces proper random entropy using OsRng and enables users to back up their recovery phrase. Changes: - SeedHolder::new_mnemonic() now uses OsRng for 256-bit random entropy and returns the generated mnemonic - Added SeedHolder::from_mnemonic() to recover a wallet from an existing mnemonic phrase - WalletChainStore::new_storage() returns the mnemonic for user backup - Added WalletChainStore::restore_storage() for recovery from a mnemonic - WalletCore::new_init_storage() now returns the mnemonic - Renamed reset_storage to restore_storage, which accepts a mnemonic for recovery - CLI displays the recovery phrase when a new wallet is created - RestoreKeys command now prompts for the mnemonic phrase via read_mnemonic_from_stdin() Note: The password parameter is retained for future storage encryption but is no longer used in seed derivation (empty passphrase is used instead). This means the mnemonic alone is sufficient to recover accounts. Usage: On first wallet initialization, users will see: IMPORTANT: Write down your recovery phrase and store it securely. This is the only way to recover your wallet if you lose access. Recovery phrase: word1 word2 word3 ... word24 To restore keys: wallet restore-keys --depth 5 Input recovery phrase: <24 words> Input password: <password>
79 lines
2.7 KiB
Rust
79 lines
2.7 KiB
Rust
#![expect(
|
|
clippy::print_stdout,
|
|
reason = "This is a CLI application, printing to stdout is expected and convenient"
|
|
)]
|
|
|
|
use anyhow::{Context as _, Result};
|
|
use clap::{CommandFactory as _, Parser as _};
|
|
use wallet::{
|
|
WalletCore,
|
|
cli::{Args, execute_continuous_run, execute_subcommand, read_password_from_stdin},
|
|
config::WalletConfigOverrides,
|
|
helperfunctions::{fetch_config_path, fetch_persistent_storage_path},
|
|
};
|
|
|
|
// TODO #169: We have sample configs for sequencer, but not for wallet
|
|
// TODO #168: Why it requires config as a directory? Maybe better to deduce directory from config
|
|
// file path?
|
|
// TODO #172: Why it requires config as env var while sequencer_service accepts as
|
|
// argument?
|
|
#[tokio::main]
|
|
async fn main() -> Result<()> {
|
|
let Args {
|
|
continuous_run,
|
|
auth,
|
|
command,
|
|
} = Args::parse();
|
|
|
|
env_logger::init();
|
|
|
|
let config_path = fetch_config_path().context("Could not fetch config path")?;
|
|
let storage_path =
|
|
fetch_persistent_storage_path().context("Could not fetch persistent storage path")?;
|
|
|
|
// Override basic auth if provided via CLI
|
|
let config_overrides = WalletConfigOverrides {
|
|
basic_auth: auth.map(|auth| auth.parse()).transpose()?.map(Some),
|
|
..Default::default()
|
|
};
|
|
|
|
if let Some(command) = command {
|
|
let mut wallet = if storage_path.exists() {
|
|
WalletCore::new_update_chain(config_path, storage_path, Some(config_overrides))?
|
|
} else {
|
|
// TODO: Maybe move to `WalletCore::from_env()` or similar?
|
|
|
|
println!("Persistent storage not found, need to execute setup");
|
|
|
|
let password = read_password_from_stdin()?;
|
|
let (wallet, mnemonic) = WalletCore::new_init_storage(
|
|
config_path,
|
|
storage_path,
|
|
Some(config_overrides),
|
|
&password,
|
|
)?;
|
|
|
|
println!();
|
|
println!("IMPORTANT: Write down your recovery phrase and store it securely.");
|
|
println!("This is the only way to recover your wallet if you lose access.");
|
|
println!();
|
|
println!("Recovery phrase:");
|
|
println!(" {mnemonic}");
|
|
println!();
|
|
|
|
wallet.store_persistent_data().await?;
|
|
wallet
|
|
};
|
|
let _output = execute_subcommand(&mut wallet, command).await?;
|
|
Ok(())
|
|
} else if continuous_run {
|
|
let mut wallet =
|
|
WalletCore::new_update_chain(config_path, storage_path, Some(config_overrides))?;
|
|
execute_continuous_run(&mut wallet).await
|
|
} else {
|
|
let help = Args::command().render_long_help();
|
|
println!("{help}");
|
|
Ok(())
|
|
}
|
|
}
|