* de-mut some InvokeContext methods (cherry picked from commitda9548fd12
) * Simplify CPI interface into MessageProcessor (cherry picked from commit9263ae1c60
) Co-authored-by: Michael Vines <mvines@gmail.com>
This commit is contained in:
@ -64,14 +64,14 @@ impl UserDefinedError for BPFError {}
|
|||||||
/// Point all log messages to the log collector
|
/// Point all log messages to the log collector
|
||||||
macro_rules! log{
|
macro_rules! log{
|
||||||
($logger:ident, $message:expr) => {
|
($logger:ident, $message:expr) => {
|
||||||
if let Ok(mut logger) = $logger.try_borrow_mut() {
|
if let Ok(logger) = $logger.try_borrow_mut() {
|
||||||
if logger.log_enabled() {
|
if logger.log_enabled() {
|
||||||
logger.log($message);
|
logger.log($message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($logger:ident, $fmt:expr, $($arg:tt)*) => {
|
($logger:ident, $fmt:expr, $($arg:tt)*) => {
|
||||||
if let Ok(mut logger) = $logger.try_borrow_mut() {
|
if let Ok(logger) = $logger.try_borrow_mut() {
|
||||||
if logger.log_enabled() {
|
if logger.log_enabled() {
|
||||||
logger.log(&format!($fmt, $($arg)*));
|
logger.log(&format!($fmt, $($arg)*));
|
||||||
}
|
}
|
||||||
|
@ -371,7 +371,7 @@ impl<'a> SyscallObject<BPFError> for SyscallLog<'a> {
|
|||||||
_rw_regions: &[MemoryRegion],
|
_rw_regions: &[MemoryRegion],
|
||||||
) -> Result<u64, EbpfError<BPFError>> {
|
) -> Result<u64, EbpfError<BPFError>> {
|
||||||
self.compute_meter.consume(self.cost)?;
|
self.compute_meter.consume(self.cost)?;
|
||||||
let mut logger = self
|
let logger = self
|
||||||
.logger
|
.logger
|
||||||
.try_borrow_mut()
|
.try_borrow_mut()
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
|
||||||
@ -409,7 +409,7 @@ impl SyscallObject<BPFError> for SyscallLogU64 {
|
|||||||
_rw_regions: &[MemoryRegion],
|
_rw_regions: &[MemoryRegion],
|
||||||
) -> Result<u64, EbpfError<BPFError>> {
|
) -> Result<u64, EbpfError<BPFError>> {
|
||||||
self.compute_meter.consume(self.cost)?;
|
self.compute_meter.consume(self.cost)?;
|
||||||
let mut logger = self
|
let logger = self
|
||||||
.logger
|
.logger
|
||||||
.try_borrow_mut()
|
.try_borrow_mut()
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
|
||||||
@ -441,7 +441,7 @@ impl SyscallObject<BPFError> for SyscallLogBpfComputeUnits {
|
|||||||
_rw_regions: &[MemoryRegion],
|
_rw_regions: &[MemoryRegion],
|
||||||
) -> Result<u64, EbpfError<BPFError>> {
|
) -> Result<u64, EbpfError<BPFError>> {
|
||||||
self.compute_meter.consume(self.cost)?;
|
self.compute_meter.consume(self.cost)?;
|
||||||
let mut logger = self
|
let logger = self
|
||||||
.logger
|
.logger
|
||||||
.try_borrow_mut()
|
.try_borrow_mut()
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
|
||||||
@ -474,7 +474,7 @@ impl<'a> SyscallObject<BPFError> for SyscallLogPubkey<'a> {
|
|||||||
_rw_regions: &[MemoryRegion],
|
_rw_regions: &[MemoryRegion],
|
||||||
) -> Result<u64, EbpfError<BPFError>> {
|
) -> Result<u64, EbpfError<BPFError>> {
|
||||||
self.compute_meter.consume(self.cost)?;
|
self.compute_meter.consume(self.cost)?;
|
||||||
let mut logger = self
|
let logger = self
|
||||||
.logger
|
.logger
|
||||||
.try_borrow_mut()
|
.try_borrow_mut()
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
|
||||||
@ -1222,13 +1222,9 @@ fn call<'a>(
|
|||||||
return Err(SyscallError::InstructionError(InstructionError::AccountNotExecutable).into());
|
return Err(SyscallError::InstructionError(InstructionError::AccountNotExecutable).into());
|
||||||
}
|
}
|
||||||
let executable_accounts = vec![(callee_program_id, program_account)];
|
let executable_accounts = vec![(callee_program_id, program_account)];
|
||||||
let mut message_processor = MessageProcessor::default();
|
|
||||||
for (program_id, process_instruction) in invoke_context.get_programs().iter() {
|
|
||||||
message_processor.add_program(*program_id, *process_instruction);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::deref_addrof)]
|
#[allow(clippy::deref_addrof)]
|
||||||
match message_processor.process_cross_program_instruction(
|
match MessageProcessor::process_cross_program_instruction(
|
||||||
&message,
|
&message,
|
||||||
&executable_accounts,
|
&executable_accounts,
|
||||||
&accounts,
|
&accounts,
|
||||||
|
@ -293,10 +293,10 @@ impl<'a> InvokeContext for ThisInvokeContext<'a> {
|
|||||||
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()
|
||||||
}
|
}
|
||||||
fn add_executor(&mut self, pubkey: &Pubkey, executor: Arc<dyn Executor>) {
|
fn add_executor(&self, pubkey: &Pubkey, executor: Arc<dyn Executor>) {
|
||||||
self.executors.borrow_mut().insert(*pubkey, executor);
|
self.executors.borrow_mut().insert(*pubkey, executor);
|
||||||
}
|
}
|
||||||
fn get_executor(&mut self, pubkey: &Pubkey) -> Option<Arc<dyn Executor>> {
|
fn get_executor(&self, pubkey: &Pubkey) -> Option<Arc<dyn Executor>> {
|
||||||
self.executors.borrow().get(&pubkey)
|
self.executors.borrow().get(&pubkey)
|
||||||
}
|
}
|
||||||
fn record_instruction(&self, instruction: &Instruction) {
|
fn record_instruction(&self, instruction: &Instruction) {
|
||||||
@ -315,7 +315,7 @@ impl Logger for ThisLogger {
|
|||||||
fn log_enabled(&self) -> bool {
|
fn log_enabled(&self) -> bool {
|
||||||
log_enabled!(log::Level::Info) || self.log_collector.is_some()
|
log_enabled!(log::Level::Info) || self.log_collector.is_some()
|
||||||
}
|
}
|
||||||
fn log(&mut self, message: &str) {
|
fn log(&self, message: &str) {
|
||||||
info!("{}", message);
|
info!("{}", message);
|
||||||
if let Some(log_collector) = &self.log_collector {
|
if let Some(log_collector) = &self.log_collector {
|
||||||
log_collector.log(message);
|
log_collector.log(message);
|
||||||
@ -490,7 +490,6 @@ impl MessageProcessor {
|
|||||||
/// Process a cross-program instruction
|
/// Process a cross-program instruction
|
||||||
/// This method calls the instruction's program entrypoint function
|
/// This method calls the instruction's program entrypoint function
|
||||||
pub fn process_cross_program_instruction(
|
pub fn process_cross_program_instruction(
|
||||||
&self,
|
|
||||||
message: &Message,
|
message: &Message,
|
||||||
executable_accounts: &[(Pubkey, RefCell<Account>)],
|
executable_accounts: &[(Pubkey, RefCell<Account>)],
|
||||||
accounts: &[Rc<RefCell<Account>>],
|
accounts: &[Rc<RefCell<Account>>],
|
||||||
@ -506,8 +505,17 @@ impl MessageProcessor {
|
|||||||
|
|
||||||
// Invoke callee
|
// Invoke callee
|
||||||
invoke_context.push(instruction.program_id(&message.account_keys))?;
|
invoke_context.push(instruction.program_id(&message.account_keys))?;
|
||||||
let mut result =
|
|
||||||
self.process_instruction(&keyed_accounts, &instruction.data, invoke_context);
|
let mut message_processor = MessageProcessor::default();
|
||||||
|
for (program_id, process_instruction) in invoke_context.get_programs().iter() {
|
||||||
|
message_processor.add_program(*program_id, *process_instruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut result = message_processor.process_instruction(
|
||||||
|
&keyed_accounts,
|
||||||
|
&instruction.data,
|
||||||
|
invoke_context,
|
||||||
|
);
|
||||||
if result.is_ok() {
|
if result.is_ok() {
|
||||||
// Verify the called program has not misbehaved
|
// Verify the called program has not misbehaved
|
||||||
result = invoke_context.verify_and_update(message, instruction, accounts);
|
result = invoke_context.verify_and_update(message, instruction, accounts);
|
||||||
@ -1580,8 +1588,6 @@ mod tests {
|
|||||||
|
|
||||||
let caller_program_id = solana_sdk::pubkey::new_rand();
|
let caller_program_id = solana_sdk::pubkey::new_rand();
|
||||||
let callee_program_id = solana_sdk::pubkey::new_rand();
|
let callee_program_id = solana_sdk::pubkey::new_rand();
|
||||||
let mut message_processor = MessageProcessor::default();
|
|
||||||
message_processor.add_program(callee_program_id, mock_process_instruction);
|
|
||||||
|
|
||||||
let mut program_account = Account::new(1, 0, &native_loader::id());
|
let mut program_account = Account::new(1, 0, &native_loader::id());
|
||||||
program_account.executable = true;
|
program_account.executable = true;
|
||||||
@ -1600,11 +1606,13 @@ mod tests {
|
|||||||
Rc::new(RefCell::new(owned_account)),
|
Rc::new(RefCell::new(owned_account)),
|
||||||
Rc::new(RefCell::new(not_owned_account)),
|
Rc::new(RefCell::new(not_owned_account)),
|
||||||
];
|
];
|
||||||
|
let programs: Vec<(_, ProcessInstructionWithContext)> =
|
||||||
|
vec![(callee_program_id, mock_process_instruction)];
|
||||||
let mut invoke_context = ThisInvokeContext::new(
|
let mut invoke_context = ThisInvokeContext::new(
|
||||||
&caller_program_id,
|
&caller_program_id,
|
||||||
Rent::default(),
|
Rent::default(),
|
||||||
vec![owned_preaccount, not_owned_preaccount],
|
vec![owned_preaccount, not_owned_preaccount],
|
||||||
&[],
|
programs.as_slice(),
|
||||||
None,
|
None,
|
||||||
BpfComputeBudget::default(),
|
BpfComputeBudget::default(),
|
||||||
Rc::new(RefCell::new(Executors::default())),
|
Rc::new(RefCell::new(Executors::default())),
|
||||||
@ -1625,7 +1633,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
let message = Message::new(&[instruction], None);
|
let message = Message::new(&[instruction], None);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
message_processor.process_cross_program_instruction(
|
MessageProcessor::process_cross_program_instruction(
|
||||||
&message,
|
&message,
|
||||||
&executable_accounts,
|
&executable_accounts,
|
||||||
&accounts,
|
&accounts,
|
||||||
@ -1652,7 +1660,7 @@ mod tests {
|
|||||||
let instruction = Instruction::new(callee_program_id, &case.0, metas.clone());
|
let instruction = Instruction::new(callee_program_id, &case.0, metas.clone());
|
||||||
let message = Message::new(&[instruction], None);
|
let message = Message::new(&[instruction], None);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
message_processor.process_cross_program_instruction(
|
MessageProcessor::process_cross_program_instruction(
|
||||||
&message,
|
&message,
|
||||||
&executable_accounts,
|
&executable_accounts,
|
||||||
&accounts,
|
&accounts,
|
||||||
|
@ -52,9 +52,9 @@ pub trait InvokeContext {
|
|||||||
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
|
||||||
/// the work that can be re-used across executions
|
/// the work that can be re-used across executions
|
||||||
fn add_executor(&mut self, pubkey: &Pubkey, executor: Arc<dyn Executor>);
|
fn add_executor(&self, pubkey: &Pubkey, executor: Arc<dyn Executor>);
|
||||||
/// Get the completed loader work that can be re-used across executions
|
/// Get the completed loader work that can be re-used across executions
|
||||||
fn get_executor(&mut self, pubkey: &Pubkey) -> Option<Arc<dyn Executor>>;
|
fn get_executor(&self, pubkey: &Pubkey) -> Option<Arc<dyn Executor>>;
|
||||||
/// Record invoked instruction
|
/// Record invoked instruction
|
||||||
fn record_instruction(&self, instruction: &Instruction);
|
fn record_instruction(&self, instruction: &Instruction);
|
||||||
/// Get the bank's active feature set
|
/// Get the bank's active feature set
|
||||||
@ -156,7 +156,7 @@ pub trait ComputeMeter {
|
|||||||
pub trait Logger {
|
pub trait Logger {
|
||||||
fn log_enabled(&self) -> bool;
|
fn log_enabled(&self) -> bool;
|
||||||
/// Log a message
|
/// Log a message
|
||||||
fn log(&mut self, message: &str);
|
fn log(&self, message: &str);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Program executor
|
/// Program executor
|
||||||
@ -197,7 +197,7 @@ impl Logger for MockLogger {
|
|||||||
fn log_enabled(&self) -> bool {
|
fn log_enabled(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
fn log(&mut self, message: &str) {
|
fn log(&self, message: &str) {
|
||||||
self.log.borrow_mut().push(message.to_string());
|
self.log.borrow_mut().push(message.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,8 +249,8 @@ impl InvokeContext for MockInvokeContext {
|
|||||||
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()))
|
||||||
}
|
}
|
||||||
fn add_executor(&mut self, _pubkey: &Pubkey, _executor: Arc<dyn Executor>) {}
|
fn add_executor(&self, _pubkey: &Pubkey, _executor: Arc<dyn Executor>) {}
|
||||||
fn get_executor(&mut self, _pubkey: &Pubkey) -> Option<Arc<dyn Executor>> {
|
fn get_executor(&self, _pubkey: &Pubkey) -> Option<Arc<dyn Executor>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn record_instruction(&self, _instruction: &Instruction) {}
|
fn record_instruction(&self, _instruction: &Instruction) {}
|
||||||
|
Reference in New Issue
Block a user