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:
committed by
GitHub
parent
015bc034a5
commit
9dfcb921cf
@ -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)
|
||||
}
|
||||
)
|
||||
);
|
||||
|
@ -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> {
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user