Rename BpfComputeBudget (#18768)

This commit is contained in:
Jack May 2021-07-22 10:18:51 -07:00 committed by GitHub
parent cbe2ed47e2
commit 7fc4cfebc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 280 additions and 168 deletions

View File

@ -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<T: Default + Sysvar + Sized + serde::de::DeserializeOwned>(
.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<Builtin>,
bpf_compute_max_units: Option<u64>,
compute_max_units: Option<u64>,
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);

View File

@ -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()),

View File

@ -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<EbpfVm<'a, BpfError, ThisInstructionMeter>, EbpfError<BpfError>> {
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![],

View File

@ -197,7 +197,7 @@ pub fn bind_syscall_context_objects<'a>(
invoke_context: &'a mut dyn InvokeContext,
heap: AlignedMemory,
) -> Result<(), EbpfError<BpfError>> {
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<T: std::fmt::Debug + Sysvar + SysvarId>(
.try_borrow()
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
invoke_context.get_compute_meter().consume(
invoke_context.get_bpf_compute_budget().sysvar_base_cost + size_of::<T>() as u64,
)?;
invoke_context
.get_compute_meter()
.consume(invoke_context.get_compute_budget().sysvar_base_cost + size_of::<T>() as u64)?;
let var = translate_type_mut::<T>(
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::<AccountMeta>())
.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<BpfError>> {
if len * size_of::<Pubkey>()
> invoke_context
.get_bpf_compute_budget()
.max_cpi_instruction_size
{
if len * size_of::<Pubkey>() > 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());

View File

@ -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<BpfComputeBudget>,
compute_budget: Option<ComputeBudget>,
/// 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<BpfComputeBudget>) {
self.bpf_compute_budget = bpf_compute_budget;
pub fn set_compute_budget(&mut self, compute_budget: Option<ComputeBudget>) {
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<solana_sdk::process_instruction::BpfComputeBudget>,
) {
self.compute_budget = bpf_compute_budget.map(|budget| budget.into());
}
pub fn hard_forks(&self) -> Arc<RwLock<HardForks>> {
@ -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()),

View File

@ -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<RefCell<AccountSharedData>>)],
programs: &'a [(Pubkey, ProcessInstructionWithContext)],
logger: Rc<RefCell<dyn Logger>>,
bpf_compute_budget: BpfComputeBudget,
compute_budget: ComputeBudget,
#[allow(deprecated)]
bpf_compute_budget: solana_sdk::process_instruction::BpfComputeBudget,
compute_meter: Rc<RefCell<dyn ComputeMeter>>,
executors: Rc<RefCell<Executors>>,
instruction_recorder: Option<InstructionRecorder>,
@ -312,7 +315,7 @@ impl<'a> ThisInvokeContext<'a> {
accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)],
programs: &'a [(Pubkey, ProcessInstructionWithContext)],
log_collector: Option<Rc<LogCollector>>,
bpf_compute_budget: BpfComputeBudget,
compute_budget: ComputeBudget,
compute_meter: Rc<RefCell<dyn ComputeMeter>>,
executors: Rc<RefCell<Executors>>,
instruction_recorder: Option<InstructionRecorder>,
@ -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<AccountSharedData>)],
) -> 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<RefCell<dyn Logger>> {
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<RefCell<dyn ComputeMeter>> {
@ -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<Rc<LogCollector>>,
@ -1155,7 +1163,7 @@ impl MessageProcessor {
instruction_recorder: Option<InstructionRecorder>,
instruction_index: usize,
feature_set: Arc<FeatureSet>,
bpf_compute_budget: BpfComputeBudget,
compute_budget: ComputeBudget,
compute_meter: Rc<RefCell<dyn ComputeMeter>>,
timings: &mut ExecuteDetailsTimings,
account_db: Arc<Accounts>,
@ -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<RefCell<Executors>>,
instruction_recorders: Option<&[InstructionRecorder]>,
feature_set: Arc<FeatureSet>,
bpf_compute_budget: BpfComputeBudget,
compute_budget: ComputeBudget,
compute_meter: Rc<RefCell<dyn ComputeMeter>>,
timings: &mut ExecuteDetailsTimings,
account_db: Arc<Accounts>,
@ -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,

View File

@ -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::<ComputeBudgetInstruction>(&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<usize>,
}
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::<ComputeBudgetInstruction>(&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()
}
);
}

View File

@ -1,3 +1,5 @@
#![cfg(feature = "full")]
use crate::{
account::{ReadableAccount, WritableAccount},
account_utils::State as AccountUtilsState,

View File

@ -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<RefCell<dyn Logger>>;
/// 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<RefCell<dyn ComputeMeter>>;
@ -100,6 +105,8 @@ pub trait InvokeContext {
);
/// Get sysvar data
fn get_sysvar_data(&self, id: &Pubkey) -> Option<Rc<Vec<u8>>>;
/// Get this invocation's compute budget
fn get_compute_budget(&self) -> &ComputeBudget;
}
/// Convenience macro to log a message with an `Rc<RefCell<dyn Logger>>`
@ -147,7 +154,8 @@ pub fn get_sysvar<T: 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<usize>,
}
impl Default for BpfComputeBudget {
fn default() -> Self {
Self::new()
#[allow(deprecated)]
impl From<ComputeBudget> 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<BpfComputeBudget> 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<InvokeContextStackFrame<'a>>,
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<KeyedAccount<'a>>) -> 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<RefCell<dyn Logger>> {
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<RefCell<dyn ComputeMeter>> {
@ -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
}
}