From d626d66b5929000fbe2b0515a5e687e125868733 Mon Sep 17 00:00:00 2001 From: Brennan Date: Thu, 6 Mar 2025 16:28:38 +0000 Subject: [PATCH 1/3] SIMD 256 --- cost-model/src/block_cost_limits.rs | 14 +++++++ runtime/src/bank.rs | 26 ++++++++++++- runtime/src/bank/tests.rs | 59 ++++++++++++++++++++++++++++- 3 files changed, 96 insertions(+), 3 deletions(-) diff --git a/cost-model/src/block_cost_limits.rs b/cost-model/src/block_cost_limits.rs index 912ee504f712fd..cd13eb43f44c52 100644 --- a/cost-model/src/block_cost_limits.rs +++ b/cost-model/src/block_cost_limits.rs @@ -27,6 +27,7 @@ pub const INSTRUCTION_DATA_BYTES_COST: u64 = 140 /*bytes per us*/ / COMPUTE_UNIT /// data size and built-in and SBF instructions. pub const MAX_BLOCK_UNITS: u64 = 48_000_000; pub const MAX_BLOCK_UNITS_SIMD_0207: u64 = 50_000_000; +pub const MAX_BLOCK_UNITS_SIMD_0256: u64 = 60_000_000; /// 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 @@ -53,3 +54,16 @@ pub const fn simd_0207_block_limits() -> (u64, u64, u64) { MAX_VOTE_UNITS, ) } + +/// Return the block limits that will be used upon activation of SIMD-0256. +/// 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_0256_block_limits() -> (u64, u64, u64) { + ( + MAX_WRITABLE_ACCOUNT_UNITS, + MAX_BLOCK_UNITS_SIMD_0256, + MAX_VOTE_UNITS, + ) +} diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 3c78a5bccda656..433429a1a94736 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -94,7 +94,10 @@ use { solana_builtins::{prototype::BuiltinPrototype, BUILTINS, STATELESS_BUILTINS}, solana_compute_budget::compute_budget::ComputeBudget, solana_compute_budget_instruction::instructions_processor::process_compute_budget_instructions, - solana_cost_model::{block_cost_limits::simd_0207_block_limits, cost_tracker::CostTracker}, + solana_cost_model::{ + block_cost_limits::{simd_0207_block_limits, simd_0256_block_limits}, + cost_tracker::CostTracker, + }, solana_feature_set::{self as feature_set, FeatureSet}, solana_fee::FeeFeatures, solana_lattice_hash::lt_hash::LtHash, @@ -4844,6 +4847,18 @@ impl Bank { ); } + if self + .feature_set + .is_active(&feature_set::raise_block_limits_to_60m::id()) + { + let (account_cost_limit, block_cost_limit, vote_cost_limit) = simd_0256_block_limits(); + self.write_cost_tracker().unwrap().set_limits( + account_cost_limit, + block_cost_limit, + vote_cost_limit, + ); + } + // If the accounts delta hash is still in use, start the background account hasher if !self .feature_set @@ -6525,6 +6540,15 @@ impl Bank { ); } + if new_feature_activations.contains(&feature_set::raise_block_limits_to_60m::id()) { + let (account_cost_limit, block_cost_limit, vote_cost_limit) = simd_0256_block_limits(); + self.write_cost_tracker().unwrap().set_limits( + account_cost_limit, + block_cost_limit, + vote_cost_limit, + ); + } + if new_feature_activations.contains(&feature_set::remove_accounts_delta_hash::id()) { // If the accounts delta hash has been removed, then we no longer need to compute the // AccountHash for modified accounts, and can stop the background account hasher. diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 1c88b586f70529..98645f8dece304 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -39,7 +39,9 @@ use { compute_budget::ComputeBudget, compute_budget_limits::{self, ComputeBudgetLimits, MAX_COMPUTE_UNIT_LIMIT}, }, - solana_cost_model::block_cost_limits::{MAX_BLOCK_UNITS, MAX_BLOCK_UNITS_SIMD_0207}, + solana_cost_model::block_cost_limits::{ + MAX_BLOCK_UNITS, MAX_BLOCK_UNITS_SIMD_0207, MAX_BLOCK_UNITS_SIMD_0256, + }, solana_feature_set::{self as feature_set, FeatureSet}, solana_inline_spl::token, solana_logger, @@ -8081,10 +8083,39 @@ fn test_block_limits() { ); // Make sure the limits propagate to the child-bank. - let bank = Bank::new_from_parent(Arc::new(bank), &Pubkey::default(), 2); + let mut 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" + ); + + // Activate `raise_block_limits_to_60m` feature + bank.store_account( + &feature_set::raise_block_limits_to_60m::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_SIMD_0207, + "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_0256, + "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(), 3); + assert_eq!( + bank.read_cost_tracker().unwrap().get_block_limit(), + MAX_BLOCK_UNITS_SIMD_0256, "child bank should have new limit" ); @@ -8111,6 +8142,30 @@ fn test_block_limits() { MAX_BLOCK_UNITS_SIMD_0207, "bank created from genesis config 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_60m::id(), + ); + let bank = Bank::new_for_tests(&genesis_config); + assert!(bank + .feature_set + .is_active(&feature_set::raise_block_limits_to_60m::id())); + assert_eq!( + bank.read_cost_tracker().unwrap().get_block_limit(), + MAX_BLOCK_UNITS_SIMD_0256, + "bank created from genesis config should have new limit" + ); } #[test] From 2dd419c9db5774005e9addb95305601bb7e87ba9 Mon Sep 17 00:00:00 2001 From: Brennan Date: Thu, 6 Mar 2025 22:03:06 +0000 Subject: [PATCH 2/3] another test --- runtime/src/bank/tests.rs | 74 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 98645f8dece304..181b0ce794e796 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -8052,9 +8052,14 @@ fn test_reserved_account_keys() { 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); + + // Ensure increased block limits features are inactive. assert!(!bank .feature_set .is_active(&feature_set::raise_block_limits_to_50m::id())); + assert!(!bank + .feature_set + .is_active(&feature_set::raise_block_limits_to_60m::id())); assert_eq!( bank.read_cost_tracker().unwrap().get_block_limit(), MAX_BLOCK_UNITS, @@ -8143,6 +8148,67 @@ fn test_block_limits() { "bank created from genesis config should have new limit" ); + activate_feature( + &mut genesis_config, + feature_set::raise_block_limits_to_60m::id(), + ); + let bank = Bank::new_for_tests(&genesis_config); + assert!(bank + .feature_set + .is_active(&feature_set::raise_block_limits_to_60m::id())); + assert_eq!( + bank.read_cost_tracker().unwrap().get_block_limit(), + MAX_BLOCK_UNITS_SIMD_0256, + "bank created from genesis config should have new limit" + ); +} + +#[test] +fn test_block_limits_feature_priority() { + let (bank0, _bank_forks) = create_simple_test_arc_bank(100_000); + let mut bank = Bank::new_from_parent(bank0, &Pubkey::default(), 1); + + // Ensure increased block limits features are inactive. + assert!(!bank + .feature_set + .is_active(&feature_set::raise_block_limits_to_50m::id())); + assert!(!bank + .feature_set + .is_active(&feature_set::raise_block_limits_to_60m::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), + ); + + // Activate `raise_block_limits_to_60m` feature + bank.store_account( + &feature_set::raise_block_limits_to_60m::id(), + &feature::create_account(&Feature::default(), 42), + ); + + // apply_feature_activations for `NewFromParent` will cause `raise_block_limits_to_60m` to be activated + bank.apply_feature_activations(ApplyFeatureActivationsCaller::NewFromParent, true); + assert_eq!( + bank.read_cost_tracker().unwrap().get_block_limit(), + MAX_BLOCK_UNITS_SIMD_0256, + "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(), 3); + assert_eq!( + bank.read_cost_tracker().unwrap().get_block_limit(), + MAX_BLOCK_UNITS_SIMD_0256, + "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. @@ -8153,11 +8219,19 @@ fn test_block_limits() { "before activating the feature, bank should have old/default limit" ); + // Activate `raise_block_limits_to_50m` feature + activate_feature( + &mut genesis_config, + feature_set::raise_block_limits_to_50m::id(), + ); + // Activate `raise_block_limits_to_60m` feature activate_feature( &mut genesis_config, feature_set::raise_block_limits_to_60m::id(), ); let bank = Bank::new_for_tests(&genesis_config); + + // `raise_block_limits_to_60m` feature and block limits should be active. assert!(bank .feature_set .is_active(&feature_set::raise_block_limits_to_60m::id())); From e629c555e63c6573360dc0a5e0b1d3d20eac7bae Mon Sep 17 00:00:00 2001 From: Brennan Date: Fri, 7 Mar 2025 15:38:17 +0000 Subject: [PATCH 3/3] 256 precedence --- runtime/src/bank.rs | 6 +++- runtime/src/bank/tests.rs | 73 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 433429a1a94736..12859b23c8f6a8 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -6531,7 +6531,11 @@ impl Bank { } } - if new_feature_activations.contains(&feature_set::raise_block_limits_to_50m::id()) { + if new_feature_activations.contains(&feature_set::raise_block_limits_to_50m::id()) + && !self + .feature_set + .is_active(&feature_set::raise_block_limits_to_60m::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, diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 181b0ce794e796..ca78761343ccf5 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -8164,7 +8164,7 @@ fn test_block_limits() { } #[test] -fn test_block_limits_feature_priority() { +fn test_block_limits_feature_dual_activation() { let (bank0, _bank_forks) = create_simple_test_arc_bank(100_000); let mut bank = Bank::new_from_parent(bank0, &Pubkey::default(), 1); @@ -8198,15 +8198,15 @@ fn test_block_limits_feature_priority() { assert_eq!( bank.read_cost_tracker().unwrap().get_block_limit(), MAX_BLOCK_UNITS_SIMD_0256, - "after activating the feature, bank should have new limit" + "after activating the feature, bank should have newest limit" ); // Make sure the limits propagate to the child-bank. - let bank = Bank::new_from_parent(Arc::new(bank), &Pubkey::default(), 3); + 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_0256, - "child bank should have new limit" + "child bank should have newest limit" ); // Test starting from a genesis config with and without feature account @@ -8238,7 +8238,70 @@ fn test_block_limits_feature_priority() { assert_eq!( bank.read_cost_tracker().unwrap().get_block_limit(), MAX_BLOCK_UNITS_SIMD_0256, - "bank created from genesis config should have new limit" + "bank created from genesis config should have newest limit" + ); +} + +#[test] +fn test_block_limits_feature_reverse_order() { + let (bank0, _bank_forks) = create_simple_test_arc_bank(100_000); + let mut bank = Bank::new_from_parent(bank0, &Pubkey::default(), 1); + + // Ensure increased block limits features are inactive. + assert!(!bank + .feature_set + .is_active(&feature_set::raise_block_limits_to_50m::id())); + assert!(!bank + .feature_set + .is_active(&feature_set::raise_block_limits_to_60m::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_60m` feature + bank.store_account( + &feature_set::raise_block_limits_to_60m::id(), + &feature::create_account(&Feature::default(), 42), + ); + + // apply_feature_activations for `NewFromParent` will cause `raise_block_limits_to_60m` to be activated + bank.apply_feature_activations(ApplyFeatureActivationsCaller::NewFromParent, true); + assert_eq!( + bank.read_cost_tracker().unwrap().get_block_limit(), + MAX_BLOCK_UNITS_SIMD_0256, + "after activating the feature, bank should have new limit" + ); + + // Make sure the limits propagate to the child-bank. + let mut 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_0256, + "child bank should have new 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 `NewFromParent` + bank.apply_feature_activations(ApplyFeatureActivationsCaller::NewFromParent, true); + assert_eq!( + bank.read_cost_tracker().unwrap().get_block_limit(), + MAX_BLOCK_UNITS_SIMD_0256, + "bank should keep the same limit" + ); + + // Make sure the SIMD-0256 limits are still in place as they take precedence over the SIMD-0207 limits. + let bank = Bank::new_from_parent(Arc::new(bank), &Pubkey::default(), 3); + assert_eq!( + bank.read_cost_tracker().unwrap().get_block_limit(), + MAX_BLOCK_UNITS_SIMD_0256, + "child bank should keep the same limit" ); }