Refactor: Use InvokeContext in all Syscalls (#21545)
* Adds ComputeMeter::mock_set_remaining(). * Adds InvokeContext::get_loader() * Adds a LogCollector to InvokeContext::new_mock(). * Adds "invoke_context: Rc<RefCell<&'a mut dyn InvokeContext>>," to all SyscallObjects. * Adds LogCollector::get_recorded_content(). * Removes loader_id parameter from bind_syscall_context_objects() and create_vm().
This commit is contained in:
committed by
GitHub
parent
9079de825b
commit
6330cbcf33
@ -92,19 +92,25 @@ impl ComputeMeter {
|
|||||||
pub fn get_remaining(&self) -> u64 {
|
pub fn get_remaining(&self) -> u64 {
|
||||||
self.remaining
|
self.remaining
|
||||||
}
|
}
|
||||||
|
/// Set compute units
|
||||||
|
///
|
||||||
|
/// Only use for tests and benchmarks
|
||||||
|
pub fn mock_set_remaining(&mut self, remaining: u64) {
|
||||||
|
self.remaining = remaining;
|
||||||
|
}
|
||||||
/// Construct a new one with the given remaining units
|
/// Construct a new one with the given remaining units
|
||||||
pub fn new_ref(remaining: u64) -> Rc<RefCell<Self>> {
|
pub fn new_ref(remaining: u64) -> Rc<RefCell<Self>> {
|
||||||
Rc::new(RefCell::new(Self { remaining }))
|
Rc::new(RefCell::new(Self { remaining }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InvokeContextStackFrame<'a> {
|
pub struct StackFrame<'a> {
|
||||||
pub number_of_program_accounts: usize,
|
pub number_of_program_accounts: usize,
|
||||||
pub keyed_accounts: Vec<KeyedAccount<'a>>,
|
pub keyed_accounts: Vec<KeyedAccount<'a>>,
|
||||||
pub keyed_accounts_range: std::ops::Range<usize>,
|
pub keyed_accounts_range: std::ops::Range<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> InvokeContextStackFrame<'a> {
|
impl<'a> StackFrame<'a> {
|
||||||
pub fn new(number_of_program_accounts: usize, keyed_accounts: Vec<KeyedAccount<'a>>) -> Self {
|
pub fn new(number_of_program_accounts: usize, keyed_accounts: Vec<KeyedAccount<'a>>) -> Self {
|
||||||
let keyed_accounts_range = std::ops::Range {
|
let keyed_accounts_range = std::ops::Range {
|
||||||
start: 0,
|
start: 0,
|
||||||
@ -126,7 +132,7 @@ impl<'a> InvokeContextStackFrame<'a> {
|
|||||||
|
|
||||||
pub struct ThisInvokeContext<'a> {
|
pub struct ThisInvokeContext<'a> {
|
||||||
instruction_index: usize,
|
instruction_index: usize,
|
||||||
invoke_stack: Vec<InvokeContextStackFrame<'a>>,
|
invoke_stack: Vec<StackFrame<'a>>,
|
||||||
rent: Rent,
|
rent: Rent,
|
||||||
pre_accounts: Vec<PreAccount>,
|
pre_accounts: Vec<PreAccount>,
|
||||||
accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)],
|
accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)],
|
||||||
@ -193,7 +199,7 @@ impl<'a> ThisInvokeContext<'a> {
|
|||||||
accounts,
|
accounts,
|
||||||
builtin_programs,
|
builtin_programs,
|
||||||
sysvars,
|
sysvars,
|
||||||
None,
|
Some(LogCollector::new_ref()),
|
||||||
ComputeBudget::default(),
|
ComputeBudget::default(),
|
||||||
ComputeMeter::new_ref(std::i64::MAX as u64),
|
ComputeMeter::new_ref(std::i64::MAX as u64),
|
||||||
Rc::new(RefCell::new(Executors::default())),
|
Rc::new(RefCell::new(Executors::default())),
|
||||||
@ -269,6 +275,8 @@ pub trait InvokeContext {
|
|||||||
fn process_instruction(&mut self, instruction_data: &[u8]) -> Result<(), InstructionError>;
|
fn process_instruction(&mut self, instruction_data: &[u8]) -> Result<(), InstructionError>;
|
||||||
/// Get the program ID of the currently executing program
|
/// Get the program ID of the currently executing program
|
||||||
fn get_caller(&self) -> Result<&Pubkey, InstructionError>;
|
fn get_caller(&self) -> Result<&Pubkey, InstructionError>;
|
||||||
|
/// Get the owner of the currently executing program
|
||||||
|
fn get_loader(&self) -> Result<Pubkey, InstructionError>;
|
||||||
/// Removes the first keyed account
|
/// Removes the first keyed account
|
||||||
#[deprecated(
|
#[deprecated(
|
||||||
since = "1.9.0",
|
since = "1.9.0",
|
||||||
@ -416,7 +424,7 @@ impl<'a> InvokeContext for ThisInvokeContext<'a> {
|
|||||||
}))
|
}))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
self.invoke_stack.push(InvokeContextStackFrame::new(
|
self.invoke_stack.push(StackFrame::new(
|
||||||
program_indices.len(),
|
program_indices.len(),
|
||||||
create_keyed_accounts_unified(keyed_accounts.as_slice()),
|
create_keyed_accounts_unified(keyed_accounts.as_slice()),
|
||||||
));
|
));
|
||||||
@ -800,6 +808,11 @@ impl<'a> InvokeContext for ThisInvokeContext<'a> {
|
|||||||
.and_then(|frame| frame.program_id())
|
.and_then(|frame| frame.program_id())
|
||||||
.ok_or(InstructionError::CallDepth)
|
.ok_or(InstructionError::CallDepth)
|
||||||
}
|
}
|
||||||
|
fn get_loader(&self) -> Result<Pubkey, InstructionError> {
|
||||||
|
self.get_instruction_keyed_accounts()
|
||||||
|
.and_then(|keyed_accounts| keyed_accounts.first().ok_or(InstructionError::CallDepth))
|
||||||
|
.and_then(|keyed_account| keyed_account.owner())
|
||||||
|
}
|
||||||
fn remove_first_keyed_account(&mut self) -> Result<(), InstructionError> {
|
fn remove_first_keyed_account(&mut self) -> Result<(), InstructionError> {
|
||||||
if !self.is_feature_active(&remove_native_loader::id()) {
|
if !self.is_feature_active(&remove_native_loader::id()) {
|
||||||
let stack_frame = &mut self
|
let stack_frame = &mut self
|
||||||
|
@ -24,6 +24,10 @@ impl LogCollector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_recorded_content(&self) -> &[String] {
|
||||||
|
self.messages.as_slice()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new_ref() -> Rc<RefCell<Self>> {
|
pub fn new_ref() -> Rc<RefCell<Self>> {
|
||||||
Rc::new(RefCell::new(Self::default()))
|
Rc::new(RefCell::new(Self::default()))
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,10 @@ use solana_bpf_loader_program::{
|
|||||||
};
|
};
|
||||||
use solana_measure::measure::Measure;
|
use solana_measure::measure::Measure;
|
||||||
use solana_program_runtime::invoke_context::{with_mock_invoke_context, InvokeContext};
|
use solana_program_runtime::invoke_context::{with_mock_invoke_context, InvokeContext};
|
||||||
use solana_rbpf::{elf::Executable, vm::{Config, InstructionMeter, SyscallRegistry}};
|
use solana_rbpf::{
|
||||||
|
elf::Executable,
|
||||||
|
vm::{Config, InstructionMeter, SyscallRegistry},
|
||||||
|
};
|
||||||
use solana_runtime::{
|
use solana_runtime::{
|
||||||
bank::Bank,
|
bank::Bank,
|
||||||
bank_client::BankClient,
|
bank_client::BankClient,
|
||||||
@ -107,7 +110,6 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
|||||||
let compute_meter = invoke_context.get_compute_meter();
|
let compute_meter = invoke_context.get_compute_meter();
|
||||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||||
let mut vm = create_vm(
|
let mut vm = create_vm(
|
||||||
&loader_id,
|
|
||||||
&executable,
|
&executable,
|
||||||
&mut inner_iter,
|
&mut inner_iter,
|
||||||
invoke_context,
|
invoke_context,
|
||||||
@ -203,12 +205,7 @@ fn bench_create_vm(bencher: &mut Bencher) {
|
|||||||
let loader_id = bpf_loader::id();
|
let loader_id = bpf_loader::id();
|
||||||
with_mock_invoke_context(loader_id, 10000001, |invoke_context| {
|
with_mock_invoke_context(loader_id, 10000001, |invoke_context| {
|
||||||
const BUDGET: u64 = 200_000;
|
const BUDGET: u64 = 200_000;
|
||||||
let compute_meter = invoke_context.get_compute_meter();
|
invoke_context.get_compute_meter().borrow_mut().mock_set_remaining(BUDGET);
|
||||||
{
|
|
||||||
let mut compute_meter = compute_meter.borrow_mut();
|
|
||||||
let to_consume = compute_meter.get_remaining() - BUDGET;
|
|
||||||
compute_meter.consume(to_consume).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize account data
|
// Serialize account data
|
||||||
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
||||||
@ -230,7 +227,6 @@ fn bench_create_vm(bencher: &mut Bencher) {
|
|||||||
|
|
||||||
bencher.iter(|| {
|
bencher.iter(|| {
|
||||||
let _ = create_vm(
|
let _ = create_vm(
|
||||||
&loader_id,
|
|
||||||
&executable,
|
&executable,
|
||||||
serialized.as_slice_mut(),
|
serialized.as_slice_mut(),
|
||||||
invoke_context,
|
invoke_context,
|
||||||
@ -247,12 +243,7 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
|||||||
let loader_id = bpf_loader::id();
|
let loader_id = bpf_loader::id();
|
||||||
with_mock_invoke_context(loader_id, 10000001, |invoke_context| {
|
with_mock_invoke_context(loader_id, 10000001, |invoke_context| {
|
||||||
const BUDGET: u64 = 200_000;
|
const BUDGET: u64 = 200_000;
|
||||||
let compute_meter = invoke_context.get_compute_meter();
|
invoke_context.get_compute_meter().borrow_mut().mock_set_remaining(BUDGET);
|
||||||
{
|
|
||||||
let mut compute_meter = compute_meter.borrow_mut();
|
|
||||||
let to_consume = compute_meter.get_remaining() - BUDGET;
|
|
||||||
compute_meter.consume(to_consume).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize account data
|
// Serialize account data
|
||||||
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
||||||
@ -271,9 +262,9 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
|||||||
register_syscalls(invoke_context).unwrap(),
|
register_syscalls(invoke_context).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let compute_meter = invoke_context.get_compute_meter();
|
||||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||||
let mut vm = create_vm(
|
let mut vm = create_vm(
|
||||||
&loader_id,
|
|
||||||
&executable,
|
&executable,
|
||||||
serialized.as_slice_mut(),
|
serialized.as_slice_mut(),
|
||||||
invoke_context,
|
invoke_context,
|
||||||
|
@ -227,7 +227,6 @@ fn run_program(name: &str) -> u64 {
|
|||||||
let mut parameter_bytes = parameter_bytes.clone();
|
let mut parameter_bytes = parameter_bytes.clone();
|
||||||
{
|
{
|
||||||
let mut vm = create_vm(
|
let mut vm = create_vm(
|
||||||
&loader_id,
|
|
||||||
&executable,
|
&executable,
|
||||||
parameter_bytes.as_slice_mut(),
|
parameter_bytes.as_slice_mut(),
|
||||||
invoke_context,
|
invoke_context,
|
||||||
|
@ -151,7 +151,6 @@ fn check_loader_id(id: &Pubkey) -> bool {
|
|||||||
|
|
||||||
/// Create the BPF virtual machine
|
/// Create the BPF virtual machine
|
||||||
pub fn create_vm<'a>(
|
pub fn create_vm<'a>(
|
||||||
loader_id: &'a Pubkey,
|
|
||||||
program: &'a Executable<BpfError, ThisInstructionMeter>,
|
program: &'a Executable<BpfError, ThisInstructionMeter>,
|
||||||
parameter_bytes: &mut [u8],
|
parameter_bytes: &mut [u8],
|
||||||
invoke_context: &'a mut dyn InvokeContext,
|
invoke_context: &'a mut dyn InvokeContext,
|
||||||
@ -168,13 +167,7 @@ pub fn create_vm<'a>(
|
|||||||
let mut heap =
|
let mut heap =
|
||||||
AlignedMemory::new_with_size(compute_budget.heap_size.unwrap_or(HEAP_LENGTH), HOST_ALIGN);
|
AlignedMemory::new_with_size(compute_budget.heap_size.unwrap_or(HEAP_LENGTH), HOST_ALIGN);
|
||||||
let mut vm = EbpfVm::new(program, heap.as_slice_mut(), parameter_bytes)?;
|
let mut vm = EbpfVm::new(program, heap.as_slice_mut(), parameter_bytes)?;
|
||||||
syscalls::bind_syscall_context_objects(
|
syscalls::bind_syscall_context_objects(&mut vm, invoke_context, heap, orig_data_lens)?;
|
||||||
loader_id,
|
|
||||||
&mut vm,
|
|
||||||
invoke_context,
|
|
||||||
heap,
|
|
||||||
orig_data_lens,
|
|
||||||
)?;
|
|
||||||
Ok(vm)
|
Ok(vm)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -984,7 +977,6 @@ impl Executor for BpfExecutor {
|
|||||||
let program_id = &invoke_context.get_caller()?.clone();
|
let program_id = &invoke_context.get_caller()?.clone();
|
||||||
let compute_meter = invoke_context.get_compute_meter();
|
let compute_meter = invoke_context.get_compute_meter();
|
||||||
let mut vm = match create_vm(
|
let mut vm = match create_vm(
|
||||||
loader_id,
|
|
||||||
&self.executable,
|
&self.executable,
|
||||||
parameter_bytes.as_slice_mut(),
|
parameter_bytes.as_slice_mut(),
|
||||||
invoke_context,
|
invoke_context,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -269,9 +269,7 @@ native machine code before execting it in the virtual machine.",
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = bpf_loader::id();
|
|
||||||
let mut vm = create_vm(
|
let mut vm = create_vm(
|
||||||
&id,
|
|
||||||
&executable,
|
&executable,
|
||||||
parameter_bytes.as_slice_mut(),
|
parameter_bytes.as_slice_mut(),
|
||||||
&mut invoke_context,
|
&mut invoke_context,
|
||||||
|
Reference in New Issue
Block a user