diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index 9a194dece0..62ab77c2f8 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -24,7 +24,7 @@ use solana_sdk::{ instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError}, keyed_account::KeyedAccount, message::Message, - process_instruction::{ComputeBudget, InvokeContext, MockInvokeContext}, + process_instruction::{BpfComputeBudget, InvokeContext, MockInvokeContext}, pubkey::Pubkey, signature::{Keypair, Signer}, sysvar::{clock, fees, rent, slot_hashes, stake_history}, @@ -721,14 +721,14 @@ fn test_program_bpf_call_depth() { let instruction = Instruction::new( program_id, - &(ComputeBudget::default().max_call_depth - 1), + &(BpfComputeBudget::default().max_call_depth - 1), vec![], ); let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction); assert!(result.is_ok()); let instruction = - Instruction::new(program_id, &ComputeBudget::default().max_call_depth, vec![]); + Instruction::new(program_id, &BpfComputeBudget::default().max_call_depth, vec![]); let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction); assert!(result.is_err()); } diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index 61e9cb9358..787d916451 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -21,7 +21,7 @@ use solana_sdk::{ bpf_loader, bpf_loader_deprecated, decode_error::DecodeError, entrypoint::SUCCESS, - feature_set::{bpf_just_in_time_compilation, compute_budget_balancing}, + feature_set::{bpf_compute_budget_balancing, bpf_just_in_time_compilation}, instruction::InstructionError, keyed_account::{is_executable, next_keyed_account, KeyedAccount}, loader_instruction::LoaderInstruction, @@ -100,7 +100,7 @@ pub fn create_and_cache_executor( .map_err(|e| map_ebpf_error(invoke_context, e))?; bpf_verifier::check( elf_bytes, - !invoke_context.is_feature_active(&compute_budget_balancing::id()), + !invoke_context.is_feature_active(&bpf_compute_budget_balancing::id()), ) .map_err(|e| map_ebpf_error(invoke_context, EbpfError::UserError(e)))?; let executor = Arc::new(BPFExecutor { executable }); @@ -122,12 +122,12 @@ pub fn create_vm<'a>( ) -> Result, EbpfError> { let heap = vec![0_u8; DEFAULT_HEAP_SIZE]; let heap_region = MemoryRegion::new_from_slice(&heap, MM_HEAP_START, true); - let compute_budget = invoke_context.get_compute_budget(); + let bpf_compute_budget = invoke_context.get_bpf_compute_budget(); let mut vm = EbpfVm::new( executable, Config { - max_call_depth: compute_budget.max_call_depth, - stack_frame_size: compute_budget.stack_frame_size, + max_call_depth: bpf_compute_budget.max_call_depth, + stack_frame_size: bpf_compute_budget.stack_frame_size, }, parameter_bytes, &[heap_region], @@ -329,7 +329,7 @@ mod tests { account::Account, feature_set::FeatureSet, instruction::InstructionError, - process_instruction::{ComputeBudget, MockInvokeContext}, + process_instruction::{BpfComputeBudget, MockInvokeContext}, rent::Rent, }; use std::{cell::RefCell, fs::File, io::Read, ops::Range, rc::Rc}; @@ -554,7 +554,7 @@ mod tests { vec![], &[], None, - ComputeBudget { + BpfComputeBudget { max_units: 1, log_units: 100, log_64_units: 100, diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index 81b7413e5d..7afc04b7ab 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -94,7 +94,7 @@ pub fn register_syscalls<'a>( invoke_context: &'a mut dyn InvokeContext, heap: Vec, ) -> Result<(), EbpfError> { - let compute_budget = invoke_context.get_compute_budget(); + let bpf_compute_budget = invoke_context.get_bpf_compute_budget(); // Syscall functions common across languages @@ -106,7 +106,7 @@ pub fn register_syscalls<'a>( vm.register_syscall( hash_symbol_name(b"sol_log_"), Syscall::Object(Box::new(SyscallLog { - cost: compute_budget.log_units, + cost: bpf_compute_budget.log_units, compute_meter: invoke_context.get_compute_meter(), logger: invoke_context.get_logger(), loader_id, @@ -115,7 +115,7 @@ pub fn register_syscalls<'a>( vm.register_syscall( hash_symbol_name(b"sol_log_64_"), Syscall::Object(Box::new(SyscallLogU64 { - cost: compute_budget.log_64_units, + cost: bpf_compute_budget.log_64_units, compute_meter: invoke_context.get_compute_meter(), logger: invoke_context.get_logger(), })), @@ -135,7 +135,7 @@ pub fn register_syscalls<'a>( vm.register_syscall( hash_symbol_name(b"sol_log_pubkey"), Syscall::Object(Box::new(SyscallLogPubkey { - cost: compute_budget.log_pubkey_units, + cost: bpf_compute_budget.log_pubkey_units, compute_meter: invoke_context.get_compute_meter(), logger: invoke_context.get_logger(), loader_id, @@ -147,8 +147,8 @@ pub fn register_syscalls<'a>( vm.register_syscall( hash_symbol_name(b"sol_sha256"), Syscall::Object(Box::new(SyscallSha256 { - sha256_base_cost: compute_budget.sha256_base_cost, - sha256_byte_cost: compute_budget.sha256_byte_cost, + sha256_base_cost: bpf_compute_budget.sha256_base_cost, + sha256_byte_cost: bpf_compute_budget.sha256_byte_cost, compute_meter: invoke_context.get_compute_meter(), loader_id, })), @@ -169,7 +169,7 @@ pub fn register_syscalls<'a>( vm.register_syscall( hash_symbol_name(b"sol_create_program_address"), Syscall::Object(Box::new(SyscallCreateProgramAddress { - cost: compute_budget.create_program_address_units, + cost: bpf_compute_budget.create_program_address_units, compute_meter: invoke_context.get_compute_meter(), loader_id, })), @@ -1301,7 +1301,7 @@ fn call<'a>( let mut invoke_context = syscall.get_context_mut()?; invoke_context .get_compute_meter() - .consume(invoke_context.get_compute_budget().invoke_units)?; + .consume(invoke_context.get_bpf_compute_budget().invoke_units)?; // Translate data passed from the VM diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index d21a98e109..ab8d2fb0f3 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -51,7 +51,7 @@ use solana_sdk::{ native_loader, native_token::sol_to_lamports, nonce, nonce_account, - process_instruction::{Executor, ProcessInstructionWithContext}, + process_instruction::{BpfComputeBudget, Executor, ProcessInstructionWithContext}, program_utils::limited_deserialize, pubkey::Pubkey, recent_blockhashes_account, @@ -671,6 +671,8 @@ pub struct Bank { /// The Message processor message_processor: MessageProcessor, + bpf_compute_budget: Option, + /// Builtin programs activated dynamically by feature feature_builtins: Arc>, @@ -807,6 +809,7 @@ impl Bank { tick_height: AtomicU64::new(parent.tick_height.load(Relaxed)), signature_count: AtomicU64::new(0), message_processor: parent.message_processor.clone(), + bpf_compute_budget: parent.bpf_compute_budget, feature_builtins: parent.feature_builtins.clone(), hard_forks: parent.hard_forks.clone(), last_vote_sync: AtomicU64::new(parent.last_vote_sync.load(Relaxed)), @@ -912,6 +915,7 @@ impl Bank { epoch_stakes: fields.epoch_stakes, is_delta: AtomicBool::new(fields.is_delta), message_processor: new(), + bpf_compute_budget: None, feature_builtins: new(), last_vote_sync: new(), rewards: new(), @@ -2353,6 +2357,9 @@ impl Bank { let mut inner_instructions: Vec> = Vec::with_capacity(txs.len()); let mut transaction_logs: Vec = Vec::with_capacity(txs.len()); + let bpf_compute_budget = self + .bpf_compute_budget + .unwrap_or_else(|| BpfComputeBudget::new(&self.feature_set)); let executed: Vec = loaded_accounts .iter_mut() @@ -2391,6 +2398,7 @@ impl Bank { executors.clone(), instruction_recorders.as_deref(), self.feature_set.clone(), + bpf_compute_budget, ); if enable_log_recording { @@ -3358,6 +3366,10 @@ impl Bank { *self.inflation.write().unwrap() = inflation; } + pub fn set_bpf_compute_budget(&mut self, bpf_compute_budget: Option) { + self.bpf_compute_budget = bpf_compute_budget; + } + pub fn hard_forks(&self) -> Arc> { self.hard_forks.clone() } diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index 33fe5f616c..b9570d8ea7 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -15,7 +15,8 @@ use solana_sdk::{ message::Message, native_loader, process_instruction::{ - ComputeBudget, ComputeMeter, Executor, InvokeContext, Logger, ProcessInstructionWithContext, + BpfComputeBudget, ComputeMeter, Executor, InvokeContext, Logger, + ProcessInstructionWithContext, }, pubkey::Pubkey, rent::Rent, @@ -206,7 +207,7 @@ pub struct ThisInvokeContext<'a> { pre_accounts: Vec, programs: &'a [(Pubkey, ProcessInstructionWithContext)], logger: Rc>, - compute_budget: ComputeBudget, + bpf_compute_budget: BpfComputeBudget, compute_meter: Rc>, executors: Rc>, instruction_recorder: Option, @@ -219,12 +220,12 @@ impl<'a> ThisInvokeContext<'a> { pre_accounts: Vec, programs: &'a [(Pubkey, ProcessInstructionWithContext)], log_collector: Option>, - compute_budget: ComputeBudget, + bpf_compute_budget: BpfComputeBudget, executors: Rc>, instruction_recorder: Option, feature_set: Arc, ) -> Self { - let mut program_ids = Vec::with_capacity(compute_budget.max_invoke_depth); + let mut program_ids = Vec::with_capacity(bpf_compute_budget.max_invoke_depth); program_ids.push(*program_id); Self { program_ids, @@ -232,9 +233,9 @@ impl<'a> ThisInvokeContext<'a> { pre_accounts, programs, logger: Rc::new(RefCell::new(ThisLogger { log_collector })), - compute_budget, + bpf_compute_budget, compute_meter: Rc::new(RefCell::new(ThisComputeMeter { - remaining: compute_budget.max_units, + remaining: bpf_compute_budget.max_units, })), executors, instruction_recorder, @@ -244,7 +245,7 @@ impl<'a> ThisInvokeContext<'a> { } impl<'a> InvokeContext for ThisInvokeContext<'a> { fn push(&mut self, key: &Pubkey) -> Result<(), InstructionError> { - if self.program_ids.len() > self.compute_budget.max_invoke_depth { + if self.program_ids.len() > self.bpf_compute_budget.max_invoke_depth { return Err(InstructionError::CallDepth); } if self.program_ids.contains(key) && self.program_ids.last() != Some(key) { @@ -286,8 +287,8 @@ impl<'a> InvokeContext for ThisInvokeContext<'a> { fn get_logger(&self) -> Rc> { self.logger.clone() } - fn get_compute_budget(&self) -> &ComputeBudget { - &self.compute_budget + fn get_bpf_compute_budget(&self) -> &BpfComputeBudget { + &self.bpf_compute_budget } fn get_compute_meter(&self) -> Rc> { self.compute_meter.clone() @@ -412,10 +413,6 @@ impl MessageProcessor { self.add_program(program_id, process_instruction); } - fn get_compute_budget(feature_set: &FeatureSet) -> ComputeBudget { - ComputeBudget::new(feature_set) - } - /// Create the KeyedAccounts that will be passed to the program fn create_keyed_accounts<'a>( message: &'a Message, @@ -653,6 +650,7 @@ impl MessageProcessor { instruction_recorder: Option, instruction_index: usize, feature_set: Arc, + bpf_compute_budget: BpfComputeBudget, ) -> Result<(), InstructionError> { // Fixup the special instructions key if present // before the account pre-values are taken care of @@ -676,7 +674,7 @@ impl MessageProcessor { pre_accounts, &self.programs, log_collector, - Self::get_compute_budget(&feature_set), + bpf_compute_budget, executors, instruction_recorder, feature_set, @@ -709,6 +707,7 @@ impl MessageProcessor { executors: Rc>, instruction_recorders: Option<&[InstructionRecorder]>, feature_set: Arc, + bpf_compute_budget: BpfComputeBudget, ) -> Result<(), TransactionError> { for (instruction_index, instruction) in message.instructions.iter().enumerate() { let instruction_recorder = instruction_recorders @@ -725,6 +724,7 @@ impl MessageProcessor { instruction_recorder, instruction_index, feature_set.clone(), + bpf_compute_budget, ) .map_err(|err| TransactionError::InstructionError(instruction_index as u8, err))?; } @@ -769,7 +769,7 @@ mod tests { pre_accounts, &[], None, - ComputeBudget::default(), + BpfComputeBudget::default(), Rc::new(RefCell::new(Executors::default())), None, Arc::new(FeatureSet::all_enabled()), @@ -1314,6 +1314,7 @@ mod tests { executors.clone(), None, Arc::new(FeatureSet::all_enabled()), + BpfComputeBudget::new(&FeatureSet::all_enabled()), ); assert_eq!(result, Ok(())); assert_eq!(accounts[0].borrow().lamports, 100); @@ -1337,6 +1338,7 @@ mod tests { executors.clone(), None, Arc::new(FeatureSet::all_enabled()), + BpfComputeBudget::new(&FeatureSet::all_enabled()), ); assert_eq!( result, @@ -1364,6 +1366,7 @@ mod tests { executors, None, Arc::new(FeatureSet::all_enabled()), + BpfComputeBudget::new(&FeatureSet::all_enabled()), ); assert_eq!( result, @@ -1475,6 +1478,7 @@ mod tests { executors.clone(), None, Arc::new(FeatureSet::all_enabled()), + BpfComputeBudget::new(&FeatureSet::all_enabled()), ); assert_eq!( result, @@ -1502,6 +1506,7 @@ mod tests { executors.clone(), None, Arc::new(FeatureSet::all_enabled()), + BpfComputeBudget::new(&FeatureSet::all_enabled()), ); assert_eq!(result, Ok(())); @@ -1526,6 +1531,7 @@ mod tests { executors, None, Arc::new(FeatureSet::all_enabled()), + BpfComputeBudget::new(&FeatureSet::all_enabled()), ); assert_eq!(result, Ok(())); assert_eq!(accounts[0].borrow().lamports, 80); @@ -1600,7 +1606,7 @@ mod tests { vec![owned_preaccount, not_owned_preaccount], &[], None, - ComputeBudget::default(), + BpfComputeBudget::default(), Rc::new(RefCell::new(Executors::default())), None, Arc::new(FeatureSet::all_enabled()), diff --git a/sdk/src/feature_set.rs b/sdk/src/feature_set.rs index 1fa6a7ce8a..b20db816f7 100644 --- a/sdk/src/feature_set.rs +++ b/sdk/src/feature_set.rs @@ -34,7 +34,7 @@ pub mod bpf_loader2_program { solana_sdk::declare_id!("DFBnrgThdzH4W6wZ12uGPoWcMnvfZj11EHnxHcVxLPhD"); } -pub mod compute_budget_balancing { +pub mod bpf_compute_budget_balancing { solana_sdk::declare_id!("HxvjqDSiF5sYdSYuCXsUnS8UeAoWsMT9iGoFP8pgV1mB"); } @@ -92,7 +92,7 @@ lazy_static! { (inflation_kill_switch::id(), "inflation kill switch"), (spl_token_v2_multisig_fix::id(), "spl-token multisig fix"), (bpf_loader2_program::id(), "bpf_loader2 program"), - (compute_budget_balancing::id(), "compute budget balancing"), + (bpf_compute_budget_balancing::id(), "compute budget balancing"), (sha256_syscall_enabled::id(), "sha256 syscall"), (no_overflow_rent_distribution::id(), "no overflow rent distribution"), (ristretto_mul_syscall_enabled::id(), "ristretto multiply syscall"), diff --git a/sdk/src/process_instruction.rs b/sdk/src/process_instruction.rs index ee442b1783..62647fbad8 100644 --- a/sdk/src/process_instruction.rs +++ b/sdk/src/process_instruction.rs @@ -1,7 +1,7 @@ use solana_sdk::{ account::Account, feature_set::{ - compute_budget_balancing, max_invoke_depth_4, max_program_call_depth_64, + bpf_compute_budget_balancing, max_invoke_depth_4, max_program_call_depth_64, pubkey_log_syscall_enabled, FeatureSet, }, instruction::{CompiledInstruction, Instruction, InstructionError}, @@ -47,7 +47,7 @@ pub trait InvokeContext { /// Get this invocation's logger fn get_logger(&self) -> Rc>; /// Get this invocation's compute budget - fn get_compute_budget(&self) -> &ComputeBudget; + fn get_bpf_compute_budget(&self) -> &BpfComputeBudget; /// Get this invocation's compute meter fn get_compute_meter(&self) -> Rc>; /// Loaders may need to do work in order to execute a program. Cache @@ -61,8 +61,8 @@ pub trait InvokeContext { fn is_feature_active(&self, feature_id: &Pubkey) -> bool; } -#[derive(Clone, Copy, Debug)] -pub struct ComputeBudget { +#[derive(Clone, Copy, Debug, AbiExample)] +pub struct BpfComputeBudget { /// Number of compute units that an instruction is allowed. Compute units /// are consumed by program execution, resources they use, etc... pub max_units: u64, @@ -88,16 +88,16 @@ pub struct ComputeBudget { /// Number of compute units consumed by logging a `Pubkey` pub log_pubkey_units: u64, } -impl Default for ComputeBudget { +impl Default for BpfComputeBudget { fn default() -> Self { Self::new(&FeatureSet::all_enabled()) } } -impl ComputeBudget { +impl BpfComputeBudget { pub fn new(feature_set: &FeatureSet) -> Self { - let mut compute_budget = + let mut bpf_compute_budget = // Original - ComputeBudget { + BpfComputeBudget { max_units: 100_000, log_units: 0, log_64_units: 0, @@ -111,36 +111,36 @@ impl ComputeBudget { log_pubkey_units: 0, }; - if feature_set.is_active(&compute_budget_balancing::id()) { - compute_budget = ComputeBudget { + if feature_set.is_active(&bpf_compute_budget_balancing::id()) { + bpf_compute_budget = BpfComputeBudget { max_units: 200_000, log_units: 100, log_64_units: 100, create_program_address_units: 1500, invoke_units: 1000, - ..compute_budget + ..bpf_compute_budget }; } if feature_set.is_active(&max_invoke_depth_4::id()) { - compute_budget = ComputeBudget { + bpf_compute_budget = BpfComputeBudget { max_invoke_depth: 4, - ..compute_budget + ..bpf_compute_budget }; } if feature_set.is_active(&max_program_call_depth_64::id()) { - compute_budget = ComputeBudget { + bpf_compute_budget = BpfComputeBudget { max_call_depth: 64, - ..compute_budget + ..bpf_compute_budget }; } if feature_set.is_active(&pubkey_log_syscall_enabled::id()) { - compute_budget = ComputeBudget { + bpf_compute_budget = BpfComputeBudget { log_pubkey_units: 100, - ..compute_budget + ..bpf_compute_budget }; } - compute_budget + bpf_compute_budget } } @@ -206,7 +206,7 @@ impl Logger for MockLogger { pub struct MockInvokeContext { pub key: Pubkey, pub logger: MockLogger, - pub compute_budget: ComputeBudget, + pub bpf_compute_budget: BpfComputeBudget, pub compute_meter: MockComputeMeter, } impl Default for MockInvokeContext { @@ -214,7 +214,7 @@ impl Default for MockInvokeContext { MockInvokeContext { key: Pubkey::default(), logger: MockLogger::default(), - compute_budget: ComputeBudget::default(), + bpf_compute_budget: BpfComputeBudget::default(), compute_meter: MockComputeMeter { remaining: std::i64::MAX as u64, }, @@ -243,8 +243,8 @@ impl InvokeContext for MockInvokeContext { fn get_logger(&self) -> Rc> { Rc::new(RefCell::new(self.logger.clone())) } - fn get_compute_budget(&self) -> &ComputeBudget { - &self.compute_budget + fn get_bpf_compute_budget(&self) -> &BpfComputeBudget { + &self.bpf_compute_budget } fn get_compute_meter(&self) -> Rc> { Rc::new(RefCell::new(self.compute_meter.clone()))