From a4d6afd0b1b9b8c8037cddb4938c6b1d34a05f47 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Wed, 26 Feb 2025 08:38:15 -0800 Subject: [PATCH 1/2] Refactor ComputeBudget and ComputeBudgetLimits - Move relevant structs into SVM boundaries --- Cargo.lock | 12 +- cli/src/compute_budget.rs | 2 +- compute-budget-instruction/Cargo.toml | 2 + .../src/compute_budget_instruction_details.rs | 8 + .../src/instructions_processor.rs | 37 +++ compute-budget/Cargo.toml | 2 +- compute-budget/src/compute_budget.rs | 222 +-------------- compute-budget/src/compute_budget_limits.rs | 63 ++++- core/src/banking_stage/consumer.rs | 1 - core/tests/scheduler_cost_adjustment.rs | 6 +- cost-model/Cargo.toml | 1 + cost-model/src/cost_model.rs | 18 +- program-runtime/Cargo.toml | 6 +- program-runtime/src/execution_budget.rs | 252 ++++++++++++++++++ program-runtime/src/invoke_context.rs | 27 +- program-runtime/src/lib.rs | 2 + program-runtime/src/mem_pool.rs | 6 +- programs/bpf_loader/Cargo.toml | 1 - programs/bpf_loader/src/lib.rs | 2 +- programs/bpf_loader/src/syscalls/mod.rs | 37 +-- programs/bpf_loader/src/syscalls/sysvar.rs | 4 +- programs/loader-v4/Cargo.toml | 1 - programs/sbf/Cargo.lock | 8 +- programs/zk-token-proof-tests/Cargo.toml | 1 + .../tests/process_transaction.rs | 2 +- runtime/src/account_saver.rs | 12 +- runtime/src/bank.rs | 2 - runtime/src/bank/check_transactions.rs | 21 +- runtime/src/bank/tests.rs | 14 +- svm/Cargo.toml | 4 +- svm/examples/Cargo.lock | 9 +- .../json-rpc/server/src/rpc_process.rs | 10 +- svm/examples/paytube/Cargo.toml | 2 +- svm/examples/paytube/src/lib.rs | 9 +- svm/examples/paytube/src/processor.rs | 11 +- svm/src/account_loader.rs | 101 ++++--- svm/src/message_processor.rs | 16 +- svm/src/transaction_processor.rs | 148 +++++----- svm/tests/concurrent_tests.rs | 8 +- svm/tests/conformance.rs | 8 +- svm/tests/integration_test.rs | 17 +- svm/tests/mock_bank.rs | 4 +- 42 files changed, 625 insertions(+), 494 deletions(-) create mode 100644 program-runtime/src/execution_budget.rs diff --git a/Cargo.lock b/Cargo.lock index 5d28a80a840bfc..9cbe4415ccfd58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6572,7 +6572,6 @@ dependencies = [ "solana-bn254", "solana-bpf-loader-program", "solana-clock", - "solana-compute-budget", "solana-cpi", "solana-curve25519", "solana-epoch-rewards", @@ -7079,7 +7078,7 @@ dependencies = [ "qualifier_attr", "solana-fee-structure", "solana-frozen-abi", - "solana-program-entrypoint", + "solana-program-runtime", ] [[package]] @@ -7094,6 +7093,7 @@ dependencies = [ "solana-builtins-default-costs", "solana-compute-budget", "solana-compute-budget-interface", + "solana-compute-budget-program", "solana-feature-set", "solana-hash", "solana-instruction", @@ -7101,6 +7101,7 @@ dependencies = [ "solana-message", "solana-packet", "solana-program", + "solana-program-runtime", "solana-pubkey", "solana-sdk-ids", "solana-signer", @@ -7335,6 +7336,7 @@ dependencies = [ "solana-message", "solana-metrics", "solana-packet", + "solana-program-runtime", "solana-pubkey", "solana-reserved-account-keys", "solana-runtime-transaction", @@ -8237,7 +8239,6 @@ dependencies = [ "solana-bincode", "solana-bpf-loader-program", "solana-clock", - "solana-compute-budget", "solana-instruction", "solana-loader-v3-interface", "solana-loader-v4-interface", @@ -8824,12 +8825,12 @@ dependencies = [ "itertools 0.12.1", "log", "percentage", + "qualifier_attr", "rand 0.8.5", "serde", "solana-account", "solana-account-info", "solana-clock", - "solana-compute-budget", "solana-epoch-rewards", "solana-epoch-schedule", "solana-feature-set", @@ -8843,6 +8844,7 @@ dependencies = [ "solana-metrics", "solana-precompiles", "solana-program-entrypoint", + "solana-program-runtime", "solana-pubkey", "solana-rent", "solana-sbpf", @@ -9993,7 +9995,6 @@ dependencies = [ "solana-account", "solana-bpf-loader-program", "solana-clock", - "solana-compute-budget", "solana-compute-budget-instruction", "solana-compute-budget-interface", "solana-compute-budget-program", @@ -10992,6 +10993,7 @@ dependencies = [ "solana-compute-budget-interface", "solana-instruction", "solana-keypair", + "solana-program-runtime", "solana-program-test", "solana-pubkey", "solana-signer", diff --git a/cli/src/compute_budget.rs b/cli/src/compute_budget.rs index 94a528966110fa..3a19adfc846419 100644 --- a/cli/src/compute_budget.rs +++ b/cli/src/compute_budget.rs @@ -1,10 +1,10 @@ use { solana_borsh::v1::try_from_slice_unchecked, solana_clap_utils::compute_budget::ComputeUnitLimit, - solana_compute_budget::compute_budget_limits::MAX_COMPUTE_UNIT_LIMIT, solana_compute_budget_interface::{self as compute_budget, ComputeBudgetInstruction}, solana_instruction::Instruction, solana_message::Message, + solana_program_runtime::execution_budget::MAX_COMPUTE_UNIT_LIMIT, solana_rpc_client::rpc_client::RpcClient, solana_rpc_client_api::config::RpcSimulateTransactionConfig, solana_transaction::Transaction, diff --git a/compute-budget-instruction/Cargo.toml b/compute-budget-instruction/Cargo.toml index 5a80dc3ba86bdd..46ba9fe0ffb673 100644 --- a/compute-budget-instruction/Cargo.toml +++ b/compute-budget-instruction/Cargo.toml @@ -18,6 +18,7 @@ solana-compute-budget-interface = { workspace = true, features = ["borsh"] } solana-feature-set = { workspace = true } solana-instruction = { workspace = true } solana-packet = { workspace = true } +solana-program-runtime = { workspace = true } solana-pubkey = { workspace = true } solana-sdk-ids = { workspace = true } solana-svm-transaction = { workspace = true } @@ -33,6 +34,7 @@ bincode = { workspace = true } criterion = { workspace = true } rand = { workspace = true } solana-builtins-default-costs = { workspace = true, features = ["dev-context-only-utils", "svm-internal"] } +solana-compute-budget-program = { workspace = true } solana-hash = { workspace = true } solana-keypair = { workspace = true } solana-message = { workspace = true } diff --git a/compute-budget-instruction/src/compute_budget_instruction_details.rs b/compute-budget-instruction/src/compute_budget_instruction_details.rs index 145172033d0dfb..59a61c11f9359e 100644 --- a/compute-budget-instruction/src/compute_budget_instruction_details.rs +++ b/compute-budget-instruction/src/compute_budget_instruction_details.rs @@ -9,6 +9,10 @@ use { solana_compute_budget_interface::ComputeBudgetInstruction, solana_feature_set::{self as feature_set, FeatureSet}, solana_instruction::error::InstructionError, + solana_program_runtime::execution_budget::{ + DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, MAX_BUILTIN_ALLOCATION_COMPUTE_UNIT_LIMIT, + MAX_COMPUTE_UNIT_LIMIT, MAX_HEAP_FRAME_BYTES, MIN_HEAP_FRAME_BYTES, + }, solana_pubkey::Pubkey, solana_svm_transaction::instruction::SVMInstruction, solana_transaction_error::{TransactionError, TransactionResult as Result}, @@ -232,6 +236,10 @@ mod test { solana_instruction::Instruction, solana_keypair::Keypair, solana_message::Message, + solana_program_runtime::execution_budget::{ + DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, MAX_BUILTIN_ALLOCATION_COMPUTE_UNIT_LIMIT, + MAX_COMPUTE_UNIT_LIMIT, MAX_HEAP_FRAME_BYTES, MIN_HEAP_FRAME_BYTES, + }, solana_pubkey::Pubkey, solana_signer::Signer, solana_svm_transaction::svm_message::SVMMessage, diff --git a/compute-budget-instruction/src/instructions_processor.rs b/compute-budget-instruction/src/instructions_processor.rs index 47e99d0b3359d0..b5c6a03f1f51d3 100644 --- a/compute-budget-instruction/src/instructions_processor.rs +++ b/compute-budget-instruction/src/instructions_processor.rs @@ -22,11 +22,16 @@ pub fn process_compute_budget_instructions<'a>( mod tests { use { super::*, + solana_compute_budget::compute_budget_limits::ComputeBudgetLimits, solana_compute_budget_interface::ComputeBudgetInstruction, solana_hash::Hash, solana_instruction::{error::InstructionError, Instruction}, solana_keypair::Keypair, solana_message::Message, + solana_program_runtime::execution_budget::{ + DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, MAX_BUILTIN_ALLOCATION_COMPUTE_UNIT_LIMIT, + MAX_COMPUTE_UNIT_LIMIT, MAX_HEAP_FRAME_BYTES, MIN_HEAP_FRAME_BYTES, + }, solana_pubkey::Pubkey, solana_signer::Signer, solana_svm_transaction::svm_message::SVMMessage, @@ -78,6 +83,30 @@ mod tests { ..ComputeBudgetLimits::default() }) ); + test!( + &[ + ComputeBudgetInstruction::set_compute_unit_limit(2000u32), + ComputeBudgetInstruction::set_compute_unit_price(1_000_000_000), + ], + Ok(ComputeBudgetLimits { + compute_unit_limit: 2000u32, + compute_unit_price: 1_000_000_000u64, + ..ComputeBudgetLimits::default() + }) + ); + test!( + &[ + ComputeBudgetInstruction::set_compute_unit_limit( + 2 * solana_compute_budget_program::DEFAULT_COMPUTE_UNITS as u32 + ), + ComputeBudgetInstruction::set_compute_unit_price(1_000_000), + ], + Ok(ComputeBudgetLimits { + compute_unit_limit: 2 * solana_compute_budget_program::DEFAULT_COMPUTE_UNITS as u32, + compute_unit_price: 1_000_000u64, + ..ComputeBudgetLimits::default() + }) + ); test!( &[ ComputeBudgetInstruction::set_compute_unit_limit(MAX_COMPUTE_UNIT_LIMIT + 1), @@ -279,6 +308,14 @@ mod tests { Err(TransactionError::DuplicateInstruction(2)) ); + test!( + &[ + ComputeBudgetInstruction::set_compute_unit_limit(2000u32), + ComputeBudgetInstruction::set_compute_unit_limit(42u32), + ], + Err(TransactionError::DuplicateInstruction(1)) + ); + test!( &[ Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]), diff --git a/compute-budget/Cargo.toml b/compute-budget/Cargo.toml index 78d4761cdc664b..2a9a1b3e9d41df 100644 --- a/compute-budget/Cargo.toml +++ b/compute-budget/Cargo.toml @@ -15,7 +15,7 @@ solana-fee-structure = { workspace = true } solana-frozen-abi = { workspace = true, optional = true, features = [ "frozen-abi", ] } -solana-program-entrypoint = { workspace = true } +solana-program-runtime = { workspace = true } [features] dev-context-only-utils = ["dep:qualifier_attr"] diff --git a/compute-budget/src/compute_budget.rs b/compute-budget/src/compute_budget.rs index 39247062f25c8d..8c1344b9485511 100644 --- a/compute-budget/src/compute_budget.rs +++ b/compute-budget/src/compute_budget.rs @@ -1,141 +1,5 @@ -use crate::compute_budget_limits::{self, ComputeBudgetLimits, DEFAULT_HEAP_COST}; -#[cfg(feature = "dev-context-only-utils")] -use qualifier_attr::qualifiers; - -#[cfg(feature = "frozen-abi")] -impl ::solana_frozen_abi::abi_example::AbiExample for ComputeBudget { - fn example() -> Self { - // ComputeBudget is not Serialize so just rely on Default. - ComputeBudget::default() - } -} - -/// Max instruction stack depth. This is the maximum nesting of instructions that can happen during -/// a transaction. -pub const MAX_INSTRUCTION_STACK_DEPTH: usize = 5; - -/// Max call depth. This is the maximum nesting of SBF to SBF call that can happen within a program. -pub const MAX_CALL_DEPTH: usize = 64; - -/// The size of one SBF stack frame. -pub const STACK_FRAME_SIZE: usize = 4096; - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct ComputeBudget { - /// Number of compute units that a transaction or individual instruction is - /// allowed to consume. Compute units are consumed by program execution, - /// resources they use, etc... - pub compute_unit_limit: u64, - /// Number of compute units consumed by a log_u64 call - pub log_64_units: u64, - /// Number of compute units consumed by a create_program_address call - pub create_program_address_units: u64, - /// Number of compute units consumed by an invoke call (not including the cost incurred by - /// the called program) - pub invoke_units: u64, - /// Maximum program instruction invocation stack depth. Invocation stack - /// depth starts at 1 for transaction instructions and the stack depth is - /// incremented each time a program invokes an instruction and decremented - /// when a program returns. - pub max_instruction_stack_depth: usize, - /// Maximum cross-program invocation and instructions per transaction - pub max_instruction_trace_length: usize, - /// Base number of compute units consumed to call SHA256 - pub sha256_base_cost: u64, - /// Incremental number of units consumed by SHA256 (based on bytes) - pub sha256_byte_cost: u64, - /// Maximum number of slices hashed per syscall - pub sha256_max_slices: u64, - /// Maximum SBF to BPF call depth - pub max_call_depth: usize, - /// Size of a stack frame in bytes, must match the size specified in the LLVM SBF backend - pub stack_frame_size: usize, - /// Number of compute units consumed by logging a `Pubkey` - pub log_pubkey_units: u64, - /// Maximum cross-program invocation instruction size - pub max_cpi_instruction_size: usize, - /// Number of account data bytes per compute unit charged during a cross-program invocation - pub cpi_bytes_per_unit: u64, - /// Base number of compute units consumed to get a sysvar - pub sysvar_base_cost: u64, - /// Number of compute units consumed to call secp256k1_recover - pub secp256k1_recover_cost: u64, - /// Number of compute units consumed to do a syscall without any work - pub syscall_base_cost: u64, - /// Number of compute units consumed to validate a curve25519 edwards point - pub curve25519_edwards_validate_point_cost: u64, - /// Number of compute units consumed to add two curve25519 edwards points - pub curve25519_edwards_add_cost: u64, - /// Number of compute units consumed to subtract two curve25519 edwards points - pub curve25519_edwards_subtract_cost: u64, - /// Number of compute units consumed to multiply a curve25519 edwards point - pub curve25519_edwards_multiply_cost: u64, - /// Number of compute units consumed for a multiscalar multiplication (msm) of edwards points. - /// The total cost is calculated as `msm_base_cost + (length - 1) * msm_incremental_cost`. - pub curve25519_edwards_msm_base_cost: u64, - /// Number of compute units consumed for a multiscalar multiplication (msm) of edwards points. - /// The total cost is calculated as `msm_base_cost + (length - 1) * msm_incremental_cost`. - pub curve25519_edwards_msm_incremental_cost: u64, - /// Number of compute units consumed to validate a curve25519 ristretto point - pub curve25519_ristretto_validate_point_cost: u64, - /// Number of compute units consumed to add two curve25519 ristretto points - pub curve25519_ristretto_add_cost: u64, - /// Number of compute units consumed to subtract two curve25519 ristretto points - pub curve25519_ristretto_subtract_cost: u64, - /// Number of compute units consumed to multiply a curve25519 ristretto point - pub curve25519_ristretto_multiply_cost: u64, - /// Number of compute units consumed for a multiscalar multiplication (msm) of ristretto points. - /// The total cost is calculated as `msm_base_cost + (length - 1) * msm_incremental_cost`. - pub curve25519_ristretto_msm_base_cost: u64, - /// Number of compute units consumed for a multiscalar multiplication (msm) of ristretto points. - /// The total cost is calculated as `msm_base_cost + (length - 1) * msm_incremental_cost`. - pub curve25519_ristretto_msm_incremental_cost: u64, - /// program heap region size, default: solana_sdk::entrypoint::HEAP_LENGTH - pub heap_size: u32, - /// Number of compute units per additional 32k heap above the default (~.5 - /// us per 32k at 15 units/us rounded up) - pub heap_cost: u64, - /// Memory operation syscall base cost - pub mem_op_base_cost: u64, - /// Number of compute units consumed to call alt_bn128_addition - pub alt_bn128_addition_cost: u64, - /// Number of compute units consumed to call alt_bn128_multiplication. - pub alt_bn128_multiplication_cost: u64, - /// Total cost will be alt_bn128_pairing_one_pair_cost_first - /// + alt_bn128_pairing_one_pair_cost_other * (num_elems - 1) - pub alt_bn128_pairing_one_pair_cost_first: u64, - pub alt_bn128_pairing_one_pair_cost_other: u64, - /// Big integer modular exponentiation base cost - pub big_modular_exponentiation_base_cost: u64, - /// Big integer moduler exponentiation cost divisor - /// The modular exponentiation cost is computed as - /// `input_length`/`big_modular_exponentiation_cost_divisor` + `big_modular_exponentiation_base_cost` - pub big_modular_exponentiation_cost_divisor: u64, - /// Coefficient `a` of the quadratic function which determines the number - /// of compute units consumed to call poseidon syscall for a given number - /// of inputs. - pub poseidon_cost_coefficient_a: u64, - /// Coefficient `c` of the quadratic function which determines the number - /// of compute units consumed to call poseidon syscall for a given number - /// of inputs. - pub poseidon_cost_coefficient_c: u64, - /// Number of compute units consumed for accessing the remaining compute units. - pub get_remaining_compute_units_cost: u64, - /// Number of compute units consumed to call alt_bn128_g1_compress. - pub alt_bn128_g1_compress: u64, - /// Number of compute units consumed to call alt_bn128_g1_decompress. - pub alt_bn128_g1_decompress: u64, - /// Number of compute units consumed to call alt_bn128_g2_compress. - pub alt_bn128_g2_compress: u64, - /// Number of compute units consumed to call alt_bn128_g2_decompress. - pub alt_bn128_g2_decompress: u64, -} - -impl Default for ComputeBudget { - fn default() -> Self { - Self::new(compute_budget_limits::MAX_COMPUTE_UNIT_LIMIT as u64) - } -} +use crate::compute_budget_limits::ComputeBudgetLimits; +pub use solana_program_runtime::execution_budget::SVMTransactionExecutionBudget as ComputeBudget; impl From for ComputeBudget { fn from(compute_budget_limits: ComputeBudgetLimits) -> Self { @@ -146,85 +10,3 @@ impl From for ComputeBudget { } } } - -impl ComputeBudget { - #[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))] - fn new(compute_unit_limit: u64) -> Self { - ComputeBudget { - compute_unit_limit, - log_64_units: 100, - create_program_address_units: 1500, - invoke_units: 1000, - max_instruction_stack_depth: MAX_INSTRUCTION_STACK_DEPTH, - max_instruction_trace_length: 64, - sha256_base_cost: 85, - sha256_byte_cost: 1, - sha256_max_slices: 20_000, - max_call_depth: MAX_CALL_DEPTH, - stack_frame_size: STACK_FRAME_SIZE, - log_pubkey_units: 100, - max_cpi_instruction_size: 1280, // IPv6 Min MTU size - cpi_bytes_per_unit: 250, // ~50MB at 200,000 units - sysvar_base_cost: 100, - secp256k1_recover_cost: 25_000, - syscall_base_cost: 100, - curve25519_edwards_validate_point_cost: 159, - curve25519_edwards_add_cost: 473, - curve25519_edwards_subtract_cost: 475, - curve25519_edwards_multiply_cost: 2_177, - curve25519_edwards_msm_base_cost: 2_273, - curve25519_edwards_msm_incremental_cost: 758, - curve25519_ristretto_validate_point_cost: 169, - curve25519_ristretto_add_cost: 521, - curve25519_ristretto_subtract_cost: 519, - curve25519_ristretto_multiply_cost: 2_208, - curve25519_ristretto_msm_base_cost: 2303, - curve25519_ristretto_msm_incremental_cost: 788, - heap_size: u32::try_from(solana_program_entrypoint::HEAP_LENGTH).unwrap(), - heap_cost: DEFAULT_HEAP_COST, - mem_op_base_cost: 10, - alt_bn128_addition_cost: 334, - alt_bn128_multiplication_cost: 3_840, - alt_bn128_pairing_one_pair_cost_first: 36_364, - alt_bn128_pairing_one_pair_cost_other: 12_121, - big_modular_exponentiation_base_cost: 190, - big_modular_exponentiation_cost_divisor: 2, - poseidon_cost_coefficient_a: 61, - poseidon_cost_coefficient_c: 542, - get_remaining_compute_units_cost: 100, - alt_bn128_g1_compress: 30, - alt_bn128_g1_decompress: 398, - alt_bn128_g2_compress: 86, - alt_bn128_g2_decompress: 13610, - } - } - - /// Returns cost of the Poseidon hash function for the given number of - /// inputs is determined by the following quadratic function: - /// - /// 61*n^2 + 542 - /// - /// Which aproximates the results of benchmarks of light-posiedon - /// library[0]. These results assume 1 CU per 33 ns. Examples: - /// - /// * 1 input - /// * light-poseidon benchmark: `18,303 / 33 ≈ 555` - /// * function: `61*1^2 + 542 = 603` - /// * 2 inputs - /// * light-poseidon benchmark: `25,866 / 33 ≈ 784` - /// * function: `61*2^2 + 542 = 786` - /// * 3 inputs - /// * light-poseidon benchmark: `37,549 / 33 ≈ 1,138` - /// * function; `61*3^2 + 542 = 1091` - /// - /// [0] https://github.com/Lightprotocol/light-poseidon#performance - pub fn poseidon_cost(&self, nr_inputs: u64) -> Option { - let squared_inputs = nr_inputs.checked_pow(2)?; - let mul_result = self - .poseidon_cost_coefficient_a - .checked_mul(squared_inputs)?; - let final_result = mul_result.checked_add(self.poseidon_cost_coefficient_c)?; - - Some(final_result) - } -} diff --git a/compute-budget/src/compute_budget_limits.rs b/compute-budget/src/compute_budget_limits.rs index ac951a2014a36a..25569d19ccccc4 100644 --- a/compute-budget/src/compute_budget_limits.rs +++ b/compute-budget/src/compute_budget_limits.rs @@ -1,19 +1,15 @@ +#[cfg(feature = "dev-context-only-utils")] +use qualifier_attr::qualifiers; use { - solana_fee_structure::FeeBudgetLimits, solana_program_entrypoint::HEAP_LENGTH, + crate::compute_budget::ComputeBudget, + solana_fee_structure::FeeBudgetLimits, + solana_program_runtime::execution_budget::{ + SVMTransactionComputeBudgetAndLimits, DEFAULT_HEAP_COST, MAX_COMPUTE_UNIT_LIMIT, + MIN_HEAP_FRAME_BYTES, + }, std::num::NonZeroU32, }; -/// Roughly 0.5us/page, where page is 32K; given roughly 15CU/us, the -/// default heap page cost = 0.5 * 15 ~= 8CU/page -pub const DEFAULT_HEAP_COST: u64 = 8; -pub const DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT: u32 = 200_000; -// SIMD-170 defines max CUs to be allocated for any builtin program instructions, that -// have not been migrated to sBPF programs. -pub const MAX_BUILTIN_ALLOCATION_COMPUTE_UNIT_LIMIT: u32 = 3_000; -pub const MAX_COMPUTE_UNIT_LIMIT: u32 = 1_400_000; -pub const MAX_HEAP_FRAME_BYTES: u32 = 256 * 1024; -pub const MIN_HEAP_FRAME_BYTES: u32 = HEAP_LENGTH as u32; - type MicroLamports = u128; /// There are 10^6 micro-lamports in one lamport @@ -43,6 +39,35 @@ impl Default for ComputeBudgetLimits { } } +impl ComputeBudgetLimits { + #[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))] + pub fn default_compute_budget_and_limits() -> SVMTransactionComputeBudgetAndLimits { + Self::get_compute_budget_and_limits(&ComputeBudgetLimits::default()) + } + + pub fn get_compute_budget_and_limits(&self) -> SVMTransactionComputeBudgetAndLimits { + let budget = ComputeBudget::from(*self); + let fee_budget = FeeBudgetLimits::from(self); + SVMTransactionComputeBudgetAndLimits { + budget, + loaded_accounts_bytes: fee_budget.loaded_accounts_data_size_limit, + priority_fee: fee_budget.prioritization_fee, + } + } + + pub fn get_limits_using_compute_budget( + &self, + budget: ComputeBudget, + ) -> SVMTransactionComputeBudgetAndLimits { + let fee_budget = FeeBudgetLimits::from(self); + SVMTransactionComputeBudgetAndLimits { + budget, + loaded_accounts_bytes: fee_budget.loaded_accounts_data_size_limit, + priority_fee: fee_budget.prioritization_fee, + } + } +} + fn get_prioritization_fee(compute_unit_price: u64, compute_unit_limit: u64) -> u64 { let micro_lamport_fee: MicroLamports = (compute_unit_price as u128).saturating_mul(compute_unit_limit as u128); @@ -67,6 +92,20 @@ impl From for FeeBudgetLimits { } } +impl From<&ComputeBudgetLimits> for FeeBudgetLimits { + fn from(val: &ComputeBudgetLimits) -> Self { + let prioritization_fee = + get_prioritization_fee(val.compute_unit_price, u64::from(val.compute_unit_limit)); + + FeeBudgetLimits { + loaded_accounts_data_size_limit: val.loaded_accounts_bytes, + heap_cost: DEFAULT_HEAP_COST, + compute_unit_limit: u64::from(val.compute_unit_limit), + prioritization_fee, + } + } +} + #[cfg(test)] mod test { use super::*; diff --git a/core/src/banking_stage/consumer.rs b/core/src/banking_stage/consumer.rs index 117e4b61d08bfc..275f071d9edc75 100644 --- a/core/src/banking_stage/consumer.rs +++ b/core/src/banking_stage/consumer.rs @@ -630,7 +630,6 @@ impl Consumer { TransactionProcessingConfig { account_overrides: None, check_program_modification_slot: bank.check_program_modification_slot(), - compute_budget: bank.compute_budget(), log_messages_bytes_limit: self.log_messages_bytes_limit, limit_to_load_programs: true, recording_config: ExecutionRecordingConfig::new_single_setting( diff --git a/core/tests/scheduler_cost_adjustment.rs b/core/tests/scheduler_cost_adjustment.rs index b93b80485fa1d6..36ab67f17ae850 100644 --- a/core/tests/scheduler_cost_adjustment.rs +++ b/core/tests/scheduler_cost_adjustment.rs @@ -1,10 +1,10 @@ #![cfg(test)] use { - solana_compute_budget::compute_budget_limits::{ + solana_cost_model::cost_model::CostModel, + solana_feature_set as feature_set, + solana_program_runtime::execution_budget::{ DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, MAX_BUILTIN_ALLOCATION_COMPUTE_UNIT_LIMIT, }, - solana_cost_model::cost_model::CostModel, - solana_feature_set::{self as feature_set}, solana_runtime::{bank::Bank, bank_forks::BankForks}, solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_sdk::{ diff --git a/cost-model/Cargo.toml b/cost-model/Cargo.toml index 8ee33b590f664d..177b15e95443b1 100644 --- a/cost-model/Cargo.toml +++ b/cost-model/Cargo.toml @@ -32,6 +32,7 @@ solana-hash = { workspace = true, optional = true } solana-message = { workspace = true, optional = true } solana-metrics = { workspace = true } solana-packet = { workspace = true } +solana-program-runtime = { workspace = true } solana-pubkey = { workspace = true } solana-runtime-transaction = { workspace = true } solana-sdk-ids = { workspace = true } diff --git a/cost-model/src/cost_model.rs b/cost-model/src/cost_model.rs index dfdca3b31eb05c..a7bbb721518fa5 100644 --- a/cost-model/src/cost_model.rs +++ b/cost-model/src/cost_model.rs @@ -10,12 +10,12 @@ use { solana_bincode::limited_deserialize, solana_borsh::v1::try_from_slice_unchecked, 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, - }, solana_compute_budget_interface::ComputeBudgetInstruction, solana_feature_set::{self as feature_set, FeatureSet}, solana_fee_structure::FeeStructure, + solana_program_runtime::execution_budget::{ + DEFAULT_HEAP_COST, DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, MAX_COMPUTE_UNIT_LIMIT, + }, solana_pubkey::Pubkey, solana_runtime_transaction::{ transaction_meta::StaticMeta, transaction_with_meta::TransactionWithMeta, @@ -403,23 +403,21 @@ mod tests { use { super::*, itertools::Itertools, - solana_compute_budget::{ - self, - compute_budget_limits::{ - DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, MAX_BUILTIN_ALLOCATION_COMPUTE_UNIT_LIMIT, - }, - }, + solana_compute_budget::{self}, solana_compute_budget_interface::ComputeBudgetInstruction, solana_fee_structure::ACCOUNT_DATA_COST_PAGE_SIZE, solana_hash::Hash, solana_instruction::Instruction, solana_keypair::Keypair, solana_message::{compiled_instruction::CompiledInstruction, Message}, + solana_program_runtime::execution_budget::{ + DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, MAX_BUILTIN_ALLOCATION_COMPUTE_UNIT_LIMIT, + }, solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_sdk_ids::system_program, solana_signer::Signer, solana_svm_transaction::svm_message::SVMMessage, - solana_system_interface::instruction::{self as system_instruction}, + solana_system_interface::instruction as system_instruction, solana_system_transaction as system_transaction, solana_transaction::Transaction, }; diff --git a/program-runtime/Cargo.toml b/program-runtime/Cargo.toml index d9073695a31891..a208aeb1792132 100644 --- a/program-runtime/Cargo.toml +++ b/program-runtime/Cargo.toml @@ -16,11 +16,11 @@ enum-iterator = { workspace = true } itertools = { workspace = true } log = { workspace = true } percentage = { workspace = true } +qualifier_attr = { workspace = true, optional = true } rand = { workspace = true } serde = { workspace = true } solana-account = { workspace = true, features = ["bincode"] } solana-clock = { workspace = true } -solana-compute-budget = { workspace = true } solana-epoch-rewards = { workspace = true } solana-epoch-schedule = { workspace = true } solana-feature-set = { workspace = true } @@ -55,8 +55,8 @@ thiserror = { workspace = true } [dev-dependencies] assert_matches = { workspace = true } solana-account-info = { workspace = true } -solana-compute-budget = { workspace = true, features = ["dev-context-only-utils"] } solana-instruction = { workspace = true, features = ["bincode"] } +solana-program-runtime = { path = ".", features = ["dev-context-only-utils"] } solana-pubkey = { workspace = true, features = ["rand"] } solana-transaction-context = { workspace = true, features = [ "dev-context-only-utils", @@ -71,11 +71,11 @@ name = "solana_program_runtime" targets = ["x86_64-unknown-linux-gnu"] [features] +dev-context-only-utils = ["dep:qualifier_attr"] dummy-for-ci-check = ["metrics"] frozen-abi = [ "dep:solana-frozen-abi", "dep:solana-frozen-abi-macro", - "solana-compute-budget/frozen-abi", ] metrics = ["dep:solana-metrics"] shuttle-test = [ diff --git a/program-runtime/src/execution_budget.rs b/program-runtime/src/execution_budget.rs new file mode 100644 index 00000000000000..4014f7e08b59b7 --- /dev/null +++ b/program-runtime/src/execution_budget.rs @@ -0,0 +1,252 @@ +#[cfg(feature = "dev-context-only-utils")] +use qualifier_attr::qualifiers; +use {solana_program_entrypoint::HEAP_LENGTH, std::num::NonZeroU32}; + +#[cfg(feature = "frozen-abi")] +impl ::solana_frozen_abi::abi_example::AbiExample + for crate::execution_budget::SVMTransactionExecutionBudget +{ + fn example() -> Self { + // ComputeBudget is not Serialize so just rely on Default. + crate::execution_budget::SVMTransactionExecutionBudget::default() + } +} + +/// Max instruction stack depth. This is the maximum nesting of instructions that can happen during +/// a transaction. +pub const MAX_INSTRUCTION_STACK_DEPTH: usize = 5; + +/// Max call depth. This is the maximum nesting of SBF to SBF call that can happen within a program. +pub const MAX_CALL_DEPTH: usize = 64; + +/// The size of one SBF stack frame. +pub const STACK_FRAME_SIZE: usize = 4096; + +pub const MAX_COMPUTE_UNIT_LIMIT: u32 = 1_400_000; + +/// Roughly 0.5us/page, where page is 32K; given roughly 15CU/us, the +/// default heap page cost = 0.5 * 15 ~= 8CU/page +pub const DEFAULT_HEAP_COST: u64 = 8; +pub const DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT: u32 = 200_000; +// SIMD-170 defines max CUs to be allocated for any builtin program instructions, that +// have not been migrated to sBPF programs. +pub const MAX_BUILTIN_ALLOCATION_COMPUTE_UNIT_LIMIT: u32 = 3_000; +pub const MAX_HEAP_FRAME_BYTES: u32 = 256 * 1024; +pub const MIN_HEAP_FRAME_BYTES: u32 = HEAP_LENGTH as u32; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct SVMTransactionExecutionBudget { + /// Number of compute units that a transaction or individual instruction is + /// allowed to consume. Compute units are consumed by program execution, + /// resources they use, etc... + pub compute_unit_limit: u64, + /// Number of compute units consumed by a log_u64 call + pub log_64_units: u64, + /// Number of compute units consumed by a create_program_address call + pub create_program_address_units: u64, + /// Number of compute units consumed by an invoke call (not including the cost incurred by + /// the called program) + pub invoke_units: u64, + /// Maximum program instruction invocation stack depth. Invocation stack + /// depth starts at 1 for transaction instructions and the stack depth is + /// incremented each time a program invokes an instruction and decremented + /// when a program returns. + pub max_instruction_stack_depth: usize, + /// Maximum cross-program invocation and instructions per transaction + pub max_instruction_trace_length: usize, + /// Base number of compute units consumed to call SHA256 + pub sha256_base_cost: u64, + /// Incremental number of units consumed by SHA256 (based on bytes) + pub sha256_byte_cost: u64, + /// Maximum number of slices hashed per syscall + pub sha256_max_slices: u64, + /// Maximum SBF to BPF call depth + pub max_call_depth: usize, + /// Size of a stack frame in bytes, must match the size specified in the LLVM SBF backend + pub stack_frame_size: usize, + /// Number of compute units consumed by logging a `Pubkey` + pub log_pubkey_units: u64, + /// Maximum cross-program invocation instruction size + pub max_cpi_instruction_size: usize, + /// Number of account data bytes per compute unit charged during a cross-program invocation + pub cpi_bytes_per_unit: u64, + /// Base number of compute units consumed to get a sysvar + pub sysvar_base_cost: u64, + /// Number of compute units consumed to call secp256k1_recover + pub secp256k1_recover_cost: u64, + /// Number of compute units consumed to do a syscall without any work + pub syscall_base_cost: u64, + /// Number of compute units consumed to validate a curve25519 edwards point + pub curve25519_edwards_validate_point_cost: u64, + /// Number of compute units consumed to add two curve25519 edwards points + pub curve25519_edwards_add_cost: u64, + /// Number of compute units consumed to subtract two curve25519 edwards points + pub curve25519_edwards_subtract_cost: u64, + /// Number of compute units consumed to multiply a curve25519 edwards point + pub curve25519_edwards_multiply_cost: u64, + /// Number of compute units consumed for a multiscalar multiplication (msm) of edwards points. + /// The total cost is calculated as `msm_base_cost + (length - 1) * msm_incremental_cost`. + pub curve25519_edwards_msm_base_cost: u64, + /// Number of compute units consumed for a multiscalar multiplication (msm) of edwards points. + /// The total cost is calculated as `msm_base_cost + (length - 1) * msm_incremental_cost`. + pub curve25519_edwards_msm_incremental_cost: u64, + /// Number of compute units consumed to validate a curve25519 ristretto point + pub curve25519_ristretto_validate_point_cost: u64, + /// Number of compute units consumed to add two curve25519 ristretto points + pub curve25519_ristretto_add_cost: u64, + /// Number of compute units consumed to subtract two curve25519 ristretto points + pub curve25519_ristretto_subtract_cost: u64, + /// Number of compute units consumed to multiply a curve25519 ristretto point + pub curve25519_ristretto_multiply_cost: u64, + /// Number of compute units consumed for a multiscalar multiplication (msm) of ristretto points. + /// The total cost is calculated as `msm_base_cost + (length - 1) * msm_incremental_cost`. + pub curve25519_ristretto_msm_base_cost: u64, + /// Number of compute units consumed for a multiscalar multiplication (msm) of ristretto points. + /// The total cost is calculated as `msm_base_cost + (length - 1) * msm_incremental_cost`. + pub curve25519_ristretto_msm_incremental_cost: u64, + /// program heap region size, default: solana_sdk::entrypoint::HEAP_LENGTH + pub heap_size: u32, + /// Number of compute units per additional 32k heap above the default (~.5 + /// us per 32k at 15 units/us rounded up) + pub heap_cost: u64, + /// Memory operation syscall base cost + pub mem_op_base_cost: u64, + /// Number of compute units consumed to call alt_bn128_addition + pub alt_bn128_addition_cost: u64, + /// Number of compute units consumed to call alt_bn128_multiplication. + pub alt_bn128_multiplication_cost: u64, + /// Total cost will be alt_bn128_pairing_one_pair_cost_first + /// + alt_bn128_pairing_one_pair_cost_other * (num_elems - 1) + pub alt_bn128_pairing_one_pair_cost_first: u64, + pub alt_bn128_pairing_one_pair_cost_other: u64, + /// Big integer modular exponentiation base cost + pub big_modular_exponentiation_base_cost: u64, + /// Big integer moduler exponentiation cost divisor + /// The modular exponentiation cost is computed as + /// `input_length`/`big_modular_exponentiation_cost_divisor` + `big_modular_exponentiation_base_cost` + pub big_modular_exponentiation_cost_divisor: u64, + /// Coefficient `a` of the quadratic function which determines the number + /// of compute units consumed to call poseidon syscall for a given number + /// of inputs. + pub poseidon_cost_coefficient_a: u64, + /// Coefficient `c` of the quadratic function which determines the number + /// of compute units consumed to call poseidon syscall for a given number + /// of inputs. + pub poseidon_cost_coefficient_c: u64, + /// Number of compute units consumed for accessing the remaining compute units. + pub get_remaining_compute_units_cost: u64, + /// Number of compute units consumed to call alt_bn128_g1_compress. + pub alt_bn128_g1_compress: u64, + /// Number of compute units consumed to call alt_bn128_g1_decompress. + pub alt_bn128_g1_decompress: u64, + /// Number of compute units consumed to call alt_bn128_g2_compress. + pub alt_bn128_g2_compress: u64, + /// Number of compute units consumed to call alt_bn128_g2_decompress. + pub alt_bn128_g2_decompress: u64, +} + +impl Default for SVMTransactionExecutionBudget { + fn default() -> Self { + Self::new(MAX_COMPUTE_UNIT_LIMIT as u64) + } +} + +impl SVMTransactionExecutionBudget { + #[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))] + fn new(compute_unit_limit: u64) -> Self { + SVMTransactionExecutionBudget { + compute_unit_limit, + log_64_units: 100, + create_program_address_units: 1500, + invoke_units: 1000, + max_instruction_stack_depth: MAX_INSTRUCTION_STACK_DEPTH, + max_instruction_trace_length: 64, + sha256_base_cost: 85, + sha256_byte_cost: 1, + sha256_max_slices: 20_000, + max_call_depth: MAX_CALL_DEPTH, + stack_frame_size: STACK_FRAME_SIZE, + log_pubkey_units: 100, + max_cpi_instruction_size: 1280, // IPv6 Min MTU size + cpi_bytes_per_unit: 250, // ~50MB at 200,000 units + sysvar_base_cost: 100, + secp256k1_recover_cost: 25_000, + syscall_base_cost: 100, + curve25519_edwards_validate_point_cost: 159, + curve25519_edwards_add_cost: 473, + curve25519_edwards_subtract_cost: 475, + curve25519_edwards_multiply_cost: 2_177, + curve25519_edwards_msm_base_cost: 2_273, + curve25519_edwards_msm_incremental_cost: 758, + curve25519_ristretto_validate_point_cost: 169, + curve25519_ristretto_add_cost: 521, + curve25519_ristretto_subtract_cost: 519, + curve25519_ristretto_multiply_cost: 2_208, + curve25519_ristretto_msm_base_cost: 2303, + curve25519_ristretto_msm_incremental_cost: 788, + heap_size: u32::try_from(solana_program_entrypoint::HEAP_LENGTH).unwrap(), + heap_cost: DEFAULT_HEAP_COST, + mem_op_base_cost: 10, + alt_bn128_addition_cost: 334, + alt_bn128_multiplication_cost: 3_840, + alt_bn128_pairing_one_pair_cost_first: 36_364, + alt_bn128_pairing_one_pair_cost_other: 12_121, + big_modular_exponentiation_base_cost: 190, + big_modular_exponentiation_cost_divisor: 2, + poseidon_cost_coefficient_a: 61, + poseidon_cost_coefficient_c: 542, + get_remaining_compute_units_cost: 100, + alt_bn128_g1_compress: 30, + alt_bn128_g1_decompress: 398, + alt_bn128_g2_compress: 86, + alt_bn128_g2_decompress: 13610, + } + } + + /// Returns cost of the Poseidon hash function for the given number of + /// inputs is determined by the following quadratic function: + /// + /// 61*n^2 + 542 + /// + /// Which aproximates the results of benchmarks of light-posiedon + /// library[0]. These results assume 1 CU per 33 ns. Examples: + /// + /// * 1 input + /// * light-poseidon benchmark: `18,303 / 33 ≈ 555` + /// * function: `61*1^2 + 542 = 603` + /// * 2 inputs + /// * light-poseidon benchmark: `25,866 / 33 ≈ 784` + /// * function: `61*2^2 + 542 = 786` + /// * 3 inputs + /// * light-poseidon benchmark: `37,549 / 33 ≈ 1,138` + /// * function; `61*3^2 + 542 = 1091` + /// + /// [0] https://github.com/Lightprotocol/light-poseidon#performance + pub fn poseidon_cost(&self, nr_inputs: u64) -> Option { + let squared_inputs = nr_inputs.checked_pow(2)?; + let mul_result = self + .poseidon_cost_coefficient_a + .checked_mul(squared_inputs)?; + let final_result = mul_result.checked_add(self.poseidon_cost_coefficient_c)?; + + Some(final_result) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct SVMTransactionComputeBudgetAndLimits { + pub budget: SVMTransactionExecutionBudget, + pub loaded_accounts_bytes: NonZeroU32, + pub priority_fee: u64, +} + +#[cfg(feature = "dev-context-only-utils")] +impl Default for SVMTransactionComputeBudgetAndLimits { + fn default() -> Self { + Self { + budget: SVMTransactionExecutionBudget::default(), + loaded_accounts_bytes: NonZeroU32::new(64 * 1024 * 1024).unwrap(), + priority_fee: 0, + } + } +} diff --git a/program-runtime/src/invoke_context.rs b/program-runtime/src/invoke_context.rs index 65c9cd1638827e..40b8cdb09bd0e6 100644 --- a/program-runtime/src/invoke_context.rs +++ b/program-runtime/src/invoke_context.rs @@ -1,5 +1,6 @@ use { crate::{ + execution_budget::SVMTransactionExecutionBudget, loaded_programs::{ ProgramCacheEntry, ProgramCacheEntryType, ProgramCacheForTxBatch, ProgramRuntimeEnvironments, @@ -9,7 +10,6 @@ use { }, solana_account::{create_account_shared_data_for_test, AccountSharedData}, solana_clock::Slot, - solana_compute_budget::compute_budget::ComputeBudget, solana_epoch_schedule::EpochSchedule, solana_feature_set::{ lift_cpi_caller_restriction, move_precompile_verification_to_svm, @@ -194,7 +194,7 @@ pub struct InvokeContext<'a> { /// Runtime configurations used to provision the invocation environment. pub environment_config: EnvironmentConfig<'a>, /// The compute budget for the current invocation. - compute_budget: ComputeBudget, + compute_budget: SVMTransactionExecutionBudget, /// Instruction compute meter, for tracking compute units consumed against /// the designated compute budget during program execution. compute_meter: RefCell, @@ -213,7 +213,7 @@ impl<'a> InvokeContext<'a> { program_cache_for_tx_batch: &'a mut ProgramCacheForTxBatch, environment_config: EnvironmentConfig<'a>, log_collector: Option>>, - compute_budget: ComputeBudget, + compute_budget: SVMTransactionExecutionBudget, ) -> Self { Self { transaction_context, @@ -627,7 +627,7 @@ impl<'a> InvokeContext<'a> { } /// Get this invocation's compute budget - pub fn get_compute_budget(&self) -> &ComputeBudget { + pub fn get_compute_budget(&self) -> &SVMTransactionExecutionBudget { &self.compute_budget } @@ -716,18 +716,18 @@ macro_rules! with_mock_invoke_context { $transaction_accounts:expr $(,)? ) => { use { - solana_compute_budget::compute_budget::ComputeBudget, solana_feature_set::FeatureSet, solana_log_collector::LogCollector, solana_type_overrides::sync::Arc, $crate::{ __private::{Hash, ReadableAccount, Rent, TransactionContext}, + execution_budget::SVMTransactionExecutionBudget, invoke_context::{EnvironmentConfig, InvokeContext}, loaded_programs::ProgramCacheForTxBatch, sysvar_cache::SysvarCache, }, }; - let compute_budget = ComputeBudget::default(); + let compute_budget = SVMTransactionExecutionBudget::default(); let mut $transaction_context = TransactionContext::new( $transaction_accounts, Rent::default(), @@ -852,9 +852,9 @@ pub fn mock_process_instruction Self; fn hash(&mut self, val: &[u8]); fn result(self) -> Self::Output; - fn get_base_cost(compute_budget: &ComputeBudget) -> u64; - fn get_byte_cost(compute_budget: &ComputeBudget) -> u64; - fn get_max_slices(compute_budget: &ComputeBudget) -> u64; + fn get_base_cost(compute_budget: &SVMTransactionExecutionBudget) -> u64; + fn get_byte_cost(compute_budget: &SVMTransactionExecutionBudget) -> u64; + fn get_max_slices(compute_budget: &SVMTransactionExecutionBudget) -> u64; } struct Sha256Hasher(Hasher); @@ -165,13 +166,13 @@ impl HasherImpl for Sha256Hasher { self.0.result() } - fn get_base_cost(compute_budget: &ComputeBudget) -> u64 { + fn get_base_cost(compute_budget: &SVMTransactionExecutionBudget) -> u64 { compute_budget.sha256_base_cost } - fn get_byte_cost(compute_budget: &ComputeBudget) -> u64 { + fn get_byte_cost(compute_budget: &SVMTransactionExecutionBudget) -> u64 { compute_budget.sha256_byte_cost } - fn get_max_slices(compute_budget: &ComputeBudget) -> u64 { + fn get_max_slices(compute_budget: &SVMTransactionExecutionBudget) -> u64 { compute_budget.sha256_max_slices } } @@ -192,13 +193,13 @@ impl HasherImpl for Blake3Hasher { self.0.result() } - fn get_base_cost(compute_budget: &ComputeBudget) -> u64 { + fn get_base_cost(compute_budget: &SVMTransactionExecutionBudget) -> u64 { compute_budget.sha256_base_cost } - fn get_byte_cost(compute_budget: &ComputeBudget) -> u64 { + fn get_byte_cost(compute_budget: &SVMTransactionExecutionBudget) -> u64 { compute_budget.sha256_byte_cost } - fn get_max_slices(compute_budget: &ComputeBudget) -> u64 { + fn get_max_slices(compute_budget: &SVMTransactionExecutionBudget) -> u64 { compute_budget.sha256_max_slices } } @@ -219,13 +220,13 @@ impl HasherImpl for Keccak256Hasher { self.0.result() } - fn get_base_cost(compute_budget: &ComputeBudget) -> u64 { + fn get_base_cost(compute_budget: &SVMTransactionExecutionBudget) -> u64 { compute_budget.sha256_base_cost } - fn get_byte_cost(compute_budget: &ComputeBudget) -> u64 { + fn get_byte_cost(compute_budget: &SVMTransactionExecutionBudget) -> u64 { compute_budget.sha256_byte_cost } - fn get_max_slices(compute_budget: &ComputeBudget) -> u64 { + fn get_max_slices(compute_budget: &SVMTransactionExecutionBudget) -> u64 { compute_budget.sha256_max_slices } } @@ -331,7 +332,7 @@ pub(crate) fn morph_into_deployment_environment_v1( pub fn create_program_runtime_environment_v1<'a>( feature_set: &FeatureSet, - compute_budget: &ComputeBudget, + compute_budget: &SVMTransactionExecutionBudget, reject_deployment_of_broken_elfs: bool, debugging_features: bool, ) -> Result>, Error> { @@ -568,7 +569,7 @@ pub fn create_program_runtime_environment_v1<'a>( } pub fn create_program_runtime_environment_v2<'a>( - compute_budget: &ComputeBudget, + compute_budget: &SVMTransactionExecutionBudget, debugging_features: bool, ) -> BuiltinProgram> { let config = Config { @@ -4899,7 +4900,7 @@ mod tests { #[test] fn test_syscall_get_epoch_stake_total_stake() { let config = Config::default(); - let mut compute_budget = ComputeBudget::default(); + let mut compute_budget = SVMTransactionExecutionBudget::default(); let sysvar_cache = Arc::::default(); let expected_total_stake = 200_000_000_000_000u64; @@ -4942,7 +4943,7 @@ mod tests { #[test] fn test_syscall_get_epoch_stake_vote_account_stake() { let config = Config::default(); - let mut compute_budget = ComputeBudget::default(); + let mut compute_budget = SVMTransactionExecutionBudget::default(); let sysvar_cache = Arc::::default(); let expected_epoch_stake = 55_000_000_000u64; diff --git a/programs/bpf_loader/src/syscalls/sysvar.rs b/programs/bpf_loader/src/syscalls/sysvar.rs index a61b304feb208a..e50e1f0b5a3345 100644 --- a/programs/bpf_loader/src/syscalls/sysvar.rs +++ b/programs/bpf_loader/src/syscalls/sysvar.rs @@ -1,4 +1,4 @@ -use super::*; +use {super::*, solana_program_runtime::execution_budget::SVMTransactionExecutionBudget}; fn get_sysvar( sysvar: Result, InstructionError>, @@ -179,7 +179,7 @@ declare_builtin_function!( memory_mapping: &mut MemoryMapping, ) -> Result { let check_aligned = invoke_context.get_check_aligned(); - let ComputeBudget { + let SVMTransactionExecutionBudget { sysvar_base_cost, cpi_bytes_per_unit, mem_op_base_cost, diff --git a/programs/loader-v4/Cargo.toml b/programs/loader-v4/Cargo.toml index 1b5675eab346e9..48e4b359a1cc16 100644 --- a/programs/loader-v4/Cargo.toml +++ b/programs/loader-v4/Cargo.toml @@ -14,7 +14,6 @@ qualifier_attr = { workspace = true } solana-account = { workspace = true } solana-bincode = { workspace = true } solana-bpf-loader-program = { workspace = true, features = ["svm-internal"] } -solana-compute-budget = { workspace = true } solana-instruction = { workspace = true } solana-loader-v3-interface = { workspace = true } solana-loader-v4-interface = { workspace = true, features = ["serde"] } diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 5ddd01633bba67..56186c2e7d1f77 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -5353,7 +5353,6 @@ dependencies = [ "solana-blake3-hasher", "solana-bn254", "solana-clock", - "solana-compute-budget", "solana-cpi", "solana-curve25519", "solana-feature-set", @@ -5630,7 +5629,7 @@ name = "solana-compute-budget" version = "2.3.0" dependencies = [ "solana-fee-structure", - "solana-program-entrypoint", + "solana-program-runtime", ] [[package]] @@ -5645,6 +5644,7 @@ dependencies = [ "solana-feature-set", "solana-instruction", "solana-packet", + "solana-program-runtime", "solana-pubkey", "solana-sdk-ids", "solana-svm-transaction", @@ -5828,6 +5828,7 @@ dependencies = [ "solana-fee-structure", "solana-metrics", "solana-packet", + "solana-program-runtime", "solana-pubkey", "solana-runtime-transaction", "solana-sdk-ids", @@ -6513,7 +6514,6 @@ dependencies = [ "solana-account", "solana-bincode", "solana-bpf-loader-program", - "solana-compute-budget", "solana-instruction", "solana-loader-v3-interface", "solana-loader-v4-interface", @@ -6950,7 +6950,6 @@ dependencies = [ "serde", "solana-account", "solana-clock", - "solana-compute-budget", "solana-epoch-rewards", "solana-epoch-schedule", "solana-feature-set", @@ -8432,7 +8431,6 @@ dependencies = [ "solana-account", "solana-bpf-loader-program", "solana-clock", - "solana-compute-budget", "solana-feature-set", "solana-fee-structure", "solana-hash", diff --git a/programs/zk-token-proof-tests/Cargo.toml b/programs/zk-token-proof-tests/Cargo.toml index 27a8192caa845c..c8abde07aead0a 100644 --- a/programs/zk-token-proof-tests/Cargo.toml +++ b/programs/zk-token-proof-tests/Cargo.toml @@ -15,6 +15,7 @@ solana-compute-budget = { workspace = true } solana-compute-budget-interface = { workspace = true } solana-instruction = { workspace = true } solana-keypair = { workspace = true } +solana-program-runtime = { workspace = true } solana-program-test = { workspace = true } solana-pubkey = { workspace = true } solana-signer = { workspace = true } diff --git a/programs/zk-token-proof-tests/tests/process_transaction.rs b/programs/zk-token-proof-tests/tests/process_transaction.rs index 8e22f9fa339e75..332b4b9dccb5e2 100644 --- a/programs/zk-token-proof-tests/tests/process_transaction.rs +++ b/programs/zk-token-proof-tests/tests/process_transaction.rs @@ -1716,7 +1716,7 @@ impl WithMaxComputeUnitLimit for Vec { fn with_max_compute_unit_limit(mut self) -> Self { self.push( solana_compute_budget_interface::ComputeBudgetInstruction::set_compute_unit_limit( - solana_compute_budget::compute_budget_limits::MAX_COMPUTE_UNIT_LIMIT, + solana_program_runtime::execution_budget::MAX_COMPUTE_UNIT_LIMIT, ), ); self diff --git a/runtime/src/account_saver.rs b/runtime/src/account_saver.rs index 0605f5a2070205..d73d9b85a6dc9d 100644 --- a/runtime/src/account_saver.rs +++ b/runtime/src/account_saver.rs @@ -177,7 +177,7 @@ fn collect_accounts_for_failed_tx<'a, T: SVMMessage>( mod tests { use { super::*, - solana_compute_budget::compute_budget_limits::ComputeBudgetLimits, + solana_program_runtime::execution_budget::SVMTransactionExecutionBudget, solana_sdk::{ account::{AccountSharedData, ReadableAccount}, fee::FeeDetails, @@ -279,7 +279,7 @@ mod tests { program_indices: vec![], fee_details: FeeDetails::default(), rollback_accounts: RollbackAccounts::default(), - compute_budget_limits: ComputeBudgetLimits::default(), + compute_budget: SVMTransactionExecutionBudget::default(), rent: 0, rent_debits: RentDebits::default(), loaded_accounts_data_size: 0, @@ -290,7 +290,7 @@ mod tests { program_indices: vec![], fee_details: FeeDetails::default(), rollback_accounts: RollbackAccounts::default(), - compute_budget_limits: ComputeBudgetLimits::default(), + compute_budget: SVMTransactionExecutionBudget::default(), rent: 0, rent_debits: RentDebits::default(), loaded_accounts_data_size: 0, @@ -353,7 +353,7 @@ mod tests { rollback_accounts: RollbackAccounts::FeePayerOnly { fee_payer_account: from_account_pre.clone(), }, - compute_budget_limits: ComputeBudgetLimits::default(), + compute_budget: SVMTransactionExecutionBudget::default(), rent: 0, rent_debits: RentDebits::default(), loaded_accounts_data_size: 0, @@ -448,7 +448,7 @@ mod tests { nonce: nonce.clone(), fee_payer_account: from_account_pre.clone(), }, - compute_budget_limits: ComputeBudgetLimits::default(), + compute_budget: SVMTransactionExecutionBudget::default(), rent: 0, rent_debits: RentDebits::default(), loaded_accounts_data_size: 0, @@ -556,7 +556,7 @@ mod tests { rollback_accounts: RollbackAccounts::SameNonceAndFeePayer { nonce: nonce.clone(), }, - compute_budget_limits: ComputeBudgetLimits::default(), + compute_budget: SVMTransactionExecutionBudget::default(), rent: 0, rent_debits: RentDebits::default(), loaded_accounts_data_size: 0, diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 3c78a5bccda656..f083d4e8e7a11f 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -3228,7 +3228,6 @@ impl Bank { TransactionProcessingConfig { account_overrides: Some(&account_overrides), check_program_modification_slot: self.check_program_modification_slot, - compute_budget: self.compute_budget(), log_messages_bytes_limit: None, limit_to_load_programs: true, recording_config: ExecutionRecordingConfig { @@ -4568,7 +4567,6 @@ impl Bank { TransactionProcessingConfig { account_overrides: None, check_program_modification_slot: self.check_program_modification_slot, - compute_budget: self.compute_budget(), log_messages_bytes_limit, limit_to_load_programs: false, recording_config, diff --git a/runtime/src/bank/check_transactions.rs b/runtime/src/bank/check_transactions.rs index b27555df15470f..ea2addeb5ce9d6 100644 --- a/runtime/src/bank/check_transactions.rs +++ b/runtime/src/bank/check_transactions.rs @@ -1,9 +1,9 @@ use { super::{Bank, BankStatusCache}, solana_accounts_db::blockhash_queue::BlockhashQueue, - solana_compute_budget::compute_budget_limits::ComputeBudgetLimits, solana_compute_budget_instruction::instructions_processor::process_compute_budget_instructions, solana_perf::perf_libs, + solana_program_runtime::execution_budget::SVMTransactionComputeBudgetAndLimits, solana_runtime_transaction::transaction_with_meta::TransactionWithMeta, solana_sdk::{ account::AccountSharedData, @@ -97,10 +97,17 @@ impl Bank { .zip(lock_results) .map(|(tx, lock_res)| match lock_res { Ok(()) => { - let compute_budget_limits = process_compute_budget_instructions( + let compute_budget_and_limits = process_compute_budget_instructions( tx.borrow().program_instructions_iter(), &self.feature_set, - ); + ) + .map(|limit| { + if let Some(compute_budget) = self.compute_budget { + limit.get_limits_using_compute_budget(compute_budget) + } else { + limit.get_compute_budget_and_limits() + } + }); self.check_transaction_age( tx.borrow(), max_age, @@ -108,7 +115,7 @@ impl Bank { &hash_queue, next_lamports_per_signature, error_counters, - compute_budget_limits, + compute_budget_and_limits, ) } Err(e) => Err(e.clone()), @@ -124,14 +131,14 @@ impl Bank { hash_queue: &BlockhashQueue, next_lamports_per_signature: u64, error_counters: &mut TransactionErrorMetrics, - compute_budget_limits: Result, + compute_budget: Result, ) -> TransactionCheckResult { let recent_blockhash = tx.recent_blockhash(); if let Some(hash_info) = hash_queue.get_hash_info_if_valid(recent_blockhash, max_age) { Ok(CheckedTransactionDetails::new( None, hash_info.lamports_per_signature(), - compute_budget_limits, + compute_budget, )) } else if let Some((nonce, previous_lamports_per_signature)) = self .check_load_and_advance_message_nonce_account( @@ -143,7 +150,7 @@ impl Bank { Ok(CheckedTransactionDetails::new( Some(nonce), previous_lamports_per_signature, - compute_budget_limits, + compute_budget, )) } else { error_counters.blockhash_not_found += 1; diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 1c88b586f70529..644643e2062ced 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -36,8 +36,7 @@ use { ancestors::Ancestors, }, solana_compute_budget::{ - compute_budget::ComputeBudget, - compute_budget_limits::{self, ComputeBudgetLimits, MAX_COMPUTE_UNIT_LIMIT}, + compute_budget::ComputeBudget, compute_budget_limits::ComputeBudgetLimits, }, solana_cost_model::block_cost_limits::{MAX_BLOCK_UNITS, MAX_BLOCK_UNITS_SIMD_0207}, solana_feature_set::{self as feature_set, FeatureSet}, @@ -45,6 +44,7 @@ use { solana_logger, solana_program_runtime::{ declare_process_instruction, + execution_budget::{self, MAX_COMPUTE_UNIT_LIMIT}, loaded_programs::{ProgramCacheEntry, ProgramCacheEntryType}, }, solana_sdk::{ @@ -9961,7 +9961,7 @@ fn test_compute_budget_program_noop() { *compute_budget, ComputeBudget { compute_unit_limit: u64::from( - compute_budget_limits::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT + execution_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT ), heap_size: 48 * 1024, ..ComputeBudget::default() @@ -9973,7 +9973,7 @@ fn test_compute_budget_program_noop() { let message = Message::new( &[ ComputeBudgetInstruction::set_compute_unit_limit( - compute_budget_limits::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, + execution_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, ), ComputeBudgetInstruction::request_heap_frame(48 * 1024), Instruction::new_with_bincode(program_id, &0, vec![]), @@ -10006,7 +10006,7 @@ fn test_compute_request_instruction() { *compute_budget, ComputeBudget { compute_unit_limit: u64::from( - compute_budget_limits::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT + execution_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT ), heap_size: 48 * 1024, ..ComputeBudget::default() @@ -10018,7 +10018,7 @@ fn test_compute_request_instruction() { let message = Message::new( &[ ComputeBudgetInstruction::set_compute_unit_limit( - compute_budget_limits::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, + execution_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, ), ComputeBudgetInstruction::request_heap_frame(48 * 1024), Instruction::new_with_bincode(program_id, &0, vec![]), @@ -10059,7 +10059,7 @@ fn test_failed_compute_request_instruction() { *compute_budget, ComputeBudget { compute_unit_limit: u64::from( - compute_budget_limits::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT + execution_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT ), heap_size: 48 * 1024, ..ComputeBudget::default() diff --git a/svm/Cargo.toml b/svm/Cargo.toml index aa54d1a0aee905..717a5ea3bbe2a4 100644 --- a/svm/Cargo.toml +++ b/svm/Cargo.toml @@ -20,7 +20,6 @@ serde_derive = { workspace = true } solana-account = { workspace = true } solana-bpf-loader-program = { workspace = true } solana-clock = { workspace = true } -solana-compute-budget = { workspace = true } solana-feature-set = { workspace = true } solana-fee-structure = { workspace = true } solana-frozen-abi = { workspace = true, optional = true, features = [ @@ -69,7 +68,6 @@ prost = { workspace = true } rand0-7 = { workspace = true } shuttle = { workspace = true } solana-clock = { workspace = true } -solana-compute-budget = { workspace = true, features = ["dev-context-only-utils"] } solana-compute-budget-instruction = { workspace = true } solana-compute-budget-interface = { workspace = true } solana-compute-budget-program = { workspace = true } @@ -79,6 +77,7 @@ solana-fee-calculator = { workspace = true } solana-keypair = { workspace = true } solana-logger = { workspace = true } solana-native-token = { workspace = true } +solana-program-runtime = { workspace = true, features = ["dev-context-only-utils"] } solana-pubkey = { workspace = true } solana-rent = { workspace = true } solana-reserved-account-keys = { workspace = true } @@ -105,7 +104,6 @@ dev-context-only-utils = ["dep:qualifier_attr"] frozen-abi = [ "dep:solana-frozen-abi", "dep:solana-frozen-abi-macro", - "solana-compute-budget/frozen-abi", "solana-program-runtime/frozen-abi", "solana-sdk/frozen-abi", ] diff --git a/svm/examples/Cargo.lock b/svm/examples/Cargo.lock index 6668e9967ea377..aeb1b98870cfcf 100644 --- a/svm/examples/Cargo.lock +++ b/svm/examples/Cargo.lock @@ -5206,7 +5206,6 @@ dependencies = [ "solana-blake3-hasher", "solana-bn254", "solana-clock", - "solana-compute-budget", "solana-cpi", "solana-curve25519", "solana-feature-set", @@ -5483,7 +5482,7 @@ name = "solana-compute-budget" version = "2.3.0" dependencies = [ "solana-fee-structure", - "solana-program-entrypoint", + "solana-program-runtime", ] [[package]] @@ -5498,6 +5497,7 @@ dependencies = [ "solana-feature-set", "solana-instruction", "solana-packet", + "solana-program-runtime", "solana-pubkey", "solana-sdk-ids", "solana-svm-transaction", @@ -5681,6 +5681,7 @@ dependencies = [ "solana-fee-structure", "solana-metrics", "solana-packet", + "solana-program-runtime", "solana-pubkey", "solana-runtime-transaction", "solana-sdk-ids", @@ -6332,7 +6333,6 @@ dependencies = [ "solana-account", "solana-bincode", "solana-bpf-loader-program", - "solana-compute-budget", "solana-instruction", "solana-loader-v3-interface", "solana-loader-v4-interface", @@ -6765,11 +6765,11 @@ dependencies = [ "itertools 0.12.1", "log", "percentage", + "qualifier_attr", "rand 0.8.5", "serde", "solana-account", "solana-clock", - "solana-compute-budget", "solana-epoch-rewards", "solana-epoch-schedule", "solana-feature-set", @@ -7750,7 +7750,6 @@ dependencies = [ "solana-account", "solana-bpf-loader-program", "solana-clock", - "solana-compute-budget", "solana-feature-set", "solana-fee-structure", "solana-hash", diff --git a/svm/examples/json-rpc/server/src/rpc_process.rs b/svm/examples/json-rpc/server/src/rpc_process.rs index 8144cae156759d..75bc7a389a4412 100644 --- a/svm/examples/json-rpc/server/src/rpc_process.rs +++ b/svm/examples/json-rpc/server/src/rpc_process.rs @@ -15,11 +15,10 @@ use { parse_token::{get_token_account_mint, is_known_spl_token_id}, UiAccount, UiAccountEncoding, UiDataSliceConfig, MAX_BASE58_BYTES, }, - solana_compute_budget::{ - compute_budget::ComputeBudget, compute_budget_limits::ComputeBudgetLimits, - }, solana_perf::packet::PACKET_DATA_SIZE, - solana_program_runtime::loaded_programs::ProgramCacheEntry, + solana_program_runtime::{ + execution_budget::SVMTransactionComputeBudgetAndLimits, loaded_programs::ProgramCacheEntry, + }, solana_rpc_client_api::{ config::*, response::{Response as RpcResponse, *}, @@ -326,7 +325,6 @@ impl JsonRpcRequestProcessor { TransactionProcessingConfig { account_overrides: Some(&account_overrides), check_program_modification_slot: false, - compute_budget: Some(ComputeBudget::default()), log_messages_bytes_limit: None, limit_to_load_programs: true, recording_config: ExecutionRecordingConfig { @@ -428,7 +426,7 @@ impl JsonRpcRequestProcessor { Ok(CheckedTransactionDetails::new( None, u64::default(), - Ok(ComputeBudgetLimits::default()), + Ok(SVMTransactionComputeBudgetAndLimits::default()), )) } diff --git a/svm/examples/paytube/Cargo.toml b/svm/examples/paytube/Cargo.toml index 9f593e07e00d66..465a5448304617 100644 --- a/svm/examples/paytube/Cargo.toml +++ b/svm/examples/paytube/Cargo.toml @@ -10,7 +10,7 @@ solana-bpf-loader-program = { workspace = true } solana-client = { workspace = true } solana-compute-budget = { workspace = true } solana-logger = { workspace = true } -solana-program-runtime = { workspace = true } +solana-program-runtime = { workspace = true, features = ["dev-context-only-utils"] } solana-sdk = { workspace = true } solana-svm = { workspace = true } solana-system-program = { workspace = true } diff --git a/svm/examples/paytube/src/lib.rs b/svm/examples/paytube/src/lib.rs index a219f7e783d314..e65bafd9eea9b1 100644 --- a/svm/examples/paytube/src/lib.rs +++ b/svm/examples/paytube/src/lib.rs @@ -67,7 +67,7 @@ use { create_transaction_batch_processor, get_transaction_check_results, PayTubeForkGraph, }, solana_client::rpc_client::RpcClient, - solana_compute_budget::compute_budget::ComputeBudget, + solana_program_runtime::execution_budget::SVMTransactionExecutionBudget, solana_sdk::{ feature_set::FeatureSet, fee::FeeStructure, hash::Hash, rent_collector::RentCollector, signature::Keypair, @@ -114,7 +114,7 @@ impl PayTubeChannel { // would likely be hoisted from the cluster. // // For example purposes, they are provided as defaults here. - let compute_budget = ComputeBudget::default(); + let compute_budget = SVMTransactionExecutionBudget::default(); let feature_set = FeatureSet::all_enabled(); let fee_structure = FeeStructure::default(); let rent_collector = RentCollector::default(); @@ -157,10 +157,7 @@ impl PayTubeChannel { // The PayTube transaction processing config for Solana SVM. // // Extended configurations for even more customization of the SVM API. - let processing_config = TransactionProcessingConfig { - compute_budget: Some(compute_budget), - ..Default::default() - }; + let processing_config = TransactionProcessingConfig::default(); // Step 1: Convert the batch of PayTube transactions into // SVM-compatible transactions for processing. diff --git a/svm/examples/paytube/src/processor.rs b/svm/examples/paytube/src/processor.rs index da76454075b915..2fa153e244eee7 100644 --- a/svm/examples/paytube/src/processor.rs +++ b/svm/examples/paytube/src/processor.rs @@ -2,10 +2,11 @@ use { solana_bpf_loader_program::syscalls::create_program_runtime_environment_v1, - solana_compute_budget::{ - compute_budget::ComputeBudget, compute_budget_limits::ComputeBudgetLimits, + solana_compute_budget::compute_budget_limits::ComputeBudgetLimits, + solana_program_runtime::{ + execution_budget::SVMTransactionExecutionBudget, + loaded_programs::{BlockRelation, ForkGraph, ProgramCacheEntry}, }, - solana_program_runtime::loaded_programs::{BlockRelation, ForkGraph, ProgramCacheEntry}, solana_sdk::{clock::Slot, feature_set::FeatureSet, transaction}, solana_svm::{ account_loader::CheckedTransactionDetails, @@ -37,7 +38,7 @@ impl ForkGraph for PayTubeForkGraph { pub(crate) fn create_transaction_batch_processor( callbacks: &CB, feature_set: &FeatureSet, - compute_budget: &ComputeBudget, + compute_budget: &SVMTransactionExecutionBudget, fork_graph: Arc>, ) -> TransactionBatchProcessor { // Create a new transaction batch processor. @@ -98,7 +99,7 @@ pub(crate) fn get_transaction_check_results( transaction::Result::Ok(CheckedTransactionDetails::new( None, lamports_per_signature, - Ok(ComputeBudgetLimits::default()) + Ok(ComputeBudgetLimits::default_compute_budget_and_limits()) )); len ] diff --git a/svm/src/account_loader.rs b/svm/src/account_loader.rs index 218e8241fafb1d..6aecd581eaefe5 100644 --- a/svm/src/account_loader.rs +++ b/svm/src/account_loader.rs @@ -13,13 +13,15 @@ use { solana_account::{ Account, AccountSharedData, ReadableAccount, WritableAccount, PROGRAM_OWNERS, }, - solana_compute_budget::compute_budget_limits::ComputeBudgetLimits, solana_feature_set::{self as feature_set, FeatureSet}, solana_fee_structure::FeeDetails, solana_instruction::{BorrowedAccountMeta, BorrowedInstruction}, solana_instructions_sysvar::construct_instructions_data, solana_nonce::state::State as NonceState, solana_nonce_account::{get_system_account_kind, SystemAccountKind}, + solana_program_runtime::execution_budget::{ + SVMTransactionComputeBudgetAndLimits, SVMTransactionExecutionBudget, + }, solana_pubkey::Pubkey, solana_rent::RentDue, solana_rent_debits::RentDebits, @@ -47,7 +49,7 @@ type TransactionValidationResult = Result; #[derive(PartialEq, Eq, Debug)] pub(crate) enum TransactionLoadResult { /// All transaction accounts were loaded successfully - Loaded(LoadedTransaction), + Loaded(Box), /// Some transaction accounts needed for execution were unable to be loaded /// but the fee payer and any nonce account needed for fee collection were /// loaded successfully @@ -65,7 +67,7 @@ pub(crate) enum TransactionLoadResult { pub struct CheckedTransactionDetails { pub(crate) nonce: Option, pub(crate) lamports_per_signature: u64, - pub(crate) compute_budget_limits: Result, + pub(crate) compute_budget_and_limits: Result, } #[cfg(feature = "dev-context-only-utils")] @@ -74,7 +76,12 @@ impl Default for CheckedTransactionDetails { Self { nonce: None, lamports_per_signature: 0, - compute_budget_limits: Ok(ComputeBudgetLimits::default()), + compute_budget_and_limits: Ok(SVMTransactionComputeBudgetAndLimits { + budget: SVMTransactionExecutionBudget::default(), + loaded_accounts_bytes: NonZeroU32::new(32) + .expect("Failed to set loaded_accounts_bytes"), + priority_fee: 0, + }), } } } @@ -83,25 +90,38 @@ impl CheckedTransactionDetails { pub fn new( nonce: Option, lamports_per_signature: u64, - compute_budget_limits: Result, + compute_budget_and_limits: Result, ) -> Self { Self { nonce, lamports_per_signature, - compute_budget_limits, + compute_budget_and_limits, } } } #[derive(PartialEq, Eq, Debug, Clone)] -#[cfg_attr(feature = "dev-context-only-utils", derive(Default))] pub(crate) struct ValidatedTransactionDetails { pub(crate) rollback_accounts: RollbackAccounts, - pub(crate) compute_budget_limits: ComputeBudgetLimits, + pub(crate) compute_budget: SVMTransactionExecutionBudget, + pub(crate) loaded_accounts_bytes_limit: NonZeroU32, pub(crate) fee_details: FeeDetails, pub(crate) loaded_fee_payer_account: LoadedTransactionAccount, } +#[cfg(feature = "dev-context-only-utils")] +impl Default for ValidatedTransactionDetails { + fn default() -> Self { + Self { + rollback_accounts: RollbackAccounts::default(), + compute_budget: SVMTransactionExecutionBudget::default(), + loaded_accounts_bytes_limit: NonZeroU32::new(32).unwrap(), + fee_details: FeeDetails::default(), + loaded_fee_payer_account: LoadedTransactionAccount::default(), + } + } +} + #[derive(PartialEq, Eq, Debug, Clone)] #[cfg_attr(feature = "dev-context-only-utils", derive(Default))] pub(crate) struct LoadedTransactionAccount { @@ -116,8 +136,8 @@ pub(crate) struct LoadedTransactionAccount { feature = "dev-context-only-utils", field_qualifiers( program_indices(pub), - compute_budget_limits(pub), - loaded_accounts_data_size(pub) + loaded_accounts_data_size(pub), + compute_budget(pub) ) )] pub struct LoadedTransaction { @@ -125,7 +145,7 @@ pub struct LoadedTransaction { pub(crate) program_indices: TransactionProgramIndices, pub fee_details: FeeDetails, pub rollback_accounts: RollbackAccounts, - pub(crate) compute_budget_limits: ComputeBudgetLimits, + pub(crate) compute_budget: SVMTransactionExecutionBudget, pub rent: TransactionRent, pub rent_debits: RentDebits, pub(crate) loaded_accounts_data_size: u32, @@ -375,22 +395,24 @@ pub(crate) fn load_transaction( account_loader, message, tx_details.loaded_fee_payer_account, - &tx_details.compute_budget_limits, + tx_details.loaded_accounts_bytes_limit, error_metrics, rent_collector, ); match load_result { - Ok(loaded_tx_accounts) => TransactionLoadResult::Loaded(LoadedTransaction { - accounts: loaded_tx_accounts.accounts, - program_indices: loaded_tx_accounts.program_indices, - fee_details: tx_details.fee_details, - rent: loaded_tx_accounts.rent, - rent_debits: loaded_tx_accounts.rent_debits, - rollback_accounts: tx_details.rollback_accounts, - compute_budget_limits: tx_details.compute_budget_limits, - loaded_accounts_data_size: loaded_tx_accounts.loaded_accounts_data_size, - }), + Ok(loaded_tx_accounts) => { + TransactionLoadResult::Loaded(Box::new(LoadedTransaction { + accounts: loaded_tx_accounts.accounts, + program_indices: loaded_tx_accounts.program_indices, + fee_details: tx_details.fee_details, + rent: loaded_tx_accounts.rent, + rent_debits: loaded_tx_accounts.rent_debits, + rollback_accounts: tx_details.rollback_accounts, + compute_budget: tx_details.compute_budget, + loaded_accounts_data_size: loaded_tx_accounts.loaded_accounts_data_size, + })) + } Err(err) => TransactionLoadResult::FeesOnly(FeesOnlyTransaction { load_error: err, fee_details: tx_details.fee_details, @@ -414,7 +436,7 @@ fn load_transaction_accounts( account_loader: &mut AccountLoader, message: &impl SVMMessage, loaded_fee_payer_account: LoadedTransactionAccount, - compute_budget_limits: &ComputeBudgetLimits, + loaded_accounts_bytes_limit: NonZeroU32, error_metrics: &mut TransactionErrorMetrics, rent_collector: &dyn SVMRentCollector, ) -> Result { @@ -435,7 +457,7 @@ fn load_transaction_accounts( accumulate_and_check_loaded_account_data_size( &mut accumulated_accounts_data_size, loaded_size, - compute_budget_limits.loaded_accounts_bytes, + loaded_accounts_bytes_limit, error_metrics, )?; @@ -531,7 +553,7 @@ fn load_transaction_accounts( accumulate_and_check_loaded_account_data_size( &mut accumulated_accounts_data_size, owner_size, - compute_budget_limits.loaded_accounts_bytes, + loaded_accounts_bytes_limit, error_metrics, )?; validated_loaders.insert(*owner_id); @@ -662,7 +684,6 @@ mod tests { transaction_processing_callback::TransactionProcessingCallback, }, solana_account::{Account, AccountSharedData, ReadableAccount, WritableAccount}, - solana_compute_budget::{compute_budget::ComputeBudget, compute_budget_limits}, solana_epoch_schedule::EpochSchedule, solana_feature_set::FeatureSet, solana_hash::Hash, @@ -1350,7 +1371,7 @@ mod tests { account: fee_payer_account.clone(), rent_collected: fee_payer_rent_debit, }, - &ComputeBudgetLimits::default(), + NonZeroU32::new(32).unwrap(), &mut error_metrics, &RentCollector::default(), ); @@ -1412,7 +1433,7 @@ mod tests { account: fee_payer_account.clone(), ..LoadedTransactionAccount::default() }, - &ComputeBudgetLimits::default(), + NonZeroU32::new(32).unwrap(), &mut error_metrics, &RentCollector::default(), ); @@ -1469,7 +1490,7 @@ mod tests { &mut account_loader, sanitized_transaction.message(), LoadedTransactionAccount::default(), - &ComputeBudgetLimits::default(), + NonZeroU32::new(32).unwrap(), &mut error_metrics, &RentCollector::default(), ); @@ -1511,7 +1532,7 @@ mod tests { &mut account_loader, sanitized_transaction.message(), LoadedTransactionAccount::default(), - &ComputeBudgetLimits::default(), + NonZeroU32::new(32).unwrap(), &mut error_metrics, &RentCollector::default(), ); @@ -1567,7 +1588,7 @@ mod tests { account: fee_payer_account.clone(), ..LoadedTransactionAccount::default() }, - &ComputeBudgetLimits::default(), + NonZeroU32::new(32).unwrap(), &mut error_metrics, &RentCollector::default(), ); @@ -1628,7 +1649,7 @@ mod tests { &mut account_loader, sanitized_transaction.message(), LoadedTransactionAccount::default(), - &ComputeBudgetLimits::default(), + NonZeroU32::new(32).unwrap(), &mut error_metrics, &RentCollector::default(), ); @@ -1680,7 +1701,7 @@ mod tests { &mut account_loader, sanitized_transaction.message(), LoadedTransactionAccount::default(), - &ComputeBudgetLimits::default(), + NonZeroU32::new(32).unwrap(), &mut error_metrics, &RentCollector::default(), ); @@ -1743,7 +1764,7 @@ mod tests { account: fee_payer_account.clone(), ..LoadedTransactionAccount::default() }, - &ComputeBudgetLimits::default(), + NonZeroU32::new(32).unwrap(), &mut error_metrics, &RentCollector::default(), ); @@ -1826,7 +1847,7 @@ mod tests { account: fee_payer_account.clone(), ..LoadedTransactionAccount::default() }, - &ComputeBudgetLimits::default(), + NonZeroU32::new(32).unwrap(), &mut error_metrics, &RentCollector::default(), ); @@ -1894,8 +1915,8 @@ mod tests { panic!("transaction loading failed"); }; - let compute_budget = ComputeBudget::new(u64::from( - compute_budget_limits::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, + let compute_budget = SVMTransactionExecutionBudget::new(u64::from( + solana_program_runtime::execution_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, )); let rent_collector = RentCollector::default(); let transaction_context = TransactionContext::new( @@ -1992,7 +2013,7 @@ mod tests { panic!("transaction loading failed"); }; assert_eq!( - loaded_transaction, + *loaded_transaction, LoadedTransaction { accounts: vec![ ( @@ -2008,7 +2029,7 @@ mod tests { program_indices: vec![vec![1], vec![1]], fee_details: FeeDetails::default(), rollback_accounts: RollbackAccounts::default(), - compute_budget_limits: ComputeBudgetLimits::default(), + compute_budget: SVMTransactionExecutionBudget::default(), rent: 0, rent_debits: RentDebits::default(), loaded_accounts_data_size: 0, @@ -2340,7 +2361,7 @@ mod tests { loaded_size: fee_payer_size as usize, rent_collected: 0, }, - &ComputeBudgetLimits::default(), + NonZeroU32::new(64 * 1024 * 1024).unwrap(), &mut TransactionErrorMetrics::default(), &RentCollector::default(), ) diff --git a/svm/src/message_processor.rs b/svm/src/message_processor.rs index 87363eee8be1ea..cfeae7e94ba751 100644 --- a/svm/src/message_processor.rs +++ b/svm/src/message_processor.rs @@ -122,7 +122,6 @@ mod tests { }, rand0_7::thread_rng, solana_account::{AccountSharedData, ReadableAccount}, - solana_compute_budget::compute_budget::ComputeBudget, solana_ed25519_program::new_ed25519_instruction, solana_feature_set::FeatureSet, solana_hash::Hash, @@ -130,6 +129,7 @@ mod tests { solana_message::{AccountKeys, Message, SanitizedMessage}, solana_program_runtime::{ declare_process_instruction, + execution_budget::SVMTransactionExecutionBudget, invoke_context::EnvironmentConfig, loaded_programs::{ProgramCacheEntry, ProgramCacheForTxBatch}, sysvar_cache::SysvarCache, @@ -252,7 +252,7 @@ mod tests { &mut program_cache_for_tx_batch, environment_config, None, - ComputeBudget::default(), + SVMTransactionExecutionBudget::default(), ); let result = process_message( &message, @@ -306,7 +306,7 @@ mod tests { &mut program_cache_for_tx_batch, environment_config, None, - ComputeBudget::default(), + SVMTransactionExecutionBudget::default(), ); let result = process_message( &message, @@ -350,7 +350,7 @@ mod tests { &mut program_cache_for_tx_batch, environment_config, None, - ComputeBudget::default(), + SVMTransactionExecutionBudget::default(), ); let result = process_message( &message, @@ -485,7 +485,7 @@ mod tests { &mut program_cache_for_tx_batch, environment_config, None, - ComputeBudget::default(), + SVMTransactionExecutionBudget::default(), ); let result = process_message( &message, @@ -524,7 +524,7 @@ mod tests { &mut program_cache_for_tx_batch, environment_config, None, - ComputeBudget::default(), + SVMTransactionExecutionBudget::default(), ); let result = process_message( &message, @@ -560,7 +560,7 @@ mod tests { &mut program_cache_for_tx_batch, environment_config, None, - ComputeBudget::default(), + SVMTransactionExecutionBudget::default(), ); let result = process_message( &message, @@ -667,7 +667,7 @@ mod tests { &mut program_cache_for_tx_batch, environment_config, None, - ComputeBudget::default(), + SVMTransactionExecutionBudget::default(), ); let result = process_message( &message, diff --git a/svm/src/transaction_processor.rs b/svm/src/transaction_processor.rs index aed4bf84c50643..78cd065647e7c8 100644 --- a/svm/src/transaction_processor.rs +++ b/svm/src/transaction_processor.rs @@ -25,11 +25,10 @@ use { create_program_runtime_environment_v1, create_program_runtime_environment_v2, }, solana_clock::{Epoch, Slot}, - solana_compute_budget::compute_budget::ComputeBudget, solana_feature_set::{ enable_transaction_loading_failure_fees, remove_accounts_executable_flag_checks, FeatureSet, }, - solana_fee_structure::{FeeBudgetLimits, FeeDetails, FeeStructure}, + solana_fee_structure::{FeeDetails, FeeStructure}, solana_hash::Hash, solana_instruction::TRANSACTION_LEVEL_STACK_HEIGHT, solana_log_collector::LogCollector, @@ -40,6 +39,7 @@ use { versions::Versions as NonceVersions, }, solana_program_runtime::{ + execution_budget::SVMTransactionExecutionBudget, invoke_context::{EnvironmentConfig, InvokeContext}, loaded_programs::{ ForkGraph, ProgramCache, ProgramCacheEntry, ProgramCacheForTxBatch, @@ -111,8 +111,6 @@ pub struct TransactionProcessingConfig<'a> { /// Whether or not to check a program's modification slot when replenishing /// a program cache instance. pub check_program_modification_slot: bool, - /// The compute budget to use for transaction execution. - pub compute_budget: Option, /// The maximum number of bytes that log messages can consume. pub log_messages_bytes_limit: Option, /// Whether to limit the number of programs loaded for the transaction @@ -447,7 +445,7 @@ impl TransactionBatchProcessor { let executed_tx = self.execute_loaded_transaction( callbacks, tx, - loaded_transaction, + *loaded_transaction, &mut execute_timings, &mut error_metrics, &mut program_cache_for_tx_batch, @@ -526,7 +524,7 @@ impl TransactionBatchProcessor { if let CheckedTransactionDetails { nonce: Some(ref nonce_info), lamports_per_signature: _, - compute_budget_limits: _, + compute_budget_and_limits: _, } = checked_details { let next_durable_nonce = DurableNonce::from_blockhash(environment_blockhash); @@ -566,10 +564,10 @@ impl TransactionBatchProcessor { let CheckedTransactionDetails { nonce, lamports_per_signature, - compute_budget_limits, + compute_budget_and_limits, } = checked_details; - let compute_budget_limits = compute_budget_limits.inspect_err(|_err| { + let compute_budget_and_limits = compute_budget_and_limits.inspect_err(|_err| { error_counters.invalid_compute_budget += 1; })?; @@ -590,14 +588,13 @@ impl TransactionBatchProcessor { ) .rent_amount; - let fee_budget_limits = FeeBudgetLimits::from(compute_budget_limits); let fee_details = if lamports_per_signature == 0 { FeeDetails::default() } else { callbacks.calculate_fee( message, fee_lamports_per_signature, - fee_budget_limits.prioritization_fee, + compute_budget_and_limits.priority_fee, account_loader.feature_set.as_ref(), ) }; @@ -625,7 +622,8 @@ impl TransactionBatchProcessor { Ok(ValidatedTransactionDetails { fee_details, rollback_accounts, - compute_budget_limits, + loaded_accounts_bytes_limit: compute_budget_and_limits.loaded_accounts_bytes, + compute_budget: compute_budget_and_limits.budget, loaded_fee_payer_account: loaded_fee_payer, }) } @@ -822,7 +820,7 @@ impl TransactionBatchProcessor { &self, callbacks: &CB, upcoming_feature_set: &FeatureSet, - compute_budget: &ComputeBudget, + compute_budget: &SVMTransactionExecutionBudget, slot_index: u64, slots_in_epoch: u64, ) { @@ -941,9 +939,7 @@ impl TransactionBatchProcessor { let lamports_before_tx = transaction_accounts_lamports_sum(&transaction_accounts).unwrap_or(0); - let compute_budget = config - .compute_budget - .unwrap_or_else(|| ComputeBudget::from(loaded_transaction.compute_budget_limits)); + let compute_budget = loaded_transaction.compute_budget; let mut transaction_context = TransactionContext::new( transaction_accounts, @@ -1204,8 +1200,6 @@ mod tests { }, solana_account::{create_account_shared_data_for_test, WritableAccount}, solana_clock::Clock, - solana_compute_budget::compute_budget_limits::ComputeBudgetLimits, - solana_compute_budget_instruction::instructions_processor::process_compute_budget_instructions, solana_compute_budget_interface::ComputeBudgetInstruction, solana_epoch_schedule::EpochSchedule, solana_feature_set::FeatureSet, @@ -1215,7 +1209,10 @@ mod tests { solana_keypair::Keypair, solana_message::{LegacyMessage, Message, MessageHeader, SanitizedMessage}, solana_nonce as nonce, - solana_program_runtime::loaded_programs::{BlockRelation, ProgramCacheEntryType}, + solana_program_runtime::{ + execution_budget::SVMTransactionComputeBudgetAndLimits, + loaded_programs::{BlockRelation, ProgramCacheEntryType}, + }, solana_rent::Rent, solana_rent_debits::RentDebits, solana_reserved_account_keys::ReservedAccountKeys, @@ -1224,7 +1221,7 @@ mod tests { solana_signature::Signature, solana_transaction::{sanitized::SanitizedTransaction, Transaction}, solana_transaction_context::TransactionContext, - solana_transaction_error::TransactionError, + solana_transaction_error::{TransactionError, TransactionError::DuplicateInstruction}, test_case::test_case, }; @@ -1451,7 +1448,7 @@ mod tests { program_indices: vec![vec![0]], fee_details: FeeDetails::default(), rollback_accounts: RollbackAccounts::default(), - compute_budget_limits: ComputeBudgetLimits::default(), + compute_budget: SVMTransactionExecutionBudget::default(), rent: 0, rent_debits: RentDebits::default(), loaded_accounts_data_size: 32, @@ -1548,7 +1545,7 @@ mod tests { program_indices: vec![vec![0]], fee_details: FeeDetails::default(), rollback_accounts: RollbackAccounts::default(), - compute_budget_limits: ComputeBudgetLimits::default(), + compute_budget: SVMTransactionExecutionBudget::default(), rent: 0, rent_debits: RentDebits::default(), loaded_accounts_data_size: 0, @@ -2140,11 +2137,6 @@ mod tests { Some(&Pubkey::new_unique()), &Hash::new_unique(), )); - let compute_budget_limits = process_compute_budget_instructions( - SVMMessage::program_instructions_iter(&message), - &FeatureSet::default(), - ) - .unwrap(); let fee_payer_address = message.fee_payer(); let current_epoch = 42; let rent_collector = RentCollector { @@ -2160,7 +2152,7 @@ mod tests { assert!( starting_balance > min_balance, "we're testing that a rent exempt fee payer can be fully drained, \ - so ensure that the starting balance is more than the min balance" + so ensure that the starting balance is more than the min balance" ); let fee_payer_rent_epoch = current_epoch; @@ -2180,15 +2172,14 @@ mod tests { let mut account_loader = (&mock_bank).into(); let mut error_counters = TransactionErrorMetrics::default(); + let mut compute_budget = SVMTransactionComputeBudgetAndLimits::default(); + compute_budget.budget.compute_unit_limit = 2000; + compute_budget.priority_fee = priority_fee; let result = TransactionBatchProcessor::::validate_transaction_nonce_and_fee_payer( &mut account_loader, &message, - CheckedTransactionDetails::new( - None, - lamports_per_signature, - Ok(compute_budget_limits), - ), + CheckedTransactionDetails::new(None, lamports_per_signature, Ok(compute_budget)), &Hash::default(), FeeStructure::default().lamports_per_signature, &rent_collector, @@ -2213,7 +2204,8 @@ mod tests { fee_payer_rent_debit, fee_payer_rent_epoch ), - compute_budget_limits, + compute_budget: compute_budget.budget, + loaded_accounts_bytes_limit: compute_budget.loaded_accounts_bytes, fee_details: FeeDetails::new(transaction_fee, priority_fee), loaded_fee_payer_account: LoadedTransactionAccount { loaded_size: fee_payer_account.data().len(), @@ -2232,11 +2224,6 @@ mod tests { Some(&Pubkey::new_unique()), &Hash::new_unique(), )); - let compute_budget_limits = process_compute_budget_instructions( - SVMMessage::program_instructions_iter(&message), - &FeatureSet::default(), - ) - .unwrap(); let fee_payer_address = message.fee_payer(); let mut rent_collector = RentCollector::default(); rent_collector.rent.lamports_per_byte_year = 1_000_000; @@ -2262,15 +2249,12 @@ mod tests { let mut account_loader = (&mock_bank).into(); let mut error_counters = TransactionErrorMetrics::default(); + let compute_budget = SVMTransactionComputeBudgetAndLimits::default(); let result = TransactionBatchProcessor::::validate_transaction_nonce_and_fee_payer( &mut account_loader, &message, - CheckedTransactionDetails::new( - None, - lamports_per_signature, - Ok(compute_budget_limits), - ), + CheckedTransactionDetails::new(None, lamports_per_signature, Ok(compute_budget)), &Hash::default(), FeeStructure::default().lamports_per_signature, &rent_collector, @@ -2295,7 +2279,8 @@ mod tests { fee_payer_rent_debit, 0, // rent epoch ), - compute_budget_limits, + compute_budget: compute_budget.budget, + loaded_accounts_bytes_limit: compute_budget.loaded_accounts_bytes, fee_details: FeeDetails::new(transaction_fee, 0), loaded_fee_payer_account: LoadedTransactionAccount { loaded_size: fee_payer_account.data().len(), @@ -2322,7 +2307,7 @@ mod tests { CheckedTransactionDetails::new( None, lamports_per_signature, - Ok(ComputeBudgetLimits::default()), + Ok(SVMTransactionComputeBudgetAndLimits::default()), ), &Hash::default(), FeeStructure::default().lamports_per_signature, @@ -2358,7 +2343,7 @@ mod tests { CheckedTransactionDetails::new( None, lamports_per_signature, - Ok(ComputeBudgetLimits::default()), + Ok(SVMTransactionComputeBudgetAndLimits::default()), ), &Hash::default(), FeeStructure::default().lamports_per_signature, @@ -2398,7 +2383,7 @@ mod tests { CheckedTransactionDetails::new( None, lamports_per_signature, - Ok(ComputeBudgetLimits::default()), + Ok(SVMTransactionComputeBudgetAndLimits::default()), ), &Hash::default(), FeeStructure::default().lamports_per_signature, @@ -2436,7 +2421,7 @@ mod tests { CheckedTransactionDetails::new( None, lamports_per_signature, - Ok(ComputeBudgetLimits::default()), + Ok(SVMTransactionComputeBudgetAndLimits::default()), ), &Hash::default(), FeeStructure::default().lamports_per_signature, @@ -2459,10 +2444,6 @@ mod tests { ], Some(&Pubkey::new_unique()), )); - let compute_budget_limits = process_compute_budget_instructions( - SVMMessage::program_instructions_iter(&message), - &FeatureSet::default(), - ); let mock_bank = MockBankCallback::default(); let mut account_loader = (&mock_bank).into(); @@ -2471,7 +2452,11 @@ mod tests { TransactionBatchProcessor::::validate_transaction_nonce_and_fee_payer( &mut account_loader, &message, - CheckedTransactionDetails::new(None, lamports_per_signature, compute_budget_limits), + CheckedTransactionDetails::new( + None, + lamports_per_signature, + Err(DuplicateInstruction(1)), + ), &Hash::default(), FeeStructure::default().lamports_per_signature, &RentCollector::default(), @@ -2497,11 +2482,10 @@ mod tests { Some(&Pubkey::new_unique()), &last_blockhash, )); - let compute_budget_limits = process_compute_budget_instructions( - SVMMessage::program_instructions_iter(&message), - &FeatureSet::default(), - ) - .unwrap(); + let compute_budget = SVMTransactionComputeBudgetAndLimits { + priority_fee: compute_unit_limit, + ..SVMTransactionComputeBudgetAndLimits::default() + }; let fee_payer_address = message.fee_payer(); let min_balance = Rent::default().minimum_balance(nonce::state::State::size()); let transaction_fee = lamports_per_signature; @@ -2542,19 +2526,19 @@ mod tests { let tx_details = CheckedTransactionDetails::new( Some(future_nonce.clone()), lamports_per_signature, - Ok(compute_budget_limits), + Ok(compute_budget), ); let result = TransactionBatchProcessor::::validate_transaction_nonce_and_fee_payer( - &mut account_loader, - &message, - tx_details, - &environment_blockhash, - FeeStructure::default().lamports_per_signature, - &rent_collector, - &mut error_counters, - &mock_bank, - ); + &mut account_loader, + &message, + tx_details, + &environment_blockhash, + FeeStructure::default().lamports_per_signature, + &rent_collector, + &mut error_counters, + &mock_bank, + ); let post_validation_fee_payer_account = { let mut account = fee_payer_account.clone(); @@ -2573,7 +2557,8 @@ mod tests { 0, // fee_payer_rent_debit 0, // fee_payer_rent_epoch ), - compute_budget_limits, + compute_budget: compute_budget.budget, + loaded_accounts_bytes_limit: compute_budget.loaded_accounts_bytes, fee_details: FeeDetails::new(transaction_fee, priority_fee), loaded_fee_payer_account: LoadedTransactionAccount { loaded_size: fee_payer_account.data().len(), @@ -2605,15 +2590,15 @@ mod tests { let mut error_counters = TransactionErrorMetrics::default(); let result = TransactionBatchProcessor::::validate_transaction_nonce_and_fee_payer( - &mut account_loader, - &message, - CheckedTransactionDetails::new(None, lamports_per_signature, Ok(compute_budget_limits)), - &Hash::default(), - FeeStructure::default().lamports_per_signature, - &rent_collector, - &mut error_counters, - &mock_bank, - ); + &mut account_loader, + &message, + CheckedTransactionDetails::new(None, lamports_per_signature, Ok(compute_budget)), + &Hash::default(), + FeeStructure::default().lamports_per_signature, + &rent_collector, + &mut error_counters, + &mock_bank, + ); assert_eq!(error_counters.insufficient_funds.0, 1); assert_eq!(result, Err(TransactionError::InsufficientFundsForFee)); @@ -2647,15 +2632,20 @@ mod tests { Some(&fee_payer_address), &Hash::new_unique(), )); + /* let compute_budget_limits = process_compute_budget_instructions( SVMMessage::program_instructions_iter(&message), &FeatureSet::default(), ) .unwrap(); + let compute_budget = compute_budget_limits.get_compute_budget_and_limits(); + + */ + let compute_budget = SVMTransactionComputeBudgetAndLimits::default(); TransactionBatchProcessor::::validate_transaction_nonce_and_fee_payer( &mut account_loader, &message, - CheckedTransactionDetails::new(None, 5000, Ok(compute_budget_limits)), + CheckedTransactionDetails::new(None, 5000, Ok(compute_budget)), &Hash::default(), FeeStructure::default().lamports_per_signature, &RentCollector::default(), diff --git a/svm/tests/concurrent_tests.rs b/svm/tests/concurrent_tests.rs index 2cfb5f4022c627..4a52928596635e 100644 --- a/svm/tests/concurrent_tests.rs +++ b/svm/tests/concurrent_tests.rs @@ -11,8 +11,10 @@ use { sync::{Arc, RwLock}, thread, Runner, }, - solana_compute_budget::compute_budget_limits::ComputeBudgetLimits, - solana_program_runtime::loaded_programs::ProgramCacheEntryType, + solana_program_runtime::{ + execution_budget::SVMTransactionComputeBudgetAndLimits, + loaded_programs::ProgramCacheEntryType, + }, solana_sdk::{ account::{AccountSharedData, ReadableAccount, WritableAccount}, bpf_loader_upgradeable, @@ -243,7 +245,7 @@ fn svm_concurrent() { Ok(CheckedTransactionDetails::new( None, 20, - Ok(ComputeBudgetLimits::default()) + Ok(SVMTransactionComputeBudgetAndLimits::default()) )) as TransactionCheckResult; TRANSACTIONS_PER_THREAD ]; diff --git a/svm/tests/conformance.rs b/svm/tests/conformance.rs index 20cdb68b9478d9..6ea59ac3d267b4 100644 --- a/svm/tests/conformance.rs +++ b/svm/tests/conformance.rs @@ -6,10 +6,10 @@ use { lazy_static::lazy_static, prost::Message, solana_bpf_loader_program::syscalls::create_program_runtime_environment_v1, - solana_compute_budget::compute_budget::ComputeBudget, solana_feature_set::{FeatureSet, FEATURE_NAMES}, solana_log_collector::LogCollector, solana_program_runtime::{ + execution_budget::SVMTransactionExecutionBudget, invoke_context::{EnvironmentConfig, InvokeContext}, loaded_programs::{ProgramCacheEntry, ProgramCacheForTxBatch}, }, @@ -216,9 +216,9 @@ fn run_fixture(fixture: InstrFixture, filename: OsString) { let transactions = vec![transaction]; - let compute_budget = ComputeBudget { + let compute_budget = SVMTransactionExecutionBudget { compute_unit_limit: input.cu_avail, - ..ComputeBudget::default() + ..SVMTransactionExecutionBudget::default() }; let v1_environment = @@ -279,7 +279,7 @@ fn execute_fixture_as_instr( mock_bank: &MockBankCallback, batch_processor: &TransactionBatchProcessor, sanitized_message: &SanitizedMessage, - compute_budget: ComputeBudget, + compute_budget: SVMTransactionExecutionBudget, output: &InstrEffects, filename: OsString, cu_avail: u64, diff --git a/svm/tests/integration_test.rs b/svm/tests/integration_test.rs index c0c800c9515567..7b21f97807c55c 100644 --- a/svm/tests/integration_test.rs +++ b/svm/tests/integration_test.rs @@ -8,8 +8,8 @@ use { WALLCLOCK_TIME, }, solana_account::PROGRAM_OWNERS, - solana_compute_budget::compute_budget_limits::ComputeBudgetLimits, solana_compute_budget_instruction::instructions_processor::process_compute_budget_instructions, + solana_program_runtime::execution_budget::SVMTransactionComputeBudgetAndLimits, solana_sdk::{ account::{AccountSharedData, ReadableAccount, WritableAccount}, bpf_loader_upgradeable, @@ -436,13 +436,16 @@ impl SvmTestEntry { .map(|item| { let message = SanitizedTransaction::from_transaction_for_tests(item.transaction); let check_result = item.check_result.map(|tx_details| { + let compute_budget_limits = process_compute_budget_instructions( + SVMMessage::program_instructions_iter(&message), + &FeatureSet::default(), + ); + let compute_budget = + compute_budget_limits.map(|v| v.get_compute_budget_and_limits()); CheckedTransactionDetails::new( tx_details.nonce, tx_details.lamports_per_signature, - process_compute_budget_instructions( - SVMMessage::program_instructions_iter(&message), - &FeatureSet::default(), - ), + compute_budget, ) }); @@ -475,7 +478,7 @@ impl TransactionBatchItem { check_result: Ok(CheckedTransactionDetails::new( Some(nonce_info), LAMPORTS_PER_SIGNATURE, - Ok(ComputeBudgetLimits::default()), + Ok(SVMTransactionComputeBudgetAndLimits::default()), )), ..Self::default() } @@ -489,7 +492,7 @@ impl Default for TransactionBatchItem { check_result: Ok(CheckedTransactionDetails::new( None, LAMPORTS_PER_SIGNATURE, - Ok(ComputeBudgetLimits::default()), + Ok(SVMTransactionComputeBudgetAndLimits::default()), )), asserts: TransactionBatchItemAsserts::default(), } diff --git a/svm/tests/mock_bank.rs b/svm/tests/mock_bank.rs index 8a51e5fff9b274..50318d9c508294 100644 --- a/svm/tests/mock_bank.rs +++ b/svm/tests/mock_bank.rs @@ -6,10 +6,10 @@ use { SyscallAbort, SyscallGetClockSysvar, SyscallGetRentSysvar, SyscallInvokeSignedRust, SyscallLog, SyscallMemcpy, SyscallMemset, SyscallSetReturnData, }, - solana_compute_budget::compute_budget::ComputeBudget, solana_feature_set::FeatureSet, solana_fee_structure::FeeDetails, solana_program_runtime::{ + execution_budget::SVMTransactionExecutionBudget, invoke_context::InvokeContext, loaded_programs::{BlockRelation, ForkGraph, ProgramCacheEntry}, solana_sbpf::{ @@ -350,7 +350,7 @@ pub fn register_builtins( } pub fn create_custom_loader<'a>() -> BuiltinProgram> { - let compute_budget = ComputeBudget::default(); + let compute_budget = SVMTransactionExecutionBudget::default(); let vm_config = Config { max_call_depth: compute_budget.max_call_depth, stack_frame_size: compute_budget.stack_frame_size, From 34d135c765387a6750f564caa19a7140d68489ae Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Wed, 5 Mar 2025 08:06:36 -0800 Subject: [PATCH 2/2] cleanup imports --- .../src/compute_budget_instruction_details.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/compute-budget-instruction/src/compute_budget_instruction_details.rs b/compute-budget-instruction/src/compute_budget_instruction_details.rs index 59a61c11f9359e..6687d1923e41d5 100644 --- a/compute-budget-instruction/src/compute_budget_instruction_details.rs +++ b/compute-budget-instruction/src/compute_budget_instruction_details.rs @@ -236,10 +236,6 @@ mod test { solana_instruction::Instruction, solana_keypair::Keypair, solana_message::Message, - solana_program_runtime::execution_budget::{ - DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, MAX_BUILTIN_ALLOCATION_COMPUTE_UNIT_LIMIT, - MAX_COMPUTE_UNIT_LIMIT, MAX_HEAP_FRAME_BYTES, MIN_HEAP_FRAME_BYTES, - }, solana_pubkey::Pubkey, solana_signer::Signer, solana_svm_transaction::svm_message::SVMMessage,