diff --git a/runtime/src/nonce_keyed_account.rs b/runtime/src/nonce_keyed_account.rs index 089f27a8813868..c41b9798bd6367 100644 --- a/runtime/src/nonce_keyed_account.rs +++ b/runtime/src/nonce_keyed_account.rs @@ -1,292 +1,314 @@ use { solana_program_runtime::{ic_msg, invoke_context::InvokeContext}, solana_sdk::{ + account::{ReadableAccount, WritableAccount}, + account_utils::State as AccountUtilsState, feature_set::{self, nonce_must_be_writable}, instruction::{checked_add, InstructionError}, + keyed_account::KeyedAccount, nonce::{self, state::Versions, State}, pubkey::Pubkey, system_instruction::{nonce_to_instruction_error, NonceError}, sysvar::rent::Rent, - transaction_context::InstructionContext, }, std::collections::HashSet, }; -pub const NONCE_ACCOUNT_INDEX: usize = 0; -pub const WITHDRAW_TO_ACCOUNT_INDEX: usize = 1; +pub trait NonceKeyedAccount { + fn advance_nonce_account( + &self, + signers: &HashSet, + invoke_context: &InvokeContext, + ) -> Result<(), InstructionError>; + fn withdraw_nonce_account( + &self, + lamports: u64, + to: &KeyedAccount, + rent: &Rent, + signers: &HashSet, + invoke_context: &InvokeContext, + ) -> Result<(), InstructionError>; + fn initialize_nonce_account( + &self, + nonce_authority: &Pubkey, + rent: &Rent, + invoke_context: &InvokeContext, + ) -> Result<(), InstructionError>; + fn authorize_nonce_account( + &self, + nonce_authority: &Pubkey, + signers: &HashSet, + invoke_context: &InvokeContext, + ) -> Result<(), InstructionError>; +} -pub fn advance_nonce_account( - invoke_context: &InvokeContext, - instruction_context: &InstructionContext, - signers: &HashSet, - nonce_account_index: usize, -) -> Result<(), InstructionError> { - let mut account = instruction_context - .try_borrow_instruction_account(invoke_context.transaction_context, nonce_account_index)?; - let merge_nonce_error_into_system_error = invoke_context - .feature_set - .is_active(&feature_set::merge_nonce_error_into_system_error::id()); +impl<'a> NonceKeyedAccount for KeyedAccount<'a> { + fn advance_nonce_account( + &self, + signers: &HashSet, + invoke_context: &InvokeContext, + ) -> Result<(), InstructionError> { + let merge_nonce_error_into_system_error = invoke_context + .feature_set + .is_active(&feature_set::merge_nonce_error_into_system_error::id()); - if invoke_context - .feature_set - .is_active(&nonce_must_be_writable::id()) - && !account.is_writable() - { - ic_msg!( - invoke_context, - "Advance nonce account: Account {} must be writeable", - account.get_key() - ); - return Err(InstructionError::InvalidArgument); - } + if invoke_context + .feature_set + .is_active(&nonce_must_be_writable::id()) + && !self.is_writable() + { + ic_msg!( + invoke_context, + "Advance nonce account: Account {} must be writeable", + self.unsigned_key() + ); + return Err(InstructionError::InvalidArgument); + } - let state = account.get_state::()?.convert_to_current(); - match state { - State::Initialized(data) => { - if !signers.contains(&data.authority) { - ic_msg!( - invoke_context, - "Advance nonce account: Account {} must be a signer", - data.authority + let state = AccountUtilsState::::state(self)?.convert_to_current(); + match state { + State::Initialized(data) => { + if !signers.contains(&data.authority) { + ic_msg!( + invoke_context, + "Advance nonce account: Account {} must be a signer", + data.authority + ); + return Err(InstructionError::MissingRequiredSignature); + } + let recent_blockhash = invoke_context.blockhash; + if data.blockhash == recent_blockhash { + ic_msg!( + invoke_context, + "Advance nonce account: nonce can only advance once per slot" + ); + return Err(nonce_to_instruction_error( + NonceError::NotExpired, + merge_nonce_error_into_system_error, + )); + } + + let new_data = nonce::state::Data::new( + data.authority, + recent_blockhash, + invoke_context.lamports_per_signature, ); - return Err(InstructionError::MissingRequiredSignature); + self.set_state(&Versions::new_current(State::Initialized(new_data))) } - let recent_blockhash = invoke_context.blockhash; - if data.blockhash == recent_blockhash { + _ => { ic_msg!( invoke_context, - "Advance nonce account: nonce can only advance once per slot" + "Advance nonce account: Account {} state is invalid", + self.unsigned_key() ); - return Err(nonce_to_instruction_error( - NonceError::NotExpired, + Err(nonce_to_instruction_error( + NonceError::BadAccountState, merge_nonce_error_into_system_error, - )); + )) } - - let new_data = nonce::state::Data::new( - data.authority, - recent_blockhash, - invoke_context.lamports_per_signature, - ); - account.set_state(&Versions::new_current(State::Initialized(new_data))) } - _ => { + } + + fn withdraw_nonce_account( + &self, + lamports: u64, + to: &KeyedAccount, + rent: &Rent, + signers: &HashSet, + invoke_context: &InvokeContext, + ) -> Result<(), InstructionError> { + let merge_nonce_error_into_system_error = invoke_context + .feature_set + .is_active(&feature_set::merge_nonce_error_into_system_error::id()); + + if invoke_context + .feature_set + .is_active(&nonce_must_be_writable::id()) + && !self.is_writable() + { ic_msg!( invoke_context, - "Advance nonce account: Account {} state is invalid", - account.get_key() + "Withdraw nonce account: Account {} must be writeable", + self.unsigned_key() ); - Err(nonce_to_instruction_error( - NonceError::BadAccountState, - merge_nonce_error_into_system_error, - )) + return Err(InstructionError::InvalidArgument); } - } -} -pub fn withdraw_nonce_account( - invoke_context: &InvokeContext, - instruction_context: &InstructionContext, - signers: &HashSet, - nonce_account_index: usize, - withdraw_to_account_index: usize, - lamports: u64, - rent: &Rent, -) -> Result<(), InstructionError> { - let mut nonce_account = instruction_context - .try_borrow_instruction_account(invoke_context.transaction_context, nonce_account_index)?; - let merge_nonce_error_into_system_error = invoke_context - .feature_set - .is_active(&feature_set::merge_nonce_error_into_system_error::id()); - - if invoke_context - .feature_set - .is_active(&nonce_must_be_writable::id()) - && !nonce_account.is_writable() - { - ic_msg!( - invoke_context, - "Withdraw nonce account: Account {} must be writeable", - nonce_account.get_key() - ); - return Err(InstructionError::InvalidArgument); - } - - let signer = match nonce_account.get_state::()?.convert_to_current() { - State::Uninitialized => { - if lamports > nonce_account.get_lamports() { - ic_msg!( - invoke_context, - "Withdraw nonce account: insufficient lamports {}, need {}", - nonce_account.get_lamports(), - lamports, - ); - return Err(InstructionError::InsufficientFunds); - } - *nonce_account.get_key() - } - State::Initialized(ref data) => { - if lamports == nonce_account.get_lamports() { - if data.blockhash == invoke_context.blockhash { - ic_msg!( - invoke_context, - "Withdraw nonce account: nonce can only advance once per slot" - ); - return Err(nonce_to_instruction_error( - NonceError::NotExpired, - merge_nonce_error_into_system_error, - )); - } - nonce_account.set_state(&Versions::new_current(State::Uninitialized))?; - } else { - let min_balance = rent.minimum_balance(nonce_account.get_data().len()); - let amount = checked_add(lamports, min_balance)?; - if amount > nonce_account.get_lamports() { + let signer = match AccountUtilsState::::state(self)?.convert_to_current() { + State::Uninitialized => { + if lamports > self.lamports()? { ic_msg!( invoke_context, "Withdraw nonce account: insufficient lamports {}, need {}", - nonce_account.get_lamports(), - amount, + self.lamports()?, + lamports, ); return Err(InstructionError::InsufficientFunds); } + *self.unsigned_key() + } + State::Initialized(ref data) => { + if lamports == self.lamports()? { + if data.blockhash == invoke_context.blockhash { + ic_msg!( + invoke_context, + "Withdraw nonce account: nonce can only advance once per slot" + ); + return Err(nonce_to_instruction_error( + NonceError::NotExpired, + merge_nonce_error_into_system_error, + )); + } + self.set_state(&Versions::new_current(State::Uninitialized))?; + } else { + let min_balance = rent.minimum_balance(self.data_len()?); + let amount = checked_add(lamports, min_balance)?; + if amount > self.lamports()? { + ic_msg!( + invoke_context, + "Withdraw nonce account: insufficient lamports {}, need {}", + self.lamports()?, + amount, + ); + return Err(InstructionError::InsufficientFunds); + } + } + data.authority } - data.authority + }; + + if !signers.contains(&signer) { + ic_msg!( + invoke_context, + "Withdraw nonce account: Account {} must sign", + signer + ); + return Err(InstructionError::MissingRequiredSignature); } - }; - if !signers.contains(&signer) { - ic_msg!( - invoke_context, - "Withdraw nonce account: Account {} must sign", - signer + let nonce_balance = self.try_account_ref_mut()?.lamports(); + self.try_account_ref_mut()?.set_lamports( + nonce_balance + .checked_sub(lamports) + .ok_or(InstructionError::ArithmeticOverflow)?, + ); + let to_balance = to.try_account_ref_mut()?.lamports(); + to.try_account_ref_mut()?.set_lamports( + to_balance + .checked_add(lamports) + .ok_or(InstructionError::ArithmeticOverflow)?, ); - return Err(InstructionError::MissingRequiredSignature); - } - - nonce_account.checked_sub_lamports(lamports)?; - drop(nonce_account); - let mut withdraw_to_account = instruction_context.try_borrow_instruction_account( - invoke_context.transaction_context, - withdraw_to_account_index, - )?; - withdraw_to_account.checked_add_lamports(lamports)?; - Ok(()) -} + Ok(()) + } -pub fn initialize_nonce_account( - invoke_context: &InvokeContext, - instruction_context: &InstructionContext, - nonce_account_index: usize, - nonce_authority: &Pubkey, - rent: &Rent, -) -> Result<(), InstructionError> { - let mut account = instruction_context - .try_borrow_instruction_account(invoke_context.transaction_context, nonce_account_index)?; - let merge_nonce_error_into_system_error = invoke_context - .feature_set - .is_active(&feature_set::merge_nonce_error_into_system_error::id()); + fn initialize_nonce_account( + &self, + nonce_authority: &Pubkey, + rent: &Rent, + invoke_context: &InvokeContext, + ) -> Result<(), InstructionError> { + let merge_nonce_error_into_system_error = invoke_context + .feature_set + .is_active(&feature_set::merge_nonce_error_into_system_error::id()); - if invoke_context - .feature_set - .is_active(&nonce_must_be_writable::id()) - && !account.is_writable() - { - ic_msg!( - invoke_context, - "Initialize nonce account: Account {} must be writeable", - account.get_key() - ); - return Err(InstructionError::InvalidArgument); - } + if invoke_context + .feature_set + .is_active(&nonce_must_be_writable::id()) + && !self.is_writable() + { + ic_msg!( + invoke_context, + "Initialize nonce account: Account {} must be writeable", + self.unsigned_key() + ); + return Err(InstructionError::InvalidArgument); + } - match account.get_state::()?.convert_to_current() { - State::Uninitialized => { - let min_balance = rent.minimum_balance(account.get_data().len()); - if account.get_lamports() < min_balance { + match AccountUtilsState::::state(self)?.convert_to_current() { + State::Uninitialized => { + let min_balance = rent.minimum_balance(self.data_len()?); + if self.lamports()? < min_balance { + ic_msg!( + invoke_context, + "Initialize nonce account: insufficient lamports {}, need {}", + self.lamports()?, + min_balance + ); + return Err(InstructionError::InsufficientFunds); + } + let data = nonce::state::Data::new( + *nonce_authority, + invoke_context.blockhash, + invoke_context.lamports_per_signature, + ); + self.set_state(&Versions::new_current(State::Initialized(data))) + } + _ => { ic_msg!( invoke_context, - "Initialize nonce account: insufficient lamports {}, need {}", - account.get_lamports(), - min_balance + "Initialize nonce account: Account {} state is invalid", + self.unsigned_key() ); - return Err(InstructionError::InsufficientFunds); + Err(nonce_to_instruction_error( + NonceError::BadAccountState, + merge_nonce_error_into_system_error, + )) } - let data = nonce::state::Data::new( - *nonce_authority, - invoke_context.blockhash, - invoke_context.lamports_per_signature, - ); - account.set_state(&Versions::new_current(State::Initialized(data))) } - _ => { + } + + fn authorize_nonce_account( + &self, + nonce_authority: &Pubkey, + signers: &HashSet, + invoke_context: &InvokeContext, + ) -> Result<(), InstructionError> { + let merge_nonce_error_into_system_error = invoke_context + .feature_set + .is_active(&feature_set::merge_nonce_error_into_system_error::id()); + + if invoke_context + .feature_set + .is_active(&nonce_must_be_writable::id()) + && !self.is_writable() + { ic_msg!( invoke_context, - "Initialize nonce account: Account {} state is invalid", - account.get_key() + "Authorize nonce account: Account {} must be writeable", + self.unsigned_key() ); - Err(nonce_to_instruction_error( - NonceError::BadAccountState, - merge_nonce_error_into_system_error, - )) + return Err(InstructionError::InvalidArgument); } - } -} -pub fn authorize_nonce_account( - invoke_context: &InvokeContext, - instruction_context: &InstructionContext, - signers: &HashSet, - nonce_account_index: usize, - nonce_authority: &Pubkey, -) -> Result<(), InstructionError> { - let mut account = instruction_context - .try_borrow_instruction_account(invoke_context.transaction_context, nonce_account_index)?; - let merge_nonce_error_into_system_error = invoke_context - .feature_set - .is_active(&feature_set::merge_nonce_error_into_system_error::id()); - - if invoke_context - .feature_set - .is_active(&nonce_must_be_writable::id()) - && !account.is_writable() - { - ic_msg!( - invoke_context, - "Authorize nonce account: Account {} must be writeable", - account.get_key() - ); - return Err(InstructionError::InvalidArgument); - } - - match account.get_state::()?.convert_to_current() { - State::Initialized(data) => { - if !signers.contains(&data.authority) { + match AccountUtilsState::::state(self)?.convert_to_current() { + State::Initialized(data) => { + if !signers.contains(&data.authority) { + ic_msg!( + invoke_context, + "Authorize nonce account: Account {} must sign", + data.authority + ); + return Err(InstructionError::MissingRequiredSignature); + } + let new_data = nonce::state::Data::new( + *nonce_authority, + data.blockhash, + data.get_lamports_per_signature(), + ); + self.set_state(&Versions::new_current(State::Initialized(new_data))) + } + _ => { ic_msg!( invoke_context, - "Authorize nonce account: Account {} must sign", - data.authority + "Authorize nonce account: Account {} state is invalid", + self.unsigned_key() ); - return Err(InstructionError::MissingRequiredSignature); + Err(nonce_to_instruction_error( + NonceError::BadAccountState, + merge_nonce_error_into_system_error, + )) } - let new_data = nonce::state::Data::new( - *nonce_authority, - data.blockhash, - data.get_lamports_per_signature(), - ); - account.set_state(&Versions::new_current(State::Initialized(new_data))) - } - _ => { - ic_msg!( - invoke_context, - "Authorize nonce account: Account {} state is invalid", - account.get_key() - ); - Err(nonce_to_instruction_error( - NonceError::BadAccountState, - merge_nonce_error_into_system_error, - )) } } } @@ -307,6 +329,9 @@ mod test { }, }; + pub const NONCE_ACCOUNT_INDEX: usize = 0; + pub const WITHDRAW_TO_ACCOUNT_INDEX: usize = 1; + macro_rules! push_instruction_context { ($invoke_context:expr, $transaction_context:ident, $instruction_context:ident, $instruction_accounts:ident) => { $invoke_context @@ -392,14 +417,9 @@ mod test { set_invoke_context_blockhash!(invoke_context, 95); let authorized = *nonce_account.get_key(); drop(nonce_account); - initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authorized, &rent, &invoke_context) + .unwrap(); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) .unwrap(); @@ -416,13 +436,9 @@ mod test { assert_eq!(state, State::Initialized(data.clone())); set_invoke_context_blockhash!(invoke_context, 63); drop(nonce_account); - advance_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .advance_nonce_account(&signers, &invoke_context) + .unwrap(); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) .unwrap(); @@ -439,13 +455,9 @@ mod test { assert_eq!(state, State::Initialized(data.clone())); set_invoke_context_blockhash!(invoke_context, 31); drop(nonce_account); - advance_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .advance_nonce_account(&signers, &invoke_context) + .unwrap(); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) .unwrap(); @@ -470,16 +482,15 @@ mod test { let expect_to_lamports = to_account.get_lamports() + withdraw_lamports; drop(nonce_account); drop(to_account); - withdraw_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - WITHDRAW_TO_ACCOUNT_INDEX, - withdraw_lamports, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .withdraw_nonce_account( + withdraw_lamports, + &invoke_context.get_keyed_accounts().unwrap()[1 + WITHDRAW_TO_ACCOUNT_INDEX], + &rent, + &signers, + &invoke_context, + ) + .unwrap(); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) .unwrap(); @@ -513,14 +524,9 @@ mod test { set_invoke_context_blockhash!(invoke_context, 31); let authority = *nonce_account.get_key(); drop(nonce_account); - initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authority, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authority, &rent, &invoke_context) + .unwrap(); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) .unwrap(); @@ -538,12 +544,8 @@ mod test { // Nonce account did not sign let signers = HashSet::new(); set_invoke_context_blockhash!(invoke_context, 0); - let result = advance_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - ); + let result = invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .advance_nonce_account(&signers, &invoke_context); assert_eq!(result, Err(InstructionError::MissingRequiredSignature)); } @@ -564,20 +566,11 @@ mod test { set_invoke_context_blockhash!(invoke_context, 63); let authorized = *nonce_account.get_key(); drop(nonce_account); - initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &rent, - ) - .unwrap(); - let result = advance_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - ); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authorized, &rent, &invoke_context) + .unwrap(); + let result = invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .advance_nonce_account(&signers, &invoke_context); assert_eq!(result, Err(SystemError::NonceBlockhashNotExpired.into())); } @@ -597,12 +590,8 @@ mod test { signers.insert(*nonce_account.get_key()); set_invoke_context_blockhash!(invoke_context, 63); drop(nonce_account); - let result = advance_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - ); + let result = invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .advance_nonce_account(&signers, &invoke_context); assert_eq!(result, Err(InstructionError::InvalidAccountData)); } @@ -627,23 +616,14 @@ mod test { let authorized = *nonce_authority.get_key(); drop(nonce_account); drop(nonce_authority); - initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authorized, &rent, &invoke_context) + .unwrap(); let mut signers = HashSet::new(); signers.insert(authorized); set_invoke_context_blockhash!(invoke_context, 31); - let result = advance_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - ); + let result = invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .advance_nonce_account(&signers, &invoke_context); assert_eq!(result, Ok(())); } @@ -668,20 +648,11 @@ mod test { let authorized = *nonce_authority.get_key(); drop(nonce_account); drop(nonce_authority); - initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &rent, - ) - .unwrap(); - let result = advance_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - ); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authorized, &rent, &invoke_context) + .unwrap(); + let result = invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .advance_nonce_account(&signers, &invoke_context); assert_eq!(result, Err(InstructionError::MissingRequiredSignature)); } @@ -713,16 +684,15 @@ mod test { let expect_to_lamports = to_account.get_lamports() + withdraw_lamports; drop(nonce_account); drop(to_account); - withdraw_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - WITHDRAW_TO_ACCOUNT_INDEX, - withdraw_lamports, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .withdraw_nonce_account( + withdraw_lamports, + &invoke_context.get_keyed_accounts().unwrap()[1 + WITHDRAW_TO_ACCOUNT_INDEX], + &rent, + &signers, + &invoke_context, + ) + .unwrap(); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) .unwrap(); @@ -763,15 +733,14 @@ mod test { let withdraw_lamports = nonce_account.get_lamports(); drop(nonce_account); drop(to_account); - let result = withdraw_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - WITHDRAW_TO_ACCOUNT_INDEX, - withdraw_lamports, - &rent, - ); + let result = invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .withdraw_nonce_account( + withdraw_lamports, + &invoke_context.get_keyed_accounts().unwrap()[1 + WITHDRAW_TO_ACCOUNT_INDEX], + &rent, + &signers, + &invoke_context, + ); assert_eq!(result, Err(InstructionError::MissingRequiredSignature)); } @@ -797,15 +766,14 @@ mod test { set_invoke_context_blockhash!(invoke_context, 0); let withdraw_lamports = nonce_account.get_lamports() + 1; drop(nonce_account); - let result = withdraw_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - WITHDRAW_TO_ACCOUNT_INDEX, - withdraw_lamports, - &rent, - ); + let result = invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .withdraw_nonce_account( + withdraw_lamports, + &invoke_context.get_keyed_accounts().unwrap()[1 + WITHDRAW_TO_ACCOUNT_INDEX], + &rent, + &signers, + &invoke_context, + ); assert_eq!(result, Err(InstructionError::InsufficientFunds)); } @@ -832,16 +800,15 @@ mod test { let to_expect_lamports = to_account.get_lamports() + withdraw_lamports; drop(nonce_account); drop(to_account); - withdraw_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - WITHDRAW_TO_ACCOUNT_INDEX, - withdraw_lamports, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .withdraw_nonce_account( + withdraw_lamports, + &invoke_context.get_keyed_accounts().unwrap()[1 + WITHDRAW_TO_ACCOUNT_INDEX], + &rent, + &signers, + &invoke_context, + ) + .unwrap(); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) .unwrap(); @@ -860,16 +827,15 @@ mod test { let to_expect_lamports = to_account.get_lamports() + withdraw_lamports; drop(nonce_account); drop(to_account); - withdraw_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - WITHDRAW_TO_ACCOUNT_INDEX, - withdraw_lamports, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .withdraw_nonce_account( + withdraw_lamports, + &invoke_context.get_keyed_accounts().unwrap()[1 + WITHDRAW_TO_ACCOUNT_INDEX], + &rent, + &signers, + &invoke_context, + ) + .unwrap(); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) .unwrap(); @@ -906,14 +872,9 @@ mod test { let authority = *nonce_account.get_key(); drop(nonce_account); drop(to_account); - initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authority, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authority, &rent, &invoke_context) + .unwrap(); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) .unwrap(); @@ -935,16 +896,15 @@ mod test { let to_expect_lamports = to_account.get_lamports() + withdraw_lamports; drop(nonce_account); drop(to_account); - withdraw_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - WITHDRAW_TO_ACCOUNT_INDEX, - withdraw_lamports, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .withdraw_nonce_account( + withdraw_lamports, + &invoke_context.get_keyed_accounts().unwrap()[1 + WITHDRAW_TO_ACCOUNT_INDEX], + &rent, + &signers, + &invoke_context, + ) + .unwrap(); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) .unwrap(); @@ -969,16 +929,15 @@ mod test { let to_expect_lamports = to_account.get_lamports() + withdraw_lamports; drop(nonce_account); drop(to_account); - withdraw_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - WITHDRAW_TO_ACCOUNT_INDEX, - withdraw_lamports, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .withdraw_nonce_account( + withdraw_lamports, + &invoke_context.get_keyed_accounts().unwrap()[1 + WITHDRAW_TO_ACCOUNT_INDEX], + &rent, + &signers, + &invoke_context, + ) + .unwrap(); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) .unwrap(); @@ -1013,14 +972,9 @@ mod test { let authorized = *nonce_account.get_key(); drop(nonce_account); drop(to_account); - initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authorized, &rent, &invoke_context) + .unwrap(); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) .unwrap(); @@ -1028,15 +982,14 @@ mod test { signers.insert(*nonce_account.get_key()); let withdraw_lamports = nonce_account.get_lamports(); drop(nonce_account); - let result = withdraw_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - WITHDRAW_TO_ACCOUNT_INDEX, - withdraw_lamports, - &rent, - ); + let result = invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .withdraw_nonce_account( + withdraw_lamports, + &invoke_context.get_keyed_accounts().unwrap()[1 + WITHDRAW_TO_ACCOUNT_INDEX], + &rent, + &signers, + &invoke_context, + ); assert_eq!(result, Err(SystemError::NonceBlockhashNotExpired.into())); } @@ -1055,14 +1008,9 @@ mod test { set_invoke_context_blockhash!(invoke_context, 95); let authorized = *nonce_account.get_key(); drop(nonce_account); - initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authorized, &rent, &invoke_context) + .unwrap(); set_invoke_context_blockhash!(invoke_context, 63); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) @@ -1071,15 +1019,14 @@ mod test { signers.insert(*nonce_account.get_key()); let withdraw_lamports = nonce_account.get_lamports() + 1; drop(nonce_account); - let result = withdraw_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - WITHDRAW_TO_ACCOUNT_INDEX, - withdraw_lamports, - &rent, - ); + let result = invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .withdraw_nonce_account( + withdraw_lamports, + &invoke_context.get_keyed_accounts().unwrap()[1 + WITHDRAW_TO_ACCOUNT_INDEX], + &rent, + &signers, + &invoke_context, + ); assert_eq!(result, Err(InstructionError::InsufficientFunds)); } @@ -1098,14 +1045,9 @@ mod test { set_invoke_context_blockhash!(invoke_context, 95); let authorized = *nonce_account.get_key(); drop(nonce_account); - initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authorized, &rent, &invoke_context) + .unwrap(); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) .unwrap(); @@ -1114,15 +1056,14 @@ mod test { signers.insert(*nonce_account.get_key()); let withdraw_lamports = 42 + 1; drop(nonce_account); - let result = withdraw_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - WITHDRAW_TO_ACCOUNT_INDEX, - withdraw_lamports, - &rent, - ); + let result = invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .withdraw_nonce_account( + withdraw_lamports, + &invoke_context.get_keyed_accounts().unwrap()[1 + WITHDRAW_TO_ACCOUNT_INDEX], + &rent, + &signers, + &invoke_context, + ); assert_eq!(result, Err(InstructionError::InsufficientFunds)); } @@ -1141,14 +1082,9 @@ mod test { set_invoke_context_blockhash!(invoke_context, 95); let authorized = *nonce_account.get_key(); drop(nonce_account); - initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authorized, &rent, &invoke_context) + .unwrap(); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) .unwrap(); @@ -1157,15 +1093,14 @@ mod test { signers.insert(*nonce_account.get_key()); let withdraw_lamports = u64::MAX - 54; drop(nonce_account); - let result = withdraw_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - WITHDRAW_TO_ACCOUNT_INDEX, - withdraw_lamports, - &rent, - ); + let result = invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .withdraw_nonce_account( + withdraw_lamports, + &invoke_context.get_keyed_accounts().unwrap()[1 + WITHDRAW_TO_ACCOUNT_INDEX], + &rent, + &signers, + &invoke_context, + ); assert_eq!(result, Err(InstructionError::InsufficientFunds)); } @@ -1191,13 +1126,8 @@ mod test { set_invoke_context_blockhash!(invoke_context, 0); let authorized = *nonce_account.get_key(); drop(nonce_account); - let result = initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &rent, - ); + let result = invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authorized, &rent, &invoke_context); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) .unwrap(); @@ -1229,22 +1159,12 @@ mod test { set_invoke_context_blockhash!(invoke_context, 31); let authorized = *nonce_account.get_key(); drop(nonce_account); - initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authorized, &rent, &invoke_context) + .unwrap(); set_invoke_context_blockhash!(invoke_context, 0); - let result = initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &rent, - ); + let result = invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authorized, &rent, &invoke_context); assert_eq!(result, Err(InstructionError::InvalidAccountData)); } @@ -1264,13 +1184,8 @@ mod test { set_invoke_context_blockhash!(invoke_context, 63); let authorized = *nonce_account.get_key(); drop(nonce_account); - let result = initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &rent, - ); + let result = invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authorized, &rent, &invoke_context); assert_eq!(result, Err(InstructionError::InsufficientFunds)); } @@ -1291,28 +1206,18 @@ mod test { set_invoke_context_blockhash!(invoke_context, 31); let authorized = *nonce_account.get_key(); drop(nonce_account); - initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authorized, &rent, &invoke_context) + .unwrap(); let authority = Pubkey::default(); let data = nonce::state::Data::new( authority, invoke_context.blockhash, invoke_context.lamports_per_signature, ); - authorize_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - &authority, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .authorize_nonce_account(&authority, &signers, &invoke_context) + .unwrap(); let nonce_account = instruction_context .try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX) .unwrap(); @@ -1338,13 +1243,8 @@ mod test { let mut signers = HashSet::new(); signers.insert(*nonce_account.get_key()); drop(nonce_account); - let result = authorize_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - &Pubkey::default(), - ); + let result = invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .authorize_nonce_account(&Pubkey::default(), &signers, &invoke_context); assert_eq!(result, Err(InstructionError::InvalidAccountData)); } @@ -1365,21 +1265,11 @@ mod test { set_invoke_context_blockhash!(invoke_context, 31); let authorized = Pubkey::default(); drop(nonce_account); - initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &rent, - ) - .unwrap(); - let result = authorize_nonce_account( - &invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - &authorized, - ); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authorized, &rent, &invoke_context) + .unwrap(); + let result = invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .authorize_nonce_account(&authorized, &signers, &invoke_context); assert_eq!(result, Err(InstructionError::MissingRequiredSignature)); } @@ -1403,14 +1293,9 @@ mod test { set_invoke_context_blockhash!(invoke_context, 0); let authorized = *nonce_account.get_key(); drop(nonce_account); - initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &rent, - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authorized, &rent, &invoke_context) + .unwrap(); assert!(verify_nonce_account( &transaction_context .get_account_at_index(NONCE_ACCOUNT_INDEX) @@ -1458,14 +1343,9 @@ mod test { set_invoke_context_blockhash!(invoke_context, 0); let authorized = *nonce_account.get_key(); drop(nonce_account); - initialize_nonce_account( - &invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &Rent::free(), - ) - .unwrap(); + invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX] + .initialize_nonce_account(&authorized, &Rent::free(), &invoke_context) + .unwrap(); set_invoke_context_blockhash!(invoke_context, 1); assert!(!verify_nonce_account( &transaction_context diff --git a/runtime/src/system_instruction_processor.rs b/runtime/src/system_instruction_processor.rs index f280cf141eddcc..1314ac4e34965a 100644 --- a/runtime/src/system_instruction_processor.rs +++ b/runtime/src/system_instruction_processor.rs @@ -1,18 +1,15 @@ use { - crate::nonce_keyed_account::{ - advance_nonce_account, authorize_nonce_account, initialize_nonce_account, - withdraw_nonce_account, NONCE_ACCOUNT_INDEX, WITHDRAW_TO_ACCOUNT_INDEX, - }, + crate::nonce_keyed_account::NonceKeyedAccount, log::*, solana_program_runtime::{ - ic_msg, invoke_context::InvokeContext, sysvar_cache::get_sysvar_with_account_check2, + ic_msg, invoke_context::InvokeContext, sysvar_cache::get_sysvar_with_account_check, }, solana_sdk::{ account::{AccountSharedData, ReadableAccount, WritableAccount}, account_utils::StateMut, feature_set, instruction::InstructionError, - keyed_account::{keyed_account_at_index, KeyedAccount}, + keyed_account::{get_signers, keyed_account_at_index, KeyedAccount}, nonce, program_utils::limited_deserialize, pubkey::Pubkey, @@ -268,15 +265,14 @@ pub fn process_instruction( instruction_data: &[u8], invoke_context: &mut InvokeContext, ) -> Result<(), InstructionError> { - let transaction_context = &invoke_context.transaction_context; - let instruction_context = transaction_context.get_current_instruction_context()?; let keyed_accounts = invoke_context.get_keyed_accounts()?; let instruction = limited_deserialize(instruction_data)?; trace!("process_instruction: {:?}", instruction); trace!("keyed_accounts: {:?}", keyed_accounts); - let signers = instruction_context.get_signers(transaction_context); + let _ = keyed_account_at_index(keyed_accounts, first_instruction_account)?; + let signers = get_signers(&keyed_accounts[first_instruction_account..]); match instruction { SystemInstruction::CreateAccount { lamports, @@ -352,12 +348,11 @@ pub fn process_instruction( ) } SystemInstruction::AdvanceNonceAccount => { - let _me = &mut keyed_account_at_index(keyed_accounts, first_instruction_account)?; + let me = &mut keyed_account_at_index(keyed_accounts, first_instruction_account)?; #[allow(deprecated)] - let recent_blockhashes = get_sysvar_with_account_check2::recent_blockhashes( + let recent_blockhashes = get_sysvar_with_account_check::recent_blockhashes( + keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?, invoke_context, - instruction_context, - first_instruction_account + 1, )?; if recent_blockhashes.is_empty() { ic_msg!( @@ -366,44 +361,28 @@ pub fn process_instruction( ); return Err(NonceError::NoRecentBlockhashes.into()); } - advance_nonce_account( - invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - ) + me.advance_nonce_account(&signers, invoke_context) } SystemInstruction::WithdrawNonceAccount(lamports) => { - let _me = &mut keyed_account_at_index(keyed_accounts, first_instruction_account)?; - let _to = &mut keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?; + let me = &mut keyed_account_at_index(keyed_accounts, first_instruction_account)?; + let to = &mut keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?; #[allow(deprecated)] - let _recent_blockhashes = get_sysvar_with_account_check2::recent_blockhashes( + let _recent_blockhashes = get_sysvar_with_account_check::recent_blockhashes( + keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?, invoke_context, - instruction_context, - first_instruction_account + 2, )?; - let rent = get_sysvar_with_account_check2::rent( + let rent = get_sysvar_with_account_check::rent( + keyed_account_at_index(keyed_accounts, first_instruction_account + 3)?, invoke_context, - instruction_context, - first_instruction_account + 3, )?; - withdraw_nonce_account( - invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - WITHDRAW_TO_ACCOUNT_INDEX, - lamports, - &rent, - ) + me.withdraw_nonce_account(lamports, to, &rent, &signers, invoke_context) } SystemInstruction::InitializeNonceAccount(authorized) => { - let _me = &mut keyed_account_at_index(keyed_accounts, first_instruction_account)?; + let me = &mut keyed_account_at_index(keyed_accounts, first_instruction_account)?; #[allow(deprecated)] - let recent_blockhashes = get_sysvar_with_account_check2::recent_blockhashes( + let recent_blockhashes = get_sysvar_with_account_check::recent_blockhashes( + keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?, invoke_context, - instruction_context, - first_instruction_account + 1, )?; if recent_blockhashes.is_empty() { ic_msg!( @@ -412,28 +391,15 @@ pub fn process_instruction( ); return Err(NonceError::NoRecentBlockhashes.into()); } - let rent = get_sysvar_with_account_check2::rent( + let rent = get_sysvar_with_account_check::rent( + keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?, invoke_context, - instruction_context, - first_instruction_account + 2, )?; - initialize_nonce_account( - invoke_context, - instruction_context, - NONCE_ACCOUNT_INDEX, - &authorized, - &rent, - ) + me.initialize_nonce_account(&authorized, &rent, invoke_context) } SystemInstruction::AuthorizeNonceAccount(nonce_authority) => { - let _me = &mut keyed_account_at_index(keyed_accounts, first_instruction_account)?; - authorize_nonce_account( - invoke_context, - instruction_context, - &signers, - NONCE_ACCOUNT_INDEX, - &nonce_authority, - ) + let me = &mut keyed_account_at_index(keyed_accounts, first_instruction_account)?; + me.authorize_nonce_account(&nonce_authority, &signers, invoke_context) } SystemInstruction::Allocate { space } => { let keyed_account = keyed_account_at_index(keyed_accounts, first_instruction_account)?;