Refactoring: Move KeyedAccounts to InvokeContext (#15410)

Collects all parametric occurrences and the construction of keyed_accounts and puts them into InvokeContext.
This commit is contained in:
Alexander Meißner
2021-04-19 18:48:48 +02:00
committed by GitHub
parent 015bc034a5
commit 9dfcb921cf
27 changed files with 1508 additions and 1408 deletions

View File

@ -89,14 +89,12 @@ macro_rules! declare_name {
/// use solana_sdk::{
/// declare_program,
/// instruction::InstructionError,
/// keyed_account::KeyedAccount,
/// process_instruction::InvokeContext,
/// pubkey::Pubkey,
/// };
///
/// fn my_process_instruction(
/// program_id: &Pubkey,
/// keyed_accounts: &[KeyedAccount],
/// instruction_data: &[u8],
/// invoke_context: &mut dyn InvokeContext,
/// ) -> Result<(), InstructionError> {
@ -124,14 +122,12 @@ macro_rules! declare_name {
/// use solana_sdk::{
/// declare_program,
/// instruction::InstructionError,
/// keyed_account::KeyedAccount,
/// process_instruction::InvokeContext,
/// pubkey::Pubkey,
/// };
///
/// fn my_process_instruction(
/// program_id: &Pubkey,
/// keyed_accounts: &[KeyedAccount],
/// instruction_data: &[u8],
/// invoke_context: &mut dyn InvokeContext,
/// ) -> Result<(), InstructionError> {
@ -158,11 +154,10 @@ macro_rules! declare_program(
#[no_mangle]
pub extern "C" fn $name(
program_id: &$crate::pubkey::Pubkey,
keyed_accounts: &[$crate::keyed_account::KeyedAccount],
instruction_data: &[u8],
invoke_context: &mut dyn $crate::process_instruction::InvokeContext,
) -> Result<(), $crate::instruction::InstructionError> {
$entrypoint(program_id, keyed_accounts, instruction_data, invoke_context)
$entrypoint(program_id, instruction_data, invoke_context)
}
)
);

View File

@ -10,7 +10,7 @@ use std::{
};
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct KeyedAccount<'a> {
is_signer: bool, // Transaction was signed by this account's key
is_writable: bool,
@ -146,6 +146,10 @@ pub fn create_keyed_accounts<'a>(
accounts.iter().map(Into::into).collect()
}
#[deprecated(
since = "1.7.0",
note = "Please use create_keyed_accounts_unified instead"
)]
pub fn create_keyed_is_signer_accounts<'a>(
accounts: &'a [(&'a Pubkey, bool, &'a RefCell<AccountSharedData>)],
) -> Vec<KeyedAccount<'a>> {
@ -160,6 +164,10 @@ pub fn create_keyed_is_signer_accounts<'a>(
.collect()
}
#[deprecated(
since = "1.7.0",
note = "Please use create_keyed_accounts_unified instead"
)]
pub fn create_keyed_readonly_accounts(
accounts: &[(Pubkey, Rc<RefCell<AccountSharedData>>)],
) -> Vec<KeyedAccount> {
@ -174,6 +182,20 @@ pub fn create_keyed_readonly_accounts(
.collect()
}
pub fn create_keyed_accounts_unified<'a>(
accounts: &[(bool, bool, &'a Pubkey, &'a RefCell<AccountSharedData>)],
) -> Vec<KeyedAccount<'a>> {
accounts
.iter()
.map(|(is_signer, is_writable, key, account)| KeyedAccount {
is_signer: *is_signer,
is_writable: *is_writable,
key,
account,
})
.collect()
}
/// Return all the signers from a set of KeyedAccounts
pub fn get_signers<A>(keyed_accounts: &[KeyedAccount]) -> A
where
@ -186,6 +208,7 @@ where
.collect::<A>()
}
#[deprecated(since = "1.7.0", note = "Please use keyed_account_at_index instead")]
/// Return the next KeyedAccount or a NotEnoughAccountKeys error
pub fn next_keyed_account<'a, 'b, I: Iterator<Item = &'a KeyedAccount<'b>>>(
iter: &mut I,
@ -193,6 +216,16 @@ pub fn next_keyed_account<'a, 'b, I: Iterator<Item = &'a KeyedAccount<'b>>>(
iter.next().ok_or(InstructionError::NotEnoughAccountKeys)
}
/// Return the KeyedAccount at the specified index or a NotEnoughAccountKeys error
pub fn keyed_account_at_index<'a>(
keyed_accounts: &'a [KeyedAccount],
index: usize,
) -> Result<&'a KeyedAccount<'a>, InstructionError> {
keyed_accounts
.get(index)
.ok_or(InstructionError::NotEnoughAccountKeys)
}
/// Return true if the first keyed_account is executable, used to determine if
/// the loader should call a program's 'main'
pub fn is_executable(keyed_accounts: &[KeyedAccount]) -> Result<bool, InstructionError> {

View File

@ -16,7 +16,7 @@ pub trait NonceKeyedAccount {
&self,
recent_blockhashes: &RecentBlockhashes,
signers: &HashSet<Pubkey>,
invoke_context: &mut dyn InvokeContext,
invoke_context: &dyn InvokeContext,
) -> Result<(), InstructionError>;
fn withdraw_nonce_account(
&self,
@ -25,20 +25,20 @@ pub trait NonceKeyedAccount {
recent_blockhashes: &RecentBlockhashes,
rent: &Rent,
signers: &HashSet<Pubkey>,
invoke_context: &mut dyn InvokeContext,
invoke_context: &dyn InvokeContext,
) -> Result<(), InstructionError>;
fn initialize_nonce_account(
&self,
nonce_authority: &Pubkey,
recent_blockhashes: &RecentBlockhashes,
rent: &Rent,
invoke_context: &mut dyn InvokeContext,
invoke_context: &dyn InvokeContext,
) -> Result<(), InstructionError>;
fn authorize_nonce_account(
&self,
nonce_authority: &Pubkey,
signers: &HashSet<Pubkey>,
invoke_context: &mut dyn InvokeContext,
invoke_context: &dyn InvokeContext,
) -> Result<(), InstructionError>;
}
@ -47,7 +47,7 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> {
&self,
recent_blockhashes: &RecentBlockhashes,
signers: &HashSet<Pubkey>,
invoke_context: &mut dyn InvokeContext,
invoke_context: &dyn InvokeContext,
) -> Result<(), InstructionError> {
if recent_blockhashes.is_empty() {
ic_msg!(
@ -102,7 +102,7 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> {
recent_blockhashes: &RecentBlockhashes,
rent: &Rent,
signers: &HashSet<Pubkey>,
invoke_context: &mut dyn InvokeContext,
invoke_context: &dyn InvokeContext,
) -> Result<(), InstructionError> {
let signer = match AccountUtilsState::<Versions>::state(self)?.convert_to_current() {
State::Uninitialized => {
@ -170,7 +170,7 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> {
nonce_authority: &Pubkey,
recent_blockhashes: &RecentBlockhashes,
rent: &Rent,
invoke_context: &mut dyn InvokeContext,
invoke_context: &dyn InvokeContext,
) -> Result<(), InstructionError> {
if recent_blockhashes.is_empty() {
ic_msg!(
@ -214,7 +214,7 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> {
&self,
nonce_authority: &Pubkey,
signers: &HashSet<Pubkey>,
invoke_context: &mut dyn InvokeContext,
invoke_context: &dyn InvokeContext,
) -> Result<(), InstructionError> {
match AccountUtilsState::<Versions>::state(self)?.convert_to_current() {
State::Initialized(data) => {
@ -300,7 +300,7 @@ mod test {
&authorized,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let state = AccountUtilsState::<Versions>::state(keyed_account)
@ -318,7 +318,7 @@ mod test {
.advance_nonce_account(
&recent_blockhashes,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let state = AccountUtilsState::<Versions>::state(keyed_account)
@ -336,7 +336,7 @@ mod test {
.advance_nonce_account(
&recent_blockhashes,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let state = AccountUtilsState::<Versions>::state(keyed_account)
@ -362,7 +362,7 @@ mod test {
&recent_blockhashes,
&rent,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
// Empties Account balance
@ -396,7 +396,7 @@ mod test {
&authority,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let pubkey = nonce_account.account.borrow().owner;
@ -415,7 +415,7 @@ mod test {
let result = nonce_account.advance_nonce_account(
&recent_blockhashes,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Err(InstructionError::MissingRequiredSignature),);
})
@ -438,14 +438,14 @@ mod test {
&authorized,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let recent_blockhashes = vec![].into_iter().collect();
let result = keyed_account.advance_nonce_account(
&recent_blockhashes,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Err(NonceError::NoRecentBlockhashes.into()));
})
@ -468,13 +468,13 @@ mod test {
&authorized,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let result = keyed_account.advance_nonce_account(
&recent_blockhashes,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Err(NonceError::NotExpired.into()));
})
@ -494,7 +494,7 @@ mod test {
let result = keyed_account.advance_nonce_account(
&recent_blockhashes,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Err(NonceError::BadAccountState.into()));
})
@ -518,7 +518,7 @@ mod test {
&authorized,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let mut signers = HashSet::new();
@ -527,7 +527,7 @@ mod test {
let result = nonce_account.advance_nonce_account(
&recent_blockhashes,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Ok(()));
});
@ -552,13 +552,13 @@ mod test {
&authorized,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let result = nonce_account.advance_nonce_account(
&recent_blockhashes,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Err(InstructionError::MissingRequiredSignature),);
});
@ -592,7 +592,7 @@ mod test {
&recent_blockhashes,
&rent,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let state = AccountUtilsState::<Versions>::state(nonce_keyed)
@ -631,7 +631,7 @@ mod test {
&recent_blockhashes,
&rent,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Err(InstructionError::MissingRequiredSignature),);
})
@ -661,7 +661,7 @@ mod test {
&recent_blockhashes,
&rent,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Err(InstructionError::InsufficientFunds));
})
@ -691,7 +691,7 @@ mod test {
&recent_blockhashes,
&rent,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let state = AccountUtilsState::<Versions>::state(nonce_keyed)
@ -711,7 +711,7 @@ mod test {
&recent_blockhashes,
&rent,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let state = AccountUtilsState::<Versions>::state(nonce_keyed)
@ -741,7 +741,7 @@ mod test {
&authority,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let state = AccountUtilsState::<Versions>::state(nonce_keyed)
@ -765,7 +765,7 @@ mod test {
&recent_blockhashes,
&rent,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let state = AccountUtilsState::<Versions>::state(nonce_keyed)
@ -791,7 +791,7 @@ mod test {
&recent_blockhashes,
&rent,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let state = AccountUtilsState::<Versions>::state(nonce_keyed)
@ -819,7 +819,7 @@ mod test {
&authorized,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
with_test_keyed_account(42, false, |to_keyed| {
@ -832,7 +832,7 @@ mod test {
&recent_blockhashes,
&rent,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Err(NonceError::NotExpired.into()));
})
@ -854,7 +854,7 @@ mod test {
&authorized,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
with_test_keyed_account(42, false, |to_keyed| {
@ -868,7 +868,7 @@ mod test {
&recent_blockhashes,
&rent,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Err(InstructionError::InsufficientFunds));
})
@ -890,7 +890,7 @@ mod test {
&authorized,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
with_test_keyed_account(42, false, |to_keyed| {
@ -904,7 +904,7 @@ mod test {
&recent_blockhashes,
&rent,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Err(InstructionError::InsufficientFunds));
})
@ -926,7 +926,7 @@ mod test {
&authorized,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
with_test_keyed_account(55, false, |to_keyed| {
@ -940,7 +940,7 @@ mod test {
&recent_blockhashes,
&rent,
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Err(InstructionError::InsufficientFunds));
})
@ -967,7 +967,7 @@ mod test {
&authority,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
let data = nonce::state::Data {
authority,
@ -998,7 +998,7 @@ mod test {
&authorized,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Err(NonceError::NoRecentBlockhashes.into()));
})
@ -1019,7 +1019,7 @@ mod test {
&authorized,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let recent_blockhashes = create_test_recent_blockhashes(0);
@ -1027,7 +1027,7 @@ mod test {
&authorized,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Err(NonceError::BadAccountState.into()));
})
@ -1047,7 +1047,7 @@ mod test {
&authorized,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Err(InstructionError::InsufficientFunds));
})
@ -1070,7 +1070,7 @@ mod test {
&authorized,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let authority = Pubkey::default();
@ -1082,7 +1082,7 @@ mod test {
let result = nonce_account.authorize_nonce_account(
&Pubkey::default(),
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Ok(()));
let state = AccountUtilsState::<Versions>::state(nonce_account)
@ -1105,7 +1105,7 @@ mod test {
let result = nonce_account.authorize_nonce_account(
&Pubkey::default(),
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Err(NonceError::BadAccountState.into()));
})
@ -1128,13 +1128,13 @@ mod test {
&authorized,
&recent_blockhashes,
&rent,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
let result = nonce_account.authorize_nonce_account(
&Pubkey::default(),
&signers,
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
);
assert_eq!(result, Err(InstructionError::MissingRequiredSignature));
})
@ -1155,7 +1155,7 @@ mod test {
&authorized,
&recent_blockhashes,
&Rent::free(),
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
assert!(verify_nonce_account(
@ -1190,7 +1190,7 @@ mod test {
&authorized,
&recent_blockhashes,
&Rent::free(),
&mut MockInvokeContext::default(),
&MockInvokeContext::new(vec![]),
)
.unwrap();
assert!(!verify_nonce_account(

View File

@ -1,7 +1,7 @@
use solana_sdk::{
account::AccountSharedData,
instruction::{CompiledInstruction, Instruction, InstructionError},
keyed_account::KeyedAccount,
keyed_account::{create_keyed_accounts_unified, KeyedAccount},
message::Message,
pubkey::Pubkey,
};
@ -15,19 +15,46 @@ use std::{cell::RefCell, fmt::Debug, rc::Rc, sync::Arc};
/// invoke_context: Invocation context
pub type LoaderEntrypoint = unsafe extern "C" fn(
program_id: &Pubkey,
keyed_accounts: &[KeyedAccount],
instruction_data: &[u8],
invoke_context: &dyn InvokeContext,
) -> Result<(), InstructionError>;
pub type ProcessInstructionWithContext =
fn(&Pubkey, &[KeyedAccount], &[u8], &mut dyn InvokeContext) -> Result<(), InstructionError>;
fn(&Pubkey, &[u8], &mut dyn InvokeContext) -> Result<(), InstructionError>;
pub struct InvokeContextStackFrame<'a> {
pub key: Pubkey,
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 {
let keyed_accounts_range = std::ops::Range {
start: 0,
end: keyed_accounts.len(),
};
Self {
key,
keyed_accounts,
keyed_accounts_range,
}
}
}
/// Invocation context passed to loaders
pub trait InvokeContext {
/// Push a program ID on to the invocation stack
fn push(&mut self, key: &Pubkey) -> Result<(), InstructionError>;
/// Pop a program ID off of the invocation stack
/// Push a stack frame onto the invocation stack
///
/// Used in MessageProcessor::process_cross_program_instruction
fn push(
&mut self,
key: &Pubkey,
keyed_accounts: &[(bool, bool, &Pubkey, &RefCell<AccountSharedData>)],
) -> Result<(), InstructionError>;
/// Pop a stack frame from the invocation stack
///
/// Used in MessageProcessor::process_cross_program_instruction
fn pop(&mut self);
/// Current depth of the invocation stake
fn invoke_depth(&self) -> usize;
@ -41,6 +68,10 @@ pub trait InvokeContext {
) -> Result<(), InstructionError>;
/// Get the program ID of the currently executing program
fn get_caller(&self) -> Result<&Pubkey, InstructionError>;
/// Removes the first keyed account
fn remove_first_keyed_account(&mut self) -> Result<(), InstructionError>;
/// Get the list of keyed accounts
fn get_keyed_accounts(&self) -> Result<&[KeyedAccount], InstructionError>;
/// Get a list of built-in programs
fn get_programs(&self) -> &[(Pubkey, ProcessInstructionWithContext)];
/// Get this invocation's logger
@ -238,7 +269,6 @@ pub trait Executor: Debug + Send + Sync {
&self,
loader_id: &Pubkey,
program_id: &Pubkey,
keyed_accounts: &[KeyedAccount],
instruction_data: &[u8],
invoke_context: &mut dyn InvokeContext,
use_jit: bool,
@ -276,42 +306,58 @@ impl Logger for MockLogger {
}
}
pub struct MockInvokeContext {
pub key: Pubkey,
pub struct MockInvokeContext<'a> {
pub invoke_stack: Vec<InvokeContextStackFrame<'a>>,
pub logger: MockLogger,
pub bpf_compute_budget: BpfComputeBudget,
pub compute_meter: MockComputeMeter,
pub programs: Vec<(Pubkey, ProcessInstructionWithContext)>,
pub accounts: Vec<(Pubkey, Rc<RefCell<AccountSharedData>>)>,
pub invoke_depth: usize,
pub sysvars: Vec<(Pubkey, Option<Rc<Vec<u8>>>)>,
}
impl Default for MockInvokeContext {
fn default() -> Self {
MockInvokeContext {
key: Pubkey::default(),
impl<'a> MockInvokeContext<'a> {
pub fn new(keyed_accounts: Vec<KeyedAccount<'a>>) -> Self {
let bpf_compute_budget = BpfComputeBudget::default();
let mut invoke_context = MockInvokeContext {
invoke_stack: Vec::with_capacity(bpf_compute_budget.max_invoke_depth),
logger: MockLogger::default(),
bpf_compute_budget: BpfComputeBudget::default(),
bpf_compute_budget,
compute_meter: MockComputeMeter {
remaining: std::i64::MAX as u64,
},
programs: vec![],
accounts: vec![],
invoke_depth: 0,
sysvars: vec![],
}
};
invoke_context
.invoke_stack
.push(InvokeContextStackFrame::new(
Pubkey::default(),
keyed_accounts,
));
invoke_context
}
}
impl InvokeContext for MockInvokeContext {
fn push(&mut self, _key: &Pubkey) -> Result<(), InstructionError> {
self.invoke_depth = self.invoke_depth.saturating_add(1);
impl<'a> InvokeContext for MockInvokeContext<'a> {
fn push(
&mut self,
key: &Pubkey,
keyed_accounts: &[(bool, bool, &Pubkey, &RefCell<AccountSharedData>)],
) -> Result<(), InstructionError> {
fn transmute_lifetime<'a, 'b>(value: Vec<KeyedAccount<'a>>) -> Vec<KeyedAccount<'b>> {
unsafe { std::mem::transmute(value) }
}
self.invoke_stack.push(InvokeContextStackFrame::new(
*key,
transmute_lifetime(create_keyed_accounts_unified(keyed_accounts)),
));
Ok(())
}
fn pop(&mut self) {
self.invoke_depth = self.invoke_depth.saturating_sub(1);
self.invoke_stack.pop();
}
fn invoke_depth(&self) -> usize {
self.invoke_depth
self.invoke_stack.len()
}
fn verify_and_update(
&mut self,
@ -323,7 +369,25 @@ impl InvokeContext for MockInvokeContext {
Ok(())
}
fn get_caller(&self) -> Result<&Pubkey, InstructionError> {
Ok(&self.key)
self.invoke_stack
.last()
.map(|frame| &frame.key)
.ok_or(InstructionError::CallDepth)
}
fn remove_first_keyed_account(&mut self) -> Result<(), InstructionError> {
let stack_frame = &mut self
.invoke_stack
.last_mut()
.ok_or(InstructionError::CallDepth)?;
stack_frame.keyed_accounts_range.start =
stack_frame.keyed_accounts_range.start.saturating_add(1);
Ok(())
}
fn get_keyed_accounts(&self) -> Result<&[KeyedAccount], InstructionError> {
self.invoke_stack
.last()
.map(|frame| &frame.keyed_accounts[frame.keyed_accounts_range.clone()])
.ok_or(InstructionError::CallDepth)
}
fn get_programs(&self) -> &[(Pubkey, ProcessInstructionWithContext)] {
&self.programs