Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Require manual confirmation to purge database with purge-db #6154

Merged
merged 7 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 1 addition & 11 deletions account_manager/src/validator/create.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::common::read_wallet_name_from_cli;
use crate::wallet::create::STDIN_INPUTS_FLAG;
use crate::{SECRETS_DIR_FLAG, WALLETS_DIR_FLAG};
use account_utils::{
random_password, read_password_from_user, strip_off_newlines, validator_definitions, PlainText,
STDIN_INPUTS_FLAG,
};
use clap::{Arg, ArgAction, ArgMatches, Command};
use clap_utils::FLAG_HEADER;
Expand Down Expand Up @@ -114,16 +114,6 @@ pub fn cli_app() -> Command {
.action(ArgAction::Set)
.display_order(0)
)
.arg(
Arg::new(STDIN_INPUTS_FLAG)
.action(ArgAction::SetTrue)
.help_heading(FLAG_HEADER)
.hide(cfg!(windows))
.long(STDIN_INPUTS_FLAG)
.help("If present, read all user inputs from stdin instead of tty.")
.display_order(0)
.action(ArgAction::SetTrue)
)
}

pub fn cli_run<E: EthSpec>(
Expand Down
11 changes: 1 addition & 10 deletions account_manager/src/validator/exit.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::wallet::create::STDIN_INPUTS_FLAG;
use account_utils::STDIN_INPUTS_FLAG;
use bls::{Keypair, PublicKey};
use clap::{Arg, ArgAction, ArgMatches, Command};
use clap_utils::FLAG_HEADER;
Expand Down Expand Up @@ -74,15 +74,6 @@ pub fn cli_app() -> Command {
.action(ArgAction::SetTrue)
.help_heading(FLAG_HEADER)
)
.arg(
Arg::new(STDIN_INPUTS_FLAG)
.action(ArgAction::SetTrue)
.help_heading(FLAG_HEADER)
.hide(cfg!(windows))
.long(STDIN_INPUTS_FLAG)
.help("If present, read all user inputs from stdin instead of tty.")
.display_order(0)
)
}

pub fn cli_run<E: EthSpec>(matches: &ArgMatches, env: Environment<E>) -> Result<(), String> {
Expand Down
13 changes: 2 additions & 11 deletions account_manager/src/validator/import.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::wallet::create::{PASSWORD_FLAG, STDIN_INPUTS_FLAG};
use crate::wallet::create::PASSWORD_FLAG;
use account_utils::validator_definitions::SigningDefinition;
use account_utils::{
eth2_keystore::Keystore,
Expand All @@ -7,7 +7,7 @@ use account_utils::{
recursively_find_voting_keystores, PasswordStorage, ValidatorDefinition,
ValidatorDefinitions, CONFIG_FILENAME,
},
ZeroizeString,
ZeroizeString, STDIN_INPUTS_FLAG,
};
use clap::{Arg, ArgAction, ArgMatches, Command};
use clap_utils::FLAG_HEADER;
Expand Down Expand Up @@ -59,15 +59,6 @@ pub fn cli_app() -> Command {
.action(ArgAction::Set)
.display_order(0),
)
.arg(
Arg::new(STDIN_INPUTS_FLAG)
.action(ArgAction::SetTrue)
.help_heading(FLAG_HEADER)
.hide(cfg!(windows))
.long(STDIN_INPUTS_FLAG)
.help("If present, read all user inputs from stdin instead of tty.")
.display_order(0),
)
.arg(
Arg::new(REUSE_PASSWORD_FLAG)
.long(REUSE_PASSWORD_FLAG)
Expand Down
12 changes: 1 addition & 11 deletions account_manager/src/validator/recover.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use super::create::STORE_WITHDRAW_FLAG;
use crate::validator::create::COUNT_FLAG;
use crate::wallet::create::STDIN_INPUTS_FLAG;
use crate::SECRETS_DIR_FLAG;
use account_utils::eth2_keystore::{keypair_from_secret, Keystore, KeystoreBuilder};
use account_utils::{random_password, read_mnemonic_from_cli};
use account_utils::{random_password, read_mnemonic_from_cli, STDIN_INPUTS_FLAG};
use clap::{Arg, ArgAction, ArgMatches, Command};
use clap_utils::FLAG_HEADER;
use directory::ensure_dir_exists;
Expand Down Expand Up @@ -76,15 +75,6 @@ pub fn cli_app() -> Command {
.help_heading(FLAG_HEADER)
.display_order(0)
)
.arg(
Arg::new(STDIN_INPUTS_FLAG)
.action(ArgAction::SetTrue)
.help_heading(FLAG_HEADER)
.hide(cfg!(windows))
.long(STDIN_INPUTS_FLAG)
.help("If present, read all user inputs from stdin instead of tty.")
.display_order(0)
)
}

pub fn cli_run(matches: &ArgMatches, validator_dir: PathBuf) -> Result<(), String> {
Expand Down
10 changes: 1 addition & 9 deletions account_manager/src/wallet/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::common::read_wallet_name_from_cli;
use crate::WALLETS_DIR_FLAG;
use account_utils::{
is_password_sufficiently_complex, random_password, read_password_from_user, strip_off_newlines,
STDIN_INPUTS_FLAG,
};
use clap::{Arg, ArgAction, ArgMatches, Command};
use eth2_wallet::{
Expand All @@ -20,7 +21,6 @@ pub const NAME_FLAG: &str = "name";
pub const PASSWORD_FLAG: &str = "password-file";
pub const TYPE_FLAG: &str = "type";
pub const MNEMONIC_FLAG: &str = "mnemonic-output-path";
pub const STDIN_INPUTS_FLAG: &str = "stdin-inputs";
pub const MNEMONIC_LENGTH_FLAG: &str = "mnemonic-length";
pub const MNEMONIC_TYPES: &[MnemonicType] = &[
MnemonicType::Words12,
Expand Down Expand Up @@ -83,14 +83,6 @@ pub fn cli_app() -> Command {
.action(ArgAction::Set)
.display_order(0)
)
.arg(
Arg::new(STDIN_INPUTS_FLAG)
.action(ArgAction::SetTrue)
.hide(cfg!(windows))
.long(STDIN_INPUTS_FLAG)
.help("If present, read all user inputs from stdin instead of tty.")
.display_order(0)
)
.arg(
Arg::new(MNEMONIC_LENGTH_FLAG)
.long(MNEMONIC_LENGTH_FLAG)
Expand Down
12 changes: 2 additions & 10 deletions account_manager/src/wallet/recover.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::wallet::create::{create_wallet_from_mnemonic, STDIN_INPUTS_FLAG};
use crate::wallet::create::create_wallet_from_mnemonic;
use crate::wallet::create::{HD_TYPE, NAME_FLAG, PASSWORD_FLAG, TYPE_FLAG};
use account_utils::read_mnemonic_from_cli;
use account_utils::{read_mnemonic_from_cli, STDIN_INPUTS_FLAG};
use clap::{Arg, ArgAction, ArgMatches, Command};
use std::path::PathBuf;

Expand Down Expand Up @@ -56,14 +56,6 @@ pub fn cli_app() -> Command {
.default_value(HD_TYPE)
.display_order(0),
)
.arg(
Arg::new(STDIN_INPUTS_FLAG)
.action(ArgAction::SetTrue)
.hide(cfg!(windows))
.long(STDIN_INPUTS_FLAG)
.help("If present, read all user inputs from stdin instead of tty.")
.display_order(0),
)
}

pub fn cli_run(matches: &ArgMatches, wallet_base_dir: PathBuf) -> Result<(), String> {
Expand Down
1 change: 1 addition & 0 deletions beacon_node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@ sensitive_url = { workspace = true }
http_api = { workspace = true }
unused_port = { workspace = true }
strum = { workspace = true }
account_utils = { workspace = true }
10 changes: 9 additions & 1 deletion beacon_node/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,15 @@ pub fn cli_app() -> Command {
.long("purge-db")
.action(ArgAction::SetTrue)
.help_heading(FLAG_HEADER)
.help("If present, the chain database will be deleted. Use with caution.")
.help("If present, the chain database will be deleted. Requires manual confirmation.")
.display_order(0)
)
.arg(
Arg::new("purge-db-force")
.long("purge-db-force")
.action(ArgAction::SetTrue)
.help_heading(FLAG_HEADER)
.help("If present, the chain database will be deleted without confirmation. Use with caution.")
.display_order(0)
)
.arg(
Expand Down
86 changes: 66 additions & 20 deletions beacon_node/src/config.rs
Original file line number Diff line number Diff line change
@@ -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_HEAD_THRESHOLD, DEFAULT_RE_ORG_MAX_EPOCHS_SINCE_FINALIZATION,
Expand All @@ -21,6 +22,7 @@ use slog::{info, warn, Logger};
use std::cmp::max;
use std::fmt::Debug;
use std::fs;
use std::io::IsTerminal;
use std::net::Ipv6Addr;
use std::net::{IpAddr, Ipv4Addr, ToSocketAddrs};
use std::num::NonZeroU16;
Expand All @@ -30,6 +32,8 @@ use std::time::Duration;
use types::graffiti::GraffitiString;
use types::{Checkpoint, Epoch, EthSpec, Hash256, PublicKeyBytes};

const PURGE_DB_CONFIRMATION: &str = "confirm";

/// Gets the fully-initialized global client.
///
/// The top-level `clap` arguments should be provided as `cli_args`.
Expand All @@ -50,26 +54,45 @@ pub fn get_config<E: EthSpec>(
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.get_flag("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.get_flag("purge-db-force") {
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.get_flag("purge-db") {
let stdin_inputs = cfg!(windows) || cli_args.get_flag(STDIN_INPUTS_FLAG);
if std::io::stdin().is_terminal() || stdin_inputs {
info!(
log,
"You are about to delete the chain database. This is irreversable \
and you will need to resync the chain."
);
info!(
log,
"Type 'confirm' to delete the database. Any other input will leave \
the database intact and Lighthouse will exit."
);
let confirmation = read_input_from_user(stdin_inputs)?;

if confirmation == PURGE_DB_CONFIRMATION {
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)?;
info!(log, "Database was deleted.");
} else {
info!(log, "Database was not deleted. Lighthouse will now close.");
std::process::exit(1);
}
} else {
warn!(
log,
"The `--purge-db` flag was passed, but Lighthouse is not running \
interactively. The database was not purged. Use `--purge-db-force` \
to purge the database without requiring confirmation."
);
}
}
}

Expand Down Expand Up @@ -1522,3 +1545,26 @@ where
.next()
.ok_or(format!("Must provide at least one value to {}", flag_name))
}

/// Remove chain, freezer and blobs 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(())
}
8 changes: 7 additions & 1 deletion book/src/help_bn.md
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,11 @@ Flags:
being 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.
If present, the chain database will be deleted. Requires manual
confirmation.
--purge-db-force
If present, the chain database will be deleted without confirmation.
Use with caution.
--reconstruct-historic-states
After a checkpoint sync, reconstruct historic states in the database.
This requires syncing all the way back to genesis.
Expand All @@ -585,6 +589,8 @@ 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
Expand Down
2 changes: 2 additions & 0 deletions book/src/help_general.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ Flags:
contain sensitive 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.
```

<style> .content main {max-width:88%;} </style>
2 changes: 2 additions & 0 deletions book/src/help_vc.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ Flags:
by builders, regardless of payload value.
--produce-block-v3
This flag is deprecated and is no longer in use.
--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.
Expand Down
2 changes: 2 additions & 0 deletions book/src/help_vm.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ Flags:
contain sensitive 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.
```

<style> .content main {max-width:88%;} </style>
2 changes: 2 additions & 0 deletions book/src/help_vm_import.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ Flags:
contain sensitive 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.
```

<style> .content main {max-width:88%;} </style>
4 changes: 2 additions & 2 deletions book/src/help_vm_move.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,6 @@ Options:
A HTTP(S) address of a validator client using the keymanager-API. This
validator client is the "source" and contains the validators that are
to be moved.
--stdin-inputs
If present, read all user inputs from stdin instead of tty.
--suggested-fee-recipient <ETH1_ADDRESS>
All created validators will use this value for the suggested fee
recipient. Omit this flag to use the default value from the VC.
Expand Down Expand Up @@ -142,6 +140,8 @@ Flags:
contain sensitive 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.
```

<style> .content main {max-width:88%;} </style>
2 changes: 2 additions & 0 deletions common/account_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<P: AsRef<Path>>(wallet_name: &str, secrets_dir: P) -> PathBuf {
secrets_dir.as_ref().join(format!("{}.pass", wallet_name))
Expand Down
Loading
Loading