From 7fc4cfebc8c29c15e7124999db261545a8f134bc Mon Sep 17 00:00:00 2001 From: Jack May Date: Thu, 22 Jul 2021 10:18:51 -0700 Subject: [PATCH] Rename BpfComputeBudget (#18768) --- program-test/src/lib.rs | 26 ++++-- programs/bpf/tests/programs.rs | 9 +- programs/bpf_loader/src/lib.rs | 21 ++--- programs/bpf_loader/src/syscalls.rs | 56 +++++------- runtime/src/bank.rs | 45 +++++---- runtime/src/message_processor.rs | 56 +++++++----- sdk/src/compute_budget.rs | 137 +++++++++++++++++++--------- sdk/src/nonce_keyed_account.rs | 2 + sdk/src/process_instruction.rs | 96 ++++++++++++++----- 9 files changed, 280 insertions(+), 168 deletions(-) diff --git a/program-test/src/lib.rs b/program-test/src/lib.rs index 636fa68d60..408a795800 100644 --- a/program-test/src/lib.rs +++ b/program-test/src/lib.rs @@ -17,6 +17,7 @@ use { account::{Account, AccountSharedData, ReadableAccount, WritableAccount}, account_info::AccountInfo, clock::{Clock, Slot}, + compute_budget::ComputeBudget, entrypoint::{ProgramResult, SUCCESS}, epoch_schedule::EpochSchedule, fee_calculator::{FeeCalculator, FeeRateGovernor}, @@ -26,9 +27,7 @@ use { instruction::InstructionError, message::Message, native_token::sol_to_lamports, - process_instruction::{ - stable_log, BpfComputeBudget, InvokeContext, ProcessInstructionWithContext, - }, + process_instruction::{stable_log, InvokeContext, ProcessInstructionWithContext}, program_error::{ProgramError, ACCOUNT_BORROW_FAILED, UNSUPPORTED_SYSVAR}, pubkey::Pubkey, rent::Rent, @@ -212,7 +211,7 @@ fn get_sysvar( .try_borrow_mut() .map_err(|_| ACCOUNT_BORROW_FAILED) .unwrap() - .consume(invoke_context.get_bpf_compute_budget().sysvar_base_cost + T::size_of() as u64) + .consume(invoke_context.get_compute_budget().sysvar_base_cost + T::size_of() as u64) .is_err() { panic!("Exceeded compute budget"); @@ -462,7 +461,7 @@ fn setup_fee_calculator(bank: Bank) -> Bank { pub struct ProgramTest { accounts: Vec<(Pubkey, AccountSharedData)>, builtins: Vec, - bpf_compute_max_units: Option, + compute_max_units: Option, prefer_bpf: bool, use_bpf_jit: bool, } @@ -492,7 +491,7 @@ impl Default for ProgramTest { Self { accounts: vec![], builtins: vec![], - bpf_compute_max_units: None, + compute_max_units: None, prefer_bpf, use_bpf_jit: false, } @@ -522,9 +521,16 @@ impl ProgramTest { self.prefer_bpf = prefer_bpf; } + /// Override the default maximum compute units + pub fn set_compute_max_units(&mut self, compute_max_units: u64) { + self.compute_max_units = Some(compute_max_units); + } + /// Override the BPF compute budget + #[allow(deprecated)] + #[deprecated(since = "1.8.0", note = "please use `set_compute_max_units` instead")] pub fn set_bpf_compute_max_units(&mut self, bpf_compute_max_units: u64) { - self.bpf_compute_max_units = Some(bpf_compute_max_units); + self.compute_max_units = Some(bpf_compute_max_units); } /// Execute the BPF program with JIT if true, interpreted if false @@ -783,10 +789,10 @@ impl ProgramTest { bank.store_account(address, account); } bank.set_capitalization(); - if let Some(max_units) = self.bpf_compute_max_units { - bank.set_bpf_compute_budget(Some(BpfComputeBudget { + if let Some(max_units) = self.compute_max_units { + bank.set_compute_budget(Some(ComputeBudget { max_units, - ..BpfComputeBudget::default() + ..ComputeBudget::default() })); } let bank = setup_fee_calculator(bank); diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index 86b1abff8e..e652b1d66a 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -34,7 +34,6 @@ use solana_sdk::{ bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, client::SyncClient, clock::MAX_PROCESSING_AGE, - compute_budget, entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS}, instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError}, keyed_account::KeyedAccount, @@ -1231,7 +1230,7 @@ fn test_program_bpf_ro_modify() { #[cfg(feature = "bpf_rust")] #[test] fn test_program_bpf_call_depth() { - use solana_sdk::process_instruction::BpfComputeBudget; + use solana_sdk::compute_budget::ComputeBudget; solana_logger::setup(); @@ -1253,7 +1252,7 @@ fn test_program_bpf_call_depth() { let instruction = Instruction::new_with_bincode( program_id, - &(BpfComputeBudget::default().max_call_depth - 1), + &(ComputeBudget::default().max_call_depth - 1), vec![], ); let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction); @@ -1261,7 +1260,7 @@ fn test_program_bpf_call_depth() { let instruction = Instruction::new_with_bincode( program_id, - &BpfComputeBudget::default().max_call_depth, + &ComputeBudget::default().max_call_depth, vec![], ); let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction); @@ -1290,7 +1289,7 @@ fn test_program_bpf_compute_budget() { ); let message = Message::new( &[ - compute_budget::request_units(1), + solana_sdk::compute_budget::ComputeBudgetInstruction::request_units(1), Instruction::new_with_bincode(program_id, &0, vec![]), ], Some(&mint_keypair.pubkey()), diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index c135dae9ac..b2b9a4d364 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -78,10 +78,10 @@ pub fn create_executor( ic_msg!(invoke_context, "Failed to register syscalls: {}", e); InstructionError::ProgramEnvironmentSetupFailure })?; - let bpf_compute_budget = invoke_context.get_bpf_compute_budget(); + let compute_budget = invoke_context.get_compute_budget(); let config = Config { - max_call_depth: bpf_compute_budget.max_call_depth, - stack_frame_size: bpf_compute_budget.stack_frame_size, + max_call_depth: compute_budget.max_call_depth, + stack_frame_size: compute_budget.stack_frame_size, enable_instruction_tracing: log_enabled!(Trace), ..Config::default() }; @@ -149,11 +149,9 @@ pub fn create_vm<'a>( parameter_bytes: &mut [u8], invoke_context: &'a mut dyn InvokeContext, ) -> Result, EbpfError> { - let bpf_compute_budget = invoke_context.get_bpf_compute_budget(); - let heap = AlignedMemory::new_with_size( - bpf_compute_budget.heap_size.unwrap_or(HEAP_LENGTH), - HOST_ALIGN, - ); + let compute_budget = invoke_context.get_compute_budget(); + let heap = + AlignedMemory::new_with_size(compute_budget.heap_size.unwrap_or(HEAP_LENGTH), HOST_ALIGN); let heap_region = MemoryRegion::new_from_slice(heap.as_slice(), MM_HEAP_START, 0, true); let mut vm = EbpfVm::new(program, parameter_bytes, &[heap_region])?; syscalls::bind_syscall_context_objects(loader_id, &mut vm, invoke_context, heap)?; @@ -866,6 +864,7 @@ mod tests { account_utils::StateMut, client::SyncClient, clock::Clock, + compute_budget::ComputeBudget, feature_set::FeatureSet, genesis_config::create_genesis_config, instruction::Instruction, @@ -873,8 +872,7 @@ mod tests { keyed_account::KeyedAccount, message::Message, process_instruction::{ - BpfComputeBudget, InvokeContextStackFrame, MockComputeMeter, MockInvokeContext, - MockLogger, + InvokeContextStackFrame, MockComputeMeter, MockInvokeContext, MockLogger, }, pubkey::Pubkey, rent::Rent, @@ -1133,7 +1131,8 @@ mod tests { keyed_accounts_range, }], logger: MockLogger::default(), - bpf_compute_budget: BpfComputeBudget::default(), + compute_budget: ComputeBudget::default(), + bpf_compute_budget: ComputeBudget::default().into(), compute_meter: MockComputeMeter::default(), programs: vec![], accounts: vec![], diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index 59e12f4597..cb43dff22b 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -197,7 +197,7 @@ pub fn bind_syscall_context_objects<'a>( invoke_context: &'a mut dyn InvokeContext, heap: AlignedMemory, ) -> Result<(), EbpfError> { - let bpf_compute_budget = invoke_context.get_bpf_compute_budget(); + let compute_budget = invoke_context.get_compute_budget(); let enforce_aligned_host_addrs = invoke_context.is_feature_active(&enforce_aligned_host_addrs::id()); @@ -223,7 +223,7 @@ pub fn bind_syscall_context_objects<'a>( )?; vm.bind_syscall_context_object( Box::new(SyscallLogU64 { - cost: bpf_compute_budget.log_64_units, + cost: compute_budget.log_64_units, compute_meter: invoke_context.get_compute_meter(), logger: invoke_context.get_logger(), }), @@ -241,7 +241,7 @@ pub fn bind_syscall_context_objects<'a>( vm.bind_syscall_context_object( Box::new(SyscallLogPubkey { - cost: bpf_compute_budget.log_pubkey_units, + cost: compute_budget.log_pubkey_units, compute_meter: invoke_context.get_compute_meter(), logger: invoke_context.get_logger(), loader_id, @@ -252,7 +252,7 @@ pub fn bind_syscall_context_objects<'a>( vm.bind_syscall_context_object( Box::new(SyscallCreateProgramAddress { - cost: bpf_compute_budget.create_program_address_units, + cost: compute_budget.create_program_address_units, compute_meter: invoke_context.get_compute_meter(), loader_id, enforce_aligned_host_addrs, @@ -262,7 +262,7 @@ pub fn bind_syscall_context_objects<'a>( vm.bind_syscall_context_object( Box::new(SyscallTryFindProgramAddress { - cost: bpf_compute_budget.create_program_address_units, + cost: compute_budget.create_program_address_units, compute_meter: invoke_context.get_compute_meter(), loader_id, enforce_aligned_host_addrs, @@ -272,8 +272,8 @@ pub fn bind_syscall_context_objects<'a>( vm.bind_syscall_context_object( Box::new(SyscallSha256 { - sha256_base_cost: bpf_compute_budget.sha256_base_cost, - sha256_byte_cost: bpf_compute_budget.sha256_byte_cost, + sha256_base_cost: compute_budget.sha256_base_cost, + sha256_byte_cost: compute_budget.sha256_byte_cost, compute_meter: invoke_context.get_compute_meter(), loader_id, enforce_aligned_host_addrs, @@ -285,8 +285,8 @@ pub fn bind_syscall_context_objects<'a>( vm, invoke_context.is_feature_active(&keccak256_syscall_enabled::id()), Box::new(SyscallKeccak256 { - base_cost: bpf_compute_budget.sha256_base_cost, - byte_cost: bpf_compute_budget.sha256_byte_cost, + base_cost: compute_budget.sha256_base_cost, + byte_cost: compute_budget.sha256_byte_cost, compute_meter: invoke_context.get_compute_meter(), loader_id, }), @@ -296,7 +296,7 @@ pub fn bind_syscall_context_objects<'a>( vm, invoke_context.is_feature_active(&memory_ops_syscalls::id()), Box::new(SyscallMemcpy { - cost: invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit, + cost: invoke_context.get_compute_budget().cpi_bytes_per_unit, compute_meter: invoke_context.get_compute_meter(), loader_id, }), @@ -305,7 +305,7 @@ pub fn bind_syscall_context_objects<'a>( vm, invoke_context.is_feature_active(&memory_ops_syscalls::id()), Box::new(SyscallMemmove { - cost: invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit, + cost: invoke_context.get_compute_budget().cpi_bytes_per_unit, compute_meter: invoke_context.get_compute_meter(), loader_id, }), @@ -314,7 +314,7 @@ pub fn bind_syscall_context_objects<'a>( vm, invoke_context.is_feature_active(&memory_ops_syscalls::id()), Box::new(SyscallMemcmp { - cost: invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit, + cost: invoke_context.get_compute_budget().cpi_bytes_per_unit, compute_meter: invoke_context.get_compute_meter(), loader_id, }), @@ -323,7 +323,7 @@ pub fn bind_syscall_context_objects<'a>( vm, invoke_context.is_feature_active(&memory_ops_syscalls::id()), Box::new(SyscallMemset { - cost: invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit, + cost: invoke_context.get_compute_budget().cpi_bytes_per_unit, compute_meter: invoke_context.get_compute_meter(), loader_id, }), @@ -332,8 +332,8 @@ pub fn bind_syscall_context_objects<'a>( vm, invoke_context.is_feature_active(&blake3_syscall_enabled::id()), Box::new(SyscallBlake3 { - base_cost: bpf_compute_budget.sha256_base_cost, - byte_cost: bpf_compute_budget.sha256_byte_cost, + base_cost: compute_budget.sha256_base_cost, + byte_cost: compute_budget.sha256_byte_cost, compute_meter: invoke_context.get_compute_meter(), loader_id, }), @@ -343,7 +343,7 @@ pub fn bind_syscall_context_objects<'a>( vm, invoke_context.is_feature_active(&secp256k1_recover_syscall_enabled::id()), Box::new(SyscallSecp256k1Recover { - cost: bpf_compute_budget.secp256k1_recover_cost, + cost: compute_budget.secp256k1_recover_cost, compute_meter: invoke_context.get_compute_meter(), loader_id, libsecp256k1_0_5_upgrade_enabled: invoke_context @@ -1043,9 +1043,9 @@ fn get_sysvar( .try_borrow() .map_err(|_| SyscallError::InvokeContextBorrowFailed)?; - invoke_context.get_compute_meter().consume( - invoke_context.get_bpf_compute_budget().sysvar_base_cost + size_of::() as u64, - )?; + invoke_context + .get_compute_meter() + .consume(invoke_context.get_compute_budget().sysvar_base_cost + size_of::() as u64)?; let var = translate_type_mut::( memory_mapping, var_addr, @@ -1689,8 +1689,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> { if invoke_context.is_feature_active(&cpi_data_cost::id()) { invoke_context.get_compute_meter().consume( - data.len() as u64 - / invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit, + data.len() as u64 / invoke_context.get_compute_budget().cpi_bytes_per_unit, )?; } @@ -2009,8 +2008,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> { if invoke_context.is_feature_active(&cpi_data_cost::id()) { invoke_context.get_compute_meter().consume( - account_info.data_len - / invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit, + account_info.data_len / invoke_context.get_compute_budget().cpi_bytes_per_unit, )?; } @@ -2213,9 +2211,7 @@ fn check_instruction_size( let size = num_accounts .saturating_mul(size_of::()) .saturating_add(data_len); - let max_size = invoke_context - .get_bpf_compute_budget() - .max_cpi_instruction_size; + let max_size = invoke_context.get_compute_budget().max_cpi_instruction_size; if size > max_size { return Err(SyscallError::InstructionTooLarge(size, max_size).into()); } @@ -2226,11 +2222,7 @@ fn check_account_infos( len: usize, invoke_context: &Ref<&mut dyn InvokeContext>, ) -> Result<(), EbpfError> { - if len * size_of::() - > invoke_context - .get_bpf_compute_budget() - .max_cpi_instruction_size - { + if len * size_of::() > invoke_context.get_compute_budget().max_cpi_instruction_size { // Cap the number of account_infos a caller can pass to approximate // maximum that accounts that could be passed in an instruction return Err(SyscallError::TooManyAccounts.into()); @@ -2305,7 +2297,7 @@ fn call<'a>( invoke_context .get_compute_meter() - .consume(invoke_context.get_bpf_compute_budget().invoke_units)?; + .consume(invoke_context.get_compute_budget().invoke_units)?; let enforce_aligned_host_addrs = invoke_context.is_feature_active(&enforce_aligned_host_addrs::id()); diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 99484c8b5b..90fb226165 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -76,7 +76,7 @@ use solana_sdk::{ INITIAL_RENT_EPOCH, MAX_PROCESSING_AGE, MAX_RECENT_BLOCKHASHES, MAX_TRANSACTION_FORWARDING_DELAY, SECONDS_PER_DAY, }, - compute_budget, + compute_budget::ComputeBudget, epoch_info::EpochInfo, epoch_schedule::EpochSchedule, feature, @@ -93,9 +93,7 @@ use solana_sdk::{ native_loader, native_token::sol_to_lamports, nonce, nonce_account, - process_instruction::{ - BpfComputeBudget, ComputeMeter, Executor, ProcessInstructionWithContext, - }, + process_instruction::{ComputeMeter, Executor, ProcessInstructionWithContext}, program_utils::limited_deserialize, pubkey::Pubkey, recent_blockhashes_account, @@ -1001,7 +999,7 @@ pub struct Bank { /// The Message processor message_processor: MessageProcessor, - bpf_compute_budget: Option, + compute_budget: Option, /// Builtin programs activated dynamically by feature #[allow(clippy::rc_buffer)] @@ -1236,7 +1234,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, + compute_budget: parent.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)), @@ -1396,7 +1394,7 @@ impl Bank { epoch_stakes: fields.epoch_stakes, is_delta: AtomicBool::new(fields.is_delta), message_processor: new(), - bpf_compute_budget: None, + compute_budget: None, feature_builtins: new(), last_vote_sync: new(), rewards: new(), @@ -3232,12 +3230,10 @@ impl Bank { let feature_set = self.feature_set.clone(); signature_count += u64::from(tx.message().header.num_required_signatures); - let mut bpf_compute_budget = self - .bpf_compute_budget - .unwrap_or_else(BpfComputeBudget::new); + let mut compute_budget = self.compute_budget.unwrap_or_else(ComputeBudget::new); let mut process_result = if feature_set.is_active(&tx_wide_compute_cap::id()) { - compute_budget::process_request(&mut bpf_compute_budget, tx) + compute_budget.process_transaction(tx) } else { Ok(()) }; @@ -3267,7 +3263,7 @@ impl Bank { }; let compute_meter = Rc::new(RefCell::new(TransactionComputeMeter::new( - bpf_compute_budget.max_units, + compute_budget.max_units, ))); process_result = self.message_processor.process_message( @@ -3279,7 +3275,7 @@ impl Bank { executors.clone(), instruction_recorders.as_deref(), feature_set, - bpf_compute_budget, + compute_budget, compute_meter, &mut timings.details, self.rc.accounts.clone(), @@ -4434,8 +4430,17 @@ 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 set_compute_budget(&mut self, compute_budget: Option) { + self.compute_budget = compute_budget; + } + + #[allow(deprecated)] + #[deprecated(since = "1.8.0", note = "please use `set_compute_budget` instead")] + pub fn set_bpf_compute_budget( + &mut self, + bpf_compute_budget: Option, + ) { + self.compute_budget = bpf_compute_budget.map(|budget| budget.into()); } pub fn hard_forks(&self) -> Arc> { @@ -5556,7 +5561,7 @@ pub(crate) mod tests { use solana_sdk::{ account::Account, clock::{DEFAULT_SLOTS_PER_EPOCH, DEFAULT_TICKS_PER_SLOT}, - compute_budget, + compute_budget::ComputeBudgetInstruction, epoch_schedule::MINIMUM_SLOTS_PER_EPOCH, feature::Feature, genesis_config::create_genesis_config, @@ -13795,12 +13800,12 @@ pub(crate) mod tests { _data: &[u8], invoke_context: &mut dyn InvokeContext, ) -> std::result::Result<(), InstructionError> { - let compute_budget = invoke_context.get_bpf_compute_budget(); + let compute_budget = invoke_context.get_compute_budget(); assert_eq!( *compute_budget, - BpfComputeBudget { + ComputeBudget { max_units: 1, - ..BpfComputeBudget::default() + ..ComputeBudget::default() } ); Ok(()) @@ -13810,7 +13815,7 @@ pub(crate) mod tests { let message = Message::new( &[ - compute_budget::request_units(1), + ComputeBudgetInstruction::request_units(1), Instruction::new_with_bincode(program_id, &0, vec![]), ], Some(&mint_keypair.pubkey()), diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index 28284946da..c3ee9034bb 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -9,6 +9,7 @@ use solana_sdk::{ account::{AccountSharedData, ReadableAccount, WritableAccount}, account_utils::StateMut, bpf_loader_upgradeable::{self, UpgradeableLoaderState}, + compute_budget::ComputeBudget, feature_set::{ instructions_sysvar_enabled, neon_evm_compute_budget, tx_wide_compute_cap, updated_verify_policy, FeatureSet, @@ -19,7 +20,7 @@ use solana_sdk::{ message::Message, native_loader, process_instruction::{ - BpfComputeBudget, ComputeMeter, Executor, InvokeContext, InvokeContextStackFrame, Logger, + ComputeMeter, Executor, InvokeContext, InvokeContextStackFrame, Logger, ProcessInstructionWithContext, }, pubkey::Pubkey, @@ -290,7 +291,9 @@ pub struct ThisInvokeContext<'a> { accounts: &'a [(Pubkey, Rc>)], programs: &'a [(Pubkey, ProcessInstructionWithContext)], logger: Rc>, - bpf_compute_budget: BpfComputeBudget, + compute_budget: ComputeBudget, + #[allow(deprecated)] + bpf_compute_budget: solana_sdk::process_instruction::BpfComputeBudget, compute_meter: Rc>, executors: Rc>, instruction_recorder: Option, @@ -312,7 +315,7 @@ impl<'a> ThisInvokeContext<'a> { accounts: &'a [(Pubkey, Rc>)], programs: &'a [(Pubkey, ProcessInstructionWithContext)], log_collector: Option>, - bpf_compute_budget: BpfComputeBudget, + compute_budget: ComputeBudget, compute_meter: Rc>, executors: Rc>, instruction_recorder: Option, @@ -331,17 +334,18 @@ impl<'a> ThisInvokeContext<'a> { compute_meter } else { Rc::new(RefCell::new(ThisComputeMeter { - remaining: bpf_compute_budget.max_units, + remaining: compute_budget.max_units, })) }; let mut invoke_context = Self { - invoke_stack: Vec::with_capacity(bpf_compute_budget.max_invoke_depth), + invoke_stack: Vec::with_capacity(compute_budget.max_invoke_depth), rent, pre_accounts, accounts, programs, logger: Rc::new(RefCell::new(ThisLogger { log_collector })), - bpf_compute_budget, + compute_budget, + bpf_compute_budget: compute_budget.into(), compute_meter, executors, instruction_recorder, @@ -366,7 +370,7 @@ impl<'a> InvokeContext for ThisInvokeContext<'a> { key: &Pubkey, keyed_accounts: &[(bool, bool, &Pubkey, &RefCell)], ) -> Result<(), InstructionError> { - if self.invoke_stack.len() > self.bpf_compute_budget.max_invoke_depth { + if self.invoke_stack.len() > self.compute_budget.max_invoke_depth { return Err(InstructionError::CallDepth); } @@ -470,7 +474,8 @@ impl<'a> InvokeContext for ThisInvokeContext<'a> { fn get_logger(&self) -> Rc> { self.logger.clone() } - fn get_bpf_compute_budget(&self) -> &BpfComputeBudget { + #[allow(deprecated)] + fn get_bpf_compute_budget(&self) -> &solana_sdk::process_instruction::BpfComputeBudget { &self.bpf_compute_budget } fn get_compute_meter(&self) -> Rc> { @@ -531,6 +536,9 @@ impl<'a> InvokeContext for ThisInvokeContext<'a> { None } } + fn get_compute_budget(&self) -> &ComputeBudget { + &self.compute_budget + } } pub struct ThisLogger { log_collector: Option>, @@ -1155,7 +1163,7 @@ impl MessageProcessor { instruction_recorder: Option, instruction_index: usize, feature_set: Arc, - bpf_compute_budget: BpfComputeBudget, + compute_budget: ComputeBudget, compute_meter: Rc>, timings: &mut ExecuteDetailsTimings, account_db: Arc, @@ -1178,13 +1186,13 @@ impl MessageProcessor { let program_id = instruction.program_id(&message.account_keys); - let mut bpf_compute_budget = bpf_compute_budget; + let mut compute_budget = compute_budget; if feature_set.is_active(&neon_evm_compute_budget::id()) && *program_id == crate::neon_evm_program::id() { // Bump the compute budget for neon_evm - bpf_compute_budget.max_units = bpf_compute_budget.max_units.max(500_000); - bpf_compute_budget.heap_size = Some(256 * 1024); + compute_budget.max_units = compute_budget.max_units.max(500_000); + compute_budget.heap_size = Some(256 * 1024); } let mut invoke_context = ThisInvokeContext::new( @@ -1196,7 +1204,7 @@ impl MessageProcessor { accounts, &self.programs, log_collector, - bpf_compute_budget, + compute_budget, compute_meter, executors, instruction_recorder, @@ -1237,7 +1245,7 @@ impl MessageProcessor { executors: Rc>, instruction_recorders: Option<&[InstructionRecorder]>, feature_set: Arc, - bpf_compute_budget: BpfComputeBudget, + compute_budget: ComputeBudget, compute_meter: Rc>, timings: &mut ExecuteDetailsTimings, account_db: Arc, @@ -1261,7 +1269,7 @@ impl MessageProcessor { instruction_recorder, instruction_index, feature_set.clone(), - bpf_compute_budget, + compute_budget, compute_meter.clone(), timings, account_db.clone(), @@ -1338,7 +1346,7 @@ mod tests { &accounts, &[], None, - BpfComputeBudget::default(), + ComputeBudget::default(), Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(Executors::default())), None, @@ -1952,7 +1960,7 @@ mod tests { executors.clone(), None, Arc::new(FeatureSet::all_enabled()), - BpfComputeBudget::new(), + ComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteDetailsTimings::default(), Arc::new(Accounts::default()), @@ -1980,7 +1988,7 @@ mod tests { executors.clone(), None, Arc::new(FeatureSet::all_enabled()), - BpfComputeBudget::new(), + ComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteDetailsTimings::default(), Arc::new(Accounts::default()), @@ -2012,7 +2020,7 @@ mod tests { executors, None, Arc::new(FeatureSet::all_enabled()), - BpfComputeBudget::new(), + ComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteDetailsTimings::default(), Arc::new(Accounts::default()), @@ -2136,7 +2144,7 @@ mod tests { executors.clone(), None, Arc::new(FeatureSet::all_enabled()), - BpfComputeBudget::new(), + ComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteDetailsTimings::default(), Arc::new(Accounts::default()), @@ -2168,7 +2176,7 @@ mod tests { executors.clone(), None, Arc::new(FeatureSet::all_enabled()), - BpfComputeBudget::new(), + ComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteDetailsTimings::default(), Arc::new(Accounts::default()), @@ -2198,7 +2206,7 @@ mod tests { executors, None, Arc::new(FeatureSet::all_enabled()), - BpfComputeBudget::new(), + ComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteDetailsTimings::default(), Arc::new(Accounts::default()), @@ -2300,7 +2308,7 @@ mod tests { &accounts, programs.as_slice(), None, - BpfComputeBudget::default(), + ComputeBudget::default(), Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(Executors::default())), None, @@ -2357,7 +2365,7 @@ mod tests { &accounts, programs.as_slice(), None, - BpfComputeBudget::default(), + ComputeBudget::default(), Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(Executors::default())), None, diff --git a/sdk/src/compute_budget.rs b/sdk/src/compute_budget.rs index 0fae0b8a81..47800a617c 100644 --- a/sdk/src/compute_budget.rs +++ b/sdk/src/compute_budget.rs @@ -1,9 +1,6 @@ #![cfg(feature = "full")] -use crate::{ - process_instruction::BpfComputeBudget, - transaction::{Transaction, TransactionError}, -}; +use crate::transaction::{Transaction, TransactionError}; use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; use solana_sdk::{ borsh::try_from_slice_unchecked, @@ -32,70 +29,126 @@ pub enum ComputeBudgetInstruction { /// allowed to consume. RequestUnits(u64), } - -/// Create a `ComputeBudgetInstruction::RequestUnits` `Instruction` -pub fn request_units(units: u64) -> Instruction { - Instruction::new_with_borsh(id(), &ComputeBudgetInstruction::RequestUnits(units), vec![]) +impl ComputeBudgetInstruction { + /// Create a `ComputeBudgetInstruction::RequestUnits` `Instruction` + pub fn request_units(units: u64) -> Instruction { + Instruction::new_with_borsh(id(), &ComputeBudgetInstruction::RequestUnits(units), vec![]) + } } -pub fn process_request( - compute_budget: &mut BpfComputeBudget, - tx: &Transaction, -) -> Result<(), TransactionError> { - let error = TransactionError::InstructionError(0, InstructionError::InvalidInstructionData); - // Compute budget instruction must be in 1st or 2nd instruction (avoid nonce marker) - for instruction in tx.message().instructions.iter().take(2) { - if check_id(instruction.program_id(&tx.message().account_keys)) { - let ComputeBudgetInstruction::RequestUnits(units) = - try_from_slice_unchecked::(&instruction.data) - .map_err(|_| error.clone())?; - if units > MAX_UNITS { - return Err(error); - } - compute_budget.max_units = units; +#[derive(Clone, Copy, Debug, AbiExample, PartialEq)] +pub struct ComputeBudget { + /// Number of compute units that an instruction is allowed. Compute units + /// are consumed by program execution, resources they use, etc... + pub max_units: 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 cross-program invocation depth allowed + pub max_invoke_depth: 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 BPF to BPF call depth + pub max_call_depth: usize, + /// Size of a stack frame in bytes, must match the size specified in the LLVM BPF 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 conpute 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, + /// Optional program heap region size, if `None` then loader default + pub heap_size: Option, +} +impl Default for ComputeBudget { + fn default() -> Self { + Self::new() + } +} +impl ComputeBudget { + pub fn new() -> Self { + ComputeBudget { + max_units: 200_000, + log_64_units: 100, + create_program_address_units: 1500, + invoke_units: 1000, + max_invoke_depth: 4, + sha256_base_cost: 85, + sha256_byte_cost: 1, + max_call_depth: 64, + stack_frame_size: 4_096, + 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, + heap_size: None, } } - Ok(()) + pub fn process_transaction(&mut self, tx: &Transaction) -> Result<(), TransactionError> { + let error = TransactionError::InstructionError(0, InstructionError::InvalidInstructionData); + // Compute budget instruction must be in 1st or 2nd instruction (avoid nonce marker) + for instruction in tx.message().instructions.iter().take(2) { + if check_id(instruction.program_id(&tx.message().account_keys)) { + let ComputeBudgetInstruction::RequestUnits(units) = + try_from_slice_unchecked::(&instruction.data) + .map_err(|_| error.clone())?; + if units > MAX_UNITS { + return Err(error); + } + self.max_units = units; + } + } + Ok(()) + } } #[cfg(test)] mod tests { use super::*; - use crate::{ - compute_budget, hash::Hash, message::Message, pubkey::Pubkey, signature::Keypair, - signer::Signer, - }; + use crate::{hash::Hash, message::Message, pubkey::Pubkey, signature::Keypair, signer::Signer}; #[test] - fn test_process_request() { + fn test_process_transaction() { let payer_keypair = Keypair::new(); - let mut compute_budget = BpfComputeBudget::default(); + let mut compute_budget = ComputeBudget::default(); let tx = Transaction::new( &[&payer_keypair], Message::new(&[], Some(&payer_keypair.pubkey())), Hash::default(), ); - process_request(&mut compute_budget, &tx).unwrap(); - assert_eq!(compute_budget, BpfComputeBudget::default()); + compute_budget.process_transaction(&tx).unwrap(); + assert_eq!(compute_budget, ComputeBudget::default()); let tx = Transaction::new( &[&payer_keypair], Message::new( &[ - compute_budget::request_units(1), + ComputeBudgetInstruction::request_units(1), Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]), ], Some(&payer_keypair.pubkey()), ), Hash::default(), ); - process_request(&mut compute_budget, &tx).unwrap(); + compute_budget.process_transaction(&tx).unwrap(); assert_eq!( compute_budget, - BpfComputeBudget { + ComputeBudget { max_units: 1, - ..BpfComputeBudget::default() + ..ComputeBudget::default() } ); @@ -103,14 +156,14 @@ mod tests { &[&payer_keypair], Message::new( &[ - compute_budget::request_units(MAX_UNITS + 1), + ComputeBudgetInstruction::request_units(MAX_UNITS + 1), Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]), ], Some(&payer_keypair.pubkey()), ), Hash::default(), ); - let result = process_request(&mut compute_budget, &tx); + let result = compute_budget.process_transaction(&tx); assert_eq!( result, Err(TransactionError::InstructionError( @@ -124,18 +177,18 @@ mod tests { Message::new( &[ Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]), - compute_budget::request_units(MAX_UNITS), + ComputeBudgetInstruction::request_units(MAX_UNITS), ], Some(&payer_keypair.pubkey()), ), Hash::default(), ); - process_request(&mut compute_budget, &tx).unwrap(); + compute_budget.process_transaction(&tx).unwrap(); assert_eq!( compute_budget, - BpfComputeBudget { + ComputeBudget { max_units: MAX_UNITS, - ..BpfComputeBudget::default() + ..ComputeBudget::default() } ); } diff --git a/sdk/src/nonce_keyed_account.rs b/sdk/src/nonce_keyed_account.rs index 336548fcad..4da76893a6 100644 --- a/sdk/src/nonce_keyed_account.rs +++ b/sdk/src/nonce_keyed_account.rs @@ -1,3 +1,5 @@ +#![cfg(feature = "full")] + use crate::{ account::{ReadableAccount, WritableAccount}, account_utils::State as AccountUtilsState, diff --git a/sdk/src/process_instruction.rs b/sdk/src/process_instruction.rs index 85c1487816..99d67bb6cb 100644 --- a/sdk/src/process_instruction.rs +++ b/sdk/src/process_instruction.rs @@ -1,5 +1,8 @@ +#![cfg(feature = "full")] + use solana_sdk::{ account::AccountSharedData, + compute_budget::ComputeBudget, instruction::{CompiledInstruction, Instruction, InstructionError}, keyed_account::{create_keyed_accounts_unified, KeyedAccount}, pubkey::Pubkey, @@ -76,6 +79,8 @@ pub trait InvokeContext { /// Get this invocation's logger fn get_logger(&self) -> Rc>; /// Get this invocation's compute budget + #[allow(deprecated)] + #[deprecated(since = "1.8.0", note = "please use `get_compute_budget` instead")] fn get_bpf_compute_budget(&self) -> &BpfComputeBudget; /// Get this invocation's compute meter fn get_compute_meter(&self) -> Rc>; @@ -100,6 +105,8 @@ pub trait InvokeContext { ); /// Get sysvar data fn get_sysvar_data(&self, id: &Pubkey) -> Option>>; + /// Get this invocation's compute budget + fn get_compute_budget(&self) -> &ComputeBudget; } /// Convenience macro to log a message with an `Rc>` @@ -147,7 +154,8 @@ pub fn get_sysvar( }) } -#[derive(Clone, Copy, Debug, AbiExample, PartialEq)] +#[deprecated(since = "1.8.0", note = "please use `ComputeBudget` instead")] +#[derive(Clone, Copy, Debug, PartialEq)] pub struct BpfComputeBudget { /// Number of compute units that an instruction is allowed. Compute units /// are consumed by program execution, resources they use, etc... @@ -182,30 +190,60 @@ pub struct BpfComputeBudget { /// Optional program heap region size, if `None` then loader default pub heap_size: Option, } -impl Default for BpfComputeBudget { - fn default() -> Self { - Self::new() +#[allow(deprecated)] +impl From for BpfComputeBudget { + fn from(item: ComputeBudget) -> Self { + BpfComputeBudget { + max_units: item.max_units, + log_64_units: item.log_64_units, + create_program_address_units: item.create_program_address_units, + invoke_units: item.invoke_units, + max_invoke_depth: item.max_invoke_depth, + sha256_base_cost: item.sha256_base_cost, + sha256_byte_cost: item.sha256_byte_cost, + max_call_depth: item.max_call_depth, + stack_frame_size: item.stack_frame_size, + log_pubkey_units: item.log_pubkey_units, + max_cpi_instruction_size: item.max_cpi_instruction_size, + cpi_bytes_per_unit: item.cpi_bytes_per_unit, + sysvar_base_cost: item.sysvar_base_cost, + secp256k1_recover_cost: item.secp256k1_recover_cost, + heap_size: item.heap_size, + } } } +#[allow(deprecated)] +impl From for ComputeBudget { + fn from(item: BpfComputeBudget) -> Self { + ComputeBudget { + max_units: item.max_units, + log_64_units: item.log_64_units, + create_program_address_units: item.create_program_address_units, + invoke_units: item.invoke_units, + max_invoke_depth: item.max_invoke_depth, + sha256_base_cost: item.sha256_base_cost, + sha256_byte_cost: item.sha256_byte_cost, + max_call_depth: item.max_call_depth, + stack_frame_size: item.stack_frame_size, + log_pubkey_units: item.log_pubkey_units, + max_cpi_instruction_size: item.max_cpi_instruction_size, + cpi_bytes_per_unit: item.cpi_bytes_per_unit, + sysvar_base_cost: item.sysvar_base_cost, + secp256k1_recover_cost: item.secp256k1_recover_cost, + heap_size: item.heap_size, + } + } +} +#[allow(deprecated)] +impl Default for BpfComputeBudget { + fn default() -> Self { + ComputeBudget::default().into() + } +} +#[allow(deprecated)] impl BpfComputeBudget { pub fn new() -> Self { - BpfComputeBudget { - max_units: 200_000, - log_64_units: 100, - create_program_address_units: 1500, - invoke_units: 1000, - max_invoke_depth: 4, - sha256_base_cost: 85, - sha256_byte_cost: 1, - max_call_depth: 64, - stack_frame_size: 4_096, - 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, - heap_size: None, - } + BpfComputeBudget::default() } } @@ -336,9 +374,12 @@ impl Logger for MockLogger { } } +#[allow(deprecated)] pub struct MockInvokeContext<'a> { pub invoke_stack: Vec>, pub logger: MockLogger, + pub compute_budget: ComputeBudget, + #[allow(deprecated)] pub bpf_compute_budget: BpfComputeBudget, pub compute_meter: MockComputeMeter, pub programs: Vec<(Pubkey, ProcessInstructionWithContext)>, @@ -348,11 +389,13 @@ pub struct MockInvokeContext<'a> { } impl<'a> MockInvokeContext<'a> { pub fn new(keyed_accounts: Vec>) -> Self { - let bpf_compute_budget = BpfComputeBudget::default(); + let compute_budget = ComputeBudget::default(); let mut invoke_context = MockInvokeContext { - invoke_stack: Vec::with_capacity(bpf_compute_budget.max_invoke_depth), + invoke_stack: Vec::with_capacity(compute_budget.max_invoke_depth), logger: MockLogger::default(), - bpf_compute_budget, + compute_budget, + #[allow(deprecated)] + bpf_compute_budget: compute_budget.into(), compute_meter: MockComputeMeter { remaining: std::i64::MAX as u64, }, @@ -442,7 +485,9 @@ impl<'a> InvokeContext for MockInvokeContext<'a> { fn get_logger(&self) -> Rc> { Rc::new(RefCell::new(self.logger.clone())) } + #[allow(deprecated)] fn get_bpf_compute_budget(&self) -> &BpfComputeBudget { + #[allow(deprecated)] &self.bpf_compute_budget } fn get_compute_meter(&self) -> Rc> { @@ -477,4 +522,7 @@ impl<'a> InvokeContext for MockInvokeContext<'a> { .iter() .find_map(|(key, sysvar)| if id == key { sysvar.clone() } else { None }) } + fn get_compute_budget(&self) -> &ComputeBudget { + &self.compute_budget + } }