From 057244e82ec61cfbd43ce1016569de4375ebe6d4 Mon Sep 17 00:00:00 2001 From: Andrew Fitzgerald Date: Mon, 16 Dec 2024 11:33:11 -0600 Subject: [PATCH 1/2] SIMD-0207: Raise block limit to 50M (#4112) * SIMD-0207: Raise block limit to 50M (#4026) * Fix loading from snapshots/genesis (cherry picked from commit 9e59baae79570628163d95a169e40f11b1db5109) # Conflicts: # cost-model/src/block_cost_limits.rs # runtime/src/bank.rs # sdk/feature-set/src/lib.rs --- cost-model/src/block_cost_limits.rs | 21 ++++++++ cost-model/src/cost_tracker.rs | 5 ++ runtime/src/bank.rs | 78 +++++++++++++++++++++++++++++ runtime/src/bank/tests.rs | 68 +++++++++++++++++++++++++ sdk/feature-set/src/lib.rs | 21 ++++++++ 5 files changed, 193 insertions(+) diff --git a/cost-model/src/block_cost_limits.rs b/cost-model/src/block_cost_limits.rs index 7fc4b2fe670b39..22940b55dcab75 100644 --- a/cost-model/src/block_cost_limits.rs +++ b/cost-model/src/block_cost_limits.rs @@ -33,17 +33,23 @@ pub const INSTRUCTION_DATA_BYTES_COST: u64 = 140 /*bytes per us*/ / COMPUTE_UNIT /// accumulated by Transactions added to it; A transaction's compute units are /// calculated by cost_model, based on transaction's signatures, write locks, /// data size and built-in and SBF instructions. +<<<<<<< HEAD pub const MAX_BLOCK_UNITS: u64 = MAX_BLOCK_REPLAY_TIME_US * COMPUTE_UNIT_TO_US_RATIO * MAX_CONCURRENCY; #[cfg(test)] static_assertions::const_assert_eq!(MAX_BLOCK_UNITS, 48_000_000); +======= +pub const MAX_BLOCK_UNITS: u64 = 48_000_000; +pub const MAX_BLOCK_UNITS_SIMD_0207: u64 = 50_000_000; +>>>>>>> 9e59baae7 (SIMD-0207: Raise block limit to 50M (#4112)) /// Number of compute units that a writable account in a block is allowed. The /// limit is to prevent too many transactions write to same account, therefore /// reduce block's parallelism. pub const MAX_WRITABLE_ACCOUNT_UNITS: u64 = MAX_BLOCK_REPLAY_TIME_US * COMPUTE_UNIT_TO_US_RATIO; +<<<<<<< HEAD #[cfg(test)] static_assertions::const_assert_eq!(MAX_WRITABLE_ACCOUNT_UNITS, 12_000_000); @@ -54,6 +60,21 @@ pub const MAX_VOTE_UNITS: u64 = (MAX_BLOCK_UNITS as f64 * 0.75_f64) as u64; #[cfg(test)] static_assertions::const_assert_eq!(MAX_VOTE_UNITS, 36_000_000); +======= +>>>>>>> 9e59baae7 (SIMD-0207: Raise block limit to 50M (#4112)) /// The maximum allowed size, in bytes, that accounts data can grow, per block. /// This can also be thought of as the maximum size of new allocations per block. pub const MAX_BLOCK_ACCOUNTS_DATA_SIZE_DELTA: u64 = 100_000_000; + +/// Return the block limits that will be used upon activation of SIMD-0207. +/// Returns as +/// (account_limit, block_limit, vote_limit) +// ^ Above order is used to be consistent with the order of +// `CostTracker::set_limits`. +pub const fn simd_0207_block_limits() -> (u64, u64, u64) { + ( + MAX_WRITABLE_ACCOUNT_UNITS, + MAX_BLOCK_UNITS_SIMD_0207, + MAX_VOTE_UNITS, + ) +} diff --git a/cost-model/src/cost_tracker.rs b/cost-model/src/cost_tracker.rs index 3b9382bba0a901..9e9122c37471dc 100644 --- a/cost-model/src/cost_tracker.rs +++ b/cost-model/src/cost_tracker.rs @@ -129,6 +129,11 @@ impl CostTracker { self.in_flight_transaction_count = 0; } + /// Get the overall block limit. + pub fn get_block_limit(&self) -> u64 { + self.block_cost_limit + } + /// allows to adjust limits initiated during construction pub fn set_limits( &mut self, diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 237208caf191d9..5023b546d0840f 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -96,7 +96,12 @@ use { create_program_runtime_environment_v1, create_program_runtime_environment_v2, }, solana_compute_budget::compute_budget::ComputeBudget, +<<<<<<< HEAD solana_cost_model::cost_tracker::CostTracker, +======= + solana_compute_budget_instruction::instructions_processor::process_compute_budget_instructions, + solana_cost_model::{block_cost_limits::simd_0207_block_limits, cost_tracker::CostTracker}, +>>>>>>> 9e59baae7 (SIMD-0207: Raise block limit to 50M (#4112)) solana_feature_set::{ self as feature_set, remove_rounding_in_fee_calculation, reward_full_priority_fee, FeatureSet, @@ -5066,6 +5071,22 @@ impl Bank { debug_do_not_add_builtins, ); + // Cost-Tracker is not serialized in snapshot or any configs. + // We must apply previously activated features related to limits here + // so that the initial bank state is consistent with the feature set. + // Cost-tracker limits are propagated through children banks. + if self + .feature_set + .is_active(&feature_set::raise_block_limits_to_50m::id()) + { + let (account_cost_limit, block_cost_limit, vote_cost_limit) = simd_0207_block_limits(); + self.write_cost_tracker().unwrap().set_limits( + account_cost_limit, + block_cost_limit, + vote_cost_limit, + ); + } + if !debug_do_not_add_builtins { for builtin in BUILTINS .iter() @@ -6639,6 +6660,63 @@ impl Bank { if new_feature_activations.contains(&feature_set::update_hashes_per_tick6::id()) { self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK6); } +<<<<<<< HEAD +======= + + if new_feature_activations.contains(&feature_set::accounts_lt_hash::id()) { + // Activating the accounts lt hash feature means we need to have an accounts lt hash + // value at the end of this if-block. If the cli arg has been used, that means we + // already have an accounts lt hash and do not need to recalculate it. + if self + .rc + .accounts + .accounts_db + .is_experimental_accumulator_hash_enabled() + { + // We already have an accounts lt hash value, so no need to recalculate it. + // Nothing else to do here. + } else { + let parent_slot = self.parent_slot; + info!( + "Calculating the accounts lt hash for slot {parent_slot} \ + as part of feature activation; this may take some time...", + ); + // We must calculate the accounts lt hash now as part of feature activation. + // Note, this bank is *not* frozen yet, which means it will later call + // `update_accounts_lt_hash()`. Therefore, we calculate the accounts lt hash based + // on *our parent*, not us! + let parent_ancestors = { + let mut ancestors = self.ancestors.clone(); + ancestors.remove(&self.slot()); + ancestors + }; + let (parent_accounts_lt_hash, duration) = meas_dur!({ + self.rc + .accounts + .accounts_db + .calculate_accounts_lt_hash_at_startup_from_index( + &parent_ancestors, + parent_slot, + ) + }); + *self.accounts_lt_hash.get_mut().unwrap() = parent_accounts_lt_hash; + info!( + "Calculating the accounts lt hash for slot {parent_slot} \ + completed in {duration:?}, accounts_lt_hash checksum: {}", + self.accounts_lt_hash.get_mut().unwrap().0.checksum(), + ); + } + } + + if new_feature_activations.contains(&feature_set::raise_block_limits_to_50m::id()) { + let (account_cost_limit, block_cost_limit, vote_cost_limit) = simd_0207_block_limits(); + self.write_cost_tracker().unwrap().set_limits( + account_cost_limit, + block_cost_limit, + vote_cost_limit, + ); + } +>>>>>>> 9e59baae7 (SIMD-0207: Raise block limit to 50M (#4112)) } fn apply_updated_hashes_per_tick(&mut self, hashes_per_tick: u64) { diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 128ec740d2014e..6cfb4c496bee95 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -38,6 +38,7 @@ use { compute_budget_limits::{self, MAX_COMPUTE_UNIT_LIMIT}, prioritization_fee::{PrioritizationFeeDetails, PrioritizationFeeType}, }, + solana_cost_model::block_cost_limits::{MAX_BLOCK_UNITS, MAX_BLOCK_UNITS_SIMD_0207}, solana_feature_set::{self as feature_set, FeatureSet}, solana_inline_spl::token, solana_logger, @@ -7999,6 +8000,73 @@ fn test_reserved_account_keys() { ); } +#[test] +fn test_block_limits() { + let (bank0, _bank_forks) = create_simple_test_arc_bank(100_000); + let mut bank = Bank::new_from_parent(bank0, &Pubkey::default(), 1); + assert!(!bank + .feature_set + .is_active(&feature_set::raise_block_limits_to_50m::id())); + assert_eq!( + bank.read_cost_tracker().unwrap().get_block_limit(), + MAX_BLOCK_UNITS, + "before activating the feature, bank should have old/default limit" + ); + + // Activate `raise_block_limits_to_50m` feature + bank.store_account( + &feature_set::raise_block_limits_to_50m::id(), + &feature::create_account(&Feature::default(), 42), + ); + // apply_feature_activations for `FinishInit` will not cause the block limit to be updated + bank.apply_feature_activations(ApplyFeatureActivationsCaller::FinishInit, true); + assert_eq!( + bank.read_cost_tracker().unwrap().get_block_limit(), + MAX_BLOCK_UNITS, + "before activating the feature, bank should have old/default limit" + ); + + // apply_feature_activations for `NewFromParent` will cause feature to be activated + bank.apply_feature_activations(ApplyFeatureActivationsCaller::NewFromParent, true); + assert_eq!( + bank.read_cost_tracker().unwrap().get_block_limit(), + MAX_BLOCK_UNITS_SIMD_0207, + "after activating the feature, bank should have new limit" + ); + + // Make sure the limits propagate to the child-bank. + let bank = Bank::new_from_parent(Arc::new(bank), &Pubkey::default(), 2); + assert_eq!( + bank.read_cost_tracker().unwrap().get_block_limit(), + MAX_BLOCK_UNITS_SIMD_0207, + "child bank should have new limit" + ); + + // Test starting from a genesis config with and without feature account + let (mut genesis_config, _keypair) = create_genesis_config(100_000); + // Without feature account in genesis, old limits are used. + let bank = Bank::new_for_tests(&genesis_config); + assert_eq!( + bank.read_cost_tracker().unwrap().get_block_limit(), + MAX_BLOCK_UNITS, + "before activating the feature, bank should have old/default limit" + ); + + activate_feature( + &mut genesis_config, + feature_set::raise_block_limits_to_50m::id(), + ); + let bank = Bank::new_for_tests(&genesis_config); + assert!(bank + .feature_set + .is_active(&feature_set::raise_block_limits_to_50m::id())); + assert_eq!( + bank.read_cost_tracker().unwrap().get_block_limit(), + MAX_BLOCK_UNITS_SIMD_0207, + "bank created from genesis config should have new limit" + ); +} + #[test] fn test_program_replacement() { let mut bank = create_simple_test_bank(0); diff --git a/sdk/feature-set/src/lib.rs b/sdk/feature-set/src/lib.rs index 5cb5f42daf492f..132e7ec8640193 100644 --- a/sdk/feature-set/src/lib.rs +++ b/sdk/feature-set/src/lib.rs @@ -881,6 +881,21 @@ pub mod migrate_stake_program_to_core_bpf { solana_pubkey::declare_id!("6M4oQ6eXneVhtLoiAr4yRYQY43eVLjrKbiDZDJc892yk"); } +<<<<<<< HEAD +======= +pub mod deplete_cu_meter_on_vm_failure { + solana_pubkey::declare_id!("B7H2caeia4ZFcpE3QcgMqbiWiBtWrdBRBSJ1DY6Ktxbq"); +} + +pub mod reserve_minimal_cus_for_builtin_instructions { + solana_pubkey::declare_id!("C9oAhLxDBm3ssWtJx1yBGzPY55r2rArHmN1pbQn6HogH"); +} + +pub mod raise_block_limits_to_50m { + solana_pubkey::declare_id!("5oMCU3JPaFLr8Zr4ct7yFA7jdk6Mw1RmB8K4u9ZbS42z"); +} + +>>>>>>> 9e59baae7 (SIMD-0207: Raise block limit to 50M (#4112)) lazy_static! { /// Map of feature identifiers to user-visible description pub static ref FEATURE_NAMES: HashMap = [ @@ -1096,6 +1111,12 @@ lazy_static! { (disable_account_loader_special_case::id(), "Disable account loader special case #3513"), (enable_secp256r1_precompile::id(), "Enable secp256r1 precompile SIMD-0075"), (migrate_stake_program_to_core_bpf::id(), "Migrate Stake program to Core BPF SIMD-0196 #3655"), +<<<<<<< HEAD +======= + (deplete_cu_meter_on_vm_failure::id(), "Deplete compute meter for vm errors SIMD-0182 #3993"), + (reserve_minimal_cus_for_builtin_instructions::id(), "Reserve minimal CUs for builtin instructions SIMD-170 #2562"), + (raise_block_limits_to_50m::id(), "Raise block limit to 50M SIMD-0207"), +>>>>>>> 9e59baae7 (SIMD-0207: Raise block limit to 50M (#4112)) /*************** ADD NEW FEATURES HERE ***************/ ] .iter() From 1876d4790ae02e5ea5d12afbb84e0d7348af9e76 Mon Sep 17 00:00:00 2001 From: Andrew Fitzgerald Date: Mon, 16 Dec 2024 12:54:09 -0600 Subject: [PATCH 2/2] resolve conflicts --- cost-model/src/block_cost_limits.rs | 7 ---- runtime/src/bank.rs | 53 ----------------------------- sdk/feature-set/src/lib.rs | 16 --------- 3 files changed, 76 deletions(-) diff --git a/cost-model/src/block_cost_limits.rs b/cost-model/src/block_cost_limits.rs index 22940b55dcab75..661b1c824fc41e 100644 --- a/cost-model/src/block_cost_limits.rs +++ b/cost-model/src/block_cost_limits.rs @@ -33,23 +33,18 @@ pub const INSTRUCTION_DATA_BYTES_COST: u64 = 140 /*bytes per us*/ / COMPUTE_UNIT /// accumulated by Transactions added to it; A transaction's compute units are /// calculated by cost_model, based on transaction's signatures, write locks, /// data size and built-in and SBF instructions. -<<<<<<< HEAD pub const MAX_BLOCK_UNITS: u64 = MAX_BLOCK_REPLAY_TIME_US * COMPUTE_UNIT_TO_US_RATIO * MAX_CONCURRENCY; #[cfg(test)] static_assertions::const_assert_eq!(MAX_BLOCK_UNITS, 48_000_000); -======= -pub const MAX_BLOCK_UNITS: u64 = 48_000_000; pub const MAX_BLOCK_UNITS_SIMD_0207: u64 = 50_000_000; ->>>>>>> 9e59baae7 (SIMD-0207: Raise block limit to 50M (#4112)) /// Number of compute units that a writable account in a block is allowed. The /// limit is to prevent too many transactions write to same account, therefore /// reduce block's parallelism. pub const MAX_WRITABLE_ACCOUNT_UNITS: u64 = MAX_BLOCK_REPLAY_TIME_US * COMPUTE_UNIT_TO_US_RATIO; -<<<<<<< HEAD #[cfg(test)] static_assertions::const_assert_eq!(MAX_WRITABLE_ACCOUNT_UNITS, 12_000_000); @@ -60,8 +55,6 @@ pub const MAX_VOTE_UNITS: u64 = (MAX_BLOCK_UNITS as f64 * 0.75_f64) as u64; #[cfg(test)] static_assertions::const_assert_eq!(MAX_VOTE_UNITS, 36_000_000); -======= ->>>>>>> 9e59baae7 (SIMD-0207: Raise block limit to 50M (#4112)) /// The maximum allowed size, in bytes, that accounts data can grow, per block. /// This can also be thought of as the maximum size of new allocations per block. pub const MAX_BLOCK_ACCOUNTS_DATA_SIZE_DELTA: u64 = 100_000_000; diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 5023b546d0840f..c804f17c738b40 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -96,12 +96,7 @@ use { create_program_runtime_environment_v1, create_program_runtime_environment_v2, }, solana_compute_budget::compute_budget::ComputeBudget, -<<<<<<< HEAD - solana_cost_model::cost_tracker::CostTracker, -======= - solana_compute_budget_instruction::instructions_processor::process_compute_budget_instructions, solana_cost_model::{block_cost_limits::simd_0207_block_limits, cost_tracker::CostTracker}, ->>>>>>> 9e59baae7 (SIMD-0207: Raise block limit to 50M (#4112)) solana_feature_set::{ self as feature_set, remove_rounding_in_fee_calculation, reward_full_priority_fee, FeatureSet, @@ -6660,53 +6655,6 @@ impl Bank { if new_feature_activations.contains(&feature_set::update_hashes_per_tick6::id()) { self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK6); } -<<<<<<< HEAD -======= - - if new_feature_activations.contains(&feature_set::accounts_lt_hash::id()) { - // Activating the accounts lt hash feature means we need to have an accounts lt hash - // value at the end of this if-block. If the cli arg has been used, that means we - // already have an accounts lt hash and do not need to recalculate it. - if self - .rc - .accounts - .accounts_db - .is_experimental_accumulator_hash_enabled() - { - // We already have an accounts lt hash value, so no need to recalculate it. - // Nothing else to do here. - } else { - let parent_slot = self.parent_slot; - info!( - "Calculating the accounts lt hash for slot {parent_slot} \ - as part of feature activation; this may take some time...", - ); - // We must calculate the accounts lt hash now as part of feature activation. - // Note, this bank is *not* frozen yet, which means it will later call - // `update_accounts_lt_hash()`. Therefore, we calculate the accounts lt hash based - // on *our parent*, not us! - let parent_ancestors = { - let mut ancestors = self.ancestors.clone(); - ancestors.remove(&self.slot()); - ancestors - }; - let (parent_accounts_lt_hash, duration) = meas_dur!({ - self.rc - .accounts - .accounts_db - .calculate_accounts_lt_hash_at_startup_from_index( - &parent_ancestors, - parent_slot, - ) - }); - *self.accounts_lt_hash.get_mut().unwrap() = parent_accounts_lt_hash; - info!( - "Calculating the accounts lt hash for slot {parent_slot} \ - completed in {duration:?}, accounts_lt_hash checksum: {}", - self.accounts_lt_hash.get_mut().unwrap().0.checksum(), - ); - } - } if new_feature_activations.contains(&feature_set::raise_block_limits_to_50m::id()) { let (account_cost_limit, block_cost_limit, vote_cost_limit) = simd_0207_block_limits(); @@ -6716,7 +6664,6 @@ impl Bank { vote_cost_limit, ); } ->>>>>>> 9e59baae7 (SIMD-0207: Raise block limit to 50M (#4112)) } fn apply_updated_hashes_per_tick(&mut self, hashes_per_tick: u64) { diff --git a/sdk/feature-set/src/lib.rs b/sdk/feature-set/src/lib.rs index 132e7ec8640193..7300964d10f1e2 100644 --- a/sdk/feature-set/src/lib.rs +++ b/sdk/feature-set/src/lib.rs @@ -881,21 +881,10 @@ pub mod migrate_stake_program_to_core_bpf { solana_pubkey::declare_id!("6M4oQ6eXneVhtLoiAr4yRYQY43eVLjrKbiDZDJc892yk"); } -<<<<<<< HEAD -======= -pub mod deplete_cu_meter_on_vm_failure { - solana_pubkey::declare_id!("B7H2caeia4ZFcpE3QcgMqbiWiBtWrdBRBSJ1DY6Ktxbq"); -} - -pub mod reserve_minimal_cus_for_builtin_instructions { - solana_pubkey::declare_id!("C9oAhLxDBm3ssWtJx1yBGzPY55r2rArHmN1pbQn6HogH"); -} - pub mod raise_block_limits_to_50m { solana_pubkey::declare_id!("5oMCU3JPaFLr8Zr4ct7yFA7jdk6Mw1RmB8K4u9ZbS42z"); } ->>>>>>> 9e59baae7 (SIMD-0207: Raise block limit to 50M (#4112)) lazy_static! { /// Map of feature identifiers to user-visible description pub static ref FEATURE_NAMES: HashMap = [ @@ -1111,12 +1100,7 @@ lazy_static! { (disable_account_loader_special_case::id(), "Disable account loader special case #3513"), (enable_secp256r1_precompile::id(), "Enable secp256r1 precompile SIMD-0075"), (migrate_stake_program_to_core_bpf::id(), "Migrate Stake program to Core BPF SIMD-0196 #3655"), -<<<<<<< HEAD -======= - (deplete_cu_meter_on_vm_failure::id(), "Deplete compute meter for vm errors SIMD-0182 #3993"), - (reserve_minimal_cus_for_builtin_instructions::id(), "Reserve minimal CUs for builtin instructions SIMD-170 #2562"), (raise_block_limits_to_50m::id(), "Raise block limit to 50M SIMD-0207"), ->>>>>>> 9e59baae7 (SIMD-0207: Raise block limit to 50M (#4112)) /*************** ADD NEW FEATURES HERE ***************/ ] .iter()