diff --git a/Cargo.lock b/Cargo.lock index 23c429edd446de..9b8dda61c6cb02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6286,6 +6286,8 @@ dependencies = [ name = "solana-builtins" version = "2.2.0" dependencies = [ + "ahash 0.8.11", + "lazy_static", "solana-address-lookup-table-program", "solana-bpf-loader-program", "solana-compute-budget-program", @@ -6302,29 +6304,6 @@ dependencies = [ "solana-zk-token-proof-program", ] -[[package]] -name = "solana-builtins-default-costs" -version = "2.2.0" -dependencies = [ - "ahash 0.8.11", - "lazy_static", - "log", - "rand 0.8.5", - "solana-address-lookup-table-program", - "solana-bpf-loader-program", - "solana-compute-budget-program", - "solana-config-program", - "solana-feature-set", - "solana-frozen-abi", - "solana-loader-v4-program", - "solana-pubkey", - "solana-sdk-ids", - "solana-stake-program", - "solana-system-program", - "solana-vote-program", - "static_assertions", -] - [[package]] name = "solana-cargo-build-sbf" version = "2.2.0" @@ -6664,7 +6643,7 @@ dependencies = [ "criterion", "log", "rand 0.8.5", - "solana-builtins-default-costs", + "solana-builtins", "solana-compute-budget", "solana-program", "solana-pubkey", @@ -6791,7 +6770,7 @@ dependencies = [ "solana-accounts-db", "solana-address-lookup-table-program", "solana-bloom", - "solana-builtins-default-costs", + "solana-builtins", "solana-client", "solana-compute-budget", "solana-compute-budget-instruction", @@ -6864,7 +6843,7 @@ dependencies = [ "lazy_static", "log", "rand 0.8.5", - "solana-builtins-default-costs", + "solana-builtins", "solana-compute-budget", "solana-compute-budget-instruction", "solana-compute-budget-program", diff --git a/Cargo.toml b/Cargo.toml index ac186c11930cf3..31209454ec5d74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,6 @@ members = [ "bloom", "bucket_map", "builtins", - "builtins-default-costs", "cargo-registry", "clap-utils", "clap-v3-utils", @@ -452,7 +451,6 @@ solana-borsh = { path = "sdk/borsh", version = "=2.2.0" } solana-bpf-loader-program = { path = "programs/bpf_loader", version = "=2.2.0" } solana-bucket-map = { path = "bucket_map", version = "=2.2.0" } solana-builtins = { path = "builtins", version = "=2.2.0" } -solana-builtins-default-costs = { path = "builtins-default-costs", version = "=2.2.0" } agave-cargo-registry = { path = "cargo-registry", version = "=2.2.0" } solana-clap-utils = { path = "clap-utils", version = "=2.2.0" } solana-clap-v3-utils = { path = "clap-v3-utils", version = "=2.2.0" } diff --git a/builtins-default-costs/Cargo.toml b/builtins-default-costs/Cargo.toml deleted file mode 100644 index 986ef59c9fcc7d..00000000000000 --- a/builtins-default-costs/Cargo.toml +++ /dev/null @@ -1,51 +0,0 @@ -[package] -name = "solana-builtins-default-costs" -description = "Solana builtins default costs" -documentation = "https://docs.rs/solana-builtins-default-costs" -version = { workspace = true } -authors = { workspace = true } -repository = { workspace = true } -homepage = { workspace = true } -license = { workspace = true } -edition = { workspace = true } - -[dependencies] -ahash = { workspace = true } -lazy_static = { workspace = true } -log = { workspace = true } -solana-address-lookup-table-program = { workspace = true } -solana-bpf-loader-program = { workspace = true } -solana-compute-budget-program = { workspace = true } -solana-config-program = { workspace = true } -solana-feature-set = { workspace = true } -solana-frozen-abi = { workspace = true, optional = true, features = [ - "frozen-abi", -] } -solana-loader-v4-program = { workspace = true } -solana-pubkey = { workspace = true } -solana-sdk-ids = { workspace = true } -solana-stake-program = { workspace = true } -solana-system-program = { workspace = true } -solana-vote-program = { workspace = true } -# Add additional builtin programs here - -[lib] -crate-type = ["lib"] -name = "solana_builtins_default_costs" - -[dev-dependencies] -rand = "0.8.5" -static_assertions = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -frozen-abi = [ - "dep:solana-frozen-abi", - "solana-vote-program/frozen-abi", -] -dev-context-only-utils = [] - -[lints] -workspace = true diff --git a/builtins-default-costs/benches/builtin_instruction_costs.rs b/builtins-default-costs/benches/builtin_instruction_costs.rs deleted file mode 100644 index 71618852be5ef5..00000000000000 --- a/builtins-default-costs/benches/builtin_instruction_costs.rs +++ /dev/null @@ -1,74 +0,0 @@ -#![feature(test)] -extern crate test; -use { - rand::Rng, - solana_builtins_default_costs::get_builtin_instruction_cost, - solana_feature_set::FeatureSet, - solana_pubkey::Pubkey, - solana_sdk_ids::{ - address_lookup_table, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, - compute_budget, config, ed25519_program, loader_v4, secp256k1_program, stake, - system_program, vote, - }, - test::Bencher, -}; - -struct BenchSetup { - pubkeys: [Pubkey; 12], - feature_set: FeatureSet, -} - -const NUM_TRANSACTIONS_PER_ITER: usize = 1024; - -fn setup(all_features_enabled: bool) -> BenchSetup { - let pubkeys: [Pubkey; 12] = [ - stake::id(), - config::id(), - vote::id(), - system_program::id(), - compute_budget::id(), - address_lookup_table::id(), - bpf_loader_upgradeable::id(), - bpf_loader_deprecated::id(), - bpf_loader::id(), - loader_v4::id(), - secp256k1_program::id(), - ed25519_program::id(), - ]; - - 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_builtins_migrated(bencher: &mut Bencher) { - let bench_setup = setup(true); - - bencher.iter(|| { - do_hash_find(&bench_setup); - }); -} diff --git a/builtins-default-costs/src/lib.rs b/builtins-default-costs/src/lib.rs deleted file mode 100644 index a1c4000a75499d..00000000000000 --- a/builtins-default-costs/src/lib.rs +++ /dev/null @@ -1,378 +0,0 @@ -#![cfg_attr(feature = "frozen-abi", feature(min_specialization))] -#![allow(clippy::arithmetic_side_effects)] -use { - ahash::AHashMap, - lazy_static::lazy_static, - solana_feature_set::{self as feature_set, FeatureSet}, - solana_pubkey::Pubkey, - solana_sdk_ids::{ - address_lookup_table, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, - compute_budget, config, ed25519_program, loader_v4, secp256k1_program, stake, - system_program, vote, - }, -}; - -#[derive(Clone)] -pub struct MigratingBuiltinCost { - native_cost: u64, - core_bpf_migration_feature: Pubkey, - // encoding positional information explicitly for migration feature item, - // its value must be correctly corresponding to this object's position - // in MIGRATING_BUILTINS_COSTS, otherwise a const validation - // `validate_position(MIGRATING_BUILTINS_COSTS)` will fail at compile time. - position: usize, -} - -#[derive(Clone)] -pub struct NotMigratingBuiltinCost { - native_cost: u64, -} - -/// DEVELOPER: when a builtin is migrated to sbpf, please add its corresponding -/// migration feature ID to BUILTIN_INSTRUCTION_COSTS, and move it from -/// NON_MIGRATING_BUILTINS_COSTS to MIGRATING_BUILTINS_COSTS, so the builtin's -/// default cost can be determined properly based on feature status. -/// When migration completed, eg the feature gate is enabled everywhere, please -/// remove that builtin entry from MIGRATING_BUILTINS_COSTS. -#[derive(Clone)] -pub enum BuiltinCost { - Migrating(MigratingBuiltinCost), - NotMigrating(NotMigratingBuiltinCost), -} - -impl BuiltinCost { - pub fn native_cost(&self) -> u64 { - match self { - BuiltinCost::Migrating(MigratingBuiltinCost { native_cost, .. }) => *native_cost, - BuiltinCost::NotMigrating(NotMigratingBuiltinCost { native_cost }) => *native_cost, - } - } - - pub fn core_bpf_migration_feature(&self) -> Option<&Pubkey> { - match self { - BuiltinCost::Migrating(MigratingBuiltinCost { - core_bpf_migration_feature, - .. - }) => Some(core_bpf_migration_feature), - BuiltinCost::NotMigrating(_) => None, - } - } - - pub fn position(&self) -> Option { - match self { - BuiltinCost::Migrating(MigratingBuiltinCost { position, .. }) => Some(*position), - BuiltinCost::NotMigrating(_) => None, - } - } - - fn has_migrated(&self, feature_set: &FeatureSet) -> bool { - match self { - BuiltinCost::Migrating(MigratingBuiltinCost { - core_bpf_migration_feature, - .. - }) => feature_set.is_active(core_bpf_migration_feature), - BuiltinCost::NotMigrating(_) => false, - } - } -} - -lazy_static! { - /// Number of compute units for each built-in programs - /// - /// DEVELOPER WARNING: This map CANNOT be modified without causing a - /// consensus failure because this map is used to calculate the compute - /// limit for transactions that don't specify a compute limit themselves as - /// of https://github.com/anza-xyz/agave/issues/2212. It's also used to - /// calculate the cost of a transaction which is used in replay to enforce - /// block cost limits as of - /// https://github.com/solana-labs/solana/issues/29595. - static ref BUILTIN_INSTRUCTION_COSTS: AHashMap = - MIGRATING_BUILTINS_COSTS - .iter() - .chain(NON_MIGRATING_BUILTINS_COSTS.iter()) - .cloned() - .collect(); - // DO NOT ADD MORE ENTRIES TO THIS MAP -} - -/// DEVELOPER WARNING: please do not add new entry into MIGRATING_BUILTINS_COSTS or -/// NON_MIGRATING_BUILTINS_COSTS, do so will modify BUILTIN_INSTRUCTION_COSTS therefore -/// cause consensus failure. However, when a builtin started being migrated to core bpf, -/// it MUST be moved from NON_MIGRATING_BUILTINS_COSTS to MIGRATING_BUILTINS_COSTS, then -/// correctly furnishing `core_bpf_migration_feature`. -/// -#[allow(dead_code)] -const TOTAL_COUNT_BUILTS: usize = 12; -#[cfg(test)] -static_assertions::const_assert_eq!( - MIGRATING_BUILTINS_COSTS.len() + NON_MIGRATING_BUILTINS_COSTS.len(), - TOTAL_COUNT_BUILTS -); - -pub const MIGRATING_BUILTINS_COSTS: &[(Pubkey, BuiltinCost)] = &[ - ( - stake::id(), - BuiltinCost::Migrating(MigratingBuiltinCost { - native_cost: solana_stake_program::stake_instruction::DEFAULT_COMPUTE_UNITS, - core_bpf_migration_feature: feature_set::migrate_stake_program_to_core_bpf::id(), - position: 0, - }), - ), - ( - config::id(), - BuiltinCost::Migrating(MigratingBuiltinCost { - native_cost: solana_config_program::config_processor::DEFAULT_COMPUTE_UNITS, - core_bpf_migration_feature: feature_set::migrate_config_program_to_core_bpf::id(), - position: 1, - }), - ), - ( - address_lookup_table::id(), - BuiltinCost::Migrating(MigratingBuiltinCost { - native_cost: solana_address_lookup_table_program::processor::DEFAULT_COMPUTE_UNITS, - core_bpf_migration_feature: - feature_set::migrate_address_lookup_table_program_to_core_bpf::id(), - position: 2, - }), - ), -]; - -pub const NON_MIGRATING_BUILTINS_COSTS: &[(Pubkey, BuiltinCost)] = &[ - ( - vote::id(), - BuiltinCost::NotMigrating(NotMigratingBuiltinCost { - native_cost: solana_vote_program::vote_processor::DEFAULT_COMPUTE_UNITS, - }), - ), - ( - system_program::id(), - BuiltinCost::NotMigrating(NotMigratingBuiltinCost { - native_cost: solana_system_program::system_processor::DEFAULT_COMPUTE_UNITS, - }), - ), - ( - compute_budget::id(), - BuiltinCost::NotMigrating(NotMigratingBuiltinCost { - native_cost: solana_compute_budget_program::DEFAULT_COMPUTE_UNITS, - }), - ), - ( - bpf_loader_upgradeable::id(), - BuiltinCost::NotMigrating(NotMigratingBuiltinCost { - native_cost: solana_bpf_loader_program::UPGRADEABLE_LOADER_COMPUTE_UNITS, - }), - ), - ( - bpf_loader_deprecated::id(), - BuiltinCost::NotMigrating(NotMigratingBuiltinCost { - native_cost: solana_bpf_loader_program::DEPRECATED_LOADER_COMPUTE_UNITS, - }), - ), - ( - bpf_loader::id(), - BuiltinCost::NotMigrating(NotMigratingBuiltinCost { - native_cost: solana_bpf_loader_program::DEFAULT_LOADER_COMPUTE_UNITS, - }), - ), - ( - loader_v4::id(), - BuiltinCost::NotMigrating(NotMigratingBuiltinCost { - native_cost: solana_loader_v4_program::DEFAULT_COMPUTE_UNITS, - }), - ), - // Note: These are precompile, run directly in bank during sanitizing; - ( - secp256k1_program::id(), - BuiltinCost::NotMigrating(NotMigratingBuiltinCost { native_cost: 0 }), - ), - ( - ed25519_program::id(), - BuiltinCost::NotMigrating(NotMigratingBuiltinCost { native_cost: 0 }), - ), -]; - -lazy_static! { - /// A table of 256 booleans indicates whether the first `u8` of a Pubkey exists in - /// BUILTIN_INSTRUCTION_COSTS. If the value is true, the Pubkey might be a builtin key; - /// if false, it cannot be a builtin key. This table allows for quick filtering of - /// builtin program IDs without the need for hashing. - pub static ref MAYBE_BUILTIN_KEY: [bool; 256] = { - let mut temp_table: [bool; 256] = [false; 256]; - BUILTIN_INSTRUCTION_COSTS - .keys() - .for_each(|key| temp_table[key.as_ref()[0] as usize] = true); - temp_table - }; -} - -pub fn get_builtin_instruction_cost<'a>( - program_id: &'a Pubkey, - feature_set: &'a FeatureSet, -) -> Option { - BUILTIN_INSTRUCTION_COSTS - .get(program_id) - .filter(|builtin_cost| !builtin_cost.has_migrated(feature_set)) - .map(|builtin_cost| builtin_cost.native_cost()) -} - -pub enum BuiltinMigrationFeatureIndex { - NotBuiltin, - BuiltinNoMigrationFeature, - BuiltinWithMigrationFeature(usize), -} - -pub fn get_builtin_migration_feature_index(program_id: &Pubkey) -> BuiltinMigrationFeatureIndex { - BUILTIN_INSTRUCTION_COSTS.get(program_id).map_or( - BuiltinMigrationFeatureIndex::NotBuiltin, - |builtin_cost| { - builtin_cost.position().map_or( - BuiltinMigrationFeatureIndex::BuiltinNoMigrationFeature, - BuiltinMigrationFeatureIndex::BuiltinWithMigrationFeature, - ) - }, - ) -} - -/// const function validates `position` correctness at compile time. -#[allow(dead_code)] -const fn validate_position(migrating_builtins: &[(Pubkey, BuiltinCost)]) { - let mut index = 0; - while index < migrating_builtins.len() { - match migrating_builtins[index].1 { - BuiltinCost::Migrating(MigratingBuiltinCost { position, .. }) => assert!( - position == index, - "migration feture must exist and at correct position" - ), - BuiltinCost::NotMigrating(_) => { - panic!("migration feture must exist and at correct position") - } - } - index += 1; - } -} -const _: () = validate_position(MIGRATING_BUILTINS_COSTS); - -/// Helper function to return ref of migration feature Pubkey at position `index` -/// from MIGRATING_BUILTINS_COSTS -pub fn get_migration_feature_id(index: usize) -> &'static Pubkey { - MIGRATING_BUILTINS_COSTS - .get(index) - .expect("valid index of MIGRATING_BUILTINS_COSTS") - .1 - .core_bpf_migration_feature() - .expect("migrating builtin") -} - -#[cfg(feature = "dev-context-only-utils")] -pub fn get_migration_feature_position(feature_id: &Pubkey) -> usize { - MIGRATING_BUILTINS_COSTS - .iter() - .position(|(_, c)| c.core_bpf_migration_feature().expect("migrating builtin") == feature_id) - .unwrap() -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_const_builtin_cost_arrays() { - // sanity check to make sure built-ins are declared in the correct array - assert!(MIGRATING_BUILTINS_COSTS - .iter() - .enumerate() - .all(|(index, (_, c))| { - c.core_bpf_migration_feature().is_some() && c.position() == Some(index) - })); - assert!(NON_MIGRATING_BUILTINS_COSTS - .iter() - .all(|(_, c)| c.core_bpf_migration_feature().is_none())); - } - - #[test] - fn test_get_builtin_instruction_cost() { - // use native cost if no migration planned - assert_eq!( - Some(solana_compute_budget_program::DEFAULT_COMPUTE_UNITS), - get_builtin_instruction_cost(&compute_budget::id(), &FeatureSet::all_enabled()) - ); - - // 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()) - ); - - // 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()); - - // None if not builtin - assert!( - get_builtin_instruction_cost(&Pubkey::new_unique(), &FeatureSet::default()).is_none() - ); - assert!( - get_builtin_instruction_cost(&Pubkey::new_unique(), &FeatureSet::all_enabled()) - .is_none() - ); - } - - #[test] - fn test_get_builtin_migration_feature_index() { - assert!(matches!( - get_builtin_migration_feature_index(&Pubkey::new_unique()), - BuiltinMigrationFeatureIndex::NotBuiltin - )); - assert!(matches!( - get_builtin_migration_feature_index(&compute_budget::id()), - BuiltinMigrationFeatureIndex::BuiltinNoMigrationFeature, - )); - let feature_index = get_builtin_migration_feature_index(&stake::id()); - assert!(matches!( - feature_index, - BuiltinMigrationFeatureIndex::BuiltinWithMigrationFeature(_) - )); - let BuiltinMigrationFeatureIndex::BuiltinWithMigrationFeature(feature_index) = - feature_index - else { - panic!("expect migrating builtin") - }; - assert_eq!( - 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()); - assert!(matches!( - feature_index, - BuiltinMigrationFeatureIndex::BuiltinWithMigrationFeature(_) - )); - let BuiltinMigrationFeatureIndex::BuiltinWithMigrationFeature(feature_index) = - feature_index - else { - panic!("expect migrating builtin") - }; - assert_eq!( - 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()); - assert!(matches!( - feature_index, - BuiltinMigrationFeatureIndex::BuiltinWithMigrationFeature(_) - )); - let BuiltinMigrationFeatureIndex::BuiltinWithMigrationFeature(feature_index) = - feature_index - else { - panic!("expect migrating builtin") - }; - assert_eq!( - get_migration_feature_id(feature_index), - &feature_set::migrate_address_lookup_table_program_to_core_bpf::id() - ); - } - - #[test] - #[should_panic(expected = "valid index of MIGRATING_BUILTINS_COSTS")] - fn test_get_migration_feature_id_invalid_index() { - let _ = get_migration_feature_id(MIGRATING_BUILTINS_COSTS.len() + 1); - } -} diff --git a/builtins/Cargo.toml b/builtins/Cargo.toml index 3cdf7f63e64136..7c416c4a36fc43 100644 --- a/builtins/Cargo.toml +++ b/builtins/Cargo.toml @@ -10,9 +10,11 @@ license = { workspace = true } edition = { workspace = true } [features] -dev-context-only-utils = [] +mock-builtin-migrations = [] [dependencies] +ahash = { workspace = true } +lazy_static = { workspace = true } solana-address-lookup-table-program = { workspace = true } solana-bpf-loader-program = { workspace = true } solana-compute-budget-program = { workspace = true } diff --git a/builtins/src/cost_modeling.rs b/builtins/src/cost_modeling.rs new file mode 100644 index 00000000000000..942773e2b3fd3a --- /dev/null +++ b/builtins/src/cost_modeling.rs @@ -0,0 +1,307 @@ +//! Configurations for handling cost modeling of builtin programs. + +use { + crate::BUILTINS, + ahash::AHashMap, + lazy_static::lazy_static, + solana_feature_set::FeatureSet, + solana_pubkey::Pubkey, + solana_sdk_ids::{ed25519_program, secp256k1_program}, +}; + +#[cfg(not(feature = "mock-builtin-migrations"))] +/// CONTRIBUTOR: If you change any builtin Core BPF migration configurations +/// in this crate's `BUILTINS` list, you must update this constant to reflect +/// the number of builtin programs that have Core BPF migration configurations. +pub const NUM_COST_MODELED_BUILTINS_WITH_MIGRATIONS: usize = 3; +#[cfg(feature = "mock-builtin-migrations")] +/// CONTRIBUTOR: Under the `mock-builtin-migrations` feature, this value is +/// `BUILTINS.len()`. If a new builtin is added, this should be updated. +pub const NUM_COST_MODELED_BUILTINS_WITH_MIGRATIONS: usize = 11; + +/// Configuration for cost modeling of a builtin program. +#[derive(Debug)] +pub enum CostModelingConfig { + /// The builtin program is cost modeled. + CostModeled { + /// The default cost of the builtin program. + default_cost: u64, + }, + /// The builtin program is not cost modeled. + NotCostModeled, +} + +impl CostModelingConfig { + /// Returns `true` if the builtin program is cost modeled. + pub fn is_cost_modeled(&self) -> bool { + matches!(self, Self::CostModeled { .. }) + } +} + +struct BuiltinCost { + default_cost: u64, + core_bpf_migration_feature: Option, +} + +#[derive(Copy, Clone, Default)] +struct BuiltinWithMigration { + program_id: Pubkey, + migration_feature_id: Pubkey, +} + +lazy_static! { + static ref BUILTIN_INSTRUCTION_COSTS: AHashMap = BUILTINS + .iter() + .filter_map(|builtin| { + match builtin.cost_modeling_config { + CostModelingConfig::CostModeled { default_cost } => Some(( + builtin.program_id, + BuiltinCost { + default_cost, + core_bpf_migration_feature: builtin + .core_bpf_migration_config + .as_ref() + .map(|config| config.feature_id), + }, + )), + CostModelingConfig::NotCostModeled => { + None + } + } + }) + .chain( + [ + ( + secp256k1_program::id(), + BuiltinCost { + default_cost: 0, // Hard-coded to zero. + core_bpf_migration_feature: None, + }, + ), + ( + ed25519_program::id(), + BuiltinCost { + default_cost: 0, // Hard-coded to zero. + core_bpf_migration_feature: None, + }, + ), + ] + .into_iter() + ) + .collect(); +} + +lazy_static! { + /// A table of 256 booleans indicates whether the first `u8` of a Pubkey exists in + /// BUILTIN_INSTRUCTION_COSTS. If the value is true, the Pubkey might be a builtin key; + /// if false, it cannot be a builtin key. This table allows for quick filtering of + /// builtin program IDs without the need for hashing. + pub static ref MAYBE_BUILTIN_KEY: [bool; 256] = { + let mut temp_table: [bool; 256] = [false; 256]; + BUILTIN_INSTRUCTION_COSTS + .keys() + .for_each(|key| temp_table[key.as_ref()[0] as usize] = true); + temp_table + }; +} + +lazy_static! { + // This lazy-static list is designed to panic if any builtin migrations + // are changed without updating `NUM_COST_MODELED_BUILTINS_WITH_MIGRATIONS`. + static ref COST_MODELED_BUILTINS_WITH_MIGRATIONS: [BuiltinWithMigration; NUM_COST_MODELED_BUILTINS_WITH_MIGRATIONS] = { + let mut temp = [BuiltinWithMigration::default(); NUM_COST_MODELED_BUILTINS_WITH_MIGRATIONS]; + let mut i: usize = 0; + for builtin in BUILTINS.iter() { + if builtin.cost_modeling_config.is_cost_modeled() { + if let Some(migration_config) = &builtin.core_bpf_migration_config { + temp[i] = BuiltinWithMigration { + program_id: builtin.program_id, + migration_feature_id: migration_config.feature_id, + }; + i = i.saturating_add(1); + } + } + } + temp + }; +} + +pub fn get_builtin_instruction_cost<'a>( + program_id: &'a Pubkey, + feature_set: &'a FeatureSet, +) -> Option { + BUILTIN_INSTRUCTION_COSTS + .get(program_id) + .and_then(|builtin_cost| { + // If the program has a Core BPF Migration feature and that feature + // is active, then the program is not considered a builtin. + if builtin_cost + .core_bpf_migration_feature + .is_some_and(|feature_id| feature_set.is_active(&feature_id)) + { + return None; + } + // Otherwise, return the default cost. + Some(builtin_cost.default_cost) + }) +} + +#[inline] +pub fn is_builtin_program(program_id: &Pubkey) -> bool { + BUILTIN_INSTRUCTION_COSTS.contains_key(program_id) +} + +/// Returns the index of a builtin in `COST_MODELED_BUILTINS_WITH_MIGRATIONS`, +/// if it exists in the list. +pub fn get_builtin_migration_feature_index(program_id: &Pubkey) -> Option { + COST_MODELED_BUILTINS_WITH_MIGRATIONS + .iter() + .position(|builtin| builtin.program_id == *program_id) +} + +/// Returns the feature ID of a builtin in `COST_MODELED_BUILTINS_WITH_MIGRATIONS` +/// by index. Panics if the index is out of bounds. +pub fn get_builtin_migration_feature_id(index: usize) -> &'static Pubkey { + &COST_MODELED_BUILTINS_WITH_MIGRATIONS[index].migration_feature_id +} + +/// Returns the index of a builtin in `COST_MODELED_BUILTINS_WITH_MIGRATIONS` +/// by feature ID. If the feature ID is not found, returns `None`. +pub fn get_builtin_migration_feature_index_from_feature_id(feature_id: &Pubkey) -> Option { + COST_MODELED_BUILTINS_WITH_MIGRATIONS + .iter() + .position(|builtin| builtin.migration_feature_id == *feature_id) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_cost_modeled_builtins_with_migrations_compiles() { + // This test is a compile-time check to ensure that the number of + // cost-modeled builtins with migration features matches the constant. + assert_eq!( + COST_MODELED_BUILTINS_WITH_MIGRATIONS.len(), + NUM_COST_MODELED_BUILTINS_WITH_MIGRATIONS + ); + } + + #[test] + fn test_maybe_builtin_key() { + let check = |key: &Pubkey, expected: bool| { + assert_eq!(MAYBE_BUILTIN_KEY[key.as_ref()[0] as usize], expected); + assert_eq!(is_builtin_program(key), expected); + }; + + check(&solana_sdk_ids::system_program::id(), true); + check(&solana_sdk_ids::vote::id(), true); + check(&solana_sdk_ids::stake::id(), true); + check(&solana_sdk_ids::config::id(), true); + check(&solana_sdk_ids::bpf_loader_deprecated::id(), true); + check(&solana_sdk_ids::bpf_loader::id(), true); + check(&solana_sdk_ids::bpf_loader_upgradeable::id(), true); + check(&solana_sdk_ids::compute_budget::id(), true); + check(&solana_sdk_ids::address_lookup_table::id(), true); + check(&solana_sdk_ids::loader_v4::id(), true); + check(&solana_sdk_ids::ed25519_program::id(), true); + check(&solana_sdk_ids::secp256k1_program::id(), true); + + // Not cost modeled. + check(&solana_sdk_ids::zk_elgamal_proof_program::id(), false); + check(&solana_sdk_ids::zk_token_proof_program::id(), false); + + // Not builtins. + check(&Pubkey::new_from_array([1; 32]), false); + check(&Pubkey::new_from_array([9; 32]), false); + } + + #[test] + fn test_get_builtin_instruction_cost() { + let feature_set = FeatureSet::all_enabled(); + + // Default cost defined, no migration. + assert_eq!( + get_builtin_instruction_cost(&solana_sdk_ids::system_program::id(), &feature_set), + Some(solana_system_program::system_processor::DEFAULT_COMPUTE_UNITS), + ); + assert_eq!( + get_builtin_instruction_cost(&solana_sdk_ids::vote::id(), &feature_set), + Some(solana_vote_program::vote_processor::DEFAULT_COMPUTE_UNITS), + ); + assert_eq!( + get_builtin_instruction_cost( + &solana_sdk_ids::bpf_loader_deprecated::id(), + &feature_set + ), + Some(solana_bpf_loader_program::DEPRECATED_LOADER_COMPUTE_UNITS), + ); + assert_eq!( + get_builtin_instruction_cost(&solana_sdk_ids::bpf_loader::id(), &feature_set), + Some(solana_bpf_loader_program::DEFAULT_LOADER_COMPUTE_UNITS), + ); + assert_eq!( + get_builtin_instruction_cost( + &solana_sdk_ids::bpf_loader_upgradeable::id(), + &feature_set + ), + Some(solana_bpf_loader_program::UPGRADEABLE_LOADER_COMPUTE_UNITS), + ); + assert_eq!( + get_builtin_instruction_cost(&solana_sdk_ids::compute_budget::id(), &feature_set), + Some(solana_compute_budget_program::DEFAULT_COMPUTE_UNITS), + ); + assert_eq!( + get_builtin_instruction_cost(&solana_sdk_ids::loader_v4::id(), &feature_set), + Some(solana_loader_v4_program::DEFAULT_COMPUTE_UNITS), + ); + assert_eq!( + get_builtin_instruction_cost(&solana_sdk_ids::ed25519_program::id(), &feature_set), + Some(0), + ); + assert_eq!( + get_builtin_instruction_cost(&solana_sdk_ids::secp256k1_program::id(), &feature_set), + Some(0), + ); + + // Default cost defined, migration active. + assert_eq!( + get_builtin_instruction_cost(&solana_sdk_ids::stake::id(), &feature_set), + None, + ); + assert_eq!( + get_builtin_instruction_cost(&solana_sdk_ids::config::id(), &feature_set), + None, + ); + assert_eq!( + get_builtin_instruction_cost(&solana_sdk_ids::address_lookup_table::id(), &feature_set), + None, + ); + + // Not cost modeled. + assert_eq!( + get_builtin_instruction_cost( + &solana_sdk_ids::zk_elgamal_proof_program::id(), + &feature_set + ), + None, + ); + assert_eq!( + get_builtin_instruction_cost( + &solana_sdk_ids::zk_token_proof_program::id(), + &feature_set + ), + None, + ); + + // Not a builtin from the list. + assert_eq!( + get_builtin_instruction_cost(&Pubkey::new_unique(), &feature_set), + None, + ); + assert_eq!( + get_builtin_instruction_cost(&Pubkey::new_unique(), &feature_set), + None, + ); + } +} diff --git a/builtins/src/lib.rs b/builtins/src/lib.rs index 5ba11fbf1cd937..02a437db70cf01 100644 --- a/builtins/src/lib.rs +++ b/builtins/src/lib.rs @@ -10,11 +10,13 @@ //! Core BPF, as well as whether or not that feature gate has been activated. pub mod core_bpf_migration; +pub mod cost_modeling; pub mod prototype; use { crate::{ core_bpf_migration::{CoreBpfMigrationConfig, CoreBpfMigrationTargetType}, + cost_modeling::CostModelingConfig, prototype::{BuiltinPrototype, StatelessBuiltinPrototype}, }, solana_feature_set as feature_set, @@ -23,48 +25,55 @@ use { macro_rules! testable_prototype { ($prototype:ident { - core_bpf_migration_config: $core_bpf_migration_config:expr, name: $name:ident, + core_bpf_migration_config: $core_bpf_migration_config:expr, $($field:ident : $value:expr),* $(,)? }) => { $prototype { + name: stringify!($name), core_bpf_migration_config: { - #[cfg(not(feature = "dev-context-only-utils"))] + #[cfg(not(feature = "mock-builtin-migrations"))] { $core_bpf_migration_config } - #[cfg(feature = "dev-context-only-utils")] + #[cfg(feature = "mock-builtin-migrations")] { Some( test_only::$name::CONFIG ) } }, - name: stringify!($name), $($field: $value),* } }; } -/// DEVELOPER: when a builtin is migrated to sbpf, please add its corresponding -/// migration feature ID to solana-builtin-default-costs::BUILTIN_INSTRUCTION_COSTS, -/// so the builtin's default cost can be determined properly based on feature status. -/// When migration completed, and the feature gate is enabled everywhere, please -/// remove that builtin entry from solana-builtin-default-costs::BUILTIN_INSTRUCTION_COSTS. +/// CONTRIBUTOR: When a builtin is scheduled to be migrated to Core BPF, add +/// the `CoreBpfMigrationConfig` to the builtin prototype here, and adjust the +/// length value in `cost_modeling::NUM_COST_MODELED_BUILTINS_WITH_MIGRATIONS`. +/// When the migration is completed and the feature is cleaned up, remove the +/// builtin from this list and update the length value again. pub static BUILTINS: &[BuiltinPrototype] = &[ testable_prototype!(BuiltinPrototype { - core_bpf_migration_config: None, name: system_program, + core_bpf_migration_config: None, + cost_modeling_config: CostModelingConfig::CostModeled { + default_cost: solana_system_program::system_processor::DEFAULT_COMPUTE_UNITS, + }, enable_feature_id: None, program_id: solana_system_program::id(), entrypoint: solana_system_program::system_processor::Entrypoint::vm, }), testable_prototype!(BuiltinPrototype { - core_bpf_migration_config: None, name: vote_program, + core_bpf_migration_config: None, + cost_modeling_config: CostModelingConfig::CostModeled { + default_cost: solana_vote_program::vote_processor::DEFAULT_COMPUTE_UNITS, + }, enable_feature_id: None, program_id: solana_vote_program::id(), entrypoint: solana_vote_program::vote_processor::Entrypoint::vm, }), BuiltinPrototype { + name: "stake_program", core_bpf_migration_config: Some(CoreBpfMigrationConfig { source_buffer_address: buffer_accounts::stake_program::id(), upgrade_authority_address: None, @@ -72,12 +81,15 @@ pub static BUILTINS: &[BuiltinPrototype] = &[ migration_target: CoreBpfMigrationTargetType::Builtin, datapoint_name: "migrate_builtin_to_core_bpf_stake_program", }), - name: "stake_program", + cost_modeling_config: CostModelingConfig::CostModeled { + default_cost: solana_stake_program::stake_instruction::DEFAULT_COMPUTE_UNITS, + }, enable_feature_id: None, program_id: solana_stake_program::id(), entrypoint: solana_stake_program::stake_instruction::Entrypoint::vm, }, BuiltinPrototype { + name: "config_program", core_bpf_migration_config: Some(CoreBpfMigrationConfig { source_buffer_address: buffer_accounts::config_program::id(), upgrade_authority_address: None, @@ -85,40 +97,55 @@ pub static BUILTINS: &[BuiltinPrototype] = &[ migration_target: CoreBpfMigrationTargetType::Builtin, datapoint_name: "migrate_builtin_to_core_bpf_config_program", }), - name: "config_program", + cost_modeling_config: CostModelingConfig::CostModeled { + default_cost: solana_config_program::config_processor::DEFAULT_COMPUTE_UNITS, + }, enable_feature_id: None, program_id: solana_config_program::id(), entrypoint: solana_config_program::config_processor::Entrypoint::vm, }, testable_prototype!(BuiltinPrototype { - core_bpf_migration_config: None, name: solana_bpf_loader_deprecated_program, + core_bpf_migration_config: None, + cost_modeling_config: CostModelingConfig::CostModeled { + default_cost: solana_bpf_loader_program::DEPRECATED_LOADER_COMPUTE_UNITS, + }, enable_feature_id: None, program_id: bpf_loader_deprecated::id(), entrypoint: solana_bpf_loader_program::Entrypoint::vm, }), testable_prototype!(BuiltinPrototype { - core_bpf_migration_config: None, name: solana_bpf_loader_program, + core_bpf_migration_config: None, + cost_modeling_config: CostModelingConfig::CostModeled { + default_cost: solana_bpf_loader_program::DEFAULT_LOADER_COMPUTE_UNITS, + }, enable_feature_id: None, program_id: bpf_loader::id(), entrypoint: solana_bpf_loader_program::Entrypoint::vm, }), testable_prototype!(BuiltinPrototype { - core_bpf_migration_config: None, name: solana_bpf_loader_upgradeable_program, + core_bpf_migration_config: None, + cost_modeling_config: CostModelingConfig::CostModeled { + default_cost: solana_bpf_loader_program::UPGRADEABLE_LOADER_COMPUTE_UNITS, + }, enable_feature_id: None, program_id: bpf_loader_upgradeable::id(), entrypoint: solana_bpf_loader_program::Entrypoint::vm, }), testable_prototype!(BuiltinPrototype { - core_bpf_migration_config: None, name: compute_budget_program, + core_bpf_migration_config: None, + cost_modeling_config: CostModelingConfig::CostModeled { + default_cost: solana_compute_budget_program::DEFAULT_COMPUTE_UNITS, + }, enable_feature_id: None, program_id: solana_sdk_ids::compute_budget::id(), entrypoint: solana_compute_budget_program::Entrypoint::vm, }), BuiltinPrototype { + name: "address_lookup_table_program", core_bpf_migration_config: Some(CoreBpfMigrationConfig { source_buffer_address: buffer_accounts::address_lookup_table_program::id(), upgrade_authority_address: None, @@ -126,28 +153,35 @@ pub static BUILTINS: &[BuiltinPrototype] = &[ migration_target: CoreBpfMigrationTargetType::Builtin, datapoint_name: "migrate_builtin_to_core_bpf_address_lookup_table_program", }), - name: "address_lookup_table_program", + cost_modeling_config: CostModelingConfig::CostModeled { + default_cost: solana_address_lookup_table_program::processor::DEFAULT_COMPUTE_UNITS, + }, enable_feature_id: None, program_id: solana_sdk_ids::address_lookup_table::id(), entrypoint: solana_address_lookup_table_program::processor::Entrypoint::vm, }, testable_prototype!(BuiltinPrototype { - core_bpf_migration_config: None, name: zk_token_proof_program, + core_bpf_migration_config: None, + cost_modeling_config: CostModelingConfig::NotCostModeled, // WARNING: DO NOT CHANGE WITHOUT FEATURE GATE!! enable_feature_id: Some(feature_set::zk_token_sdk_enabled::id()), program_id: solana_sdk_ids::zk_token_proof_program::id(), entrypoint: solana_zk_token_proof_program::Entrypoint::vm, }), testable_prototype!(BuiltinPrototype { - core_bpf_migration_config: None, name: loader_v4, + core_bpf_migration_config: None, + cost_modeling_config: CostModelingConfig::CostModeled { + default_cost: solana_loader_v4_program::DEFAULT_COMPUTE_UNITS, + }, enable_feature_id: Some(feature_set::enable_program_runtime_v2_and_loader_v4::id()), program_id: solana_sdk_ids::loader_v4::id(), entrypoint: solana_loader_v4_program::Entrypoint::vm, }), testable_prototype!(BuiltinPrototype { - core_bpf_migration_config: None, name: zk_elgamal_proof_program, + core_bpf_migration_config: None, + cost_modeling_config: CostModelingConfig::NotCostModeled, // WARNING: DO NOT CHANGE WITHOUT FEATURE GATE!! enable_feature_id: Some(feature_set::zk_elgamal_proof_program_enabled::id()), program_id: solana_sdk_ids::zk_elgamal_proof_program::id(), entrypoint: solana_zk_elgamal_proof_program::Entrypoint::vm, @@ -189,7 +223,7 @@ mod buffer_accounts { // into the builtins list for both the feature ID and the source program ID. // These arbitrary IDs can then be used to configure feature-activation runtime // tests. -#[cfg(any(test, feature = "dev-context-only-utils"))] +#[cfg(any(test, feature = "mock-builtin-migrations"))] pub mod test_only { use crate::core_bpf_migration::{CoreBpfMigrationConfig, CoreBpfMigrationTargetType}; pub mod system_program { @@ -369,6 +403,7 @@ mod tests { // Since a macro is used to initialize the test IDs from the `test_only` // module, best to ensure the lists have the expected values within a test // context. + #[cfg(feature = "mock-builtin-migrations")] #[test] fn test_testable_prototypes() { assert_eq!( diff --git a/builtins/src/prototype.rs b/builtins/src/prototype.rs index 2b76dd5c353fec..b9147dd07a5ff5 100644 --- a/builtins/src/prototype.rs +++ b/builtins/src/prototype.rs @@ -1,14 +1,17 @@ //! Prototype layouts for builtins. use { - crate::core_bpf_migration::CoreBpfMigrationConfig, - solana_program_runtime::invoke_context::BuiltinFunctionWithContext, solana_pubkey::Pubkey, + crate::{core_bpf_migration::CoreBpfMigrationConfig, cost_modeling::CostModelingConfig}, + solana_program_runtime::invoke_context::BuiltinFunctionWithContext, + solana_pubkey::Pubkey, }; /// Transitions of built-in programs at epoch boundaries when features are activated. pub struct BuiltinPrototype { /// Configurations for migrating the builtin to Core BPF. pub core_bpf_migration_config: Option, + /// Configurations for cost modeling. + pub cost_modeling_config: CostModelingConfig, /// Feature ID that enables the builtin program. /// If None, the built-in program is always enabled. pub enable_feature_id: Option, @@ -27,6 +30,7 @@ impl std::fmt::Debug for BuiltinPrototype { builder.field("name", &self.name); builder.field("enable_feature_id", &self.enable_feature_id); builder.field("core_bpf_migration_config", &self.core_bpf_migration_config); + builder.field("cost_modeling_config", &self.cost_modeling_config); builder.finish() } } diff --git a/compute-budget-instruction/Cargo.toml b/compute-budget-instruction/Cargo.toml index 8e5bdd0b1c9bf7..9e505487c1c16d 100644 --- a/compute-budget-instruction/Cargo.toml +++ b/compute-budget-instruction/Cargo.toml @@ -11,7 +11,7 @@ edition = { workspace = true } [dependencies] log = { workspace = true } -solana-builtins-default-costs = { workspace = true } +solana-builtins = { workspace = true } solana-compute-budget = { workspace = true } solana-pubkey = { workspace = true } solana-sdk = { workspace = true } @@ -26,7 +26,6 @@ name = "solana_compute_budget_instruction" 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] diff --git a/compute-budget-instruction/src/builtin_programs_filter.rs b/compute-budget-instruction/src/builtin_programs_filter.rs index 1525dd1f2cfc61..7d1ba3aff91b24 100644 --- a/compute-budget-instruction/src/builtin_programs_filter.rs +++ b/compute-budget-instruction/src/builtin_programs_filter.rs @@ -1,6 +1,6 @@ use { - solana_builtins_default_costs::{ - get_builtin_migration_feature_index, BuiltinMigrationFeatureIndex, MAYBE_BUILTIN_KEY, + solana_builtins::cost_modeling::{ + get_builtin_migration_feature_index, is_builtin_program, MAYBE_BUILTIN_KEY, }, solana_sdk::{packet::PACKET_DATA_SIZE, pubkey::Pubkey}, }; @@ -48,14 +48,16 @@ impl BuiltinProgramsFilter { return ProgramKind::NotBuiltin; } - match get_builtin_migration_feature_index(program_id) { - BuiltinMigrationFeatureIndex::NotBuiltin => ProgramKind::NotBuiltin, - BuiltinMigrationFeatureIndex::BuiltinNoMigrationFeature => ProgramKind::Builtin, - BuiltinMigrationFeatureIndex::BuiltinWithMigrationFeature( - core_bpf_migration_feature_index, - ) => ProgramKind::MigratingBuiltin { - core_bpf_migration_feature_index, - }, + if is_builtin_program(program_id) { + if let Some(index) = get_builtin_migration_feature_index(program_id) { + ProgramKind::MigratingBuiltin { + core_bpf_migration_feature_index: index, + } + } else { + ProgramKind::Builtin + } + } else { + ProgramKind::NotBuiltin } } } @@ -63,7 +65,8 @@ impl BuiltinProgramsFilter { #[cfg(test)] mod test { use { - super::*, solana_builtins_default_costs::get_migration_feature_position, + super::*, + solana_builtins::cost_modeling::get_builtin_migration_feature_index_from_feature_id, solana_sdk::feature_set, }; @@ -127,9 +130,9 @@ mod test { assert_eq!( test_store.get_program_kind(index, &migrating_builtin_pubkey), ProgramKind::MigratingBuiltin { - core_bpf_migration_feature_index: get_migration_feature_position( - &migration_feature_id - ), + core_bpf_migration_feature_index: + get_builtin_migration_feature_index_from_feature_id(&migration_feature_id) + .unwrap(), } ); } diff --git a/compute-budget-instruction/src/compute_budget_instruction_details.rs b/compute-budget-instruction/src/compute_budget_instruction_details.rs index e0ef6341694167..45ee08654ec13e 100644 --- a/compute-budget-instruction/src/compute_budget_instruction_details.rs +++ b/compute-budget-instruction/src/compute_budget_instruction_details.rs @@ -3,7 +3,9 @@ use { builtin_programs_filter::{BuiltinProgramsFilter, ProgramKind}, compute_budget_program_id_filter::ComputeBudgetProgramIdFilter, }, - solana_builtins_default_costs::{get_migration_feature_id, MIGRATING_BUILTINS_COSTS}, + solana_builtins::cost_modeling::{ + get_builtin_migration_feature_id, NUM_COST_MODELED_BUILTINS_WITH_MIGRATIONS, + }, solana_compute_budget::compute_budget_limits::*, solana_sdk::{ borsh1::try_from_slice_unchecked, @@ -22,16 +24,17 @@ use { #[cfg_attr(feature = "dev-context-only-utils", derive(Clone))] #[derive(Debug)] struct MigrationBuiltinFeatureCounter { - // The vector of counters, matching the size of the static vector MIGRATION_FEATURE_IDS, - // each counter representing the number of times its corresponding feature ID is + // The vector of counters, matching the size of the + // `NUM_COST_MODELED_BUILTINS_WITH_MIGRATIONS` constant, each counter + // representing the number of times its corresponding feature ID is // referenced in this transaction. - migrating_builtin: [u16; MIGRATING_BUILTINS_COSTS.len()], + migrating_builtin: [u16; NUM_COST_MODELED_BUILTINS_WITH_MIGRATIONS], } impl Default for MigrationBuiltinFeatureCounter { fn default() -> Self { Self { - migrating_builtin: [0; MIGRATING_BUILTINS_COSTS.len()], + migrating_builtin: [0; NUM_COST_MODELED_BUILTINS_WITH_MIGRATIONS], } } } @@ -217,7 +220,8 @@ impl ComputeBudgetInstructionDetails { .iter() .enumerate() .fold((0, 0), |(migrated, not_migrated), (index, count)| { - if *count > 0 && feature_set.is_active(get_migration_feature_id(index)) { + if *count > 0 && feature_set.is_active(get_builtin_migration_feature_id(index)) + { (migrated + count, not_migrated) } else { (migrated, not_migrated + count) @@ -243,7 +247,7 @@ impl ComputeBudgetInstructionDetails { mod test { use { super::*, - solana_builtins_default_costs::get_migration_feature_position, + solana_builtins::cost_modeling::get_builtin_migration_feature_index_from_feature_id, solana_sdk::{ instruction::Instruction, message::Message, @@ -585,8 +589,10 @@ mod test { &Pubkey::new_unique(), ), ]); - let feature_id_index = - get_migration_feature_position(&feature_set::migrate_stake_program_to_core_bpf::id()); + let feature_id_index = get_builtin_migration_feature_index_from_feature_id( + &feature_set::migrate_stake_program_to_core_bpf::id(), + ) + .unwrap(); let mut expected_details = ComputeBudgetInstructionDetails { num_non_compute_budget_instructions: 2, num_non_builtin_instructions: 1, diff --git a/compute-budget-instruction/src/compute_budget_program_id_filter.rs b/compute-budget-instruction/src/compute_budget_program_id_filter.rs index 62ec47b7209ef0..b606626635e8fc 100644 --- a/compute-budget-instruction/src/compute_budget_program_id_filter.rs +++ b/compute-budget-instruction/src/compute_budget_program_id_filter.rs @@ -1,6 +1,6 @@ // static account keys has max use { - crate::builtin_programs_filter::FILTER_SIZE, solana_builtins_default_costs::MAYBE_BUILTIN_KEY, + crate::builtin_programs_filter::FILTER_SIZE, solana_builtins::cost_modeling::MAYBE_BUILTIN_KEY, solana_sdk::pubkey::Pubkey, }; diff --git a/core/Cargo.toml b/core/Cargo.toml index 0143180ced5b4d..4ae5405d0ece67 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -47,7 +47,7 @@ serde_derive = { workspace = true } slab = { workspace = true } solana-accounts-db = { workspace = true } solana-bloom = { workspace = true } -solana-builtins-default-costs = { workspace = true } +solana-builtins = { workspace = true } solana-client = { workspace = true } solana-compute-budget = { workspace = true } solana-compute-budget-instruction = { workspace = true } diff --git a/core/src/banking_stage/packet_filter.rs b/core/src/banking_stage/packet_filter.rs index b9176c9b8ac91d..b87624d8abd86f 100644 --- a/core/src/banking_stage/packet_filter.rs +++ b/core/src/banking_stage/packet_filter.rs @@ -1,7 +1,7 @@ use { super::immutable_deserialized_packet::ImmutableDeserializedPacket, lazy_static::lazy_static, - solana_builtins_default_costs::get_builtin_instruction_cost, + solana_builtins::cost_modeling::get_builtin_instruction_cost, solana_sdk::{ ed25519_program, feature_set::FeatureSet, saturating_add_assign, secp256k1_program, }, diff --git a/cost-model/Cargo.toml b/cost-model/Cargo.toml index 1e0593daedeeaa..b80a29b857047e 100644 --- a/cost-model/Cargo.toml +++ b/cost-model/Cargo.toml @@ -13,7 +13,7 @@ edition = { workspace = true } ahash = { workspace = true } lazy_static = { workspace = true } log = { workspace = true } -solana-builtins-default-costs = { workspace = true } +solana-builtins = { workspace = true } solana-compute-budget = { workspace = true } solana-compute-budget-instruction = { workspace = true } solana-feature-set = { workspace = true } diff --git a/cost-model/src/cost_model.rs b/cost-model/src/cost_model.rs index f958ce6cb4eed1..6588a8baffe233 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::get_builtin_instruction_cost, + solana_builtins::cost_modeling::get_builtin_instruction_cost, solana_compute_budget::compute_budget_limits::{ DEFAULT_HEAP_COST, DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, MAX_COMPUTE_UNIT_LIMIT, }, diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index b5ae6a5cfd16b9..84c89c9d38f6b8 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -5155,6 +5155,8 @@ dependencies = [ name = "solana-builtins" version = "2.2.0" dependencies = [ + "ahash 0.8.11", + "lazy_static", "solana-address-lookup-table-program", "solana-bpf-loader-program", "solana-compute-budget-program", @@ -5171,26 +5173,6 @@ dependencies = [ "solana-zk-token-proof-program", ] -[[package]] -name = "solana-builtins-default-costs" -version = "2.2.0" -dependencies = [ - "ahash 0.8.11", - "lazy_static", - "log", - "solana-address-lookup-table-program", - "solana-bpf-loader-program", - "solana-compute-budget-program", - "solana-config-program", - "solana-feature-set", - "solana-loader-v4-program", - "solana-pubkey", - "solana-sdk-ids", - "solana-stake-program", - "solana-system-program", - "solana-vote-program", -] - [[package]] name = "solana-clap-utils" version = "2.2.0" @@ -5361,7 +5343,7 @@ name = "solana-compute-budget-instruction" version = "2.2.0" dependencies = [ "log", - "solana-builtins-default-costs", + "solana-builtins", "solana-compute-budget", "solana-pubkey", "solana-sdk", @@ -5460,7 +5442,7 @@ dependencies = [ "slab", "solana-accounts-db", "solana-bloom", - "solana-builtins-default-costs", + "solana-builtins", "solana-client", "solana-compute-budget", "solana-compute-budget-instruction", @@ -5518,7 +5500,7 @@ dependencies = [ "ahash 0.8.11", "lazy_static", "log", - "solana-builtins-default-costs", + "solana-builtins", "solana-compute-budget", "solana-compute-budget-instruction", "solana-feature-set", diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 0bec4f1ea64660..3f0e57830791e1 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -106,7 +106,7 @@ memoffset = { workspace = true } rand0-7 = { package = "rand", version = "0.7" } rand_chacha = { workspace = true } solana-accounts-db = { workspace = true, features = ["dev-context-only-utils"] } -solana-builtins = { workspace = true, features = ["dev-context-only-utils"] } +solana-builtins = { workspace = true, features = ["mock-builtin-migrations"] } solana-logger = { workspace = true } # See order-crates-for-publishing.py for using this unusual `path = "."` solana-runtime = { path = ".", features = ["dev-context-only-utils"] } diff --git a/scripts/patch-crates.sh b/scripts/patch-crates.sh index 45a2d67caf7f9b..1af7e7ca0b8eeb 100644 --- a/scripts/patch-crates.sh +++ b/scripts/patch-crates.sh @@ -14,7 +14,6 @@ update_solana_dependencies() { solana-banks-server solana-bloom solana-bucket-map - solana-builtins-default-costs solana-clap-utils solana-clap-v3-utils solana-cli-config @@ -151,7 +150,6 @@ patch_crates_io_solana_no_header() { crates_map+=("solana-banks-server banks-server") crates_map+=("solana-bloom bloom") crates_map+=("solana-bucket-map bucket_map") - crates_map+=("solana-builtins-default-costs builtins-default-costs") crates_map+=("solana-clap-utils clap-utils") crates_map+=("solana-clap-v3-utils clap-v3-utils") crates_map+=("solana-cli-config cli-config") diff --git a/svm/examples/Cargo.lock b/svm/examples/Cargo.lock index 10e72b4ec732ff..e5e06d6c1d623f 100644 --- a/svm/examples/Cargo.lock +++ b/svm/examples/Cargo.lock @@ -5006,6 +5006,8 @@ dependencies = [ name = "solana-builtins" version = "2.2.0" dependencies = [ + "ahash 0.8.11", + "lazy_static", "solana-address-lookup-table-program", "solana-bpf-loader-program", "solana-compute-budget-program", @@ -5022,26 +5024,6 @@ dependencies = [ "solana-zk-token-proof-program", ] -[[package]] -name = "solana-builtins-default-costs" -version = "2.2.0" -dependencies = [ - "ahash 0.8.11", - "lazy_static", - "log", - "solana-address-lookup-table-program", - "solana-bpf-loader-program", - "solana-compute-budget-program", - "solana-config-program", - "solana-feature-set", - "solana-loader-v4-program", - "solana-pubkey", - "solana-sdk-ids", - "solana-stake-program", - "solana-system-program", - "solana-vote-program", -] - [[package]] name = "solana-clap-utils" version = "2.2.0" @@ -5212,7 +5194,7 @@ name = "solana-compute-budget-instruction" version = "2.2.0" dependencies = [ "log", - "solana-builtins-default-costs", + "solana-builtins", "solana-compute-budget", "solana-pubkey", "solana-sdk", @@ -5311,7 +5293,7 @@ dependencies = [ "slab", "solana-accounts-db", "solana-bloom", - "solana-builtins-default-costs", + "solana-builtins", "solana-client", "solana-compute-budget", "solana-compute-budget-instruction", @@ -5369,7 +5351,7 @@ dependencies = [ "ahash 0.8.11", "lazy_static", "log", - "solana-builtins-default-costs", + "solana-builtins", "solana-compute-budget", "solana-compute-budget-instruction", "solana-feature-set",