Disable cross-program invocations for OperatingMode::Stable (#11272)
This commit is contained in:
parent
cd043b5d70
commit
2dbed80e48
|
@ -105,6 +105,7 @@ pub fn get_entered_epoch_callback(operating_mode: OperatingMode) -> EnteredEpoch
|
|||
bank.add_native_program(name, program_id);
|
||||
}
|
||||
}
|
||||
bank.set_cross_program_support(OperatingMode::Stable != operating_mode);
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -159,6 +159,9 @@ impl InvokeContext for MockInvokeContext {
|
|||
fn get_logger(&self) -> Rc<RefCell<dyn Logger>> {
|
||||
Rc::new(RefCell::new(self.mock_logger.clone()))
|
||||
}
|
||||
fn is_cross_program_supported(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct MockLogger {
|
||||
|
|
|
@ -326,6 +326,9 @@ mod tests {
|
|||
fn get_logger(&self) -> Rc<RefCell<dyn Logger>> {
|
||||
Rc::new(RefCell::new(self.mock_logger.clone()))
|
||||
}
|
||||
fn is_cross_program_supported(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct MockLogger {
|
||||
|
|
|
@ -794,6 +794,7 @@ fn call<'a>(
|
|||
message_processor.add_program(*program_id, *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)]
|
||||
match message_processor.process_cross_program_instruction(
|
||||
|
|
|
@ -449,6 +449,9 @@ impl Bank {
|
|||
bank.update_rent();
|
||||
bank.update_epoch_schedule();
|
||||
bank.update_recent_blockhashes();
|
||||
if bank.operating_mode == Some(OperatingMode::Stable) {
|
||||
bank.message_processor.set_cross_program_support(false);
|
||||
}
|
||||
bank
|
||||
}
|
||||
|
||||
|
@ -1191,6 +1194,11 @@ impl Bank {
|
|||
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.
|
||||
pub fn last_blockhash(&self) -> Hash {
|
||||
self.blockhash_queue.read().unwrap().last_hash()
|
||||
|
|
|
@ -160,6 +160,7 @@ pub struct ThisInvokeContext {
|
|||
pre_accounts: Vec<PreAccount>,
|
||||
programs: Vec<(Pubkey, ProcessInstruction)>,
|
||||
logger: Rc<RefCell<dyn Logger>>,
|
||||
is_cross_program_supported: bool,
|
||||
}
|
||||
impl ThisInvokeContext {
|
||||
const MAX_INVOCATION_DEPTH: usize = 5;
|
||||
|
@ -169,6 +170,7 @@ impl ThisInvokeContext {
|
|||
pre_accounts: Vec<PreAccount>,
|
||||
programs: Vec<(Pubkey, ProcessInstruction)>,
|
||||
log_collector: Option<Rc<LogCollector>>,
|
||||
is_cross_program_supported: bool,
|
||||
) -> Self {
|
||||
let mut program_ids = Vec::with_capacity(Self::MAX_INVOCATION_DEPTH);
|
||||
program_ids.push(*program_id);
|
||||
|
@ -178,6 +180,7 @@ impl ThisInvokeContext {
|
|||
pre_accounts,
|
||||
programs,
|
||||
logger: Rc::new(RefCell::new(ThisLogger { log_collector })),
|
||||
is_cross_program_supported,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -225,6 +228,9 @@ impl InvokeContext for ThisInvokeContext {
|
|||
fn get_logger(&self) -> Rc<RefCell<dyn Logger>> {
|
||||
self.logger.clone()
|
||||
}
|
||||
fn is_cross_program_supported(&self) -> bool {
|
||||
self.is_cross_program_supported
|
||||
}
|
||||
}
|
||||
pub struct ThisLogger {
|
||||
log_collector: Option<Rc<LogCollector>>,
|
||||
|
@ -244,7 +250,7 @@ impl Logger for ThisLogger {
|
|||
pub type ProcessInstructionWithContext =
|
||||
fn(&Pubkey, &[KeyedAccount], &[u8], &mut dyn InvokeContext) -> Result<(), InstructionError>;
|
||||
|
||||
#[derive(Default, Deserialize, Serialize)]
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct MessageProcessor {
|
||||
#[serde(skip)]
|
||||
programs: Vec<(Pubkey, ProcessInstruction)>,
|
||||
|
@ -252,6 +258,18 @@ pub struct MessageProcessor {
|
|||
loaders: Vec<(Pubkey, ProcessInstructionWithContext)>,
|
||||
#[serde(skip)]
|
||||
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 {
|
||||
fn clone(&self) -> Self {
|
||||
|
@ -259,6 +277,7 @@ impl Clone for MessageProcessor {
|
|||
programs: self.programs.clone(),
|
||||
loaders: self.loaders.clone(),
|
||||
native_loader: NativeLoader::default(),
|
||||
is_cross_program_supported: self.is_cross_program_supported,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -292,6 +311,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
|
||||
fn create_keyed_accounts<'a>(
|
||||
message: &'a Message,
|
||||
|
@ -369,6 +392,10 @@ impl MessageProcessor {
|
|||
accounts: &[Rc<RefCell<Account>>],
|
||||
invoke_context: &mut dyn InvokeContext,
|
||||
) -> Result<(), InstructionError> {
|
||||
if !self.is_cross_program_supported {
|
||||
return Err(InstructionError::ReentrancyNotAllowed);
|
||||
}
|
||||
|
||||
let instruction = &message.instructions[0];
|
||||
|
||||
// Verify the calling program hasn't misbehaved
|
||||
|
@ -523,6 +550,7 @@ impl MessageProcessor {
|
|||
pre_accounts,
|
||||
self.programs.clone(), // get rid of clone
|
||||
log_collector,
|
||||
self.is_cross_program_supported,
|
||||
);
|
||||
let keyed_accounts =
|
||||
Self::create_keyed_accounts(message, instruction, executable_accounts, accounts)?;
|
||||
|
@ -595,8 +623,14 @@ mod tests {
|
|||
true,
|
||||
))
|
||||
}
|
||||
let mut invoke_context =
|
||||
ThisInvokeContext::new(&program_ids[0], Rent::default(), pre_accounts, vec![], None);
|
||||
let mut invoke_context = ThisInvokeContext::new(
|
||||
&program_ids[0],
|
||||
Rent::default(),
|
||||
pre_accounts,
|
||||
vec![],
|
||||
None,
|
||||
true,
|
||||
);
|
||||
|
||||
// Check call depth increases and has a limit
|
||||
let mut depth_reached = 1;
|
||||
|
@ -1365,6 +1399,7 @@ mod tests {
|
|||
vec![owned_preaccount, not_owned_preaccount],
|
||||
vec![],
|
||||
None,
|
||||
true,
|
||||
);
|
||||
let metas = vec![
|
||||
AccountMeta::new(owned_key, false),
|
||||
|
|
|
@ -214,6 +214,8 @@ pub trait InvokeContext {
|
|||
fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)];
|
||||
/// Get this invocation's logger
|
||||
fn get_logger(&self) -> Rc<RefCell<dyn Logger>>;
|
||||
/// Are cross program invocations supported
|
||||
fn is_cross_program_supported(&self) -> bool;
|
||||
}
|
||||
|
||||
/// Log messages
|
||||
|
|
Loading…
Reference in New Issue