Feature: TransactionContext, InstructionContext and BorrowedAccount (#21706)

* Adds TransactionContext, InstructionContext and BorrowedAccount.

* Redirects the usage of accounts in InvokeContext through TransactionContext.
Also use the types declared in transaction_context.rs everywhere.

* Adjusts all affected tests.
This commit is contained in:
Alexander Meißner
2021-12-27 18:49:32 +01:00
committed by GitHub
parent bb97c8fdcd
commit a06646631c
14 changed files with 926 additions and 530 deletions

View File

@ -37,6 +37,7 @@ use {
system_program,
sysvar::{self, instructions::construct_instructions_data},
transaction::{Result, SanitizedTransaction, TransactionError},
transaction_context::TransactionAccount,
},
std::{
cmp::Reverse,
@ -105,12 +106,11 @@ pub struct Accounts {
}
// for the load instructions
pub type TransactionAccounts = Vec<(Pubkey, AccountSharedData)>;
pub type TransactionRent = u64;
pub type TransactionProgramIndices = Vec<Vec<usize>>;
#[derive(PartialEq, Debug, Clone)]
pub struct LoadedTransaction {
pub accounts: TransactionAccounts,
pub accounts: Vec<TransactionAccount>,
pub program_indices: TransactionProgramIndices,
pub rent: TransactionRent,
pub rent_debits: RentDebits,
@ -385,7 +385,7 @@ impl Accounts {
fn load_executable_accounts(
&self,
ancestors: &Ancestors,
accounts: &mut Vec<(Pubkey, AccountSharedData)>,
accounts: &mut Vec<TransactionAccount>,
mut program_account_index: usize,
error_counters: &mut ErrorCounters,
) -> Result<Vec<usize>> {
@ -606,7 +606,7 @@ impl Accounts {
&self,
slot: Slot,
program_id: Option<&Pubkey>,
) -> Vec<(Pubkey, AccountSharedData)> {
) -> Vec<TransactionAccount> {
self.scan_slot(slot, |stored_account| {
let hit = match program_id {
None => true,
@ -721,7 +721,7 @@ impl Accounts {
}
fn load_while_filtering<F: Fn(&AccountSharedData) -> bool>(
collector: &mut Vec<(Pubkey, AccountSharedData)>,
collector: &mut Vec<TransactionAccount>,
some_account_tuple: Option<(&Pubkey, AccountSharedData, Slot)>,
filter: F,
) {
@ -739,11 +739,11 @@ impl Accounts {
bank_id: BankId,
program_id: &Pubkey,
config: &ScanConfig,
) -> ScanResult<Vec<(Pubkey, AccountSharedData)>> {
) -> ScanResult<Vec<TransactionAccount>> {
self.accounts_db.scan_accounts(
ancestors,
bank_id,
|collector: &mut Vec<(Pubkey, AccountSharedData)>, some_account_tuple| {
|collector: &mut Vec<TransactionAccount>, some_account_tuple| {
Self::load_while_filtering(collector, some_account_tuple, |account| {
account.owner() == program_id
})
@ -759,11 +759,11 @@ impl Accounts {
program_id: &Pubkey,
filter: F,
config: &ScanConfig,
) -> ScanResult<Vec<(Pubkey, AccountSharedData)>> {
) -> ScanResult<Vec<TransactionAccount>> {
self.accounts_db.scan_accounts(
ancestors,
bank_id,
|collector: &mut Vec<(Pubkey, AccountSharedData)>, some_account_tuple| {
|collector: &mut Vec<TransactionAccount>, some_account_tuple| {
Self::load_while_filtering(collector, some_account_tuple, |account| {
account.owner() == program_id && filter(account)
})
@ -796,9 +796,9 @@ impl Accounts {
}
fn maybe_abort_scan(
result: ScanResult<Vec<(Pubkey, AccountSharedData)>>,
result: ScanResult<Vec<TransactionAccount>>,
config: &ScanConfig,
) -> ScanResult<Vec<(Pubkey, AccountSharedData)>> {
) -> ScanResult<Vec<TransactionAccount>> {
if config.is_aborted() {
ScanResult::Err(ScanError::Aborted(
"The accumulated scan results exceeded the limit".to_string(),
@ -816,7 +816,7 @@ impl Accounts {
filter: F,
config: &ScanConfig,
byte_limit_for_scan: Option<usize>,
) -> ScanResult<Vec<(Pubkey, AccountSharedData)>> {
) -> ScanResult<Vec<TransactionAccount>> {
let sum = AtomicUsize::default();
let config = config.recreate_with_abort();
let result = self
@ -825,7 +825,7 @@ impl Accounts {
ancestors,
bank_id,
*index_key,
|collector: &mut Vec<(Pubkey, AccountSharedData)>, some_account_tuple| {
|collector: &mut Vec<TransactionAccount>, some_account_tuple| {
Self::load_while_filtering(collector, some_account_tuple, |account| {
let use_account = filter(account);
if use_account
@ -887,13 +887,13 @@ impl Accounts {
&self,
ancestors: &Ancestors,
range: R,
) -> Vec<(Pubkey, AccountSharedData)> {
) -> Vec<TransactionAccount> {
self.accounts_db.range_scan_accounts(
"load_to_collect_rent_eagerly_scan_elapsed",
ancestors,
range,
&ScanConfig::new(true),
|collector: &mut Vec<(Pubkey, AccountSharedData)>, option| {
|collector: &mut Vec<TransactionAccount>, option| {
Self::load_while_filtering(collector, option, |_| true)
},
)
@ -1277,7 +1277,7 @@ mod tests {
fn load_accounts_with_fee_and_rent(
tx: Transaction,
ka: &[(Pubkey, AccountSharedData)],
ka: &[TransactionAccount],
lamports_per_signature: u64,
rent_collector: &RentCollector,
error_counters: &mut ErrorCounters,
@ -1310,7 +1310,7 @@ mod tests {
fn load_accounts_with_fee(
tx: Transaction,
ka: &[(Pubkey, AccountSharedData)],
ka: &[TransactionAccount],
lamports_per_signature: u64,
error_counters: &mut ErrorCounters,
) -> Vec<TransactionLoadResult> {
@ -1325,7 +1325,7 @@ mod tests {
fn load_accounts(
tx: Transaction,
ka: &[(Pubkey, AccountSharedData)],
ka: &[TransactionAccount],
error_counters: &mut ErrorCounters,
) -> Vec<TransactionLoadResult> {
load_accounts_with_fee(tx, ka, 0, error_counters)
@ -1390,7 +1390,7 @@ mod tests {
#[test]
fn test_load_accounts_no_account_0_exists() {
let accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
let accounts: Vec<TransactionAccount> = Vec::new();
let mut error_counters = ErrorCounters::default();
let keypair = Keypair::new();
@ -1416,7 +1416,7 @@ mod tests {
#[test]
fn test_load_accounts_unknown_program_id() {
let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
let mut accounts: Vec<TransactionAccount> = Vec::new();
let mut error_counters = ErrorCounters::default();
let keypair = Keypair::new();
@ -1450,7 +1450,7 @@ mod tests {
#[test]
fn test_load_accounts_insufficient_funds() {
let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
let mut accounts: Vec<TransactionAccount> = Vec::new();
let mut error_counters = ErrorCounters::default();
let keypair = Keypair::new();
@ -1486,7 +1486,7 @@ mod tests {
#[test]
fn test_load_accounts_invalid_account_for_fee() {
let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
let mut accounts: Vec<TransactionAccount> = Vec::new();
let mut error_counters = ErrorCounters::default();
let keypair = Keypair::new();
@ -1588,7 +1588,7 @@ mod tests {
#[test]
fn test_load_accounts_no_loaders() {
let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
let mut accounts: Vec<TransactionAccount> = Vec::new();
let mut error_counters = ErrorCounters::default();
let keypair = Keypair::new();
@ -1629,7 +1629,7 @@ mod tests {
#[test]
fn test_load_accounts_max_call_depth() {
let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
let mut accounts: Vec<TransactionAccount> = Vec::new();
let mut error_counters = ErrorCounters::default();
let keypair = Keypair::new();
@ -1695,7 +1695,7 @@ mod tests {
#[test]
fn test_load_accounts_bad_owner() {
let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
let mut accounts: Vec<TransactionAccount> = Vec::new();
let mut error_counters = ErrorCounters::default();
let keypair = Keypair::new();
@ -1730,7 +1730,7 @@ mod tests {
#[test]
fn test_load_accounts_not_executable() {
let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
let mut accounts: Vec<TransactionAccount> = Vec::new();
let mut error_counters = ErrorCounters::default();
let keypair = Keypair::new();
@ -1764,7 +1764,7 @@ mod tests {
#[test]
fn test_load_accounts_multiple_loaders() {
let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
let mut accounts: Vec<TransactionAccount> = Vec::new();
let mut error_counters = ErrorCounters::default();
let keypair = Keypair::new();
@ -1860,7 +1860,7 @@ mod tests {
#[test]
fn test_load_accounts_executable_with_write_lock() {
let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
let mut accounts: Vec<TransactionAccount> = Vec::new();
let mut error_counters = ErrorCounters::default();
let keypair = Keypair::new();
@ -1916,7 +1916,7 @@ mod tests {
#[test]
fn test_load_accounts_upgradeable_with_write_lock() {
let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
let mut accounts: Vec<TransactionAccount> = Vec::new();
let mut error_counters = ErrorCounters::default();
let keypair = Keypair::new();
@ -2013,7 +2013,7 @@ mod tests {
#[test]
fn test_load_accounts_programdata_with_write_lock() {
let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
let mut accounts: Vec<TransactionAccount> = Vec::new();
let mut error_counters = ErrorCounters::default();
let keypair = Keypair::new();

View File

@ -37,7 +37,7 @@
use solana_sdk::recent_blockhashes_account;
use {
crate::{
accounts::{AccountAddressFilter, Accounts, TransactionAccounts, TransactionLoadResult},
accounts::{AccountAddressFilter, Accounts, TransactionLoadResult},
accounts_db::{
AccountShrinkThreshold, AccountsDbConfig, ErrorCounters, SnapshotStorages,
ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS, ACCOUNTS_DB_CONFIG_FOR_TESTING,
@ -74,10 +74,7 @@ use {
solana_metrics::{inc_new_counter_debug, inc_new_counter_info},
solana_program_runtime::{
instruction_recorder::InstructionRecorder,
invoke_context::{
BuiltinProgram, Executor, Executors, ProcessInstructionWithContext,
TransactionAccountRefCells,
},
invoke_context::{BuiltinProgram, Executor, Executors, ProcessInstructionWithContext},
log_collector::LogCollector,
timings::ExecuteDetailsTimings,
},
@ -127,6 +124,7 @@ use {
Result, SanitizedTransaction, Transaction, TransactionError,
TransactionVerificationMode, VersionedTransaction,
},
transaction_context::{TransactionAccount, TransactionContext},
},
solana_stake_program::stake_state::{
self, InflationPointCalculationEvent, PointValue, StakeState,
@ -515,7 +513,7 @@ pub struct TransactionResults {
pub struct TransactionSimulationResult {
pub result: Result<()>,
pub logs: TransactionLogMessages,
pub post_simulation_accounts: Vec<(Pubkey, AccountSharedData)>,
pub post_simulation_accounts: Vec<TransactionAccount>,
pub units_consumed: u64,
}
pub struct TransactionBalancesSet {
@ -654,7 +652,7 @@ impl NonceFull {
pub fn from_partial(
partial: NoncePartial,
message: &SanitizedMessage,
accounts: &[(Pubkey, AccountSharedData)],
accounts: &[TransactionAccount],
rent_debits: &RentDebits,
) -> Result<Self> {
let fee_payer = (0..message.account_keys_len()).find_map(|i| {
@ -3287,7 +3285,7 @@ impl Bank {
pub fn check_transaction_for_nonce(
&self,
tx: &SanitizedTransaction,
) -> Option<(Pubkey, AccountSharedData)> {
) -> Option<TransactionAccount> {
tx.get_durable_nonce(self.feature_set.is_active(&nonce_must_be_writable::id()))
.and_then(|nonce_address| {
self.get_account_with_fixed_root(nonce_address)
@ -3404,31 +3402,11 @@ impl Bank {
}
}
/// Converts Accounts into RefCell<AccountSharedData>, this involves moving
/// ownership by draining the source
fn accounts_to_refcells(accounts: &mut TransactionAccounts) -> TransactionAccountRefCells {
accounts
.drain(..)
.map(|(pubkey, account)| (pubkey, RefCell::new(account)))
.collect()
}
/// Converts back from RefCell<AccountSharedData> to AccountSharedData, this involves moving
/// ownership by draining the sources
fn refcells_to_accounts(
accounts: &mut TransactionAccounts,
mut account_refcells: TransactionAccountRefCells,
) {
for (pubkey, account_refcell) in account_refcells.drain(..) {
accounts.push((pubkey, account_refcell.into_inner()))
}
}
/// Get any cached executors needed by the transaction
fn get_executors(
&self,
message: &SanitizedMessage,
accounts: &[(Pubkey, AccountSharedData)],
accounts: &[TransactionAccount],
program_indices: &[Vec<usize>],
) -> Rc<RefCell<Executors>> {
let mut num_executors = message.account_keys_len();
@ -3573,8 +3551,12 @@ impl Bank {
&loaded_transaction.program_indices,
);
let account_refcells =
Self::accounts_to_refcells(&mut loaded_transaction.accounts);
let mut transaction_accounts = Vec::new();
std::mem::swap(&mut loaded_transaction.accounts, &mut transaction_accounts);
let transaction_context = TransactionContext::new(
transaction_accounts,
compute_budget.max_invoke_depth,
);
let instruction_recorder = if enable_cpi_recording {
Some(InstructionRecorder::new_ref(
@ -3598,7 +3580,7 @@ impl Bank {
&self.builtin_programs.vec,
legacy_message,
&loaded_transaction.program_indices,
&account_refcells,
&transaction_context,
self.rent_collector.rent,
log_collector.clone(),
executors.clone(),
@ -3637,10 +3619,7 @@ impl Bank {
}),
);
Self::refcells_to_accounts(
&mut loaded_transaction.accounts,
account_refcells,
);
loaded_transaction.accounts = transaction_context.deconstruct();
if process_result.is_ok() {
self.update_executors(executors);
@ -4993,7 +4972,7 @@ impl Bank {
&self,
program_id: &Pubkey,
config: &ScanConfig,
) -> ScanResult<Vec<(Pubkey, AccountSharedData)>> {
) -> ScanResult<Vec<TransactionAccount>> {
self.rc
.accounts
.load_by_program(&self.ancestors, self.bank_id, program_id, config)
@ -5004,7 +4983,7 @@ impl Bank {
program_id: &Pubkey,
filter: F,
config: &ScanConfig,
) -> ScanResult<Vec<(Pubkey, AccountSharedData)>> {
) -> ScanResult<Vec<TransactionAccount>> {
self.rc.accounts.load_by_program_with_filter(
&self.ancestors,
self.bank_id,
@ -5020,7 +4999,7 @@ impl Bank {
filter: F,
config: &ScanConfig,
byte_limit_for_scan: Option<usize>,
) -> ScanResult<Vec<(Pubkey, AccountSharedData)>> {
) -> ScanResult<Vec<TransactionAccount>> {
self.rc.accounts.load_by_index_key_with_filter(
&self.ancestors,
self.bank_id,
@ -5044,7 +5023,7 @@ impl Bank {
pub fn get_program_accounts_modified_since_parent(
&self,
program_id: &Pubkey,
) -> Vec<(Pubkey, AccountSharedData)> {
) -> Vec<TransactionAccount> {
self.rc
.accounts
.load_by_program_slot(self.slot(), Some(program_id))
@ -5060,7 +5039,7 @@ impl Bank {
.get_logs_for_address(address)
}
pub fn get_all_accounts_modified_since_parent(&self) -> Vec<(Pubkey, AccountSharedData)> {
pub fn get_all_accounts_modified_since_parent(&self) -> Vec<TransactionAccount> {
self.rc.accounts.load_by_program_slot(self.slot(), None)
}
@ -6722,8 +6701,7 @@ pub(crate) mod tests {
mock_program_id: Pubkey,
generic_rent_due_for_system_account: u64,
) {
let mut account_pairs: Vec<(Pubkey, AccountSharedData)> =
Vec::with_capacity(keypairs.len() - 1);
let mut account_pairs: Vec<TransactionAccount> = Vec::with_capacity(keypairs.len() - 1);
account_pairs.push((
keypairs[0].pubkey(),
AccountSharedData::new(

View File

@ -3,9 +3,7 @@ use {
solana_measure::measure::Measure,
solana_program_runtime::{
instruction_recorder::InstructionRecorder,
invoke_context::{
BuiltinProgram, Executors, InstructionAccount, InvokeContext, TransactionAccountRefCell,
},
invoke_context::{BuiltinProgram, Executors, InvokeContext},
log_collector::LogCollector,
timings::ExecuteDetailsTimings,
},
@ -20,6 +18,7 @@ use {
rent::Rent,
sysvar::instructions,
transaction::TransactionError,
transaction_context::{InstructionAccount, TransactionContext},
},
std::{cell::RefCell, rc::Rc, sync::Arc},
};
@ -54,7 +53,7 @@ impl MessageProcessor {
builtin_programs: &[BuiltinProgram],
message: &Message,
program_indices: &[Vec<usize>],
accounts: &[TransactionAccountRefCell],
transaction_context: &TransactionContext,
rent: Rent,
log_collector: Option<Rc<RefCell<LogCollector>>>,
executors: Rc<RefCell<Executors>>,
@ -67,8 +66,8 @@ impl MessageProcessor {
lamports_per_signature: u64,
) -> Result<ProcessedMessageInfo, TransactionError> {
let mut invoke_context = InvokeContext::new(
transaction_context,
rent,
accounts,
builtin_programs,
sysvars,
log_collector,
@ -99,15 +98,18 @@ impl MessageProcessor {
// Fixup the special instructions key if present
// before the account pre-values are taken care of
for (pubkey, account) in accounts.iter().take(message.account_keys.len()) {
if instructions::check_id(pubkey) {
let mut mut_account_ref = account.borrow_mut();
instructions::store_current_index(
mut_account_ref.data_as_mut_slice(),
instruction_index as u16,
);
break;
}
if let Some(account_index) = invoke_context
.transaction_context
.find_index_of_account(&instructions::id())
{
let mut mut_account_ref = invoke_context
.transaction_context
.get_account_at_index(account_index)
.borrow_mut();
instructions::store_current_index(
mut_account_ref.data_as_mut_slice(),
instruction_index as u16,
);
}
let instruction_accounts = instruction
@ -221,39 +223,38 @@ mod tests {
let accounts = vec![
(
solana_sdk::pubkey::new_rand(),
RefCell::new(AccountSharedData::new(100, 1, &mock_system_program_id)),
AccountSharedData::new(100, 1, &mock_system_program_id),
),
(
solana_sdk::pubkey::new_rand(),
RefCell::new(AccountSharedData::new(0, 1, &mock_system_program_id)),
AccountSharedData::new(0, 1, &mock_system_program_id),
),
(
mock_system_program_id,
RefCell::new(create_loadable_account_for_test("mock_system_program")),
create_loadable_account_for_test("mock_system_program"),
),
];
let transaction_context = TransactionContext::new(accounts, 1);
let program_indices = vec![vec![2]];
let executors = Rc::new(RefCell::new(Executors::default()));
let account_metas = vec![
AccountMeta::new(accounts[0].0, true),
AccountMeta::new_readonly(accounts[1].0, false),
AccountMeta::new(*transaction_context.get_key_of_account_at_index(0), true),
AccountMeta::new_readonly(*transaction_context.get_key_of_account_at_index(1), false),
];
let message = Message::new(
&[Instruction::new_with_bincode(
mock_system_program_id,
&MockSystemInstruction::Correct,
account_metas.clone(),
)],
Some(&accounts[0].0),
Some(transaction_context.get_key_of_account_at_index(0)),
);
let result = MessageProcessor::process_message(
builtin_programs,
&message,
&program_indices,
&accounts,
&transaction_context,
rent_collector.rent,
None,
executors.clone(),
@ -266,8 +267,20 @@ mod tests {
0,
);
assert!(result.is_ok());
assert_eq!(accounts[0].1.borrow().lamports(), 100);
assert_eq!(accounts[1].1.borrow().lamports(), 0);
assert_eq!(
transaction_context
.get_account_at_index(0)
.borrow()
.lamports(),
100
);
assert_eq!(
transaction_context
.get_account_at_index(1)
.borrow()
.lamports(),
0
);
let message = Message::new(
&[Instruction::new_with_bincode(
@ -275,14 +288,13 @@ mod tests {
&MockSystemInstruction::AttemptCredit { lamports: 50 },
account_metas.clone(),
)],
Some(&accounts[0].0),
Some(transaction_context.get_key_of_account_at_index(0)),
);
let result = MessageProcessor::process_message(
builtin_programs,
&message,
&program_indices,
&accounts,
&transaction_context,
rent_collector.rent,
None,
executors.clone(),
@ -308,14 +320,13 @@ mod tests {
&MockSystemInstruction::AttemptDataChange { data: 50 },
account_metas,
)],
Some(&accounts[0].0),
Some(transaction_context.get_key_of_account_at_index(0)),
);
let result = MessageProcessor::process_message(
builtin_programs,
&message,
&program_indices,
&accounts,
&transaction_context,
rent_collector.rent,
None,
executors,
@ -425,25 +436,24 @@ mod tests {
let accounts = vec![
(
solana_sdk::pubkey::new_rand(),
RefCell::new(AccountSharedData::new(100, 1, &mock_program_id)),
AccountSharedData::new(100, 1, &mock_program_id),
),
(
solana_sdk::pubkey::new_rand(),
RefCell::new(AccountSharedData::new(0, 1, &mock_program_id)),
AccountSharedData::new(0, 1, &mock_program_id),
),
(
mock_program_id,
RefCell::new(create_loadable_account_for_test("mock_system_program")),
create_loadable_account_for_test("mock_system_program"),
),
];
let transaction_context = TransactionContext::new(accounts, 1);
let program_indices = vec![vec![2]];
let executors = Rc::new(RefCell::new(Executors::default()));
let account_metas = vec![
AccountMeta::new(accounts[0].0, true),
AccountMeta::new(accounts[1].0, false),
AccountMeta::new(accounts[0].0, false),
AccountMeta::new(*transaction_context.get_key_of_account_at_index(0), true),
AccountMeta::new(*transaction_context.get_key_of_account_at_index(1), false),
AccountMeta::new(*transaction_context.get_key_of_account_at_index(0), false),
];
// Try to borrow mut the same account
@ -453,13 +463,13 @@ mod tests {
&MockSystemInstruction::BorrowFail,
account_metas.clone(),
)],
Some(&accounts[0].0),
Some(transaction_context.get_key_of_account_at_index(0)),
);
let result = MessageProcessor::process_message(
builtin_programs,
&message,
&program_indices,
&accounts,
&transaction_context,
rent_collector.rent,
None,
executors.clone(),
@ -486,13 +496,13 @@ mod tests {
&MockSystemInstruction::MultiBorrowMut,
account_metas.clone(),
)],
Some(&accounts[0].0),
Some(transaction_context.get_key_of_account_at_index(0)),
);
let result = MessageProcessor::process_message(
builtin_programs,
&message,
&program_indices,
&accounts,
&transaction_context,
rent_collector.rent,
None,
executors.clone(),
@ -516,13 +526,13 @@ mod tests {
},
account_metas,
)],
Some(&accounts[0].0),
Some(transaction_context.get_key_of_account_at_index(0)),
);
let result = MessageProcessor::process_message(
builtin_programs,
&message,
&program_indices,
&accounts,
&transaction_context,
rent_collector.rent,
None,
executors,
@ -535,9 +545,24 @@ mod tests {
0,
);
assert!(result.is_ok());
assert_eq!(accounts[0].1.borrow().lamports(), 80);
assert_eq!(accounts[1].1.borrow().lamports(), 20);
assert_eq!(accounts[0].1.borrow().data(), &vec![42]);
assert_eq!(
transaction_context
.get_account_at_index(0)
.borrow()
.lamports(),
80
);
assert_eq!(
transaction_context
.get_account_at_index(1)
.borrow()
.lamports(),
20
);
assert_eq!(
transaction_context.get_account_at_index(0).borrow().data(),
&vec![42]
);
}
#[test]
@ -560,9 +585,10 @@ mod tests {
let mut mock_program_account = AccountSharedData::new(1, 0, &native_loader::id());
mock_program_account.set_executable(true);
let accounts = vec![
(secp256k1_program::id(), RefCell::new(secp256k1_account)),
(mock_program_id, RefCell::new(mock_program_account)),
(secp256k1_program::id(), secp256k1_account),
(mock_program_id, mock_program_account),
];
let transaction_context = TransactionContext::new(accounts, 1);
let message = Message::new(
&[
@ -574,12 +600,11 @@ mod tests {
],
None,
);
let result = MessageProcessor::process_message(
builtin_programs,
&message,
&[vec![0], vec![1]],
&accounts,
&transaction_context,
RentCollector::default().rent,
None,
Rc::new(RefCell::new(Executors::default())),

View File

@ -326,32 +326,25 @@ mod test {
nonce::{self, State},
nonce_account::{create_account, verify_nonce_account},
system_instruction::SystemError,
transaction_context::TransactionContext,
},
};
fn with_test_keyed_account<F>(lamports: u64, signer: bool, f: F)
fn with_mockup<F>(lamports: u64, signer: bool, mut f: F)
where
F: Fn(&KeyedAccount),
F: FnMut(&mut InvokeContext, &KeyedAccount),
{
let transaction_context = TransactionContext::new(Vec::new(), 1);
let mut invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let pubkey = Pubkey::new_unique();
let account = create_account(lamports);
let keyed_account = KeyedAccount::new(&pubkey, signer, &account);
f(&keyed_account)
f(&mut invoke_context, &keyed_account)
}
fn create_test_blockhash(seed: usize) -> (Hash, u64) {
(
hash(&bincode::serialize(&seed).unwrap()),
(seed as u64).saturating_mul(100),
)
}
fn create_invoke_context_with_blockhash<'a>(seed: usize) -> InvokeContext<'a> {
let mut invoke_context = InvokeContext::new_mock(&[], &[]);
let (blockhash, lamports_per_signature) = create_test_blockhash(seed);
invoke_context.blockhash = blockhash;
invoke_context.lamports_per_signature = lamports_per_signature;
invoke_context
fn set_invoke_context_blockhash(invoke_context: &mut InvokeContext, seed: usize) {
invoke_context.blockhash = hash(&bincode::serialize(&seed).unwrap());
invoke_context.lamports_per_signature = (seed as u64).saturating_mul(100);
}
#[test]
@ -366,7 +359,7 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |keyed_account| {
with_mockup(min_lamports + 42, true, |invoke_context, keyed_account| {
let data = nonce::state::Data {
authority: *keyed_account.unsigned_key(),
..nonce::state::Data::default()
@ -378,10 +371,10 @@ mod test {
.convert_to_current();
// New is in Uninitialzed state
assert_eq!(state, State::Uninitialized);
let invoke_context = create_invoke_context_with_blockhash(95);
set_invoke_context_blockhash(invoke_context, 95);
let authorized = keyed_account.unsigned_key();
keyed_account
.initialize_nonce_account(authorized, &rent, &invoke_context)
.initialize_nonce_account(authorized, &rent, invoke_context)
.unwrap();
let state = AccountUtilsState::<Versions>::state(keyed_account)
.unwrap()
@ -393,9 +386,9 @@ mod test {
);
// First nonce instruction drives state from Uninitialized to Initialized
assert_eq!(state, State::Initialized(data.clone()));
let invoke_context = create_invoke_context_with_blockhash(63);
set_invoke_context_blockhash(invoke_context, 63);
keyed_account
.advance_nonce_account(&signers, &invoke_context)
.advance_nonce_account(&signers, invoke_context)
.unwrap();
let state = AccountUtilsState::<Versions>::state(keyed_account)
.unwrap()
@ -407,9 +400,9 @@ mod test {
);
// Second nonce instruction consumes and replaces stored nonce
assert_eq!(state, State::Initialized(data.clone()));
let invoke_context = create_invoke_context_with_blockhash(31);
set_invoke_context_blockhash(invoke_context, 31);
keyed_account
.advance_nonce_account(&signers, &invoke_context)
.advance_nonce_account(&signers, invoke_context)
.unwrap();
let state = AccountUtilsState::<Versions>::state(keyed_account)
.unwrap()
@ -421,8 +414,8 @@ mod test {
);
// Third nonce instruction for fun and profit
assert_eq!(state, State::Initialized(data));
with_test_keyed_account(42, false, |to_keyed| {
let invoke_context = create_invoke_context_with_blockhash(0);
with_mockup(42, false, |_invoke_context, to_keyed| {
set_invoke_context_blockhash(invoke_context, 0);
let withdraw_lamports = keyed_account.account.borrow().lamports();
let expect_nonce_lamports =
keyed_account.account.borrow().lamports() - withdraw_lamports;
@ -433,7 +426,7 @@ mod test {
to_keyed,
&rent,
&signers,
&invoke_context,
invoke_context,
)
.unwrap();
// Empties Account balance
@ -459,11 +452,11 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |nonce_account| {
let invoke_context = create_invoke_context_with_blockhash(31);
with_mockup(min_lamports + 42, true, |invoke_context, nonce_account| {
set_invoke_context_blockhash(invoke_context, 31);
let authority = *nonce_account.unsigned_key();
nonce_account
.initialize_nonce_account(&authority, &rent, &invoke_context)
.initialize_nonce_account(&authority, &rent, invoke_context)
.unwrap();
let pubkey = *nonce_account.account.borrow().owner();
let nonce_account = KeyedAccount::new(&pubkey, false, nonce_account.account);
@ -477,9 +470,9 @@ mod test {
);
assert_eq!(state, State::Initialized(data));
let signers = HashSet::new();
let invoke_context = create_invoke_context_with_blockhash(0);
set_invoke_context_blockhash(invoke_context, 0);
let result = nonce_account.advance_nonce_account(&signers, &invoke_context);
let result = nonce_account.advance_nonce_account(&signers, invoke_context);
assert_eq!(result, Err(InstructionError::MissingRequiredSignature),);
})
}
@ -491,15 +484,15 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |keyed_account| {
with_mockup(min_lamports + 42, true, |invoke_context, keyed_account| {
let mut signers = HashSet::new();
signers.insert(*keyed_account.signer_key().unwrap());
let invoke_context = create_invoke_context_with_blockhash(63);
set_invoke_context_blockhash(invoke_context, 63);
let authorized = *keyed_account.unsigned_key();
keyed_account
.initialize_nonce_account(&authorized, &rent, &invoke_context)
.initialize_nonce_account(&authorized, &rent, invoke_context)
.unwrap();
let result = keyed_account.advance_nonce_account(&signers, &invoke_context);
let result = keyed_account.advance_nonce_account(&signers, invoke_context);
assert_eq!(result, Err(SystemError::NonceBlockhashNotExpired.into()));
})
}
@ -511,11 +504,11 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |keyed_account| {
with_mockup(min_lamports + 42, true, |invoke_context, keyed_account| {
let mut signers = HashSet::new();
signers.insert(*keyed_account.signer_key().unwrap());
let invoke_context = create_invoke_context_with_blockhash(63);
let result = keyed_account.advance_nonce_account(&signers, &invoke_context);
set_invoke_context_blockhash(invoke_context, 63);
let result = keyed_account.advance_nonce_account(&signers, invoke_context);
assert_eq!(result, Err(InstructionError::InvalidAccountData));
})
}
@ -527,19 +520,19 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |nonce_account| {
with_test_keyed_account(42, true, |nonce_authority| {
with_mockup(min_lamports + 42, true, |invoke_context, nonce_account| {
with_mockup(42, true, |_invoke_context, nonce_authority| {
let mut signers = HashSet::new();
signers.insert(*nonce_account.signer_key().unwrap());
let invoke_context = create_invoke_context_with_blockhash(63);
set_invoke_context_blockhash(invoke_context, 63);
let authorized = *nonce_authority.unsigned_key();
nonce_account
.initialize_nonce_account(&authorized, &rent, &invoke_context)
.initialize_nonce_account(&authorized, &rent, invoke_context)
.unwrap();
let mut signers = HashSet::new();
signers.insert(*nonce_authority.signer_key().unwrap());
let invoke_context = create_invoke_context_with_blockhash(31);
let result = nonce_account.advance_nonce_account(&signers, &invoke_context);
set_invoke_context_blockhash(invoke_context, 31);
let result = nonce_account.advance_nonce_account(&signers, invoke_context);
assert_eq!(result, Ok(()));
});
});
@ -552,16 +545,16 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |nonce_account| {
with_test_keyed_account(42, false, |nonce_authority| {
with_mockup(min_lamports + 42, true, |invoke_context, nonce_account| {
with_mockup(42, false, |_invoke_context, nonce_authority| {
let mut signers = HashSet::new();
signers.insert(*nonce_account.signer_key().unwrap());
let invoke_context = create_invoke_context_with_blockhash(63);
set_invoke_context_blockhash(invoke_context, 63);
let authorized = *nonce_authority.unsigned_key();
nonce_account
.initialize_nonce_account(&authorized, &rent, &invoke_context)
.initialize_nonce_account(&authorized, &rent, invoke_context)
.unwrap();
let result = nonce_account.advance_nonce_account(&signers, &invoke_context);
let result = nonce_account.advance_nonce_account(&signers, invoke_context);
assert_eq!(result, Err(InstructionError::MissingRequiredSignature),);
});
});
@ -574,15 +567,15 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |nonce_keyed| {
with_mockup(min_lamports + 42, true, |invoke_context, nonce_keyed| {
let state = AccountUtilsState::<Versions>::state(nonce_keyed)
.unwrap()
.convert_to_current();
assert_eq!(state, State::Uninitialized);
with_test_keyed_account(42, false, |to_keyed| {
with_mockup(42, false, |_invoke_context, to_keyed| {
let mut signers = HashSet::new();
signers.insert(*nonce_keyed.signer_key().unwrap());
let invoke_context = create_invoke_context_with_blockhash(0);
set_invoke_context_blockhash(invoke_context, 0);
let withdraw_lamports = nonce_keyed.account.borrow().lamports();
let expect_nonce_lamports =
nonce_keyed.account.borrow().lamports() - withdraw_lamports;
@ -593,7 +586,7 @@ mod test {
to_keyed,
&rent,
&signers,
&invoke_context,
invoke_context,
)
.unwrap();
let state = AccountUtilsState::<Versions>::state(nonce_keyed)
@ -620,21 +613,21 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, false, |nonce_keyed| {
with_mockup(min_lamports + 42, false, |invoke_context, nonce_keyed| {
let state = AccountUtilsState::<Versions>::state(nonce_keyed)
.unwrap()
.convert_to_current();
assert_eq!(state, State::Uninitialized);
with_test_keyed_account(42, false, |to_keyed| {
with_mockup(42, false, |_invoke_context, to_keyed| {
let signers = HashSet::new();
let invoke_context = create_invoke_context_with_blockhash(0);
set_invoke_context_blockhash(invoke_context, 0);
let lamports = nonce_keyed.account.borrow().lamports();
let result = nonce_keyed.withdraw_nonce_account(
lamports,
to_keyed,
&rent,
&signers,
&invoke_context,
invoke_context,
);
assert_eq!(result, Err(InstructionError::MissingRequiredSignature),);
})
@ -648,22 +641,22 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |nonce_keyed| {
with_mockup(min_lamports + 42, true, |invoke_context, nonce_keyed| {
let state = AccountUtilsState::<Versions>::state(nonce_keyed)
.unwrap()
.convert_to_current();
assert_eq!(state, State::Uninitialized);
with_test_keyed_account(42, false, |to_keyed| {
with_mockup(42, false, |_invoke_context, to_keyed| {
let mut signers = HashSet::new();
signers.insert(*nonce_keyed.signer_key().unwrap());
let invoke_context = create_invoke_context_with_blockhash(0);
set_invoke_context_blockhash(invoke_context, 0);
let lamports = nonce_keyed.account.borrow().lamports() + 1;
let result = nonce_keyed.withdraw_nonce_account(
lamports,
to_keyed,
&rent,
&signers,
&invoke_context,
invoke_context,
);
assert_eq!(result, Err(InstructionError::InsufficientFunds));
})
@ -677,11 +670,11 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |nonce_keyed| {
with_test_keyed_account(42, false, |to_keyed| {
with_mockup(min_lamports + 42, true, |invoke_context, nonce_keyed| {
with_mockup(42, false, |_invoke_context, to_keyed| {
let mut signers = HashSet::new();
signers.insert(*nonce_keyed.signer_key().unwrap());
let invoke_context = create_invoke_context_with_blockhash(0);
set_invoke_context_blockhash(invoke_context, 0);
let withdraw_lamports = nonce_keyed.account.borrow().lamports() / 2;
let nonce_expect_lamports =
nonce_keyed.account.borrow().lamports() - withdraw_lamports;
@ -692,7 +685,7 @@ mod test {
to_keyed,
&rent,
&signers,
&invoke_context,
invoke_context,
)
.unwrap();
let state = AccountUtilsState::<Versions>::state(nonce_keyed)
@ -714,7 +707,7 @@ mod test {
to_keyed,
&rent,
&signers,
&invoke_context,
invoke_context,
)
.unwrap();
let state = AccountUtilsState::<Versions>::state(nonce_keyed)
@ -737,13 +730,13 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |nonce_keyed| {
with_mockup(min_lamports + 42, true, |invoke_context, nonce_keyed| {
let mut signers = HashSet::new();
signers.insert(*nonce_keyed.signer_key().unwrap());
let invoke_context = create_invoke_context_with_blockhash(31);
set_invoke_context_blockhash(invoke_context, 31);
let authority = *nonce_keyed.unsigned_key();
nonce_keyed
.initialize_nonce_account(&authority, &rent, &invoke_context)
.initialize_nonce_account(&authority, &rent, invoke_context)
.unwrap();
let state = AccountUtilsState::<Versions>::state(nonce_keyed)
.unwrap()
@ -754,7 +747,7 @@ mod test {
invoke_context.lamports_per_signature,
);
assert_eq!(state, State::Initialized(data.clone()));
with_test_keyed_account(42, false, |to_keyed| {
with_mockup(42, false, |_invoke_context, to_keyed| {
let withdraw_lamports = nonce_keyed.account.borrow().lamports() - min_lamports;
let nonce_expect_lamports =
nonce_keyed.account.borrow().lamports() - withdraw_lamports;
@ -765,7 +758,7 @@ mod test {
to_keyed,
&rent,
&signers,
&invoke_context,
invoke_context,
)
.unwrap();
let state = AccountUtilsState::<Versions>::state(nonce_keyed)
@ -782,7 +775,7 @@ mod test {
nonce_expect_lamports
);
assert_eq!(to_keyed.account.borrow().lamports(), to_expect_lamports);
let invoke_context = create_invoke_context_with_blockhash(0);
set_invoke_context_blockhash(invoke_context, 0);
let withdraw_lamports = nonce_keyed.account.borrow().lamports();
let nonce_expect_lamports =
nonce_keyed.account.borrow().lamports() - withdraw_lamports;
@ -793,7 +786,7 @@ mod test {
to_keyed,
&rent,
&signers,
&invoke_context,
invoke_context,
)
.unwrap();
let state = AccountUtilsState::<Versions>::state(nonce_keyed)
@ -816,13 +809,13 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |nonce_keyed| {
let invoke_context = create_invoke_context_with_blockhash(0);
with_mockup(min_lamports + 42, true, |invoke_context, nonce_keyed| {
set_invoke_context_blockhash(invoke_context, 0);
let authorized = *nonce_keyed.unsigned_key();
nonce_keyed
.initialize_nonce_account(&authorized, &rent, &invoke_context)
.initialize_nonce_account(&authorized, &rent, invoke_context)
.unwrap();
with_test_keyed_account(42, false, |to_keyed| {
with_mockup(42, false, |_invoke_context, to_keyed| {
let mut signers = HashSet::new();
signers.insert(*nonce_keyed.signer_key().unwrap());
let withdraw_lamports = nonce_keyed.account.borrow().lamports();
@ -831,7 +824,7 @@ mod test {
to_keyed,
&rent,
&signers,
&invoke_context,
invoke_context,
);
assert_eq!(result, Err(SystemError::NonceBlockhashNotExpired.into()));
})
@ -845,14 +838,14 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |nonce_keyed| {
let invoke_context = create_invoke_context_with_blockhash(95);
with_mockup(min_lamports + 42, true, |invoke_context, nonce_keyed| {
set_invoke_context_blockhash(invoke_context, 95);
let authorized = *nonce_keyed.unsigned_key();
nonce_keyed
.initialize_nonce_account(&authorized, &rent, &invoke_context)
.initialize_nonce_account(&authorized, &rent, invoke_context)
.unwrap();
with_test_keyed_account(42, false, |to_keyed| {
let invoke_context = create_invoke_context_with_blockhash(63);
with_mockup(42, false, |_invoke_context, to_keyed| {
set_invoke_context_blockhash(invoke_context, 63);
let mut signers = HashSet::new();
signers.insert(*nonce_keyed.signer_key().unwrap());
let withdraw_lamports = nonce_keyed.account.borrow().lamports() + 1;
@ -861,7 +854,7 @@ mod test {
to_keyed,
&rent,
&signers,
&invoke_context,
invoke_context,
);
assert_eq!(result, Err(InstructionError::InsufficientFunds));
})
@ -875,14 +868,14 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |nonce_keyed| {
let invoke_context = create_invoke_context_with_blockhash(95);
with_mockup(min_lamports + 42, true, |invoke_context, nonce_keyed| {
set_invoke_context_blockhash(invoke_context, 95);
let authorized = *nonce_keyed.unsigned_key();
nonce_keyed
.initialize_nonce_account(&authorized, &rent, &invoke_context)
.initialize_nonce_account(&authorized, &rent, invoke_context)
.unwrap();
with_test_keyed_account(42, false, |to_keyed| {
let invoke_context = create_invoke_context_with_blockhash(63);
with_mockup(42, false, |_invoke_context, to_keyed| {
set_invoke_context_blockhash(invoke_context, 63);
let mut signers = HashSet::new();
signers.insert(*nonce_keyed.signer_key().unwrap());
let withdraw_lamports = nonce_keyed.account.borrow().lamports() - min_lamports + 1;
@ -891,7 +884,7 @@ mod test {
to_keyed,
&rent,
&signers,
&invoke_context,
invoke_context,
);
assert_eq!(result, Err(InstructionError::InsufficientFunds));
})
@ -905,14 +898,14 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |nonce_keyed| {
let invoke_context = create_invoke_context_with_blockhash(95);
with_mockup(min_lamports + 42, true, |invoke_context, nonce_keyed| {
set_invoke_context_blockhash(invoke_context, 95);
let authorized = *nonce_keyed.unsigned_key();
nonce_keyed
.initialize_nonce_account(&authorized, &rent, &invoke_context)
.initialize_nonce_account(&authorized, &rent, invoke_context)
.unwrap();
with_test_keyed_account(55, false, |to_keyed| {
let invoke_context = create_invoke_context_with_blockhash(63);
with_mockup(55, false, |_invoke_context, to_keyed| {
set_invoke_context_blockhash(invoke_context, 63);
let mut signers = HashSet::new();
signers.insert(*nonce_keyed.signer_key().unwrap());
let withdraw_lamports = u64::MAX - 54;
@ -921,7 +914,7 @@ mod test {
to_keyed,
&rent,
&signers,
&invoke_context,
invoke_context,
);
assert_eq!(result, Err(InstructionError::InsufficientFunds));
})
@ -935,16 +928,16 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |keyed_account| {
with_mockup(min_lamports + 42, true, |invoke_context, keyed_account| {
let state = AccountUtilsState::<Versions>::state(keyed_account)
.unwrap()
.convert_to_current();
assert_eq!(state, State::Uninitialized);
let mut signers = HashSet::new();
signers.insert(*keyed_account.signer_key().unwrap());
let invoke_context = create_invoke_context_with_blockhash(0);
set_invoke_context_blockhash(invoke_context, 0);
let authority = *keyed_account.unsigned_key();
let result = keyed_account.initialize_nonce_account(&authority, &rent, &invoke_context);
let result = keyed_account.initialize_nonce_account(&authority, &rent, invoke_context);
let data = nonce::state::Data::new(
authority,
invoke_context.blockhash,
@ -965,15 +958,14 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |keyed_account| {
let invoke_context = create_invoke_context_with_blockhash(31);
with_mockup(min_lamports + 42, true, |invoke_context, keyed_account| {
set_invoke_context_blockhash(invoke_context, 31);
let authorized = *keyed_account.unsigned_key();
keyed_account
.initialize_nonce_account(&authorized, &rent, &invoke_context)
.initialize_nonce_account(&authorized, &rent, invoke_context)
.unwrap();
let invoke_context = create_invoke_context_with_blockhash(0);
let result =
keyed_account.initialize_nonce_account(&authorized, &rent, &invoke_context);
set_invoke_context_blockhash(invoke_context, 0);
let result = keyed_account.initialize_nonce_account(&authorized, &rent, invoke_context);
assert_eq!(result, Err(InstructionError::InvalidAccountData));
})
}
@ -985,11 +977,10 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports - 42, true, |keyed_account| {
let invoke_context = create_invoke_context_with_blockhash(63);
with_mockup(min_lamports - 42, true, |invoke_context, keyed_account| {
set_invoke_context_blockhash(invoke_context, 63);
let authorized = *keyed_account.unsigned_key();
let result =
keyed_account.initialize_nonce_account(&authorized, &rent, &invoke_context);
let result = keyed_account.initialize_nonce_account(&authorized, &rent, invoke_context);
assert_eq!(result, Err(InstructionError::InsufficientFunds));
})
}
@ -1001,13 +992,13 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |nonce_account| {
with_mockup(min_lamports + 42, true, |invoke_context, nonce_account| {
let mut signers = HashSet::new();
signers.insert(*nonce_account.signer_key().unwrap());
let invoke_context = create_invoke_context_with_blockhash(31);
set_invoke_context_blockhash(invoke_context, 31);
let authorized = *nonce_account.unsigned_key();
nonce_account
.initialize_nonce_account(&authorized, &rent, &invoke_context)
.initialize_nonce_account(&authorized, &rent, invoke_context)
.unwrap();
let authority = Pubkey::default();
let data = nonce::state::Data::new(
@ -1015,11 +1006,8 @@ mod test {
invoke_context.blockhash,
invoke_context.lamports_per_signature,
);
let result = nonce_account.authorize_nonce_account(
&Pubkey::default(),
&signers,
&invoke_context,
);
let result =
nonce_account.authorize_nonce_account(&Pubkey::default(), &signers, invoke_context);
assert_eq!(result, Ok(()));
let state = AccountUtilsState::<Versions>::state(nonce_account)
.unwrap()
@ -1035,14 +1023,11 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |nonce_account| {
with_mockup(min_lamports + 42, true, |invoke_context, nonce_account| {
let mut signers = HashSet::new();
signers.insert(*nonce_account.signer_key().unwrap());
let result = nonce_account.authorize_nonce_account(
&Pubkey::default(),
&signers,
&InvokeContext::new_mock(&[], &[]),
);
let result =
nonce_account.authorize_nonce_account(&Pubkey::default(), &signers, invoke_context);
assert_eq!(result, Err(InstructionError::InvalidAccountData));
})
}
@ -1054,35 +1039,32 @@ mod test {
..Rent::default()
};
let min_lamports = rent.minimum_balance(State::size());
with_test_keyed_account(min_lamports + 42, true, |nonce_account| {
with_mockup(min_lamports + 42, true, |invoke_context, nonce_account| {
let mut signers = HashSet::new();
signers.insert(*nonce_account.signer_key().unwrap());
let invoke_context = create_invoke_context_with_blockhash(31);
set_invoke_context_blockhash(invoke_context, 31);
let authorized = &Pubkey::default().clone();
nonce_account
.initialize_nonce_account(authorized, &rent, &invoke_context)
.initialize_nonce_account(authorized, &rent, invoke_context)
.unwrap();
let result = nonce_account.authorize_nonce_account(
&Pubkey::default(),
&signers,
&invoke_context,
);
let result =
nonce_account.authorize_nonce_account(&Pubkey::default(), &signers, invoke_context);
assert_eq!(result, Err(InstructionError::MissingRequiredSignature));
})
}
#[test]
fn verify_nonce_ok() {
with_test_keyed_account(42, true, |nonce_account| {
with_mockup(42, true, |invoke_context, nonce_account| {
let mut signers = HashSet::new();
signers.insert(nonce_account.signer_key().unwrap());
let state: State = nonce_account.state().unwrap();
// New is in Uninitialzed state
assert_eq!(state, State::Uninitialized);
let invoke_context = create_invoke_context_with_blockhash(0);
set_invoke_context_blockhash(invoke_context, 0);
let authorized = nonce_account.unsigned_key();
nonce_account
.initialize_nonce_account(authorized, &Rent::free(), &invoke_context)
.initialize_nonce_account(authorized, &Rent::free(), invoke_context)
.unwrap();
assert!(verify_nonce_account(
&nonce_account.account.borrow(),
@ -1093,7 +1075,7 @@ mod test {
#[test]
fn verify_nonce_bad_acc_state_fail() {
with_test_keyed_account(42, true, |nonce_account| {
with_mockup(42, true, |_invoke_context, nonce_account| {
assert!(!verify_nonce_account(
&nonce_account.account.borrow(),
&Hash::default()
@ -1103,18 +1085,18 @@ mod test {
#[test]
fn verify_nonce_bad_query_hash_fail() {
with_test_keyed_account(42, true, |nonce_account| {
with_mockup(42, true, |invoke_context, nonce_account| {
let mut signers = HashSet::new();
signers.insert(nonce_account.signer_key().unwrap());
let state: State = nonce_account.state().unwrap();
// New is in Uninitialzed state
assert_eq!(state, State::Uninitialized);
let invoke_context = create_invoke_context_with_blockhash(0);
set_invoke_context_blockhash(invoke_context, 0);
let authorized = nonce_account.unsigned_key();
nonce_account
.initialize_nonce_account(authorized, &Rent::free(), &invoke_context)
.initialize_nonce_account(authorized, &Rent::free(), invoke_context)
.unwrap();
let invoke_context = create_invoke_context_with_blockhash(1);
set_invoke_context_blockhash(invoke_context, 1);
assert!(!verify_nonce_account(
&nonce_account.account.borrow(),
&invoke_context.blockhash,

View File

@ -502,6 +502,7 @@ mod tests {
system_instruction, system_program, sysvar,
sysvar::recent_blockhashes::IterItem,
transaction::TransactionError,
transaction_context::TransactionContext,
};
use {
super::*,
@ -674,7 +675,8 @@ mod tests {
#[test]
fn test_address_create_with_seed_mismatch() {
let invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let from = Pubkey::new_unique();
let seed = "dull boy";
let to = Pubkey::new_unique();
@ -688,7 +690,8 @@ mod tests {
#[test]
fn test_create_account_with_seed_missing_sig() {
let invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let new_owner = Pubkey::new(&[9; 32]);
let from = Pubkey::new_unique();
let seed = "dull boy";
@ -718,7 +721,8 @@ mod tests {
#[test]
fn test_create_with_zero_lamports() {
let invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
// create account with zero lamports transferred
let new_owner = Pubkey::new(&[9; 32]);
let from = Pubkey::new_unique();
@ -752,7 +756,8 @@ mod tests {
#[test]
fn test_create_negative_lamports() {
let invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
// Attempt to create account with more lamports than remaining in from_account
let new_owner = Pubkey::new(&[9; 32]);
let from = Pubkey::new_unique();
@ -776,7 +781,8 @@ mod tests {
#[test]
fn test_request_more_than_allowed_data_length() {
let invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let from_account = RefCell::new(AccountSharedData::new(100, 0, &system_program::id()));
let from = Pubkey::new_unique();
let to_account = RefCell::new(AccountSharedData::new(0, 0, &system_program::id()));
@ -823,7 +829,8 @@ mod tests {
#[test]
fn test_create_already_in_use() {
let invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
// Attempt to create system account in account already owned by another program
let new_owner = Pubkey::new(&[9; 32]);
let from = Pubkey::new_unique();
@ -891,7 +898,8 @@ mod tests {
#[test]
fn test_create_unsigned() {
let invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
// Attempt to create an account without signing the transfer
let new_owner = Pubkey::new(&[9; 32]);
let from = Pubkey::new_unique();
@ -946,7 +954,8 @@ mod tests {
#[test]
fn test_create_sysvar_invalid_id_with_feature() {
let invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
// Attempt to create system account in account already owned by another program
let from = Pubkey::new_unique();
let from_account = RefCell::new(AccountSharedData::new(100, 0, &system_program::id()));
@ -980,7 +989,8 @@ mod tests {
feature_set
.inactive
.insert(feature_set::rent_for_sysvars::id());
let mut invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let mut invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
invoke_context.feature_set = Arc::new(feature_set);
// Attempt to create system account in account already owned by another program
let from = Pubkey::new_unique();
@ -1007,7 +1017,8 @@ mod tests {
#[test]
fn test_create_data_populated() {
let invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
// Attempt to create system account in account with populated data
let new_owner = Pubkey::new(&[9; 32]);
let from = Pubkey::new_unique();
@ -1040,7 +1051,8 @@ mod tests {
#[test]
fn test_create_from_account_is_nonce_fail() {
let invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let nonce = Pubkey::new_unique();
let nonce_account = RefCell::new(
AccountSharedData::new_data(
@ -1078,7 +1090,8 @@ mod tests {
#[test]
fn test_assign() {
let invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let new_owner = Pubkey::new(&[9; 32]);
let pubkey = Pubkey::new_unique();
let mut account = AccountSharedData::new(100, 0, &system_program::id());
@ -1120,7 +1133,8 @@ mod tests {
#[test]
fn test_assign_to_sysvar_with_feature() {
let invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let new_owner = sysvar::id();
let from = Pubkey::new_unique();
let mut from_account = AccountSharedData::new(100, 0, &system_program::id());
@ -1146,7 +1160,8 @@ mod tests {
feature_set
.inactive
.insert(feature_set::rent_for_sysvars::id());
let mut invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let mut invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
invoke_context.feature_set = Arc::new(feature_set);
let new_owner = sysvar::id();
let from = Pubkey::new_unique();
@ -1197,7 +1212,8 @@ mod tests {
#[test]
fn test_transfer_lamports() {
let invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let from = Pubkey::new_unique();
let from_account = RefCell::new(AccountSharedData::new(100, 0, &Pubkey::new(&[2; 32]))); // account owner should not matter
let to = Pubkey::new(&[3; 32]);
@ -1235,7 +1251,8 @@ mod tests {
#[test]
fn test_transfer_with_seed() {
let invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let base = Pubkey::new_unique();
let base_account = RefCell::new(AccountSharedData::new(100, 0, &Pubkey::new(&[2; 32]))); // account owner should not matter
let from_base_keyed_account = KeyedAccount::new(&base, true, &base_account);
@ -1295,7 +1312,8 @@ mod tests {
#[test]
fn test_transfer_lamports_from_nonce_account_fail() {
let invoke_context = InvokeContext::new_mock(&[], &[]);
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let from = Pubkey::new_unique();
let from_account = RefCell::new(
AccountSharedData::new_data(