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
9 changed files with 280 additions and 168 deletions

View File

@ -17,6 +17,7 @@ use {
account::{Account, AccountSharedData, ReadableAccount, WritableAccount}, account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
account_info::AccountInfo, account_info::AccountInfo,
clock::{Clock, Slot}, clock::{Clock, Slot},
compute_budget::ComputeBudget,
entrypoint::{ProgramResult, SUCCESS}, entrypoint::{ProgramResult, SUCCESS},
epoch_schedule::EpochSchedule, epoch_schedule::EpochSchedule,
fee_calculator::{FeeCalculator, FeeRateGovernor}, fee_calculator::{FeeCalculator, FeeRateGovernor},
@ -26,9 +27,7 @@ use {
instruction::InstructionError, instruction::InstructionError,
message::Message, message::Message,
native_token::sol_to_lamports, native_token::sol_to_lamports,
process_instruction::{ process_instruction::{stable_log, InvokeContext, ProcessInstructionWithContext},
stable_log, BpfComputeBudget, InvokeContext, ProcessInstructionWithContext,
},
program_error::{ProgramError, ACCOUNT_BORROW_FAILED, UNSUPPORTED_SYSVAR}, program_error::{ProgramError, ACCOUNT_BORROW_FAILED, UNSUPPORTED_SYSVAR},
pubkey::Pubkey, pubkey::Pubkey,
rent::Rent, rent::Rent,
@ -212,7 +211,7 @@ fn get_sysvar<T: Default + Sysvar + Sized + serde::de::DeserializeOwned>(
.try_borrow_mut() .try_borrow_mut()
.map_err(|_| ACCOUNT_BORROW_FAILED) .map_err(|_| ACCOUNT_BORROW_FAILED)
.unwrap() .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() .is_err()
{ {
panic!("Exceeded compute budget"); panic!("Exceeded compute budget");
@ -462,7 +461,7 @@ fn setup_fee_calculator(bank: Bank) -> Bank {
pub struct ProgramTest { pub struct ProgramTest {
accounts: Vec<(Pubkey, AccountSharedData)>, accounts: Vec<(Pubkey, AccountSharedData)>,
builtins: Vec<Builtin>, builtins: Vec<Builtin>,
bpf_compute_max_units: Option<u64>, compute_max_units: Option<u64>,
prefer_bpf: bool, prefer_bpf: bool,
use_bpf_jit: bool, use_bpf_jit: bool,
} }
@ -492,7 +491,7 @@ impl Default for ProgramTest {
Self { Self {
accounts: vec![], accounts: vec![],
builtins: vec![], builtins: vec![],
bpf_compute_max_units: None, compute_max_units: None,
prefer_bpf, prefer_bpf,
use_bpf_jit: false, use_bpf_jit: false,
} }
@ -522,9 +521,16 @@ impl ProgramTest {
self.prefer_bpf = prefer_bpf; 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 /// 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) { 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 /// Execute the BPF program with JIT if true, interpreted if false
@ -783,10 +789,10 @@ impl ProgramTest {
bank.store_account(address, account); bank.store_account(address, account);
} }
bank.set_capitalization(); bank.set_capitalization();
if let Some(max_units) = self.bpf_compute_max_units { if let Some(max_units) = self.compute_max_units {
bank.set_bpf_compute_budget(Some(BpfComputeBudget { bank.set_compute_budget(Some(ComputeBudget {
max_units, max_units,
..BpfComputeBudget::default() ..ComputeBudget::default()
})); }));
} }
let bank = setup_fee_calculator(bank); let bank = setup_fee_calculator(bank);

View File

@ -34,7 +34,6 @@ use solana_sdk::{
bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable,
client::SyncClient, client::SyncClient,
clock::MAX_PROCESSING_AGE, clock::MAX_PROCESSING_AGE,
compute_budget,
entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS}, entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS},
instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError}, instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
keyed_account::KeyedAccount, keyed_account::KeyedAccount,
@ -1231,7 +1230,7 @@ fn test_program_bpf_ro_modify() {
#[cfg(feature = "bpf_rust")] #[cfg(feature = "bpf_rust")]
#[test] #[test]
fn test_program_bpf_call_depth() { fn test_program_bpf_call_depth() {
use solana_sdk::process_instruction::BpfComputeBudget; use solana_sdk::compute_budget::ComputeBudget;
solana_logger::setup(); solana_logger::setup();
@ -1253,7 +1252,7 @@ fn test_program_bpf_call_depth() {
let instruction = Instruction::new_with_bincode( let instruction = Instruction::new_with_bincode(
program_id, program_id,
&(BpfComputeBudget::default().max_call_depth - 1), &(ComputeBudget::default().max_call_depth - 1),
vec![], vec![],
); );
let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction); 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( let instruction = Instruction::new_with_bincode(
program_id, program_id,
&BpfComputeBudget::default().max_call_depth, &ComputeBudget::default().max_call_depth,
vec![], vec![],
); );
let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction); 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( 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![]), Instruction::new_with_bincode(program_id, &0, vec![]),
], ],
Some(&mint_keypair.pubkey()), Some(&mint_keypair.pubkey()),

View File

@ -78,10 +78,10 @@ pub fn create_executor(
ic_msg!(invoke_context, "Failed to register syscalls: {}", e); ic_msg!(invoke_context, "Failed to register syscalls: {}", e);
InstructionError::ProgramEnvironmentSetupFailure InstructionError::ProgramEnvironmentSetupFailure
})?; })?;
let bpf_compute_budget = invoke_context.get_bpf_compute_budget(); let compute_budget = invoke_context.get_compute_budget();
let config = Config { let config = Config {
max_call_depth: bpf_compute_budget.max_call_depth, max_call_depth: compute_budget.max_call_depth,
stack_frame_size: bpf_compute_budget.stack_frame_size, stack_frame_size: compute_budget.stack_frame_size,
enable_instruction_tracing: log_enabled!(Trace), enable_instruction_tracing: log_enabled!(Trace),
..Config::default() ..Config::default()
}; };
@ -149,11 +149,9 @@ pub fn create_vm<'a>(
parameter_bytes: &mut [u8], parameter_bytes: &mut [u8],
invoke_context: &'a mut dyn InvokeContext, invoke_context: &'a mut dyn InvokeContext,
) -> Result<EbpfVm<'a, BpfError, ThisInstructionMeter>, EbpfError<BpfError>> { ) -> Result<EbpfVm<'a, BpfError, ThisInstructionMeter>, EbpfError<BpfError>> {
let bpf_compute_budget = invoke_context.get_bpf_compute_budget(); let compute_budget = invoke_context.get_compute_budget();
let heap = AlignedMemory::new_with_size( let heap =
bpf_compute_budget.heap_size.unwrap_or(HEAP_LENGTH), AlignedMemory::new_with_size(compute_budget.heap_size.unwrap_or(HEAP_LENGTH), HOST_ALIGN);
HOST_ALIGN,
);
let heap_region = MemoryRegion::new_from_slice(heap.as_slice(), MM_HEAP_START, 0, true); 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])?; let mut vm = EbpfVm::new(program, parameter_bytes, &[heap_region])?;
syscalls::bind_syscall_context_objects(loader_id, &mut vm, invoke_context, heap)?; syscalls::bind_syscall_context_objects(loader_id, &mut vm, invoke_context, heap)?;
@ -866,6 +864,7 @@ mod tests {
account_utils::StateMut, account_utils::StateMut,
client::SyncClient, client::SyncClient,
clock::Clock, clock::Clock,
compute_budget::ComputeBudget,
feature_set::FeatureSet, feature_set::FeatureSet,
genesis_config::create_genesis_config, genesis_config::create_genesis_config,
instruction::Instruction, instruction::Instruction,
@ -873,8 +872,7 @@ mod tests {
keyed_account::KeyedAccount, keyed_account::KeyedAccount,
message::Message, message::Message,
process_instruction::{ process_instruction::{
BpfComputeBudget, InvokeContextStackFrame, MockComputeMeter, MockInvokeContext, InvokeContextStackFrame, MockComputeMeter, MockInvokeContext, MockLogger,
MockLogger,
}, },
pubkey::Pubkey, pubkey::Pubkey,
rent::Rent, rent::Rent,
@ -1133,7 +1131,8 @@ mod tests {
keyed_accounts_range, keyed_accounts_range,
}], }],
logger: MockLogger::default(), logger: MockLogger::default(),
bpf_compute_budget: BpfComputeBudget::default(), compute_budget: ComputeBudget::default(),
bpf_compute_budget: ComputeBudget::default().into(),
compute_meter: MockComputeMeter::default(), compute_meter: MockComputeMeter::default(),
programs: vec![], programs: vec![],
accounts: vec![], accounts: vec![],

View File

@ -197,7 +197,7 @@ pub fn bind_syscall_context_objects<'a>(
invoke_context: &'a mut dyn InvokeContext, invoke_context: &'a mut dyn InvokeContext,
heap: AlignedMemory, heap: AlignedMemory,
) -> Result<(), EbpfError<BpfError>> { ) -> 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 = let enforce_aligned_host_addrs =
invoke_context.is_feature_active(&enforce_aligned_host_addrs::id()); 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( vm.bind_syscall_context_object(
Box::new(SyscallLogU64 { Box::new(SyscallLogU64 {
cost: bpf_compute_budget.log_64_units, cost: compute_budget.log_64_units,
compute_meter: invoke_context.get_compute_meter(), compute_meter: invoke_context.get_compute_meter(),
logger: invoke_context.get_logger(), logger: invoke_context.get_logger(),
}), }),
@ -241,7 +241,7 @@ pub fn bind_syscall_context_objects<'a>(
vm.bind_syscall_context_object( vm.bind_syscall_context_object(
Box::new(SyscallLogPubkey { Box::new(SyscallLogPubkey {
cost: bpf_compute_budget.log_pubkey_units, cost: compute_budget.log_pubkey_units,
compute_meter: invoke_context.get_compute_meter(), compute_meter: invoke_context.get_compute_meter(),
logger: invoke_context.get_logger(), logger: invoke_context.get_logger(),
loader_id, loader_id,
@ -252,7 +252,7 @@ pub fn bind_syscall_context_objects<'a>(
vm.bind_syscall_context_object( vm.bind_syscall_context_object(
Box::new(SyscallCreateProgramAddress { 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(), compute_meter: invoke_context.get_compute_meter(),
loader_id, loader_id,
enforce_aligned_host_addrs, enforce_aligned_host_addrs,
@ -262,7 +262,7 @@ pub fn bind_syscall_context_objects<'a>(
vm.bind_syscall_context_object( vm.bind_syscall_context_object(
Box::new(SyscallTryFindProgramAddress { 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(), compute_meter: invoke_context.get_compute_meter(),
loader_id, loader_id,
enforce_aligned_host_addrs, enforce_aligned_host_addrs,
@ -272,8 +272,8 @@ pub fn bind_syscall_context_objects<'a>(
vm.bind_syscall_context_object( vm.bind_syscall_context_object(
Box::new(SyscallSha256 { Box::new(SyscallSha256 {
sha256_base_cost: bpf_compute_budget.sha256_base_cost, sha256_base_cost: compute_budget.sha256_base_cost,
sha256_byte_cost: bpf_compute_budget.sha256_byte_cost, sha256_byte_cost: compute_budget.sha256_byte_cost,
compute_meter: invoke_context.get_compute_meter(), compute_meter: invoke_context.get_compute_meter(),
loader_id, loader_id,
enforce_aligned_host_addrs, enforce_aligned_host_addrs,
@ -285,8 +285,8 @@ pub fn bind_syscall_context_objects<'a>(
vm, vm,
invoke_context.is_feature_active(&keccak256_syscall_enabled::id()), invoke_context.is_feature_active(&keccak256_syscall_enabled::id()),
Box::new(SyscallKeccak256 { Box::new(SyscallKeccak256 {
base_cost: bpf_compute_budget.sha256_base_cost, base_cost: compute_budget.sha256_base_cost,
byte_cost: bpf_compute_budget.sha256_byte_cost, byte_cost: compute_budget.sha256_byte_cost,
compute_meter: invoke_context.get_compute_meter(), compute_meter: invoke_context.get_compute_meter(),
loader_id, loader_id,
}), }),
@ -296,7 +296,7 @@ pub fn bind_syscall_context_objects<'a>(
vm, vm,
invoke_context.is_feature_active(&memory_ops_syscalls::id()), invoke_context.is_feature_active(&memory_ops_syscalls::id()),
Box::new(SyscallMemcpy { 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(), compute_meter: invoke_context.get_compute_meter(),
loader_id, loader_id,
}), }),
@ -305,7 +305,7 @@ pub fn bind_syscall_context_objects<'a>(
vm, vm,
invoke_context.is_feature_active(&memory_ops_syscalls::id()), invoke_context.is_feature_active(&memory_ops_syscalls::id()),
Box::new(SyscallMemmove { 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(), compute_meter: invoke_context.get_compute_meter(),
loader_id, loader_id,
}), }),
@ -314,7 +314,7 @@ pub fn bind_syscall_context_objects<'a>(
vm, vm,
invoke_context.is_feature_active(&memory_ops_syscalls::id()), invoke_context.is_feature_active(&memory_ops_syscalls::id()),
Box::new(SyscallMemcmp { 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(), compute_meter: invoke_context.get_compute_meter(),
loader_id, loader_id,
}), }),
@ -323,7 +323,7 @@ pub fn bind_syscall_context_objects<'a>(
vm, vm,
invoke_context.is_feature_active(&memory_ops_syscalls::id()), invoke_context.is_feature_active(&memory_ops_syscalls::id()),
Box::new(SyscallMemset { 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(), compute_meter: invoke_context.get_compute_meter(),
loader_id, loader_id,
}), }),
@ -332,8 +332,8 @@ pub fn bind_syscall_context_objects<'a>(
vm, vm,
invoke_context.is_feature_active(&blake3_syscall_enabled::id()), invoke_context.is_feature_active(&blake3_syscall_enabled::id()),
Box::new(SyscallBlake3 { Box::new(SyscallBlake3 {
base_cost: bpf_compute_budget.sha256_base_cost, base_cost: compute_budget.sha256_base_cost,
byte_cost: bpf_compute_budget.sha256_byte_cost, byte_cost: compute_budget.sha256_byte_cost,
compute_meter: invoke_context.get_compute_meter(), compute_meter: invoke_context.get_compute_meter(),
loader_id, loader_id,
}), }),
@ -343,7 +343,7 @@ pub fn bind_syscall_context_objects<'a>(
vm, vm,
invoke_context.is_feature_active(&secp256k1_recover_syscall_enabled::id()), invoke_context.is_feature_active(&secp256k1_recover_syscall_enabled::id()),
Box::new(SyscallSecp256k1Recover { Box::new(SyscallSecp256k1Recover {
cost: bpf_compute_budget.secp256k1_recover_cost, cost: compute_budget.secp256k1_recover_cost,
compute_meter: invoke_context.get_compute_meter(), compute_meter: invoke_context.get_compute_meter(),
loader_id, loader_id,
libsecp256k1_0_5_upgrade_enabled: invoke_context libsecp256k1_0_5_upgrade_enabled: invoke_context
@ -1043,9 +1043,9 @@ fn get_sysvar<T: std::fmt::Debug + Sysvar + SysvarId>(
.try_borrow() .try_borrow()
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?; .map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
invoke_context.get_compute_meter().consume( invoke_context
invoke_context.get_bpf_compute_budget().sysvar_base_cost + size_of::<T>() as u64, .get_compute_meter()
)?; .consume(invoke_context.get_compute_budget().sysvar_base_cost + size_of::<T>() as u64)?;
let var = translate_type_mut::<T>( let var = translate_type_mut::<T>(
memory_mapping, memory_mapping,
var_addr, var_addr,
@ -1689,8 +1689,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> {
if invoke_context.is_feature_active(&cpi_data_cost::id()) { if invoke_context.is_feature_active(&cpi_data_cost::id()) {
invoke_context.get_compute_meter().consume( invoke_context.get_compute_meter().consume(
data.len() as u64 data.len() as u64 / invoke_context.get_compute_budget().cpi_bytes_per_unit,
/ invoke_context.get_bpf_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()) { if invoke_context.is_feature_active(&cpi_data_cost::id()) {
invoke_context.get_compute_meter().consume( invoke_context.get_compute_meter().consume(
account_info.data_len account_info.data_len / invoke_context.get_compute_budget().cpi_bytes_per_unit,
/ invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit,
)?; )?;
} }
@ -2213,9 +2211,7 @@ fn check_instruction_size(
let size = num_accounts let size = num_accounts
.saturating_mul(size_of::<AccountMeta>()) .saturating_mul(size_of::<AccountMeta>())
.saturating_add(data_len); .saturating_add(data_len);
let max_size = invoke_context let max_size = invoke_context.get_compute_budget().max_cpi_instruction_size;
.get_bpf_compute_budget()
.max_cpi_instruction_size;
if size > max_size { if size > max_size {
return Err(SyscallError::InstructionTooLarge(size, max_size).into()); return Err(SyscallError::InstructionTooLarge(size, max_size).into());
} }
@ -2226,11 +2222,7 @@ fn check_account_infos(
len: usize, len: usize,
invoke_context: &Ref<&mut dyn InvokeContext>, invoke_context: &Ref<&mut dyn InvokeContext>,
) -> Result<(), EbpfError<BpfError>> { ) -> Result<(), EbpfError<BpfError>> {
if len * size_of::<Pubkey>() if len * size_of::<Pubkey>() > invoke_context.get_compute_budget().max_cpi_instruction_size {
> invoke_context
.get_bpf_compute_budget()
.max_cpi_instruction_size
{
// Cap the number of account_infos a caller can pass to approximate // Cap the number of account_infos a caller can pass to approximate
// maximum that accounts that could be passed in an instruction // maximum that accounts that could be passed in an instruction
return Err(SyscallError::TooManyAccounts.into()); return Err(SyscallError::TooManyAccounts.into());
@ -2305,7 +2297,7 @@ fn call<'a>(
invoke_context invoke_context
.get_compute_meter() .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 = let enforce_aligned_host_addrs =
invoke_context.is_feature_active(&enforce_aligned_host_addrs::id()); 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, INITIAL_RENT_EPOCH, MAX_PROCESSING_AGE, MAX_RECENT_BLOCKHASHES,
MAX_TRANSACTION_FORWARDING_DELAY, SECONDS_PER_DAY, MAX_TRANSACTION_FORWARDING_DELAY, SECONDS_PER_DAY,
}, },
compute_budget, compute_budget::ComputeBudget,
epoch_info::EpochInfo, epoch_info::EpochInfo,
epoch_schedule::EpochSchedule, epoch_schedule::EpochSchedule,
feature, feature,
@ -93,9 +93,7 @@ use solana_sdk::{
native_loader, native_loader,
native_token::sol_to_lamports, native_token::sol_to_lamports,
nonce, nonce_account, nonce, nonce_account,
process_instruction::{ process_instruction::{ComputeMeter, Executor, ProcessInstructionWithContext},
BpfComputeBudget, ComputeMeter, Executor, ProcessInstructionWithContext,
},
program_utils::limited_deserialize, program_utils::limited_deserialize,
pubkey::Pubkey, pubkey::Pubkey,
recent_blockhashes_account, recent_blockhashes_account,
@ -1001,7 +999,7 @@ pub struct Bank {
/// The Message processor /// The Message processor
message_processor: MessageProcessor, message_processor: MessageProcessor,
bpf_compute_budget: Option<BpfComputeBudget>, compute_budget: Option<ComputeBudget>,
/// Builtin programs activated dynamically by feature /// Builtin programs activated dynamically by feature
#[allow(clippy::rc_buffer)] #[allow(clippy::rc_buffer)]
@ -1236,7 +1234,7 @@ impl Bank {
tick_height: AtomicU64::new(parent.tick_height.load(Relaxed)), tick_height: AtomicU64::new(parent.tick_height.load(Relaxed)),
signature_count: AtomicU64::new(0), signature_count: AtomicU64::new(0),
message_processor: parent.message_processor.clone(), message_processor: parent.message_processor.clone(),
bpf_compute_budget: parent.bpf_compute_budget, compute_budget: parent.compute_budget,
feature_builtins: parent.feature_builtins.clone(), feature_builtins: parent.feature_builtins.clone(),
hard_forks: parent.hard_forks.clone(), hard_forks: parent.hard_forks.clone(),
last_vote_sync: AtomicU64::new(parent.last_vote_sync.load(Relaxed)), last_vote_sync: AtomicU64::new(parent.last_vote_sync.load(Relaxed)),
@ -1396,7 +1394,7 @@ impl Bank {
epoch_stakes: fields.epoch_stakes, epoch_stakes: fields.epoch_stakes,
is_delta: AtomicBool::new(fields.is_delta), is_delta: AtomicBool::new(fields.is_delta),
message_processor: new(), message_processor: new(),
bpf_compute_budget: None, compute_budget: None,
feature_builtins: new(), feature_builtins: new(),
last_vote_sync: new(), last_vote_sync: new(),
rewards: new(), rewards: new(),
@ -3232,12 +3230,10 @@ impl Bank {
let feature_set = self.feature_set.clone(); let feature_set = self.feature_set.clone();
signature_count += u64::from(tx.message().header.num_required_signatures); signature_count += u64::from(tx.message().header.num_required_signatures);
let mut bpf_compute_budget = self let mut compute_budget = self.compute_budget.unwrap_or_else(ComputeBudget::new);
.bpf_compute_budget
.unwrap_or_else(BpfComputeBudget::new);
let mut process_result = if feature_set.is_active(&tx_wide_compute_cap::id()) { 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 { } else {
Ok(()) Ok(())
}; };
@ -3267,7 +3263,7 @@ impl Bank {
}; };
let compute_meter = Rc::new(RefCell::new(TransactionComputeMeter::new( 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( process_result = self.message_processor.process_message(
@ -3279,7 +3275,7 @@ impl Bank {
executors.clone(), executors.clone(),
instruction_recorders.as_deref(), instruction_recorders.as_deref(),
feature_set, feature_set,
bpf_compute_budget, compute_budget,
compute_meter, compute_meter,
&mut timings.details, &mut timings.details,
self.rc.accounts.clone(), self.rc.accounts.clone(),
@ -4434,8 +4430,17 @@ impl Bank {
*self.inflation.write().unwrap() = inflation; *self.inflation.write().unwrap() = inflation;
} }
pub fn set_bpf_compute_budget(&mut self, bpf_compute_budget: Option<BpfComputeBudget>) { pub fn set_compute_budget(&mut self, compute_budget: Option<ComputeBudget>) {
self.bpf_compute_budget = bpf_compute_budget; 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>> { pub fn hard_forks(&self) -> Arc<RwLock<HardForks>> {
@ -5556,7 +5561,7 @@ pub(crate) mod tests {
use solana_sdk::{ use solana_sdk::{
account::Account, account::Account,
clock::{DEFAULT_SLOTS_PER_EPOCH, DEFAULT_TICKS_PER_SLOT}, clock::{DEFAULT_SLOTS_PER_EPOCH, DEFAULT_TICKS_PER_SLOT},
compute_budget, compute_budget::ComputeBudgetInstruction,
epoch_schedule::MINIMUM_SLOTS_PER_EPOCH, epoch_schedule::MINIMUM_SLOTS_PER_EPOCH,
feature::Feature, feature::Feature,
genesis_config::create_genesis_config, genesis_config::create_genesis_config,
@ -13795,12 +13800,12 @@ pub(crate) mod tests {
_data: &[u8], _data: &[u8],
invoke_context: &mut dyn InvokeContext, invoke_context: &mut dyn InvokeContext,
) -> std::result::Result<(), InstructionError> { ) -> std::result::Result<(), InstructionError> {
let compute_budget = invoke_context.get_bpf_compute_budget(); let compute_budget = invoke_context.get_compute_budget();
assert_eq!( assert_eq!(
*compute_budget, *compute_budget,
BpfComputeBudget { ComputeBudget {
max_units: 1, max_units: 1,
..BpfComputeBudget::default() ..ComputeBudget::default()
} }
); );
Ok(()) Ok(())
@ -13810,7 +13815,7 @@ pub(crate) mod tests {
let message = Message::new( let message = Message::new(
&[ &[
compute_budget::request_units(1), ComputeBudgetInstruction::request_units(1),
Instruction::new_with_bincode(program_id, &0, vec![]), Instruction::new_with_bincode(program_id, &0, vec![]),
], ],
Some(&mint_keypair.pubkey()), Some(&mint_keypair.pubkey()),

View File

@ -9,6 +9,7 @@ use solana_sdk::{
account::{AccountSharedData, ReadableAccount, WritableAccount}, account::{AccountSharedData, ReadableAccount, WritableAccount},
account_utils::StateMut, account_utils::StateMut,
bpf_loader_upgradeable::{self, UpgradeableLoaderState}, bpf_loader_upgradeable::{self, UpgradeableLoaderState},
compute_budget::ComputeBudget,
feature_set::{ feature_set::{
instructions_sysvar_enabled, neon_evm_compute_budget, tx_wide_compute_cap, instructions_sysvar_enabled, neon_evm_compute_budget, tx_wide_compute_cap,
updated_verify_policy, FeatureSet, updated_verify_policy, FeatureSet,
@ -19,7 +20,7 @@ use solana_sdk::{
message::Message, message::Message,
native_loader, native_loader,
process_instruction::{ process_instruction::{
BpfComputeBudget, ComputeMeter, Executor, InvokeContext, InvokeContextStackFrame, Logger, ComputeMeter, Executor, InvokeContext, InvokeContextStackFrame, Logger,
ProcessInstructionWithContext, ProcessInstructionWithContext,
}, },
pubkey::Pubkey, pubkey::Pubkey,
@ -290,7 +291,9 @@ pub struct ThisInvokeContext<'a> {
accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)], accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)],
programs: &'a [(Pubkey, ProcessInstructionWithContext)], programs: &'a [(Pubkey, ProcessInstructionWithContext)],
logger: Rc<RefCell<dyn Logger>>, 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>>, compute_meter: Rc<RefCell<dyn ComputeMeter>>,
executors: Rc<RefCell<Executors>>, executors: Rc<RefCell<Executors>>,
instruction_recorder: Option<InstructionRecorder>, instruction_recorder: Option<InstructionRecorder>,
@ -312,7 +315,7 @@ impl<'a> ThisInvokeContext<'a> {
accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)], accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)],
programs: &'a [(Pubkey, ProcessInstructionWithContext)], programs: &'a [(Pubkey, ProcessInstructionWithContext)],
log_collector: Option<Rc<LogCollector>>, log_collector: Option<Rc<LogCollector>>,
bpf_compute_budget: BpfComputeBudget, compute_budget: ComputeBudget,
compute_meter: Rc<RefCell<dyn ComputeMeter>>, compute_meter: Rc<RefCell<dyn ComputeMeter>>,
executors: Rc<RefCell<Executors>>, executors: Rc<RefCell<Executors>>,
instruction_recorder: Option<InstructionRecorder>, instruction_recorder: Option<InstructionRecorder>,
@ -331,17 +334,18 @@ impl<'a> ThisInvokeContext<'a> {
compute_meter compute_meter
} else { } else {
Rc::new(RefCell::new(ThisComputeMeter { Rc::new(RefCell::new(ThisComputeMeter {
remaining: bpf_compute_budget.max_units, remaining: compute_budget.max_units,
})) }))
}; };
let mut invoke_context = Self { 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, rent,
pre_accounts, pre_accounts,
accounts, accounts,
programs, programs,
logger: Rc::new(RefCell::new(ThisLogger { log_collector })), logger: Rc::new(RefCell::new(ThisLogger { log_collector })),
bpf_compute_budget, compute_budget,
bpf_compute_budget: compute_budget.into(),
compute_meter, compute_meter,
executors, executors,
instruction_recorder, instruction_recorder,
@ -366,7 +370,7 @@ impl<'a> InvokeContext for ThisInvokeContext<'a> {
key: &Pubkey, key: &Pubkey,
keyed_accounts: &[(bool, bool, &Pubkey, &RefCell<AccountSharedData>)], keyed_accounts: &[(bool, bool, &Pubkey, &RefCell<AccountSharedData>)],
) -> Result<(), InstructionError> { ) -> 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); return Err(InstructionError::CallDepth);
} }
@ -470,7 +474,8 @@ impl<'a> InvokeContext for ThisInvokeContext<'a> {
fn get_logger(&self) -> Rc<RefCell<dyn Logger>> { fn get_logger(&self) -> Rc<RefCell<dyn Logger>> {
self.logger.clone() 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 &self.bpf_compute_budget
} }
fn get_compute_meter(&self) -> Rc<RefCell<dyn ComputeMeter>> { fn get_compute_meter(&self) -> Rc<RefCell<dyn ComputeMeter>> {
@ -531,6 +536,9 @@ impl<'a> InvokeContext for ThisInvokeContext<'a> {
None None
} }
} }
fn get_compute_budget(&self) -> &ComputeBudget {
&self.compute_budget
}
} }
pub struct ThisLogger { pub struct ThisLogger {
log_collector: Option<Rc<LogCollector>>, log_collector: Option<Rc<LogCollector>>,
@ -1155,7 +1163,7 @@ impl MessageProcessor {
instruction_recorder: Option<InstructionRecorder>, instruction_recorder: Option<InstructionRecorder>,
instruction_index: usize, instruction_index: usize,
feature_set: Arc<FeatureSet>, feature_set: Arc<FeatureSet>,
bpf_compute_budget: BpfComputeBudget, compute_budget: ComputeBudget,
compute_meter: Rc<RefCell<dyn ComputeMeter>>, compute_meter: Rc<RefCell<dyn ComputeMeter>>,
timings: &mut ExecuteDetailsTimings, timings: &mut ExecuteDetailsTimings,
account_db: Arc<Accounts>, account_db: Arc<Accounts>,
@ -1178,13 +1186,13 @@ impl MessageProcessor {
let program_id = instruction.program_id(&message.account_keys); 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()) if feature_set.is_active(&neon_evm_compute_budget::id())
&& *program_id == crate::neon_evm_program::id() && *program_id == crate::neon_evm_program::id()
{ {
// Bump the compute budget for neon_evm // Bump the compute budget for neon_evm
bpf_compute_budget.max_units = bpf_compute_budget.max_units.max(500_000); compute_budget.max_units = compute_budget.max_units.max(500_000);
bpf_compute_budget.heap_size = Some(256 * 1024); compute_budget.heap_size = Some(256 * 1024);
} }
let mut invoke_context = ThisInvokeContext::new( let mut invoke_context = ThisInvokeContext::new(
@ -1196,7 +1204,7 @@ impl MessageProcessor {
accounts, accounts,
&self.programs, &self.programs,
log_collector, log_collector,
bpf_compute_budget, compute_budget,
compute_meter, compute_meter,
executors, executors,
instruction_recorder, instruction_recorder,
@ -1237,7 +1245,7 @@ impl MessageProcessor {
executors: Rc<RefCell<Executors>>, executors: Rc<RefCell<Executors>>,
instruction_recorders: Option<&[InstructionRecorder]>, instruction_recorders: Option<&[InstructionRecorder]>,
feature_set: Arc<FeatureSet>, feature_set: Arc<FeatureSet>,
bpf_compute_budget: BpfComputeBudget, compute_budget: ComputeBudget,
compute_meter: Rc<RefCell<dyn ComputeMeter>>, compute_meter: Rc<RefCell<dyn ComputeMeter>>,
timings: &mut ExecuteDetailsTimings, timings: &mut ExecuteDetailsTimings,
account_db: Arc<Accounts>, account_db: Arc<Accounts>,
@ -1261,7 +1269,7 @@ impl MessageProcessor {
instruction_recorder, instruction_recorder,
instruction_index, instruction_index,
feature_set.clone(), feature_set.clone(),
bpf_compute_budget, compute_budget,
compute_meter.clone(), compute_meter.clone(),
timings, timings,
account_db.clone(), account_db.clone(),
@ -1338,7 +1346,7 @@ mod tests {
&accounts, &accounts,
&[], &[],
None, None,
BpfComputeBudget::default(), ComputeBudget::default(),
Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(MockComputeMeter::default())),
Rc::new(RefCell::new(Executors::default())), Rc::new(RefCell::new(Executors::default())),
None, None,
@ -1952,7 +1960,7 @@ mod tests {
executors.clone(), executors.clone(),
None, None,
Arc::new(FeatureSet::all_enabled()), Arc::new(FeatureSet::all_enabled()),
BpfComputeBudget::new(), ComputeBudget::new(),
Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(MockComputeMeter::default())),
&mut ExecuteDetailsTimings::default(), &mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default()), Arc::new(Accounts::default()),
@ -1980,7 +1988,7 @@ mod tests {
executors.clone(), executors.clone(),
None, None,
Arc::new(FeatureSet::all_enabled()), Arc::new(FeatureSet::all_enabled()),
BpfComputeBudget::new(), ComputeBudget::new(),
Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(MockComputeMeter::default())),
&mut ExecuteDetailsTimings::default(), &mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default()), Arc::new(Accounts::default()),
@ -2012,7 +2020,7 @@ mod tests {
executors, executors,
None, None,
Arc::new(FeatureSet::all_enabled()), Arc::new(FeatureSet::all_enabled()),
BpfComputeBudget::new(), ComputeBudget::new(),
Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(MockComputeMeter::default())),
&mut ExecuteDetailsTimings::default(), &mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default()), Arc::new(Accounts::default()),
@ -2136,7 +2144,7 @@ mod tests {
executors.clone(), executors.clone(),
None, None,
Arc::new(FeatureSet::all_enabled()), Arc::new(FeatureSet::all_enabled()),
BpfComputeBudget::new(), ComputeBudget::new(),
Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(MockComputeMeter::default())),
&mut ExecuteDetailsTimings::default(), &mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default()), Arc::new(Accounts::default()),
@ -2168,7 +2176,7 @@ mod tests {
executors.clone(), executors.clone(),
None, None,
Arc::new(FeatureSet::all_enabled()), Arc::new(FeatureSet::all_enabled()),
BpfComputeBudget::new(), ComputeBudget::new(),
Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(MockComputeMeter::default())),
&mut ExecuteDetailsTimings::default(), &mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default()), Arc::new(Accounts::default()),
@ -2198,7 +2206,7 @@ mod tests {
executors, executors,
None, None,
Arc::new(FeatureSet::all_enabled()), Arc::new(FeatureSet::all_enabled()),
BpfComputeBudget::new(), ComputeBudget::new(),
Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(MockComputeMeter::default())),
&mut ExecuteDetailsTimings::default(), &mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default()), Arc::new(Accounts::default()),
@ -2300,7 +2308,7 @@ mod tests {
&accounts, &accounts,
programs.as_slice(), programs.as_slice(),
None, None,
BpfComputeBudget::default(), ComputeBudget::default(),
Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(MockComputeMeter::default())),
Rc::new(RefCell::new(Executors::default())), Rc::new(RefCell::new(Executors::default())),
None, None,
@ -2357,7 +2365,7 @@ mod tests {
&accounts, &accounts,
programs.as_slice(), programs.as_slice(),
None, None,
BpfComputeBudget::default(), ComputeBudget::default(),
Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(MockComputeMeter::default())),
Rc::new(RefCell::new(Executors::default())), Rc::new(RefCell::new(Executors::default())),
None, None,

View File

@ -1,9 +1,6 @@
#![cfg(feature = "full")] #![cfg(feature = "full")]
use crate::{ use crate::transaction::{Transaction, TransactionError};
process_instruction::BpfComputeBudget,
transaction::{Transaction, TransactionError},
};
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
use solana_sdk::{ use solana_sdk::{
borsh::try_from_slice_unchecked, borsh::try_from_slice_unchecked,
@ -32,70 +29,126 @@ pub enum ComputeBudgetInstruction {
/// allowed to consume. /// allowed to consume.
RequestUnits(u64), RequestUnits(u64),
} }
impl ComputeBudgetInstruction {
/// Create a `ComputeBudgetInstruction::RequestUnits` `Instruction` /// Create a `ComputeBudgetInstruction::RequestUnits` `Instruction`
pub fn request_units(units: u64) -> Instruction { pub fn request_units(units: u64) -> Instruction {
Instruction::new_with_borsh(id(), &ComputeBudgetInstruction::RequestUnits(units), vec![]) Instruction::new_with_borsh(id(), &ComputeBudgetInstruction::RequestUnits(units), vec![])
}
} }
pub fn process_request( #[derive(Clone, Copy, Debug, AbiExample, PartialEq)]
compute_budget: &mut BpfComputeBudget, pub struct ComputeBudget {
tx: &Transaction, /// Number of compute units that an instruction is allowed. Compute units
) -> Result<(), TransactionError> { /// are consumed by program execution, resources they use, etc...
let error = TransactionError::InstructionError(0, InstructionError::InvalidInstructionData); pub max_units: u64,
// Compute budget instruction must be in 1st or 2nd instruction (avoid nonce marker) /// Number of compute units consumed by a log_u64 call
for instruction in tx.message().instructions.iter().take(2) { pub log_64_units: u64,
if check_id(instruction.program_id(&tx.message().account_keys)) { /// Number of compute units consumed by a create_program_address call
let ComputeBudgetInstruction::RequestUnits(units) = pub create_program_address_units: u64,
try_from_slice_unchecked::<ComputeBudgetInstruction>(&instruction.data) /// Number of compute units consumed by an invoke call (not including the cost incurred by
.map_err(|_| error.clone())?; /// the called program)
if units > MAX_UNITS { pub invoke_units: u64,
return Err(error); /// Maximum cross-program invocation depth allowed
} pub max_invoke_depth: usize,
compute_budget.max_units = units; /// 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)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::{ use crate::{hash::Hash, message::Message, pubkey::Pubkey, signature::Keypair, signer::Signer};
compute_budget, hash::Hash, message::Message, pubkey::Pubkey, signature::Keypair,
signer::Signer,
};
#[test] #[test]
fn test_process_request() { fn test_process_transaction() {
let payer_keypair = Keypair::new(); let payer_keypair = Keypair::new();
let mut compute_budget = BpfComputeBudget::default(); let mut compute_budget = ComputeBudget::default();
let tx = Transaction::new( let tx = Transaction::new(
&[&payer_keypair], &[&payer_keypair],
Message::new(&[], Some(&payer_keypair.pubkey())), Message::new(&[], Some(&payer_keypair.pubkey())),
Hash::default(), Hash::default(),
); );
process_request(&mut compute_budget, &tx).unwrap(); compute_budget.process_transaction(&tx).unwrap();
assert_eq!(compute_budget, BpfComputeBudget::default()); assert_eq!(compute_budget, ComputeBudget::default());
let tx = Transaction::new( let tx = Transaction::new(
&[&payer_keypair], &[&payer_keypair],
Message::new( Message::new(
&[ &[
compute_budget::request_units(1), ComputeBudgetInstruction::request_units(1),
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]), Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
], ],
Some(&payer_keypair.pubkey()), Some(&payer_keypair.pubkey()),
), ),
Hash::default(), Hash::default(),
); );
process_request(&mut compute_budget, &tx).unwrap(); compute_budget.process_transaction(&tx).unwrap();
assert_eq!( assert_eq!(
compute_budget, compute_budget,
BpfComputeBudget { ComputeBudget {
max_units: 1, max_units: 1,
..BpfComputeBudget::default() ..ComputeBudget::default()
} }
); );
@ -103,14 +156,14 @@ mod tests {
&[&payer_keypair], &[&payer_keypair],
Message::new( Message::new(
&[ &[
compute_budget::request_units(MAX_UNITS + 1), ComputeBudgetInstruction::request_units(MAX_UNITS + 1),
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]), Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
], ],
Some(&payer_keypair.pubkey()), Some(&payer_keypair.pubkey()),
), ),
Hash::default(), Hash::default(),
); );
let result = process_request(&mut compute_budget, &tx); let result = compute_budget.process_transaction(&tx);
assert_eq!( assert_eq!(
result, result,
Err(TransactionError::InstructionError( Err(TransactionError::InstructionError(
@ -124,18 +177,18 @@ mod tests {
Message::new( Message::new(
&[ &[
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]), Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
compute_budget::request_units(MAX_UNITS), ComputeBudgetInstruction::request_units(MAX_UNITS),
], ],
Some(&payer_keypair.pubkey()), Some(&payer_keypair.pubkey()),
), ),
Hash::default(), Hash::default(),
); );
process_request(&mut compute_budget, &tx).unwrap(); compute_budget.process_transaction(&tx).unwrap();
assert_eq!( assert_eq!(
compute_budget, compute_budget,
BpfComputeBudget { ComputeBudget {
max_units: MAX_UNITS, max_units: MAX_UNITS,
..BpfComputeBudget::default() ..ComputeBudget::default()
} }
); );
} }

View File

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

View File

@ -1,5 +1,8 @@
#![cfg(feature = "full")]
use solana_sdk::{ use solana_sdk::{
account::AccountSharedData, account::AccountSharedData,
compute_budget::ComputeBudget,
instruction::{CompiledInstruction, Instruction, InstructionError}, instruction::{CompiledInstruction, Instruction, InstructionError},
keyed_account::{create_keyed_accounts_unified, KeyedAccount}, keyed_account::{create_keyed_accounts_unified, KeyedAccount},
pubkey::Pubkey, pubkey::Pubkey,
@ -76,6 +79,8 @@ pub trait InvokeContext {
/// Get this invocation's logger /// Get this invocation's logger
fn get_logger(&self) -> Rc<RefCell<dyn Logger>>; fn get_logger(&self) -> Rc<RefCell<dyn Logger>>;
/// Get this invocation's compute budget /// 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; fn get_bpf_compute_budget(&self) -> &BpfComputeBudget;
/// Get this invocation's compute meter /// Get this invocation's compute meter
fn get_compute_meter(&self) -> Rc<RefCell<dyn ComputeMeter>>; fn get_compute_meter(&self) -> Rc<RefCell<dyn ComputeMeter>>;
@ -100,6 +105,8 @@ pub trait InvokeContext {
); );
/// Get sysvar data /// Get sysvar data
fn get_sysvar_data(&self, id: &Pubkey) -> Option<Rc<Vec<u8>>>; 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>>` /// 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 { pub struct BpfComputeBudget {
/// Number of compute units that an instruction is allowed. Compute units /// Number of compute units that an instruction is allowed. Compute units
/// are consumed by program execution, resources they use, etc... /// 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 /// Optional program heap region size, if `None` then loader default
pub heap_size: Option<usize>, pub heap_size: Option<usize>,
} }
impl Default for BpfComputeBudget { #[allow(deprecated)]
fn default() -> Self { impl From<ComputeBudget> for BpfComputeBudget {
Self::new() 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 { impl BpfComputeBudget {
pub fn new() -> Self { pub fn new() -> Self {
BpfComputeBudget { BpfComputeBudget::default()
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,
}
} }
} }
@ -336,9 +374,12 @@ impl Logger for MockLogger {
} }
} }
#[allow(deprecated)]
pub struct MockInvokeContext<'a> { pub struct MockInvokeContext<'a> {
pub invoke_stack: Vec<InvokeContextStackFrame<'a>>, pub invoke_stack: Vec<InvokeContextStackFrame<'a>>,
pub logger: MockLogger, pub logger: MockLogger,
pub compute_budget: ComputeBudget,
#[allow(deprecated)]
pub bpf_compute_budget: BpfComputeBudget, pub bpf_compute_budget: BpfComputeBudget,
pub compute_meter: MockComputeMeter, pub compute_meter: MockComputeMeter,
pub programs: Vec<(Pubkey, ProcessInstructionWithContext)>, pub programs: Vec<(Pubkey, ProcessInstructionWithContext)>,
@ -348,11 +389,13 @@ pub struct MockInvokeContext<'a> {
} }
impl<'a> MockInvokeContext<'a> { impl<'a> MockInvokeContext<'a> {
pub fn new(keyed_accounts: Vec<KeyedAccount<'a>>) -> Self { 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 { 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(), logger: MockLogger::default(),
bpf_compute_budget, compute_budget,
#[allow(deprecated)]
bpf_compute_budget: compute_budget.into(),
compute_meter: MockComputeMeter { compute_meter: MockComputeMeter {
remaining: std::i64::MAX as u64, remaining: std::i64::MAX as u64,
}, },
@ -442,7 +485,9 @@ impl<'a> InvokeContext for MockInvokeContext<'a> {
fn get_logger(&self) -> Rc<RefCell<dyn Logger>> { fn get_logger(&self) -> Rc<RefCell<dyn Logger>> {
Rc::new(RefCell::new(self.logger.clone())) Rc::new(RefCell::new(self.logger.clone()))
} }
#[allow(deprecated)]
fn get_bpf_compute_budget(&self) -> &BpfComputeBudget { fn get_bpf_compute_budget(&self) -> &BpfComputeBudget {
#[allow(deprecated)]
&self.bpf_compute_budget &self.bpf_compute_budget
} }
fn get_compute_meter(&self) -> Rc<RefCell<dyn ComputeMeter>> { fn get_compute_meter(&self) -> Rc<RefCell<dyn ComputeMeter>> {
@ -477,4 +522,7 @@ impl<'a> InvokeContext for MockInvokeContext<'a> {
.iter() .iter()
.find_map(|(key, sysvar)| if id == key { sysvar.clone() } else { None }) .find_map(|(key, sysvar)| if id == key { sysvar.clone() } else { None })
} }
fn get_compute_budget(&self) -> &ComputeBudget {
&self.compute_budget
}
} }