* Disable cross-program invocations for OperatingMode::Stable (#11272)
(cherry picked from commit 2dbed80e48
)
# Conflicts:
# programs/bpf/benches/bpf_loader.rs
# programs/bpf_loader/src/lib.rs
# runtime/src/message_processor.rs
# sdk/src/entrypoint_native.rs
* fix conflicts
Co-authored-by: Jack May <jack@solana.com>
This commit is contained in:
@ -107,6 +107,7 @@ pub fn get_entered_epoch_callback(operating_mode: OperatingMode) -> EnteredEpoch
|
|||||||
bank.add_native_program(name, program_id);
|
bank.add_native_program(name, program_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bank.set_cross_program_support(OperatingMode::Stable != operating_mode);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,4 +159,7 @@ impl InvokeContext for MockInvokeContext {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
fn log(&mut self, _message: &str) {}
|
fn log(&mut self, _message: &str) {}
|
||||||
|
fn is_cross_program_supported(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -356,7 +356,8 @@ mod bpf {
|
|||||||
let derived_key2 =
|
let derived_key2 =
|
||||||
Pubkey::create_program_address(&[b"Lil'", b"Bits"], &invoked_program_id).unwrap();
|
Pubkey::create_program_address(&[b"Lil'", b"Bits"], &invoked_program_id).unwrap();
|
||||||
let derived_key3 =
|
let derived_key3 =
|
||||||
Pubkey::create_program_address(&[derived_key2.as_ref()], &invoked_program_id).unwrap();
|
Pubkey::create_program_address(&[derived_key2.as_ref()], &invoked_program_id)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let mint_pubkey = mint_keypair.pubkey();
|
let mint_pubkey = mint_keypair.pubkey();
|
||||||
let account_metas = vec![
|
let account_metas = vec![
|
||||||
|
@ -295,6 +295,9 @@ mod tests {
|
|||||||
info!("[MockInvokeContext::log] {}", message);
|
info!("[MockInvokeContext::log] {}", message);
|
||||||
self.log.push(message.to_string());
|
self.log.push(message.to_string());
|
||||||
}
|
}
|
||||||
|
fn is_cross_program_supported(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustversion::since(1.46.0)]
|
#[rustversion::since(1.46.0)]
|
||||||
|
@ -825,6 +825,7 @@ fn call<'a>(
|
|||||||
message_processor.add_program(*program_id, *process_instruction);
|
message_processor.add_program(*program_id, *process_instruction);
|
||||||
}
|
}
|
||||||
message_processor.add_loader(bpf_loader::id(), crate::process_instruction);
|
message_processor.add_loader(bpf_loader::id(), crate::process_instruction);
|
||||||
|
message_processor.set_cross_program_support(invoke_context.is_cross_program_supported());
|
||||||
|
|
||||||
#[allow(clippy::deref_addrof)]
|
#[allow(clippy::deref_addrof)]
|
||||||
match message_processor.process_cross_program_instruction(
|
match message_processor.process_cross_program_instruction(
|
||||||
|
@ -373,6 +373,9 @@ impl Bank {
|
|||||||
bank.update_rent();
|
bank.update_rent();
|
||||||
bank.update_epoch_schedule();
|
bank.update_epoch_schedule();
|
||||||
bank.update_recent_blockhashes();
|
bank.update_recent_blockhashes();
|
||||||
|
if bank.operating_mode == Some(OperatingMode::Stable) {
|
||||||
|
bank.message_processor.set_cross_program_support(false);
|
||||||
|
}
|
||||||
bank
|
bank
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -977,6 +980,11 @@ impl Bank {
|
|||||||
debug!("Added native program {} under {:?}", name, program_id);
|
debug!("Added native program {} under {:?}", name, program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_cross_program_support(&mut self, is_supported: bool) {
|
||||||
|
self.message_processor
|
||||||
|
.set_cross_program_support(is_supported);
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the last block hash registered.
|
/// Return the last block hash registered.
|
||||||
pub fn last_blockhash(&self) -> Hash {
|
pub fn last_blockhash(&self) -> Hash {
|
||||||
self.blockhash_queue.read().unwrap().last_hash()
|
self.blockhash_queue.read().unwrap().last_hash()
|
||||||
|
@ -161,6 +161,7 @@ pub struct ThisInvokeContext<'a> {
|
|||||||
pub pre_accounts: Vec<PreAccount>,
|
pub pre_accounts: Vec<PreAccount>,
|
||||||
pub programs: Vec<(Pubkey, ProcessInstruction)>,
|
pub programs: Vec<(Pubkey, ProcessInstruction)>,
|
||||||
pub log_collector: Option<&'a LogCollector>,
|
pub log_collector: Option<&'a LogCollector>,
|
||||||
|
is_cross_program_supported: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ThisInvokeContext<'a> {
|
impl<'a> ThisInvokeContext<'a> {
|
||||||
@ -171,6 +172,7 @@ impl<'a> ThisInvokeContext<'a> {
|
|||||||
pre_accounts: Vec<PreAccount>,
|
pre_accounts: Vec<PreAccount>,
|
||||||
programs: Vec<(Pubkey, ProcessInstruction)>,
|
programs: Vec<(Pubkey, ProcessInstruction)>,
|
||||||
log_collector: Option<&'a LogCollector>,
|
log_collector: Option<&'a LogCollector>,
|
||||||
|
is_cross_program_supported: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut program_ids = Vec::with_capacity(Self::MAX_INVOCATION_DEPTH);
|
let mut program_ids = Vec::with_capacity(Self::MAX_INVOCATION_DEPTH);
|
||||||
program_ids.push(*program_id);
|
program_ids.push(*program_id);
|
||||||
@ -180,6 +182,7 @@ impl<'a> ThisInvokeContext<'a> {
|
|||||||
pre_accounts,
|
pre_accounts,
|
||||||
programs,
|
programs,
|
||||||
log_collector,
|
log_collector,
|
||||||
|
is_cross_program_supported,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,7 +229,6 @@ impl<'a> InvokeContext for ThisInvokeContext<'a> {
|
|||||||
fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)] {
|
fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)] {
|
||||||
&self.programs
|
&self.programs
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
||||||
}
|
}
|
||||||
@ -237,12 +239,15 @@ impl<'a> InvokeContext for ThisInvokeContext<'a> {
|
|||||||
log_collector.log(message);
|
log_collector.log(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn is_cross_program_supported(&self) -> bool {
|
||||||
|
self.is_cross_program_supported
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ProcessInstructionWithContext =
|
pub type ProcessInstructionWithContext =
|
||||||
fn(&Pubkey, &[KeyedAccount], &[u8], &mut dyn InvokeContext) -> Result<(), InstructionError>;
|
fn(&Pubkey, &[KeyedAccount], &[u8], &mut dyn InvokeContext) -> Result<(), InstructionError>;
|
||||||
|
|
||||||
#[derive(Default, Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct MessageProcessor {
|
pub struct MessageProcessor {
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
programs: Vec<(Pubkey, ProcessInstruction)>,
|
programs: Vec<(Pubkey, ProcessInstruction)>,
|
||||||
@ -250,6 +255,18 @@ pub struct MessageProcessor {
|
|||||||
loaders: Vec<(Pubkey, ProcessInstructionWithContext)>,
|
loaders: Vec<(Pubkey, ProcessInstructionWithContext)>,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
native_loader: NativeLoader,
|
native_loader: NativeLoader,
|
||||||
|
#[serde(skip)]
|
||||||
|
is_cross_program_supported: bool,
|
||||||
|
}
|
||||||
|
impl Default for MessageProcessor {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
programs: vec![],
|
||||||
|
loaders: vec![],
|
||||||
|
native_loader: NativeLoader::default(),
|
||||||
|
is_cross_program_supported: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl Clone for MessageProcessor {
|
impl Clone for MessageProcessor {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
@ -257,6 +274,7 @@ impl Clone for MessageProcessor {
|
|||||||
programs: self.programs.clone(),
|
programs: self.programs.clone(),
|
||||||
loaders: self.loaders.clone(),
|
loaders: self.loaders.clone(),
|
||||||
native_loader: NativeLoader::default(),
|
native_loader: NativeLoader::default(),
|
||||||
|
is_cross_program_supported: self.is_cross_program_supported,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,6 +298,10 @@ impl MessageProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_cross_program_support(&mut self, is_supported: bool) {
|
||||||
|
self.is_cross_program_supported = is_supported;
|
||||||
|
}
|
||||||
|
|
||||||
/// 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,
|
||||||
@ -357,6 +379,10 @@ impl MessageProcessor {
|
|||||||
accounts: &[Rc<RefCell<Account>>],
|
accounts: &[Rc<RefCell<Account>>],
|
||||||
invoke_context: &mut dyn InvokeContext,
|
invoke_context: &mut dyn InvokeContext,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
|
if !self.is_cross_program_supported {
|
||||||
|
return Err(InstructionError::ReentrancyNotAllowed);
|
||||||
|
}
|
||||||
|
|
||||||
let instruction = &message.instructions[0];
|
let instruction = &message.instructions[0];
|
||||||
|
|
||||||
// Verify the calling program hasn't misbehaved
|
// Verify the calling program hasn't misbehaved
|
||||||
@ -511,6 +537,7 @@ impl MessageProcessor {
|
|||||||
pre_accounts,
|
pre_accounts,
|
||||||
self.programs.clone(),
|
self.programs.clone(),
|
||||||
log_collector,
|
log_collector,
|
||||||
|
self.is_cross_program_supported,
|
||||||
);
|
);
|
||||||
let keyed_accounts =
|
let keyed_accounts =
|
||||||
Self::create_keyed_accounts(message, instruction, executable_accounts, accounts)?;
|
Self::create_keyed_accounts(message, instruction, executable_accounts, accounts)?;
|
||||||
@ -583,8 +610,14 @@ mod tests {
|
|||||||
true,
|
true,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
let mut invoke_context =
|
let mut invoke_context = ThisInvokeContext::new(
|
||||||
ThisInvokeContext::new(&program_ids[0], Rent::default(), pre_accounts, vec![], None);
|
&program_ids[0],
|
||||||
|
Rent::default(),
|
||||||
|
pre_accounts,
|
||||||
|
vec![],
|
||||||
|
None,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
// Check call depth increases and has a limit
|
// Check call depth increases and has a limit
|
||||||
let mut depth_reached = 1;
|
let mut depth_reached = 1;
|
||||||
@ -1352,6 +1385,7 @@ mod tests {
|
|||||||
vec![owned_preaccount, not_owned_preaccount],
|
vec![owned_preaccount, not_owned_preaccount],
|
||||||
vec![],
|
vec![],
|
||||||
None,
|
None,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
let metas = vec![
|
let metas = vec![
|
||||||
AccountMeta::new(owned_key, false),
|
AccountMeta::new(owned_key, false),
|
||||||
|
@ -209,4 +209,6 @@ pub trait InvokeContext {
|
|||||||
fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)];
|
fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)];
|
||||||
fn log_enabled(&self) -> bool;
|
fn log_enabled(&self) -> bool;
|
||||||
fn log(&mut self, message: &str);
|
fn log(&mut self, message: &str);
|
||||||
|
/// Are cross program invocations supported
|
||||||
|
fn is_cross_program_supported(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user