From 9b8850f99e12e7303e28c181aef7b7e5ec9279da Mon Sep 17 00:00:00 2001 From: Jon Cinque Date: Tue, 12 Apr 2022 02:28:10 +0200 Subject: [PATCH] test-validator: Add `--max-compute-units` flag (#24130) * test-validator: Add `--max-compute-units` flag * Add `RuntimeConfig` for tweaking runtime behavior * Actually add the file * Move RuntimeConfig to runtime --- Cargo.lock | 1 + core/src/validator.rs | 12 +++---- ledger-tool/src/main.rs | 38 +++++++++++++++++----- ledger/src/bank_forks_utils.rs | 8 +++-- ledger/src/blockstore_processor.rs | 19 +++++++---- local-cluster/src/validator_configs.rs | 3 +- runtime/src/lib.rs | 1 + runtime/src/runtime_config.rs | 9 +++++ test-validator/Cargo.toml | 1 + test-validator/src/lib.rs | 22 +++++++++++-- validator/src/bin/solana-test-validator.rs | 13 ++++++++ validator/src/main.rs | 8 +++-- 12 files changed, 106 insertions(+), 29 deletions(-) create mode 100644 runtime/src/runtime_config.rs diff --git a/Cargo.lock b/Cargo.lock index 543416c598..ffc82e27e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5930,6 +5930,7 @@ dependencies = [ "solana-ledger", "solana-logger 1.11.0", "solana-net-utils", + "solana-program-runtime", "solana-program-test", "solana-rpc", "solana-runtime", diff --git a/core/src/validator.rs b/core/src/validator.rs index 129a2577ed..40f1d7cdba 100644 --- a/core/src/validator.rs +++ b/core/src/validator.rs @@ -73,6 +73,7 @@ use { commitment::BlockCommitmentCache, cost_model::CostModel, hardened_unpack::{open_genesis_config, MAX_GENESIS_ARCHIVE_UNPACKED_SIZE}, + runtime_config::RuntimeConfig, snapshot_archive_info::SnapshotArchiveInfoGetter, snapshot_config::SnapshotConfig, snapshot_hash::StartingSnapshotHashes, @@ -110,7 +111,6 @@ const MAX_COMPLETED_DATA_SETS_IN_CHANNEL: usize = 100_000; const WAIT_FOR_SUPERMAJORITY_THRESHOLD_PERCENT: u64 = 80; pub struct ValidatorConfig { - pub dev_halt_at_slot: Option, pub expected_genesis_hash: Option, pub expected_bank_hash: Option, pub expected_shred_version: Option, @@ -146,7 +146,6 @@ pub struct ValidatorConfig { pub debug_keys: Option>>, pub contact_debug_interval: u64, pub contact_save_interval: u64, - pub bpf_jit: bool, pub send_transaction_service_config: send_transaction_service::Config, pub no_poh_speed_test: bool, pub no_os_memory_stats_reporting: bool, @@ -165,12 +164,12 @@ pub struct ValidatorConfig { pub accounts_shrink_ratio: AccountShrinkThreshold, pub wait_to_vote_slot: Option, pub ledger_column_options: LedgerColumnOptions, + pub runtime_config: RuntimeConfig, } impl Default for ValidatorConfig { fn default() -> Self { Self { - dev_halt_at_slot: None, expected_genesis_hash: None, expected_bank_hash: None, expected_shred_version: None, @@ -206,7 +205,6 @@ impl Default for ValidatorConfig { debug_keys: None, contact_debug_interval: DEFAULT_CONTACT_DEBUG_INTERVAL_MILLIS, contact_save_interval: DEFAULT_CONTACT_SAVE_INTERVAL_MILLIS, - bpf_jit: false, send_transaction_service_config: send_transaction_service::Config::default(), no_poh_speed_test: true, no_os_memory_stats_reporting: true, @@ -225,6 +223,7 @@ impl Default for ValidatorConfig { accounts_db_config: None, wait_to_vote_slot: None, ledger_column_options: LedgerColumnOptions::default(), + runtime_config: RuntimeConfig::default(), } } } @@ -736,7 +735,7 @@ impl Validator { (None, None, None, None) }; - if config.dev_halt_at_slot.is_some() { + if config.runtime_config.dev_halt_at_slot.is_some() { // Simulate a confirmed root to avoid RPC errors with CommitmentConfig::finalized() and // to ensure RPC endpoints like getConfirmedBlock, which require a confirmed root, work block_commitment_cache @@ -1308,9 +1307,7 @@ fn load_blockstore( let blockstore_root_scan = BlockstoreRootScan::new(config, &blockstore, exit); let process_options = blockstore_processor::ProcessOptions { - bpf_jit: config.bpf_jit, poh_verify: config.poh_verify, - dev_halt_at_slot: config.dev_halt_at_slot, new_hard_forks: config.new_hard_forks.clone(), debug_keys: config.debug_keys.clone(), account_indexes: config.account_indexes.clone(), @@ -1319,6 +1316,7 @@ fn load_blockstore( shrink_ratio: config.accounts_shrink_ratio, accounts_db_test_hash_calculation: config.accounts_db_test_hash_calculation, accounts_db_skip_shrink: config.accounts_db_skip_shrink, + runtime_config: config.runtime_config.clone(), ..blockstore_processor::ProcessOptions::default() }; diff --git a/ledger-tool/src/main.rs b/ledger-tool/src/main.rs index ba922fb5c3..f7229f0617 100644 --- a/ledger-tool/src/main.rs +++ b/ledger-tool/src/main.rs @@ -39,6 +39,7 @@ use { cost_model::CostModel, cost_tracker::CostTracker, hardened_unpack::{open_genesis_config, MAX_GENESIS_ARCHIVE_UNPACKED_SIZE}, + runtime_config::RuntimeConfig, snapshot_archive_info::SnapshotArchiveInfoGetter, snapshot_config::SnapshotConfig, snapshot_hash::StartingSnapshotHashes, @@ -1785,9 +1786,12 @@ fn main() { } ("shred-version", Some(arg_matches)) => { let process_options = ProcessOptions { - dev_halt_at_slot: Some(0), new_hard_forks: hardforks_of(arg_matches, "hard_forks"), poh_verify: false, + runtime_config: RuntimeConfig { + dev_halt_at_slot: Some(0), + ..RuntimeConfig::default() + }, ..ProcessOptions::default() }; let genesis_config = open_genesis_config_by(&ledger_path, arg_matches); @@ -1862,9 +1866,12 @@ fn main() { } ("bank-hash", Some(arg_matches)) => { let process_options = ProcessOptions { - dev_halt_at_slot: Some(0), new_hard_forks: hardforks_of(arg_matches, "hard_forks"), poh_verify: false, + runtime_config: RuntimeConfig { + dev_halt_at_slot: Some(0), + ..RuntimeConfig::default() + }, ..ProcessOptions::default() }; let genesis_config = open_genesis_config_by(&ledger_path, arg_matches); @@ -2089,10 +2096,8 @@ fn main() { }); let process_options = ProcessOptions { - dev_halt_at_slot: value_t!(arg_matches, "halt_at_slot", Slot).ok(), new_hard_forks: hardforks_of(arg_matches, "hard_forks"), poh_verify: !arg_matches.is_present("skip_poh_verify"), - bpf_jit: !matches.is_present("no_bpf_jit"), accounts_db_caching_enabled: !arg_matches.is_present("no_accounts_db_caching"), limit_load_slot_count_from_snapshot: value_t!( arg_matches, @@ -2106,6 +2111,11 @@ fn main() { accounts_db_test_hash_calculation: arg_matches .is_present("accounts_db_test_hash_calculation"), accounts_db_skip_shrink: arg_matches.is_present("accounts_db_skip_shrink"), + runtime_config: RuntimeConfig { + dev_halt_at_slot: value_t!(arg_matches, "halt_at_slot", Slot).ok(), + bpf_jit: !matches.is_present("no_bpf_jit"), + ..RuntimeConfig::default() + }, ..ProcessOptions::default() }; let print_accounts_stats = arg_matches.is_present("print_accounts_stats"); @@ -2142,9 +2152,12 @@ fn main() { let output_file = value_t_or_exit!(arg_matches, "graph_filename", String); let process_options = ProcessOptions { - dev_halt_at_slot: value_t!(arg_matches, "halt_at_slot", Slot).ok(), new_hard_forks: hardforks_of(arg_matches, "hard_forks"), poh_verify: false, + runtime_config: RuntimeConfig { + dev_halt_at_slot: value_t!(arg_matches, "halt_at_slot", Slot).ok(), + ..RuntimeConfig::default() + }, ..ProcessOptions::default() }; @@ -2268,9 +2281,12 @@ fn main() { &genesis_config, &blockstore, ProcessOptions { - dev_halt_at_slot: Some(snapshot_slot), new_hard_forks, poh_verify: false, + runtime_config: RuntimeConfig { + dev_halt_at_slot: Some(snapshot_slot), + ..RuntimeConfig::default() + }, ..ProcessOptions::default() }, snapshot_archive_path, @@ -2565,9 +2581,12 @@ fn main() { ("accounts", Some(arg_matches)) => { let dev_halt_at_slot = value_t!(arg_matches, "halt_at_slot", Slot).ok(); let process_options = ProcessOptions { - dev_halt_at_slot, new_hard_forks: hardforks_of(arg_matches, "hard_forks"), poh_verify: false, + runtime_config: RuntimeConfig { + dev_halt_at_slot, + ..RuntimeConfig::default() + }, ..ProcessOptions::default() }; let genesis_config = open_genesis_config_by(&ledger_path, arg_matches); @@ -2628,9 +2647,12 @@ fn main() { ("capitalization", Some(arg_matches)) => { let dev_halt_at_slot = value_t!(arg_matches, "halt_at_slot", Slot).ok(); let process_options = ProcessOptions { - dev_halt_at_slot, new_hard_forks: hardforks_of(arg_matches, "hard_forks"), poh_verify: false, + runtime_config: RuntimeConfig { + dev_halt_at_slot, + ..RuntimeConfig::default() + }, ..ProcessOptions::default() }; let genesis_config = open_genesis_config_by(&ledger_path, arg_matches); diff --git a/ledger/src/bank_forks_utils.rs b/ledger/src/bank_forks_utils.rs index 2ad84fac23..ac4a6f41b5 100644 --- a/ledger/src/bank_forks_utils.rs +++ b/ledger/src/bank_forks_utils.rs @@ -211,14 +211,16 @@ fn bank_forks_from_snapshot( process::exit(1); } - let (deserialized_bank, full_snapshot_archive_info, incremental_snapshot_archive_info) = + let (mut deserialized_bank, full_snapshot_archive_info, incremental_snapshot_archive_info) = snapshot_utils::bank_from_latest_snapshot_archives( &snapshot_config.bank_snapshots_dir, &snapshot_config.snapshot_archives_dir, &account_paths, genesis_config, process_options.debug_keys.clone(), - Some(&crate::builtins::get(process_options.bpf_jit)), + Some(&crate::builtins::get( + process_options.runtime_config.bpf_jit, + )), process_options.account_indexes.clone(), process_options.accounts_db_caching_enabled, process_options.limit_load_slot_count_from_snapshot, @@ -235,6 +237,8 @@ fn bank_forks_from_snapshot( deserialized_bank.set_shrink_paths(shrink_paths); } + deserialized_bank.set_compute_budget(process_options.runtime_config.compute_budget); + let full_snapshot_hash = FullSnapshotHash { hash: ( full_snapshot_archive_info.slot(), diff --git a/ledger/src/blockstore_processor.rs b/ledger/src/blockstore_processor.rs index 3dd7a223c7..b897c78aaa 100644 --- a/ledger/src/blockstore_processor.rs +++ b/ledger/src/blockstore_processor.rs @@ -30,6 +30,7 @@ use { block_cost_limits::*, commitment::VOTE_THRESHOLD_SIZE, cost_model::CostModel, + runtime_config::RuntimeConfig, snapshot_config::SnapshotConfig, snapshot_package::{PendingAccountsPackage, SnapshotType}, snapshot_utils, @@ -544,10 +545,8 @@ pub type ProcessCallback = Arc; #[derive(Default, Clone)] pub struct ProcessOptions { - pub bpf_jit: bool, pub poh_verify: bool, pub full_leader_cache: bool, - pub dev_halt_at_slot: Option, pub entry_callback: Option, pub override_num_threads: Option, pub new_hard_forks: Option>, @@ -561,6 +560,7 @@ pub struct ProcessOptions { pub accounts_db_config: Option, pub verify_index: bool, pub shrink_ratio: AccountShrinkThreshold, + pub runtime_config: RuntimeConfig, } pub fn test_process_blockstore( @@ -603,11 +603,11 @@ pub(crate) fn process_blockstore_for_bank_0( accounts_update_notifier: Option, ) -> BankForks { // Setup bank for slot 0 - let bank0 = Bank::new_with_paths( + let mut bank0 = Bank::new_with_paths( genesis_config, account_paths, opts.debug_keys.clone(), - Some(&crate::builtins::get(opts.bpf_jit)), + Some(&crate::builtins::get(opts.runtime_config.bpf_jit)), opts.account_indexes.clone(), opts.accounts_db_caching_enabled, opts.shrink_ratio, @@ -615,6 +615,7 @@ pub(crate) fn process_blockstore_for_bank_0( opts.accounts_db_config.clone(), accounts_update_notifier, ); + bank0.set_compute_budget(opts.runtime_config.compute_budget); let bank_forks = BankForks::new(bank0); info!("processing ledger for slot 0..."); @@ -1147,7 +1148,10 @@ fn load_frozen_forks( &mut pending_slots, )?; - let dev_halt_at_slot = opts.dev_halt_at_slot.unwrap_or(std::u64::MAX); + let dev_halt_at_slot = opts + .runtime_config + .dev_halt_at_slot + .unwrap_or(std::u64::MAX); if bank_forks.root() != dev_halt_at_slot { while !pending_slots.is_empty() { timing.details.per_program_timings.clear(); @@ -3084,8 +3088,11 @@ pub mod tests { // Specify halting at slot 0 let opts = ProcessOptions { poh_verify: true, - dev_halt_at_slot: Some(0), accounts_db_test_hash_calculation: true, + runtime_config: RuntimeConfig { + dev_halt_at_slot: Some(0), + ..RuntimeConfig::default() + }, ..ProcessOptions::default() }; let (bank_forks, ..) = test_process_blockstore(&genesis_config, &blockstore, opts); diff --git a/local-cluster/src/validator_configs.rs b/local-cluster/src/validator_configs.rs index d249cd5f24..23ab368d97 100644 --- a/local-cluster/src/validator_configs.rs +++ b/local-cluster/src/validator_configs.rs @@ -6,7 +6,6 @@ use { pub fn safe_clone_config(config: &ValidatorConfig) -> ValidatorConfig { ValidatorConfig { - dev_halt_at_slot: config.dev_halt_at_slot, expected_genesis_hash: config.expected_genesis_hash, expected_bank_hash: config.expected_bank_hash, expected_shred_version: config.expected_shred_version, @@ -43,7 +42,6 @@ pub fn safe_clone_config(config: &ValidatorConfig) -> ValidatorConfig { debug_keys: config.debug_keys.clone(), contact_debug_interval: config.contact_debug_interval, contact_save_interval: config.contact_save_interval, - bpf_jit: config.bpf_jit, send_transaction_service_config: config.send_transaction_service_config.clone(), no_poh_speed_test: config.no_poh_speed_test, no_os_memory_stats_reporting: config.no_os_memory_stats_reporting, @@ -62,6 +60,7 @@ pub fn safe_clone_config(config: &ValidatorConfig) -> ValidatorConfig { accounts_db_config: config.accounts_db_config.clone(), wait_to_vote_slot: config.wait_to_vote_slot, ledger_column_options: config.ledger_column_options.clone(), + runtime_config: config.runtime_config.clone(), } } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 01d46007af..6703b81030 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -44,6 +44,7 @@ mod pubkey_bins; mod read_only_accounts_cache; pub mod rent_collector; mod rolling_bit_field; +pub mod runtime_config; pub mod secondary_index; pub mod serde_snapshot; mod shared_buffer_reader; diff --git a/runtime/src/runtime_config.rs b/runtime/src/runtime_config.rs new file mode 100644 index 0000000000..199f04ad10 --- /dev/null +++ b/runtime/src/runtime_config.rs @@ -0,0 +1,9 @@ +use {solana_program_runtime::compute_budget::ComputeBudget, solana_sdk::clock::Slot}; + +/// Encapsulates flags that can be used to tweak the runtime behavior. +#[derive(Default, Clone)] +pub struct RuntimeConfig { + pub bpf_jit: bool, + pub dev_halt_at_slot: Option, + pub compute_budget: Option, +} diff --git a/test-validator/Cargo.toml b/test-validator/Cargo.toml index 5849f5eecb..68912ca914 100644 --- a/test-validator/Cargo.toml +++ b/test-validator/Cargo.toml @@ -22,6 +22,7 @@ solana-gossip = { path = "../gossip", version = "=1.11.0" } solana-ledger = { path = "../ledger", version = "=1.11.0" } solana-logger = { path = "../logger", version = "=1.11.0" } solana-net-utils = { path = "../net-utils", version = "=1.11.0" } +solana-program-runtime = { path = "../program-runtime", version = "=1.11.0" } solana-program-test = { path = "../program-test", version = "=1.11.0" } solana-rpc = { path = "../rpc", version = "=1.11.0" } solana-runtime = { path = "../runtime", version = "=1.11.0" } diff --git a/test-validator/src/lib.rs b/test-validator/src/lib.rs index 305591d2ec..7233628311 100644 --- a/test-validator/src/lib.rs +++ b/test-validator/src/lib.rs @@ -16,11 +16,13 @@ use { blockstore::create_new_ledger, blockstore_db::LedgerColumnOptions, create_new_tmp_ledger, }, solana_net_utils::PortRange, + solana_program_runtime::compute_budget::ComputeBudget, solana_rpc::{rpc::JsonRpcConfig, rpc_pubsub_service::PubSubConfig}, solana_runtime::{ accounts_db::AccountsDbConfig, accounts_index::AccountsIndexConfig, bank_forks::BankForks, genesis_utils::create_genesis_config_with_leader_ex, - hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE, snapshot_config::SnapshotConfig, + hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE, runtime_config::RuntimeConfig, + snapshot_config::SnapshotConfig, }, solana_sdk::{ account::{Account, AccountSharedData}, @@ -111,6 +113,7 @@ pub struct TestValidatorGenesis { pub geyser_plugin_config_files: Option>, pub accounts_db_caching_enabled: bool, deactivate_feature_set: HashSet, + max_compute_units: Option, } impl Default for TestValidatorGenesis { @@ -138,6 +141,7 @@ impl Default for TestValidatorGenesis { geyser_plugin_config_files: Option::>::default(), accounts_db_caching_enabled: bool::default(), deactivate_feature_set: HashSet::::default(), + max_compute_units: Option::::default(), } } } @@ -235,6 +239,11 @@ impl TestValidatorGenesis { self } + pub fn max_compute_units(&mut self, max_compute_units: u64) -> &mut Self { + self.max_compute_units = Some(max_compute_units); + self + } + /// Add an account to the test environment pub fn add_account(&mut self, address: Pubkey, account: AccountSharedData) -> &mut Self { self.accounts.insert(address, account); @@ -666,6 +675,15 @@ impl TestValidator { ..AccountsDbConfig::default() }); + let runtime_config = RuntimeConfig { + bpf_jit: !config.no_bpf_jit, + compute_budget: config.max_compute_units.map(|max_units| ComputeBudget { + max_units, + ..ComputeBudget::default() + }), + ..RuntimeConfig::default() + }; + let mut validator_config = ValidatorConfig { geyser_plugin_config_files: config.geyser_plugin_config_files.clone(), accounts_db_caching_enabled: config.accounts_db_caching_enabled, @@ -690,12 +708,12 @@ impl TestValidator { }), enforce_ulimit_nofile: false, warp_slot: config.warp_slot, - bpf_jit: !config.no_bpf_jit, validator_exit: config.validator_exit.clone(), rocksdb_compaction_interval: Some(100), // Compact every 100 slots max_ledger_shreds: config.max_ledger_shreds, no_wait_for_vote_to_start_leader: true, accounts_db_config, + runtime_config, ..ValidatorConfig::default_for_test() }; if let Some(ref tower_storage) = config.tower_storage { diff --git a/validator/src/bin/solana-test-validator.rs b/validator/src/bin/solana-test-validator.rs index 85f9fb67f8..3dd6ff63f3 100644 --- a/validator/src/bin/solana-test-validator.rs +++ b/validator/src/bin/solana-test-validator.rs @@ -354,6 +354,14 @@ fn main() { .multiple(true) .help("deactivate this feature in genesis.") ) + .arg( + Arg::with_name("max_compute_units") + .long("max-compute-units") + .value_name("COMPUTE_UNITS") + .validator(is_parsable::) + .takes_value(true) + .help("Override the runtime's maximum compute units") + ) .get_matches(); let output = if matches.is_present("quiet") { @@ -462,6 +470,7 @@ fn main() { exit(1); }) }); + let max_compute_units = value_t!(matches, "max_compute_units", u64).ok(); let faucet_addr = Some(SocketAddr::new( IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), @@ -724,6 +733,10 @@ fn main() { ); } + if let Some(max_compute_units) = max_compute_units { + genesis.max_compute_units(max_compute_units); + } + match genesis.start_with_mint_address(mint_address, socket_addr_space) { Ok(test_validator) => { *admin_service_post_init.write().unwrap() = diff --git a/validator/src/main.rs b/validator/src/main.rs index 1324673d84..181a522f1b 100644 --- a/validator/src/main.rs +++ b/validator/src/main.rs @@ -50,6 +50,7 @@ use { AccountsIndexConfig, }, hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE, + runtime_config::RuntimeConfig, snapshot_config::SnapshotConfig, snapshot_utils::{ self, ArchiveFormat, SnapshotVersion, DEFAULT_FULL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS, @@ -2326,7 +2327,6 @@ pub fn main() { let mut validator_config = ValidatorConfig { require_tower: matches.is_present("require_tower"), tower_storage, - dev_halt_at_slot: value_t!(matches, "dev_halt_at_slot", Slot).ok(), expected_genesis_hash: matches .value_of("expected_genesis_hash") .map(|s| Hash::from_str(s).unwrap()), @@ -2403,7 +2403,6 @@ pub fn main() { poh_verify: !matches.is_present("skip_poh_verify"), debug_keys, contact_debug_interval, - bpf_jit: !matches.is_present("no_bpf_jit"), send_transaction_service_config: send_transaction_service::Config { retry_rate_ms: value_t_or_exit!(matches, "rpc_send_transaction_retry_ms", u64), leader_forward_count: value_t_or_exit!( @@ -2439,6 +2438,11 @@ pub fn main() { tpu_coalesce_ms, no_wait_for_vote_to_start_leader: matches.is_present("no_wait_for_vote_to_start_leader"), accounts_shrink_ratio, + runtime_config: RuntimeConfig { + dev_halt_at_slot: value_t!(matches, "dev_halt_at_slot", Slot).ok(), + bpf_jit: !matches.is_present("no_bpf_jit"), + ..RuntimeConfig::default() + }, ..ValidatorConfig::default() };