Refactor: Make program_id always last in program chain (#20598)

* Replaces program_id field in InvokeContextStackFrame by index.

* Swaps order of program account and programdata account.

* Removes program_id parameter from InvokeContext::push().
This commit is contained in:
Alexander Meißner
2021-10-13 08:58:20 +02:00
committed by GitHub
parent c231cfe235
commit 1d813ea078
5 changed files with 114 additions and 141 deletions

View File

@ -31,23 +31,29 @@ pub type ProcessInstructionWithContext =
fn(usize, &[u8], &mut dyn InvokeContext) -> Result<(), InstructionError>;
pub struct InvokeContextStackFrame<'a> {
pub key: Pubkey,
pub number_of_program_accounts: usize,
pub keyed_accounts: Vec<KeyedAccount<'a>>,
pub keyed_accounts_range: std::ops::Range<usize>,
}
impl<'a> InvokeContextStackFrame<'a> {
pub fn new(key: Pubkey, 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 {
start: 0,
end: keyed_accounts.len(),
};
Self {
key,
number_of_program_accounts,
keyed_accounts,
keyed_accounts_range,
}
}
pub fn program_id(&self) -> Option<&Pubkey> {
self.keyed_accounts
.get(self.number_of_program_accounts.saturating_sub(1))
.map(|keyed_account| keyed_account.unsigned_key())
}
}
/// Invocation context passed to loaders
@ -55,7 +61,6 @@ pub trait InvokeContext {
/// Push a stack frame onto the invocation stack
fn push(
&mut self,
key: &Pubkey,
message: &Message,
instruction: &CompiledInstruction,
program_indices: &[usize],
@ -473,9 +478,17 @@ impl<'a> MockInvokeContext<'a> {
fee_calculator: FeeCalculator::default(),
return_data: (Pubkey::default(), Vec::new()),
};
let number_of_program_accounts = keyed_accounts
.iter()
.position(|keyed_account| keyed_account.unsigned_key() == program_id)
.unwrap_or(0)
.saturating_add(1);
invoke_context
.invoke_stack
.push(InvokeContextStackFrame::new(*program_id, keyed_accounts));
.push(InvokeContextStackFrame::new(
number_of_program_accounts,
keyed_accounts,
));
invoke_context
}
}
@ -498,14 +511,13 @@ pub fn mock_set_sysvar<T: Sysvar>(
impl<'a> InvokeContext for MockInvokeContext<'a> {
fn push(
&mut self,
_key: &Pubkey,
_message: &Message,
_instruction: &CompiledInstruction,
_program_indices: &[usize],
_account_indices: Option<&[usize]>,
) -> Result<(), InstructionError> {
self.invoke_stack.push(InvokeContextStackFrame::new(
*_key,
0,
create_keyed_accounts_unified(&[]),
));
Ok(())
@ -535,7 +547,7 @@ impl<'a> InvokeContext for MockInvokeContext<'a> {
fn get_caller(&self) -> Result<&Pubkey, InstructionError> {
self.invoke_stack
.last()
.map(|frame| &frame.key)
.and_then(|frame| frame.program_id())
.ok_or(InstructionError::CallDepth)
}
fn remove_first_keyed_account(&mut self) -> Result<(), InstructionError> {