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