Native/builtin programs now receive an InvokeContext (bp #13286) (#13298)

* Native/builtin programs now receive an InvokeContext

(cherry picked from commit df8dab9d2b)

* Remove MessageProcessor::loaders

(cherry picked from commit 2664a1f7ef)

* Remove Entrypoint type

(cherry picked from commit 225bed11c7)

* Remove programs clone()

(cherry picked from commit 33884d847a)

* Add sol_log_compute_units syscall

(cherry picked from commit 66e51a7363)

* Add Bank::set_bpf_compute_budget()

(cherry picked from commit 7d686b72a0)

* Rebase

Co-authored-by: Michael Vines <mvines@gmail.com>
This commit is contained in:
mergify[bot]
2020-10-30 07:47:17 +00:00
committed by GitHub
parent 36b7c2ea97
commit 40a3885d3b
43 changed files with 631 additions and 477 deletions

View File

@@ -16,17 +16,15 @@ use solana_rbpf::{
memory_region::MemoryRegion,
vm::{Config, EbpfVm, Executable, InstructionMeter},
};
use solana_runtime::{
feature_set::compute_budget_balancing,
process_instruction::{ComputeMeter, Executor, InvokeContext},
};
use solana_sdk::{
bpf_loader, bpf_loader_deprecated,
decode_error::DecodeError,
entrypoint::SUCCESS,
feature_set::bpf_compute_budget_balancing,
instruction::InstructionError,
keyed_account::{is_executable, next_keyed_account, KeyedAccount},
loader_instruction::LoaderInstruction,
process_instruction::{ComputeMeter, Executor, InvokeContext},
program_utils::limited_deserialize,
pubkey::Pubkey,
};
@@ -101,7 +99,7 @@ pub fn create_and_cache_executor(
.map_err(|e| map_ebpf_error(invoke_context, e))?;
bpf_verifier::check(
elf_bytes,
!invoke_context.is_feature_active(&compute_budget_balancing::id()),
!invoke_context.is_feature_active(&bpf_compute_budget_balancing::id()),
)
.map_err(|e| map_ebpf_error(invoke_context, EbpfError::UserError(e)))?;
let executor = Arc::new(BPFExecutor { executable });
@@ -116,12 +114,12 @@ pub fn create_vm<'a>(
parameter_accounts: &'a [KeyedAccount<'a>],
invoke_context: &'a mut dyn InvokeContext,
) -> Result<(EbpfVm<'a, BPFError>, MemoryRegion), EbpfError<BPFError>> {
let compute_budget = invoke_context.get_compute_budget();
let bpf_compute_budget = invoke_context.get_bpf_compute_budget();
let mut vm = EbpfVm::new(
executable,
Config {
max_call_depth: compute_budget.max_call_depth,
stack_frame_size: compute_budget.stack_frame_size,
max_call_depth: bpf_compute_budget.max_call_depth,
stack_frame_size: bpf_compute_budget.stack_frame_size,
},
)?;
let heap_region =
@@ -312,13 +310,14 @@ impl Executor for BPFExecutor {
mod tests {
use super::*;
use rand::Rng;
use solana_runtime::{
bpf_test_utils::MockInvokeContext,
use solana_runtime::message_processor::{Executors, ThisInvokeContext};
use solana_sdk::{
account::Account,
feature_set::FeatureSet,
message_processor::{Executors, ThisInvokeContext},
process_instruction::ComputeBudget,
instruction::InstructionError,
process_instruction::{BpfComputeBudget, MockInvokeContext},
rent::Rent,
};
use solana_sdk::{account::Account, rent::Rent};
use std::{cell::RefCell, fs::File, io::Read, ops::Range, rc::Rc};
struct TestInstructionMeter {
@@ -533,9 +532,9 @@ mod tests {
&program_id,
Rent::default(),
vec![],
vec![],
&[],
None,
ComputeBudget {
BpfComputeBudget {
max_units: 1,
log_units: 100,
log_64_units: 100,

View File

@@ -7,22 +7,21 @@ use solana_rbpf::{
memory_region::{translate_addr, MemoryRegion},
vm::{EbpfVm, SyscallObject},
};
use solana_runtime::{
feature_set::{
pubkey_log_syscall_enabled, ristretto_mul_syscall_enabled, sha256_syscall_enabled,
},
message_processor::MessageProcessor,
process_instruction::{ComputeMeter, InvokeContext, Logger},
};
use solana_runtime::message_processor::MessageProcessor;
use solana_sdk::{
account::Account,
account_info::AccountInfo,
bpf_loader, bpf_loader_deprecated,
bpf_loader_deprecated,
entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS},
feature_set::{
pubkey_log_syscall_enabled, ristretto_mul_syscall_enabled, sha256_syscall_enabled,
sol_log_compute_units_syscall,
},
hash::{Hasher, HASH_BYTES},
instruction::{AccountMeta, Instruction, InstructionError},
keyed_account::KeyedAccount,
message::Message,
process_instruction::{ComputeMeter, InvokeContext, Logger},
program_error::ProgramError,
pubkey::{Pubkey, PubkeyError},
};
@@ -98,7 +97,7 @@ pub fn register_syscalls<'a>(
callers_keyed_accounts: &'a [KeyedAccount<'a>],
invoke_context: &'a mut dyn InvokeContext,
) -> Result<MemoryRegion, 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
@@ -107,7 +106,7 @@ pub fn register_syscalls<'a>(
vm.register_syscall_with_context_ex(
"sol_log_",
Box::new(SyscallLog {
cost: compute_budget.log_units,
cost: bpf_compute_budget.log_units,
compute_meter: invoke_context.get_compute_meter(),
logger: invoke_context.get_logger(),
loader_id,
@@ -116,17 +115,27 @@ pub fn register_syscalls<'a>(
vm.register_syscall_with_context_ex(
"sol_log_64_",
Box::new(SyscallLogU64 {
cost: compute_budget.log_64_units,
cost: bpf_compute_budget.log_64_units,
compute_meter: invoke_context.get_compute_meter(),
logger: invoke_context.get_logger(),
}),
)?;
if invoke_context.is_feature_active(&sol_log_compute_units_syscall::id()) {
vm.register_syscall_with_context_ex(
"sol_log_compute_units_",
Box::new(SyscallLogBpfComputeUnits {
cost: 0,
compute_meter: invoke_context.get_compute_meter(),
logger: invoke_context.get_logger(),
}),
)?;
}
if invoke_context.is_feature_active(&pubkey_log_syscall_enabled::id()) {
vm.register_syscall_with_context_ex(
"sol_log_pubkey",
Box::new(SyscallLogPubkey {
cost: compute_budget.log_pubkey_units,
cost: bpf_compute_budget.log_pubkey_units,
compute_meter: invoke_context.get_compute_meter(),
logger: invoke_context.get_logger(),
loader_id,
@@ -138,8 +147,8 @@ pub fn register_syscalls<'a>(
vm.register_syscall_with_context_ex(
"sol_sha256",
Box::new(SyscallSha256 {
sha256_base_cost: compute_budget.sha256_base_cost,
sha256_byte_cost: compute_budget.sha256_byte_cost,
sha256_base_cost: bpf_compute_budget.sha256_base_cost,
sha256_byte_cost: bpf_compute_budget.sha256_byte_cost,
compute_meter: invoke_context.get_compute_meter(),
loader_id,
}),
@@ -160,7 +169,7 @@ pub fn register_syscalls<'a>(
vm.register_syscall_with_context_ex(
"sol_create_program_address",
Box::new(SyscallCreateProgramAddress {
cost: compute_budget.create_program_address_units,
cost: bpf_compute_budget.create_program_address_units,
compute_meter: invoke_context.get_compute_meter(),
loader_id,
}),
@@ -414,6 +423,38 @@ impl SyscallObject<BPFError> for SyscallLogU64 {
}
}
/// Log current compute consumption
pub struct SyscallLogBpfComputeUnits {
cost: u64,
compute_meter: Rc<RefCell<dyn ComputeMeter>>,
logger: Rc<RefCell<dyn Logger>>,
}
impl SyscallObject<BPFError> for SyscallLogBpfComputeUnits {
fn call(
&mut self,
_arg1: u64,
_arg2: u64,
_arg3: u64,
_arg4: u64,
_arg5: u64,
_ro_regions: &[MemoryRegion],
_rw_regions: &[MemoryRegion],
) -> Result<u64, EbpfError<BPFError>> {
self.compute_meter.consume(self.cost)?;
let mut logger = self
.logger
.try_borrow_mut()
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
if logger.log_enabled() {
logger.log(&format!(
"Program consumption: {} units remaining",
self.compute_meter.borrow().get_remaining()
));
}
Ok(0)
}
}
/// Log 5 64-bit values
pub struct SyscallLogPubkey<'a> {
cost: u64,
@@ -1147,7 +1188,7 @@ fn call<'a>(
let mut invoke_context = syscall.get_context_mut()?;
invoke_context
.get_compute_meter()
.consume(invoke_context.get_compute_budget().invoke_units)?;
.consume(invoke_context.get_bpf_compute_budget().invoke_units)?;
// Translate data passed from the VM
@@ -1185,8 +1226,6 @@ fn call<'a>(
for (program_id, process_instruction) in invoke_context.get_programs().iter() {
message_processor.add_program(*program_id, *process_instruction);
}
message_processor.add_loader(bpf_loader::id(), crate::process_instruction);
message_processor.add_loader(bpf_loader_deprecated::id(), crate::process_instruction);
#[allow(clippy::deref_addrof)]
match message_processor.process_cross_program_instruction(
@@ -1237,8 +1276,11 @@ fn call<'a>(
#[cfg(test)]
mod tests {
use super::*;
use solana_runtime::bpf_test_utils::{MockComputeMeter, MockLogger};
use solana_sdk::hash::hashv;
use solana_sdk::{
bpf_loader,
hash::hashv,
process_instruction::{MockComputeMeter, MockLogger},
};
use std::str::FromStr;
macro_rules! assert_access_violation {