From 64ecfaf7694a2a2940d26499843c134e4459ec7e Mon Sep 17 00:00:00 2001 From: Brooks Date: Fri, 23 Jun 2023 18:34:18 -0400 Subject: [PATCH] Renames --boot-from-local-state to --use-snapshot-archives-at-startup (#32217) --- Cargo.lock | 2 + ledger-tool/src/main.rs | 70 ++++++++++++------- ledger/Cargo.toml | 2 + ledger/src/bank_forks_utils.rs | 15 ++-- ledger/src/lib.rs | 1 + .../src/use_snapshot_archives_at_startup.rs | 41 +++++++++++ programs/sbf/Cargo.lock | 2 + validator/src/cli.rs | 18 +++-- validator/src/main.rs | 14 +++- 9 files changed, 119 insertions(+), 46 deletions(-) create mode 100644 ledger/src/use_snapshot_archives_at_startup.rs diff --git a/Cargo.lock b/Cargo.lock index 29e0da102..55da71154 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5998,6 +5998,8 @@ dependencies = [ "spl-token", "spl-token-2022", "static_assertions", + "strum", + "strum_macros", "tempfile", "test-case", "thiserror", diff --git a/ledger-tool/src/main.rs b/ledger-tool/src/main.rs index d8af9dfe4..7fec357b8 100644 --- a/ledger-tool/src/main.rs +++ b/ledger-tool/src/main.rs @@ -41,6 +41,7 @@ use { }, blockstore_processor::ProcessOptions, shred::Shred, + use_snapshot_archives_at_startup::{self, UseSnapshotArchivesAtStartup}, }, solana_measure::{measure, measure::Measure}, solana_runtime::{ @@ -1169,21 +1170,15 @@ fn main() { .multiple(true) .takes_value(true) .help("Log when transactions are processed that reference the given key(s)."); - let boot_from_local_state = Arg::with_name("boot_from_local_state") - .long("boot-from-local-state") - .takes_value(false) - .hidden(hidden_unless_forced()) - .help("Boot from state already on disk") - .long_help( - "Boot from state already on disk, instead of \ - extracting it from a snapshot archive. \ - This requires primary access, so another instance of \ - solana-ledger-tool or solana-validator cannot \ - simultaneously use the same ledger/accounts. \ - Note, this will use the latest state available, \ - which may be newer than the latest snapshot archive.", - ) - .conflicts_with("no_snapshot"); + let use_snapshot_archives_at_startup = + Arg::with_name(use_snapshot_archives_at_startup::cli::NAME) + .long(use_snapshot_archives_at_startup::cli::LONG_ARG) + .hidden(hidden_unless_forced()) + .takes_value(true) + .possible_values(use_snapshot_archives_at_startup::cli::POSSIBLE_VALUES) + .default_value(use_snapshot_archives_at_startup::cli::default_value()) + .help(use_snapshot_archives_at_startup::cli::HELP) + .long_help(use_snapshot_archives_at_startup::cli::LONG_HELP); let default_max_full_snapshot_archives_to_retain = &DEFAULT_MAX_FULL_SNAPSHOT_ARCHIVES_TO_RETAIN.to_string(); @@ -1543,7 +1538,7 @@ fn main() { .arg(&max_genesis_archive_unpacked_size_arg) .arg(&debug_key_arg) .arg(&geyser_plugin_args) - .arg(&boot_from_local_state) + .arg(&use_snapshot_archives_at_startup) .arg( Arg::with_name("skip_poh_verify") .long("skip-poh-verify") @@ -1599,7 +1594,7 @@ fn main() { .arg(&halt_at_slot_arg) .arg(&hard_forks_arg) .arg(&max_genesis_archive_unpacked_size_arg) - .arg(&boot_from_local_state) + .arg(&use_snapshot_archives_at_startup) .arg( Arg::with_name("include_all_votes") .long("include-all-votes") @@ -1639,7 +1634,7 @@ fn main() { .arg(&maximum_full_snapshot_archives_to_retain) .arg(&maximum_incremental_snapshot_archives_to_retain) .arg(&geyser_plugin_args) - .arg(&boot_from_local_state) + .arg(&use_snapshot_archives_at_startup) .arg( Arg::with_name("snapshot_slot") .index(1) @@ -1828,7 +1823,7 @@ fn main() { .arg(&hard_forks_arg) .arg(&geyser_plugin_args) .arg(&accounts_data_encoding_arg) - .arg(&boot_from_local_state) + .arg(&use_snapshot_archives_at_startup) .arg( Arg::with_name("include_sysvars") .long("include-sysvars") @@ -1861,7 +1856,7 @@ fn main() { .arg(&hard_forks_arg) .arg(&max_genesis_archive_unpacked_size_arg) .arg(&geyser_plugin_args) - .arg(&boot_from_local_state) + .arg(&use_snapshot_archives_at_startup) .arg( Arg::with_name("warp_epoch") .required(false) @@ -2518,6 +2513,11 @@ fn main() { ); } + let boot_from_local_state = value_t_or_exit!( + arg_matches, + use_snapshot_archives_at_startup::cli::NAME, + UseSnapshotArchivesAtStartup + ) == UseSnapshotArchivesAtStartup::Never; let process_options = ProcessOptions { new_hard_forks: hardforks_of(arg_matches, "hard_forks"), run_verification: !(arg_matches.is_present("skip_poh_verify") @@ -2540,7 +2540,7 @@ fn main() { .is_present("accounts_db_test_hash_calculation"), accounts_db_skip_shrink: arg_matches.is_present("accounts_db_skip_shrink"), runtime_config: RuntimeConfig::default(), - boot_from_local_state: arg_matches.is_present("boot_from_local_state"), + boot_from_local_state, ..ProcessOptions::default() }; let print_accounts_stats = arg_matches.is_present("print_accounts_stats"); @@ -2583,12 +2583,17 @@ fn main() { ), }; + let boot_from_local_state = value_t_or_exit!( + arg_matches, + use_snapshot_archives_at_startup::cli::NAME, + UseSnapshotArchivesAtStartup + ) == UseSnapshotArchivesAtStartup::Never; let process_options = ProcessOptions { new_hard_forks: hardforks_of(arg_matches, "hard_forks"), halt_at_slot: value_t!(arg_matches, "halt_at_slot", Slot).ok(), run_verification: false, accounts_db_config: Some(get_accounts_db_config(&ledger_path, arg_matches)), - boot_from_local_state: arg_matches.is_present("boot_from_local_state"), + boot_from_local_state, ..ProcessOptions::default() }; @@ -2710,12 +2715,17 @@ fn main() { NonZeroUsize ); let genesis_config = open_genesis_config_by(&ledger_path, arg_matches); + let boot_from_local_state = value_t_or_exit!( + arg_matches, + use_snapshot_archives_at_startup::cli::NAME, + UseSnapshotArchivesAtStartup + ) == UseSnapshotArchivesAtStartup::Never; let mut process_options = ProcessOptions { new_hard_forks, run_verification: false, accounts_db_config: Some(get_accounts_db_config(&ledger_path, arg_matches)), accounts_db_skip_shrink: arg_matches.is_present("accounts_db_skip_shrink"), - boot_from_local_state: arg_matches.is_present("boot_from_local_state"), + boot_from_local_state, ..ProcessOptions::default() }; let blockstore = Arc::new(open_blockstore( @@ -3123,12 +3133,17 @@ fn main() { } ("accounts", Some(arg_matches)) => { let halt_at_slot = value_t!(arg_matches, "halt_at_slot", Slot).ok(); + let boot_from_local_state = value_t_or_exit!( + arg_matches, + use_snapshot_archives_at_startup::cli::NAME, + UseSnapshotArchivesAtStartup + ) == UseSnapshotArchivesAtStartup::Never; let process_options = ProcessOptions { new_hard_forks: hardforks_of(arg_matches, "hard_forks"), halt_at_slot, run_verification: false, accounts_db_config: Some(get_accounts_db_config(&ledger_path, arg_matches)), - boot_from_local_state: arg_matches.is_present("boot_from_local_state"), + boot_from_local_state, ..ProcessOptions::default() }; let genesis_config = open_genesis_config_by(&ledger_path, arg_matches); @@ -3214,12 +3229,17 @@ fn main() { } ("capitalization", Some(arg_matches)) => { let halt_at_slot = value_t!(arg_matches, "halt_at_slot", Slot).ok(); + let boot_from_local_state = value_t_or_exit!( + arg_matches, + use_snapshot_archives_at_startup::cli::NAME, + UseSnapshotArchivesAtStartup + ) == UseSnapshotArchivesAtStartup::Never; let process_options = ProcessOptions { new_hard_forks: hardforks_of(arg_matches, "hard_forks"), halt_at_slot, run_verification: false, accounts_db_config: Some(get_accounts_db_config(&ledger_path, arg_matches)), - boot_from_local_state: arg_matches.is_present("boot_from_local_state"), + boot_from_local_state, ..ProcessOptions::default() }; let genesis_config = open_genesis_config_by(&ledger_path, arg_matches); diff --git a/ledger/Cargo.toml b/ledger/Cargo.toml index 0bc385cea..1cea2d179 100644 --- a/ledger/Cargo.toml +++ b/ledger/Cargo.toml @@ -56,6 +56,8 @@ solana-vote-program = { workspace = true } spl-token = { workspace = true, features = ["no-entrypoint"] } spl-token-2022 = { workspace = true, features = ["no-entrypoint"] } static_assertions = { workspace = true } +strum = { workspace = true, features = ["derive"] } +strum_macros = { workspace = true } tempfile = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true, features = ["full"] } diff --git a/ledger/src/bank_forks_utils.rs b/ledger/src/bank_forks_utils.rs index bd5b791b3..4193b5047 100644 --- a/ledger/src/bank_forks_utils.rs +++ b/ledger/src/bank_forks_utils.rs @@ -231,9 +231,8 @@ fn bank_forks_from_snapshot( full_snapshot_archive_info.slot(), ); - // If a newer snapshot archive was downloaded, it is possible that the snapshot - // slot is higher than the local bank we just loaded. It is unlikely the user - // intended to still boot from local state in this scenario. + // If a newer snapshot archive was downloaded, it is possible that its slot is + // higher than the local bank we just loaded. Did the user intend for this? let latest_snapshot_archive_slot = std::cmp::max( full_snapshot_archive_info.slot(), incremental_snapshot_archive_info @@ -242,14 +241,14 @@ fn bank_forks_from_snapshot( .unwrap_or(0), ); if bank.slot() < latest_snapshot_archive_slot { - error!( - "Attempting to boot from local state at a slot {} that is *older* than the latest \ - snapshot archive slot {}, which is not supported. Either remove the snapshot archive \ - or remove the --boot-from-local-state CLI flag.", + warn!( + "Starting up from local state at slot {}, which is *older* \ + than the latest snapshot archive at slot {}. If this is not \ + desired, change the --use-snapshot-archives-at-startup \ + CLI option to \"always\" and restart.", bank.slot(), latest_snapshot_archive_slot, ); - process::exit(1); } ( diff --git a/ledger/src/lib.rs b/ledger/src/lib.rs index 274bd6d36..470d03cf2 100644 --- a/ledger/src/lib.rs +++ b/ledger/src/lib.rs @@ -28,6 +28,7 @@ pub mod sigverify_shreds; pub mod slot_stats; mod staking_utils; pub mod token_balances; +pub mod use_snapshot_archives_at_startup; #[macro_use] extern crate solana_metrics; diff --git a/ledger/src/use_snapshot_archives_at_startup.rs b/ledger/src/use_snapshot_archives_at_startup.rs new file mode 100644 index 000000000..a10cfb066 --- /dev/null +++ b/ledger/src/use_snapshot_archives_at_startup.rs @@ -0,0 +1,41 @@ +use strum::{Display, EnumString, EnumVariantNames, IntoStaticStr, VariantNames}; + +/// When should snapshot archives be used at startup? +#[derive( + Debug, Default, Clone, Copy, PartialEq, Eq, Display, EnumString, EnumVariantNames, IntoStaticStr, +)] +#[strum(serialize_all = "kebab-case")] +pub enum UseSnapshotArchivesAtStartup { + /// If snapshot archives are used, they will be extracted and overwrite any existing state + /// already on disk. This will incur the associated runtime costs for extracting. + #[default] + Always, + /// If snapshot archive are not used, then the local snapshot state already on disk is + /// used instead. If there is no local state on disk, startup will fail. + Never, +} + +pub mod cli { + use super::*; + + pub const NAME: &str = "use_snapshot_archives_at_startup"; + pub const LONG_ARG: &str = "use-snapshot-archives-at-startup"; + pub const HELP: &str = "When should snapshot archives be used at startup?"; + pub const LONG_HELP: &str = "At startup, when should snapshot archives be extracted \ + versus using what is already on disk? \ + \nSpecifying \"always\" will always startup by extracting snapshot archives \ + and disregard any snapshot-related state already on disk. \ + Note that starting up from snapshot archives will incur the runtime costs \ + associated with extracting the archives and rebuilding the local state. \ + \nSpecifying \"never\" will never startup from snapshot archives \ + and will only use snapshot-related state already on disk. \ + If there is no state already on disk, startup will fail. \ + Note, this will use the latest state available, \ + which may be newer than the latest snapshot archive."; + + pub const POSSIBLE_VALUES: &[&str] = UseSnapshotArchivesAtStartup::VARIANTS; + + pub fn default_value() -> &'static str { + UseSnapshotArchivesAtStartup::default().into() + } +} diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 30e937bfe..576380c2d 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -5006,6 +5006,8 @@ dependencies = [ "spl-token", "spl-token-2022", "static_assertions", + "strum", + "strum_macros", "tempfile", "thiserror", "tokio", diff --git a/validator/src/cli.rs b/validator/src/cli.rs index 0e4ed9f1d..6d11ecc79 100644 --- a/validator/src/cli.rs +++ b/validator/src/cli.rs @@ -19,6 +19,7 @@ use { validator::{BlockProductionMethod, BlockVerificationMethod}, }, solana_faucet::faucet::{self, FAUCET_PORT}, + solana_ledger::use_snapshot_archives_at_startup, solana_net_utils::{MINIMUM_VALIDATOR_PORT_RANGE_WIDTH, VALIDATOR_PORT_RANGE}, solana_rpc::{rpc::MAX_REQUEST_BODY_SIZE, rpc_pubsub_service::PubSubConfig}, solana_rpc_client_api::request::MAX_MULTIPLE_ACCOUNTS, @@ -292,17 +293,14 @@ pub fn app<'a>(version: &'a str, default_args: &'a DefaultArgs) -> App<'a, 'a> { .help("Use DIR as snapshot location [default: --ledger value]"), ) .arg( - Arg::with_name("boot_from_local_state") - .long("boot-from-local-state") - .takes_value(false) + Arg::with_name(use_snapshot_archives_at_startup::cli::NAME) + .long(use_snapshot_archives_at_startup::cli::LONG_ARG) .hidden(hidden_unless_forced()) - .help("Boot from state already on disk") - .long_help( - "Boot from state already on disk, instead of \ - extracting it from a snapshot archive. \ - Note, this will use the latest state available, \ - which may be newer than the latest snapshot archive.", - ) + .takes_value(true) + .possible_values(use_snapshot_archives_at_startup::cli::POSSIBLE_VALUES) + .default_value(use_snapshot_archives_at_startup::cli::default_value()) + .help(use_snapshot_archives_at_startup::cli::HELP) + .long_help(use_snapshot_archives_at_startup::cli::LONG_HELP) ) .arg( Arg::with_name("incremental_snapshot_archive_path") diff --git a/validator/src/main.rs b/validator/src/main.rs index 69f61abf5..1c4180665 100644 --- a/validator/src/main.rs +++ b/validator/src/main.rs @@ -20,8 +20,12 @@ use { }, }, solana_gossip::{cluster_info::Node, legacy_contact_info::LegacyContactInfo as ContactInfo}, - solana_ledger::blockstore_options::{ - BlockstoreCompressionType, BlockstoreRecoveryMode, LedgerColumnOptions, ShredStorageType, + solana_ledger::{ + blockstore_options::{ + BlockstoreCompressionType, BlockstoreRecoveryMode, LedgerColumnOptions, + ShredStorageType, + }, + use_snapshot_archives_at_startup::{self, UseSnapshotArchivesAtStartup}, }, solana_perf::recycler::enable_recycler_warming, solana_poh::poh_service, @@ -1374,7 +1378,11 @@ pub fn main() { }, staked_nodes_overrides: staked_nodes_overrides.clone(), replay_slots_concurrently: matches.is_present("replay_slots_concurrently"), - boot_from_local_state: matches.is_present("boot_from_local_state"), + boot_from_local_state: value_t_or_exit!( + matches, + use_snapshot_archives_at_startup::cli::NAME, + UseSnapshotArchivesAtStartup + ) == UseSnapshotArchivesAtStartup::Never, ..ValidatorConfig::default() };