diff --git a/Cargo.lock b/Cargo.lock index 306580e4303..bcddbbf6e30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -585,6 +585,7 @@ dependencies = [ name = "beacon_node" version = "4.6.0-rc.0" dependencies = [ + "account_utils", "beacon_chain", "clap", "clap_utils", diff --git a/account_manager/src/validator/create.rs b/account_manager/src/validator/create.rs index da01121055e..1ba458e5363 100644 --- a/account_manager/src/validator/create.rs +++ b/account_manager/src/validator/create.rs @@ -103,13 +103,6 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .conflicts_with("count") .takes_value(true), ) - .arg( - Arg::with_name(STDIN_INPUTS_FLAG) - .takes_value(false) - .hidden(cfg!(windows)) - .long(STDIN_INPUTS_FLAG) - .help("If present, read all user inputs from stdin instead of tty."), - ) } pub fn cli_run( diff --git a/account_manager/src/validator/exit.rs b/account_manager/src/validator/exit.rs index bc9e0ee1dd6..2e893e504d6 100644 --- a/account_manager/src/validator/exit.rs +++ b/account_manager/src/validator/exit.rs @@ -64,13 +64,6 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .long(NO_CONFIRMATION) .help("Exits without prompting for confirmation that you understand the implications of a voluntary exit. This should be used with caution") ) - .arg( - Arg::with_name(STDIN_INPUTS_FLAG) - .takes_value(false) - .hidden(cfg!(windows)) - .long(STDIN_INPUTS_FLAG) - .help("If present, read all user inputs from stdin instead of tty."), - ) } pub fn cli_run(matches: &ArgMatches, env: Environment) -> Result<(), String> { diff --git a/account_manager/src/validator/import.rs b/account_manager/src/validator/import.rs index 339d9a2914f..b8f9d9dff74 100644 --- a/account_manager/src/validator/import.rs +++ b/account_manager/src/validator/import.rs @@ -56,13 +56,6 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .required_unless(KEYSTORE_FLAG) .takes_value(true), ) - .arg( - Arg::with_name(STDIN_INPUTS_FLAG) - .takes_value(false) - .hidden(cfg!(windows)) - .long(STDIN_INPUTS_FLAG) - .help("If present, read all user inputs from stdin instead of tty."), - ) .arg( Arg::with_name(REUSE_PASSWORD_FLAG) .long(REUSE_PASSWORD_FLAG) diff --git a/account_manager/src/validator/recover.rs b/account_manager/src/validator/recover.rs index 33d3b189266..438961f24a0 100644 --- a/account_manager/src/validator/recover.rs +++ b/account_manager/src/validator/recover.rs @@ -68,13 +68,6 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { instead generate them from the wallet seed when required.", ), ) - .arg( - Arg::with_name(STDIN_INPUTS_FLAG) - .takes_value(false) - .hidden(cfg!(windows)) - .long(STDIN_INPUTS_FLAG) - .help("If present, read all user inputs from stdin instead of tty."), - ) } pub fn cli_run(matches: &ArgMatches, validator_dir: PathBuf) -> Result<(), String> { diff --git a/account_manager/src/wallet/create.rs b/account_manager/src/wallet/create.rs index accee11b5a2..913b88a810d 100644 --- a/account_manager/src/wallet/create.rs +++ b/account_manager/src/wallet/create.rs @@ -79,13 +79,6 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { ) .takes_value(true) ) - .arg( - Arg::with_name(STDIN_INPUTS_FLAG) - .takes_value(false) - .hidden(cfg!(windows)) - .long(STDIN_INPUTS_FLAG) - .help("If present, read all user inputs from stdin instead of tty."), - ) .arg( Arg::with_name(MNEMONIC_LENGTH_FLAG) .long(MNEMONIC_LENGTH_FLAG) diff --git a/account_manager/src/wallet/recover.rs b/account_manager/src/wallet/recover.rs index 6e047aca8d2..78c11c0b7f8 100644 --- a/account_manager/src/wallet/recover.rs +++ b/account_manager/src/wallet/recover.rs @@ -52,13 +52,6 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .possible_values(&[HD_TYPE]) .default_value(HD_TYPE), ) - .arg( - Arg::with_name(STDIN_INPUTS_FLAG) - .takes_value(false) - .hidden(cfg!(windows)) - .long(STDIN_INPUTS_FLAG) - .help("If present, read all user inputs from stdin instead of tty."), - ) } pub fn cli_run(matches: &ArgMatches, wallet_base_dir: PathBuf) -> Result<(), String> { diff --git a/beacon_node/Cargo.toml b/beacon_node/Cargo.toml index d6d7de8b8de..4904909fc90 100644 --- a/beacon_node/Cargo.toml +++ b/beacon_node/Cargo.toml @@ -48,3 +48,4 @@ sensitive_url = { workspace = true } http_api = { workspace = true } unused_port = { workspace = true } strum = { workspace = true } +account_utils = { workspace = true } diff --git a/beacon_node/src/cli.rs b/beacon_node/src/cli.rs index 002bb344a3e..a889a545965 100644 --- a/beacon_node/src/cli.rs +++ b/beacon_node/src/cli.rs @@ -723,6 +723,12 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .long("purge-db") .help("If present, the chain database will be deleted. Use with caution.") ) + .arg( + Arg::with_name("purge-db-safe") + .long("purge-db-safe") + .help("The same as --purge-db but requires manual confirmation before the database \ + is purged.") + ) .arg( Arg::with_name("compact-db") .long("compact-db") diff --git a/beacon_node/src/config.rs b/beacon_node/src/config.rs index c940049c50d..9c5f50f2a92 100644 --- a/beacon_node/src/config.rs +++ b/beacon_node/src/config.rs @@ -1,3 +1,4 @@ +use account_utils::{read_input_from_user, STDIN_INPUTS_FLAG}; use beacon_chain::chain_config::{ DisallowedReOrgOffsets, ReOrgThreshold, DEFAULT_PREPARE_PAYLOAD_LOOKAHEAD_FACTOR, DEFAULT_RE_ORG_MAX_EPOCHS_SINCE_FINALIZATION, DEFAULT_RE_ORG_THRESHOLD, @@ -28,6 +29,8 @@ use std::str::FromStr; use std::time::Duration; use types::{Checkpoint, Epoch, EthSpec, Hash256, PublicKeyBytes, GRAFFITI_BYTES_LEN}; +const PURGE_DB_CONFIRMATION: &str = "confirm"; + /// Gets the fully-initialized global client. /// /// The top-level `clap` arguments should be provided as `cli_args`. @@ -48,26 +51,33 @@ pub fn get_config( client_config.set_data_dir(get_data_dir(cli_args)); // If necessary, remove any existing database and configuration - if client_config.data_dir().exists() && cli_args.is_present("purge-db") { - // Remove the chain_db. - let chain_db = client_config.get_db_path(); - if chain_db.exists() { - fs::remove_dir_all(chain_db) - .map_err(|err| format!("Failed to remove chain_db: {}", err))?; - } - - // Remove the freezer db. - let freezer_db = client_config.get_freezer_db_path(); - if freezer_db.exists() { - fs::remove_dir_all(freezer_db) - .map_err(|err| format!("Failed to remove freezer_db: {}", err))?; - } - - // Remove the blobs db. - let blobs_db = client_config.get_blobs_db_path(); - if blobs_db.exists() { - fs::remove_dir_all(blobs_db) - .map_err(|err| format!("Failed to remove blobs_db: {}", err))?; + if client_config.data_dir().exists() { + if cli_args.is_present("purge-db") { + let chain_db = client_config.get_db_path(); + let freezer_db = client_config.get_freezer_db_path(); + let blobs_db = client_config.get_blobs_db_path(); + purge_db(chain_db, freezer_db, blobs_db)?; + } else if cli_args.is_present("purge-db-safe") { + let stdin_inputs = cfg!(windows) || cli_args.is_present(STDIN_INPUTS_FLAG); + eprintln!( + "You are about to delete the chain database. This is irreversable \ + and you will need to resync the chain." + ); + eprintln!( + "Type 'confirm' to delete the database. Any other input will leave \ + the database intact." + ); + let confirmation = read_input_from_user(stdin_inputs)?; + + if confirmation == PURGE_DB_CONFIRMATION { + eprintln!("Database was deleted."); + let chain_db = client_config.get_db_path(); + let freezer_db = client_config.get_freezer_db_path(); + let blobs_db = client_config.get_blobs_db_path(); + purge_db(chain_db, freezer_db, blobs_db)?; + } else { + eprintln!("Database was not deleted."); + } } } @@ -1427,6 +1437,29 @@ pub fn set_network_config( Ok(()) } +/// Remove chain and freezer db. +fn purge_db(chain_db: PathBuf, freezer_db: PathBuf, blobs_db: PathBuf) -> Result<(), String> { + // Remove the chain_db. + if chain_db.exists() { + fs::remove_dir_all(chain_db) + .map_err(|err| format!("Failed to remove chain_db: {}", err))?; + } + + // Remove the freezer db. + if freezer_db.exists() { + fs::remove_dir_all(freezer_db) + .map_err(|err| format!("Failed to remove freezer_db: {}", err))?; + } + + // Remove the blobs db. + if blobs_db.exists() { + fs::remove_dir_all(blobs_db) + .map_err(|err| format!("Failed to remove blobs_db: {}", err))?; + } + + Ok(()) +} + /// Gets the datadir which should be used. pub fn get_data_dir(cli_args: &ArgMatches) -> PathBuf { // Read the `--datadir` flag. diff --git a/book/src/help_bn.md b/book/src/help_bn.md index dff2ab6876a..0a679a43906 100644 --- a/book/src/help_bn.md +++ b/book/src/help_bn.md @@ -101,6 +101,8 @@ FLAGS: referenced by validator client using the --proposer-node flag. This configuration is for enabling more secure setups. --purge-db If present, the chain database will be deleted. Use with caution. + --purge-db-safe The same as --purge-db but requires manual confirmation before the + database is purged. --reconstruct-historic-states After a checkpoint sync, reconstruct historic states in the database. This requires syncing all the way back to genesis. --reset-payload-statuses When present, Lighthouse will forget the payload statuses of any already- @@ -115,6 +117,7 @@ FLAGS: server on localhost:5052 and import deposit logs from the execution node. This is equivalent to `--http` on merge-ready networks, or `--http --eth1` pre-merge + --stdin-inputs If present, read all user inputs from stdin instead of tty. --subscribe-all-subnets Subscribe to all subnets regardless of validator count. This will also advertise the beacon node as being long-lived subscribed to all subnets. --validator-monitor-auto Enables the automatic detection and monitoring of validators connected to diff --git a/book/src/help_general.md b/book/src/help_general.md index fbe05693e70..b52e8ef4c0b 100644 --- a/book/src/help_general.md +++ b/book/src/help_general.md @@ -24,6 +24,7 @@ FLAGS: information about your validator and so this flag should be used with caution. For Windows users, the log file permissions will be inherited from the parent folder. + --stdin-inputs If present, read all user inputs from stdin instead of tty. -V, --version Prints version information OPTIONS: diff --git a/book/src/help_vc.md b/book/src/help_vc.md index 62b64efd411..d038b0a1c75 100644 --- a/book/src/help_vc.md +++ b/book/src/help_vc.md @@ -60,6 +60,7 @@ FLAGS: Enable block production via the block v3 endpoint for this validator client. This should only be enabled when paired with a beacon node that has this endpoint implemented. This flag will be enabled by default in future. + --stdin-inputs If present, read all user inputs from stdin instead of tty. --unencrypted-http-transport This is a safety flag to ensure that the user is aware that the http transport is unencrypted and using a custom HTTP address is unsafe. diff --git a/book/src/help_vm.md b/book/src/help_vm.md index fa08aa4f65f..efb0c1cabc8 100644 --- a/book/src/help_vm.md +++ b/book/src/help_vm.md @@ -20,6 +20,7 @@ FLAGS: information about your validator and so this flag should be used with caution. For Windows users, the log file permissions will be inherited from the parent folder. + --stdin-inputs If present, read all user inputs from stdin instead of tty. -V, --version Prints version information OPTIONS: diff --git a/book/src/help_vm_import.md b/book/src/help_vm_import.md index 3960a55f1a2..4b79c915533 100644 --- a/book/src/help_vm_import.md +++ b/book/src/help_vm_import.md @@ -27,6 +27,7 @@ FLAGS: information about your validator and so this flag should be used with caution. For Windows users, the log file permissions will be inherited from the parent folder. + --stdin-inputs If present, read all user inputs from stdin instead of tty. -V, --version Prints version information OPTIONS: diff --git a/common/account_utils/src/lib.rs b/common/account_utils/src/lib.rs index 8707ae531f7..665953fa522 100644 --- a/common/account_utils/src/lib.rs +++ b/common/account_utils/src/lib.rs @@ -35,6 +35,8 @@ const DEFAULT_PASSWORD_LEN: usize = 48; pub const MNEMONIC_PROMPT: &str = "Enter the mnemonic phrase:"; +pub const STDIN_INPUTS_FLAG: &str = "stdin-inputs"; + /// Returns the "default" path where a wallet should store its password file. pub fn default_wallet_password_path>(wallet_name: &str, secrets_dir: P) -> PathBuf { secrets_dir.as_ref().join(format!("{}.pass", wallet_name)) diff --git a/lighthouse/src/main.rs b/lighthouse/src/main.rs index b8cedfde0d7..c5310510479 100644 --- a/lighthouse/src/main.rs +++ b/lighthouse/src/main.rs @@ -1,5 +1,6 @@ mod metrics; +use account_utils::STDIN_INPUTS_FLAG; use beacon_node::ProductionBeaconNode; use clap::{App, Arg, ArgMatches}; use clap_utils::{flags::DISABLE_MALLOC_TUNING_FLAG, get_eth2_network_config}; @@ -80,6 +81,14 @@ fn main() { cfg!(feature = "gnosis"), ).as_str() ) + .arg( + Arg::with_name(STDIN_INPUTS_FLAG) + .takes_value(false) + .hidden(cfg!(windows)) + .global(true) + .long(STDIN_INPUTS_FLAG) + .help("If present, read all user inputs from stdin instead of tty."), + ) .arg( Arg::with_name("env_log") .short("l") diff --git a/validator_manager/src/common.rs b/validator_manager/src/common.rs index 6a3f93a3f78..e59b7164108 100644 --- a/validator_manager/src/common.rs +++ b/validator_manager/src/common.rs @@ -1,3 +1,4 @@ +pub use account_utils::STDIN_INPUTS_FLAG; use account_utils::{strip_off_newlines, ZeroizeString}; use eth2::lighthouse_vc::std_types::{InterchangeJsonStr, KeystoreJsonStr}; use eth2::{ @@ -15,7 +16,6 @@ use tree_hash::TreeHash; use types::*; pub const IGNORE_DUPLICATES_FLAG: &str = "ignore-duplicates"; -pub const STDIN_INPUTS_FLAG: &str = "stdin-inputs"; pub const COUNT_FLAG: &str = "count"; /// When the `ethereum/staking-deposit-cli` tool generates deposit data JSON, it adds a diff --git a/validator_manager/src/create_validators.rs b/validator_manager/src/create_validators.rs index 8ea740ff5bb..bb2d28229e0 100644 --- a/validator_manager/src/create_validators.rs +++ b/validator_manager/src/create_validators.rs @@ -88,13 +88,6 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .help("If present, the mnemonic will be read in from this file.") .takes_value(true), ) - .arg( - Arg::with_name(STDIN_INPUTS_FLAG) - .takes_value(false) - .hidden(cfg!(windows)) - .long(STDIN_INPUTS_FLAG) - .help("If present, read all user inputs from stdin instead of tty."), - ) .arg( Arg::with_name(DISABLE_DEPOSITS_FLAG) .long(DISABLE_DEPOSITS_FLAG) diff --git a/validator_manager/src/move_validators.rs b/validator_manager/src/move_validators.rs index fa886e8f941..00d42ea9bff 100644 --- a/validator_manager/src/move_validators.rs +++ b/validator_manager/src/move_validators.rs @@ -163,13 +163,6 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .possible_values(&["true", "false"]) .takes_value(true), ) - .arg( - Arg::with_name(STDIN_INPUTS_FLAG) - .takes_value(false) - .hidden(cfg!(windows)) - .long(STDIN_INPUTS_FLAG) - .help("If present, read all user inputs from stdin instead of tty."), - ) } #[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]