diff --git a/builtins-default-costs/benches/builtin_instruction_costs.rs b/builtins-default-costs/benches/builtin_instruction_costs.rs index 04443655c01300..4aeee4b51c8f78 100644 --- a/builtins-default-costs/benches/builtin_instruction_costs.rs +++ b/builtins-default-costs/benches/builtin_instruction_costs.rs @@ -2,22 +2,23 @@ extern crate test; use { rand::Rng, - solana_builtins_default_costs::BUILTIN_INSTRUCTION_COSTS, + solana_builtins_default_costs::get_builtin_instruction_cost, solana_sdk::{ address_lookup_table, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, - compute_budget, ed25519_program, loader_v4, pubkey::Pubkey, secp256k1_program, + compute_budget, ed25519_program, feature_set::FeatureSet, loader_v4, pubkey::Pubkey, + secp256k1_program, }, test::Bencher, }; struct BenchSetup { pubkeys: [Pubkey; 12], + feature_set: FeatureSet, } const NUM_TRANSACTIONS_PER_ITER: usize = 1024; -const DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT: u32 = 200_000; -fn setup() -> BenchSetup { +fn setup(all_features_enabled: bool) -> BenchSetup { let pubkeys: [Pubkey; 12] = [ solana_stake_program::id(), solana_config_program::id(), @@ -33,23 +34,39 @@ fn setup() -> BenchSetup { ed25519_program::id(), ]; - BenchSetup { pubkeys } + let feature_set = if all_features_enabled { + FeatureSet::all_enabled() + } else { + FeatureSet::default() + }; + + BenchSetup { + pubkeys, + feature_set, + } +} + +fn do_hash_find(setup: &BenchSetup) { + for _t in 0..NUM_TRANSACTIONS_PER_ITER { + let idx = rand::thread_rng().gen_range(0..setup.pubkeys.len()); + get_builtin_instruction_cost(&setup.pubkeys[idx], &setup.feature_set); + } +} + +#[bench] +fn bench_hash_find_builtins_not_migrated(bencher: &mut Bencher) { + let bench_setup = setup(false); + + bencher.iter(|| { + do_hash_find(&bench_setup); + }); } #[bench] -fn bench_hash_find(bencher: &mut Bencher) { - let BenchSetup { pubkeys } = setup(); +fn bench_hash_find_builtins_migrated(bencher: &mut Bencher) { + let bench_setup = setup(true); bencher.iter(|| { - for _t in 0..NUM_TRANSACTIONS_PER_ITER { - let idx = rand::thread_rng().gen_range(0..pubkeys.len()); - let ix_execution_cost = - if let Some(builtin_cost) = BUILTIN_INSTRUCTION_COSTS.get(&pubkeys[idx]) { - *builtin_cost - } else { - u64::from(DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT) - }; - assert!(ix_execution_cost != DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64); - } + do_hash_find(&bench_setup); }); } diff --git a/builtins-default-costs/src/lib.rs b/builtins-default-costs/src/lib.rs index 183ece674b1ee0..d8c320bdc5d781 100644 --- a/builtins-default-costs/src/lib.rs +++ b/builtins-default-costs/src/lib.rs @@ -298,11 +298,15 @@ mod test { // use native cost if migration is planned but not activated assert_eq!( Some(solana_stake_program::stake_instruction::DEFAULT_COMPUTE_UNITS), - get_builtin_instruction_cost(&stake::id(), &FeatureSet::default()) + get_builtin_instruction_cost(&solana_stake_program::id(), &FeatureSet::default()) ); // None if migration is planned and activated, in which case, it's no longer builtin - assert!(get_builtin_instruction_cost(&stake::id(), &FeatureSet::all_enabled()).is_none()); + assert!(get_builtin_instruction_cost( + &solana_stake_program::id(), + &FeatureSet::all_enabled() + ) + .is_none()); // None if not builtin assert!( @@ -324,7 +328,7 @@ mod test { get_builtin_migration_feature_index(&compute_budget::id()), BuiltinMigrationFeatureIndex::BuiltinNoMigrationFeature, )); - let feature_index = get_builtin_migration_feature_index(&stake::id()); + let feature_index = get_builtin_migration_feature_index(&solana_stake_program::id()); assert!(matches!( feature_index, BuiltinMigrationFeatureIndex::BuiltinWithMigrationFeature(_) @@ -338,7 +342,7 @@ mod test { get_migration_feature_id(feature_index), &feature_set::migrate_stake_program_to_core_bpf::id() ); - let feature_index = get_builtin_migration_feature_index(&config::id()); + let feature_index = get_builtin_migration_feature_index(&solana_config_program::id()); assert!(matches!( feature_index, BuiltinMigrationFeatureIndex::BuiltinWithMigrationFeature(_) @@ -352,7 +356,8 @@ mod test { get_migration_feature_id(feature_index), &feature_set::migrate_config_program_to_core_bpf::id() ); - let feature_index = get_builtin_migration_feature_index(&address_lookup_table::id()); + let feature_index = + get_builtin_migration_feature_index(&address_lookup_table::program::id()); assert!(matches!( feature_index, BuiltinMigrationFeatureIndex::BuiltinWithMigrationFeature(_) diff --git a/core/src/banking_stage/packet_filter.rs b/core/src/banking_stage/packet_filter.rs index 4c38d70762e35e..057f0f90c45df9 100644 --- a/core/src/banking_stage/packet_filter.rs +++ b/core/src/banking_stage/packet_filter.rs @@ -1,10 +1,19 @@ use { super::immutable_deserialized_packet::ImmutableDeserializedPacket, - solana_builtins_default_costs::BUILTIN_INSTRUCTION_COSTS, - solana_sdk::{ed25519_program, saturating_add_assign, secp256k1_program}, + lazy_static::lazy_static, + solana_builtins_default_costs::get_builtin_instruction_cost, + solana_sdk::{ + ed25519_program, feature_set::FeatureSet, saturating_add_assign, secp256k1_program, + }, thiserror::Error, }; +lazy_static! { + // To calculate the static_builtin_cost_sum conservatively, an all-enabled dummy feature_set + // is used. It lowers required minimal compute_unit_limit, aligns with future versions. + static ref FEATURE_SET: FeatureSet = FeatureSet::all_enabled(); +} + #[derive(Debug, Error, PartialEq)] pub enum PacketFilterFailure { #[error("Insufficient compute unit limit")] @@ -22,8 +31,8 @@ impl ImmutableDeserializedPacket { pub fn check_insufficent_compute_unit_limit(&self) -> Result<(), PacketFilterFailure> { let mut static_builtin_cost_sum: u64 = 0; for (program_id, _) in self.transaction().get_message().program_instructions_iter() { - if let Some(ix_cost) = BUILTIN_INSTRUCTION_COSTS.get(program_id) { - saturating_add_assign!(static_builtin_cost_sum, *ix_cost); + if let Some(ix_cost) = get_builtin_instruction_cost(program_id, &FEATURE_SET) { + saturating_add_assign!(static_builtin_cost_sum, ix_cost); } } diff --git a/cost-model/src/cost_model.rs b/cost-model/src/cost_model.rs index 6bafd9837ed6dc..0d15a9f7f5226f 100644 --- a/cost-model/src/cost_model.rs +++ b/cost-model/src/cost_model.rs @@ -7,7 +7,7 @@ use { crate::{block_cost_limits::*, transaction_cost::*}, - solana_builtins_default_costs::BUILTIN_INSTRUCTION_COSTS, + solana_builtins_default_costs::get_builtin_instruction_cost, solana_compute_budget::compute_budget_limits::{ DEFAULT_HEAP_COST, DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, MAX_COMPUTE_UNIT_LIMIT, }, @@ -193,8 +193,8 @@ impl CostModel { for (program_id, instruction) in transaction.program_instructions_iter() { let ix_execution_cost = - if let Some(builtin_cost) = BUILTIN_INSTRUCTION_COSTS.get(program_id) { - *builtin_cost + if let Some(builtin_cost) = get_builtin_instruction_cost(program_id, feature_set) { + builtin_cost } else { has_user_space_instructions = true; u64::from(DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT) diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 6e83d296518eb8..c832fb63479f95 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -4994,6 +4994,7 @@ dependencies = [ "solana-bpf-loader-program", "solana-compute-budget-program", "solana-config-program", + "solana-feature-set", "solana-loader-v4-program", "solana-sdk", "solana-stake-program", diff --git a/runtime-transaction/Cargo.toml b/runtime-transaction/Cargo.toml index 9ccb325593da89..21232747d4cde0 100644 --- a/runtime-transaction/Cargo.toml +++ b/runtime-transaction/Cargo.toml @@ -27,11 +27,15 @@ name = "solana_runtime_transaction" bincode = { workspace = true } criterion = { workspace = true } rand = { workspace = true } +solana-builtins-default-costs = { workspace = true, features = ["dev-context-only-utils"] } solana-program = { workspace = true } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] +[features] +dev-context-only-utils = [] + [[bench]] name = "process_compute_budget_instructions" harness = false