diff --git a/programs/bpf/benches/bpf_loader.rs b/programs/bpf/benches/bpf_loader.rs index 28008650f6..a78cd22c10 100644 --- a/programs/bpf/benches/bpf_loader.rs +++ b/programs/bpf/benches/bpf_loader.rs @@ -6,7 +6,7 @@ use byteorder::{ByteOrder, LittleEndian, WriteBytesExt}; use solana_rbpf::EbpfVm; use solana_sdk::{ account::Account, - entrypoint_native::InvokeContext, + entrypoint_native::{InvokeContext, ProcessInstruction}, instruction::{CompiledInstruction, InstructionError}, message::Message, pubkey::Pubkey, @@ -152,4 +152,7 @@ impl InvokeContext for MockInvokeContext { fn get_caller(&self) -> Result<&Pubkey, InstructionError> { Ok(&self.key) } + fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)] { + &[] + } } diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index 1a0f98268f..2b4b66d068 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -259,7 +259,8 @@ mod tests { use super::*; use rand::Rng; use solana_sdk::{ - account::Account, instruction::CompiledInstruction, message::Message, rent::Rent, + account::Account, entrypoint_native::ProcessInstruction, instruction::CompiledInstruction, + message::Message, rent::Rent, }; use std::{cell::RefCell, fs::File, io::Read, ops::Range, rc::Rc}; @@ -283,6 +284,9 @@ mod tests { fn get_caller(&self) -> Result<&Pubkey, InstructionError> { Ok(&self.key) } + fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)] { + &[] + } } #[test] diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index 80194977e4..a3a928feb6 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -6,7 +6,7 @@ use solana_rbpf::{ memory_region::{translate_addr, MemoryRegion}, EbpfVm, }; -use solana_runtime::{builtin_programs::get_builtin_programs, message_processor::MessageProcessor}; +use solana_runtime::message_processor::MessageProcessor; use solana_sdk::{ account::Account, account::KeyedAccount, @@ -767,9 +767,8 @@ fn call<'a>( let program_account = (*accounts[callee_program_id_index]).clone(); let executable_accounts = vec![(callee_program_id, program_account)]; let mut message_processor = MessageProcessor::default(); - let builtin_programs = get_builtin_programs(); - for program in builtin_programs.iter() { - message_processor.add_program(program.id, program.process_instruction); + 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); diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 13c6425f60..d88ff05af9 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -12,7 +12,7 @@ use crate::{ blockhash_queue::BlockhashQueue, builtin_programs::get_builtin_programs, epoch_stakes::{EpochStakes, NodeVoteAccounts}, - message_processor::{MessageProcessor, ProcessInstruction}, + message_processor::MessageProcessor, nonce_utils, rent_collector::RentCollector, stakes::Stakes, @@ -35,6 +35,7 @@ use solana_sdk::{ Epoch, Slot, SlotCount, SlotIndex, UnixTimestamp, DEFAULT_TICKS_PER_SECOND, MAX_PROCESSING_AGE, MAX_RECENT_BLOCKHASHES, SECONDS_PER_DAY, }, + entrypoint_native::ProcessInstruction, epoch_info::EpochInfo, epoch_schedule::EpochSchedule, fee_calculator::{FeeCalculator, FeeRateGovernor}, diff --git a/runtime/src/builtin_programs.rs b/runtime/src/builtin_programs.rs index 1808549902..5fd7396dc5 100644 --- a/runtime/src/builtin_programs.rs +++ b/runtime/src/builtin_programs.rs @@ -1,5 +1,5 @@ -use crate::{message_processor::ProcessInstruction, system_instruction_processor}; -use solana_sdk::{pubkey::Pubkey, system_program}; +use crate::system_instruction_processor; +use solana_sdk::{entrypoint_native::ProcessInstruction, pubkey::Pubkey, system_program}; pub struct BuiltinProgram { pub name: String, diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index c9655dbd56..0504de8fc0 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use solana_sdk::{ account::{create_keyed_readonly_accounts, Account, KeyedAccount}, clock::Epoch, - entrypoint_native::InvokeContext, + entrypoint_native::{InvokeContext, ProcessInstruction}, instruction::{CompiledInstruction, InstructionError}, message::Message, native_loader, @@ -151,21 +151,28 @@ impl PreAccount { } } -#[derive(Debug, Default)] +#[derive(Default)] pub struct ThisInvokeContext { pub program_ids: Vec, pub rent: Rent, pub pre_accounts: Vec, + pub programs: Vec<(Pubkey, ProcessInstruction)>, } impl ThisInvokeContext { const MAX_INVOCATION_DEPTH: usize = 5; - pub fn new(program_id: &Pubkey, rent: Rent, pre_accounts: Vec) -> Self { + pub fn new( + program_id: &Pubkey, + rent: Rent, + pre_accounts: Vec, + programs: Vec<(Pubkey, ProcessInstruction)>, + ) -> Self { let mut program_ids = Vec::with_capacity(Self::MAX_INVOCATION_DEPTH); program_ids.push(*program_id); Self { program_ids, rent, pre_accounts, + programs, } } } @@ -207,9 +214,12 @@ impl InvokeContext for ThisInvokeContext { .last() .ok_or(InstructionError::GenericError) } + + fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)] { + &self.programs + } } -pub type ProcessInstruction = fn(&Pubkey, &[KeyedAccount], &[u8]) -> Result<(), InstructionError>; pub type ProcessInstructionWithContext = fn(&Pubkey, &[KeyedAccount], &[u8], &mut dyn InvokeContext) -> Result<(), InstructionError>; @@ -479,6 +489,7 @@ impl MessageProcessor { instruction.program_id(&message.account_keys), rent_collector.rent, pre_accounts, + self.programs.clone(), ); let keyed_accounts = Self::create_keyed_accounts(message, instruction, executable_accounts, accounts)?; @@ -555,7 +566,7 @@ mod tests { )) } let mut invoke_context = - ThisInvokeContext::new(&program_ids[0], Rent::default(), pre_accounts); + ThisInvokeContext::new(&program_ids[0], Rent::default(), pre_accounts, vec![]); // Check call depth increases and has a limit let mut depth_reached = 1; @@ -1303,6 +1314,7 @@ mod tests { &caller_program_id, Rent::default(), vec![owned_preaccount, not_owned_preaccount], + vec![], ); let metas = vec![ AccountMeta::new(owned_key, false), diff --git a/sdk/src/entrypoint_native.rs b/sdk/src/entrypoint_native.rs index e3c497b96f..bdf9328f7c 100644 --- a/sdk/src/entrypoint_native.rs +++ b/sdk/src/entrypoint_native.rs @@ -146,6 +146,8 @@ macro_rules! declare_loader( ) ); +pub type ProcessInstruction = fn(&Pubkey, &[KeyedAccount], &[u8]) -> Result<(), InstructionError>; + /// Cross-program invocation context passed to loaders pub trait InvokeContext { fn push(&mut self, key: &Pubkey) -> Result<(), InstructionError>; @@ -157,4 +159,5 @@ pub trait InvokeContext { accounts: &[Rc>], ) -> Result<(), InstructionError>; fn get_caller(&self) -> Result<&Pubkey, InstructionError>; + fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)]; }