Revert: `KeyedAccount` refactoings in builtin programs (#23649)
* Revert "Replaces KeyedAccount by BorrowedAccount in the BPF loader. (#23056)"6c56eb9663
* Revert "Replaces `KeyedAccount` by `BorrowedAccount` in `system_instruction_processor`. (#23217)"ee7e411d68
* Revert "Replaces `KeyedAccount` by `BorrowedAccount` in `nonce_keyed_account`. (#23214)"1a68f81f89
* Revert "Replaces KeyedAccount by BorrowedAccount in the config processor. (#23302)"a14c7c37ee
* Revert "Replaces `KeyedAccount` by `BorrowedAccount` in vote processor (#23348)"e2fa6a0f7a
* Revert "Refactor: Prepare stake_instruction.rs to remove `KeyedAccount`s (#23375)"ee3fc39f1c
This commit is contained in:
parent
44ab660172
commit
584ac80b1e
File diff suppressed because it is too large
Load Diff
|
@ -5,29 +5,33 @@ use {
|
|||
bincode::deserialize,
|
||||
solana_program_runtime::{ic_msg, invoke_context::InvokeContext},
|
||||
solana_sdk::{
|
||||
feature_set, instruction::InstructionError, program_utils::limited_deserialize,
|
||||
account::{ReadableAccount, WritableAccount},
|
||||
feature_set,
|
||||
instruction::InstructionError,
|
||||
keyed_account::keyed_account_at_index,
|
||||
program_utils::limited_deserialize,
|
||||
pubkey::Pubkey,
|
||||
},
|
||||
std::collections::BTreeSet,
|
||||
};
|
||||
|
||||
pub fn process_instruction(
|
||||
_first_instruction_account: usize,
|
||||
first_instruction_account: usize,
|
||||
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 key_list: ConfigKeys = limited_deserialize(data)?;
|
||||
let config_keyed_account =
|
||||
&mut keyed_account_at_index(keyed_accounts, first_instruction_account)?;
|
||||
let current_data: ConfigKeys = {
|
||||
let config_account =
|
||||
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||
if config_account.get_owner() != &crate::id() {
|
||||
let config_account = config_keyed_account.try_account_ref_mut()?;
|
||||
if config_account.owner() != &crate::id() {
|
||||
return Err(InstructionError::InvalidAccountOwner);
|
||||
}
|
||||
|
||||
deserialize(config_account.get_data()).map_err(|err| {
|
||||
deserialize(config_account.data()).map_err(|err| {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Unable to deserialize config account: {}",
|
||||
|
@ -46,7 +50,7 @@ pub fn process_instruction(
|
|||
if current_signer_keys.is_empty() {
|
||||
// Config account keypair must be a signer on account initialization,
|
||||
// or when no signers specified in Config data
|
||||
if !instruction_context.is_signer(instruction_context.get_number_of_program_accounts())? {
|
||||
if config_keyed_account.signer_key().is_none() {
|
||||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
}
|
||||
|
@ -54,10 +58,9 @@ pub fn process_instruction(
|
|||
let mut counter = 0;
|
||||
for (signer, _) in key_list.keys.iter().filter(|(_, is_signer)| *is_signer) {
|
||||
counter += 1;
|
||||
if signer != instruction_context.get_instruction_account_key(transaction_context, 0)? {
|
||||
let is_signer = instruction_context
|
||||
.is_signer(instruction_context.get_number_of_program_accounts() + counter)
|
||||
.map_err(|_| {
|
||||
if signer != config_keyed_account.unsigned_key() {
|
||||
let signer_account =
|
||||
keyed_account_at_index(keyed_accounts, counter + 1).map_err(|_| {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"account {:?} is not in account list",
|
||||
|
@ -65,7 +68,8 @@ pub fn process_instruction(
|
|||
);
|
||||
InstructionError::MissingRequiredSignature
|
||||
})?;
|
||||
if !is_signer {
|
||||
let signer_key = signer_account.signer_key();
|
||||
if signer_key.is_none() {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"account {:?} signer_key().is_none()",
|
||||
|
@ -73,9 +77,7 @@ pub fn process_instruction(
|
|||
);
|
||||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
if instruction_context.get_instruction_account_key(transaction_context, counter)?
|
||||
!= signer
|
||||
{
|
||||
if signer_key.unwrap() != signer {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"account[{:?}].signer_key() does not match Config data)",
|
||||
|
@ -94,9 +96,7 @@ pub fn process_instruction(
|
|||
);
|
||||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
} else if !instruction_context
|
||||
.is_signer(instruction_context.get_number_of_program_accounts())?
|
||||
{
|
||||
} else if config_keyed_account.signer_key().is_none() {
|
||||
ic_msg!(invoke_context, "account[0].signer_key().is_none()");
|
||||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
|
@ -125,13 +125,15 @@ pub fn process_instruction(
|
|||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
|
||||
let mut config_account =
|
||||
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||
if config_account.get_data().len() < data.len() {
|
||||
if config_keyed_account.data_len()? < data.len() {
|
||||
ic_msg!(invoke_context, "instruction data too large");
|
||||
return Err(InstructionError::InvalidInstructionData);
|
||||
}
|
||||
config_account.get_data_mut()[..data.len()].copy_from_slice(data);
|
||||
|
||||
config_keyed_account
|
||||
.try_account_ref_mut()?
|
||||
.data_as_mut_slice()[..data.len()]
|
||||
.copy_from_slice(data);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -144,7 +146,7 @@ mod tests {
|
|||
serde_derive::{Deserialize, Serialize},
|
||||
solana_program_runtime::invoke_context::mock_process_instruction,
|
||||
solana_sdk::{
|
||||
account::{AccountSharedData, ReadableAccount},
|
||||
account::AccountSharedData,
|
||||
instruction::AccountMeta,
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, Signer},
|
||||
|
|
|
@ -7,12 +7,12 @@ use {
|
|||
crate::{config, stake_state::StakeAccount},
|
||||
log::*,
|
||||
solana_program_runtime::{
|
||||
invoke_context::InvokeContext, sysvar_cache::get_sysvar_with_account_check2,
|
||||
invoke_context::InvokeContext, sysvar_cache::get_sysvar_with_account_check,
|
||||
},
|
||||
solana_sdk::{
|
||||
feature_set,
|
||||
instruction::InstructionError,
|
||||
keyed_account::keyed_account_at_index,
|
||||
keyed_account::{get_signers, keyed_account_at_index},
|
||||
program_utils::limited_deserialize,
|
||||
stake::{
|
||||
instruction::StakeInstruction,
|
||||
|
@ -23,138 +23,44 @@ use {
|
|||
},
|
||||
};
|
||||
|
||||
pub mod instruction_account_indices {
|
||||
pub enum Initialize {
|
||||
StakeAccount = 0,
|
||||
Rent = 1,
|
||||
}
|
||||
|
||||
pub enum Authorize {
|
||||
StakeAccount = 0,
|
||||
Clock = 1,
|
||||
// CurrentAuthority = 2,
|
||||
Custodian = 3,
|
||||
}
|
||||
|
||||
pub enum AuthorizeWithSeed {
|
||||
StakeAccount = 0,
|
||||
AuthorityBase = 1,
|
||||
Clock = 2,
|
||||
Custodian = 3,
|
||||
}
|
||||
|
||||
pub enum DelegateStake {
|
||||
StakeAccount = 0,
|
||||
VoteAccount = 1,
|
||||
Clock = 2,
|
||||
StakeHistory = 3,
|
||||
ConfigAccount = 4,
|
||||
}
|
||||
|
||||
pub enum Split {
|
||||
StakeAccount = 0,
|
||||
SplitTo = 1,
|
||||
}
|
||||
|
||||
pub enum Merge {
|
||||
StakeAccount = 0,
|
||||
MergeFrom = 1,
|
||||
Clock = 2,
|
||||
StakeHistory = 3,
|
||||
}
|
||||
|
||||
pub enum Withdraw {
|
||||
StakeAccount = 0,
|
||||
Recipient = 1,
|
||||
Clock = 2,
|
||||
StakeHistory = 3,
|
||||
WithdrawAuthority = 4,
|
||||
Custodian = 5,
|
||||
}
|
||||
|
||||
pub enum Deactivate {
|
||||
StakeAccount = 0,
|
||||
Clock = 1,
|
||||
}
|
||||
|
||||
pub enum SetLockup {
|
||||
StakeAccount = 0,
|
||||
// Clock = 1,
|
||||
}
|
||||
|
||||
pub enum InitializeChecked {
|
||||
StakeAccount = 0,
|
||||
Rent = 1,
|
||||
AuthorizedStaker = 2,
|
||||
AuthorizedWithdrawer = 3,
|
||||
}
|
||||
|
||||
pub enum AuthorizeChecked {
|
||||
StakeAccount = 0,
|
||||
Clock = 1,
|
||||
// CurrentAuthority = 2,
|
||||
Authorized = 3,
|
||||
Custodian = 4,
|
||||
}
|
||||
|
||||
pub enum AuthorizeCheckedWithSeed {
|
||||
StakeAccount = 0,
|
||||
AuthorityBase = 1,
|
||||
Clock = 2,
|
||||
Authorized = 3,
|
||||
Custodian = 4,
|
||||
}
|
||||
|
||||
pub enum SetLockupChecked {
|
||||
StakeAccount = 0,
|
||||
// Clock = 1,
|
||||
Custodian = 2,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_instruction(
|
||||
first_instruction_account: usize,
|
||||
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()?;
|
||||
|
||||
trace!("process_instruction: {:?}", data);
|
||||
trace!("keyed_accounts: {:?}", keyed_accounts);
|
||||
|
||||
let me = &keyed_account_at_index(keyed_accounts, first_instruction_account)?;
|
||||
if me.owner()? != id() {
|
||||
return Err(InstructionError::InvalidAccountOwner);
|
||||
}
|
||||
|
||||
let signers = instruction_context.get_signers(transaction_context);
|
||||
let signers = get_signers(&keyed_accounts[first_instruction_account..]);
|
||||
match limited_deserialize(data)? {
|
||||
StakeInstruction::Initialize(authorized, lockup) => {
|
||||
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 + 1)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::Initialize::Rent as usize,
|
||||
)?;
|
||||
me.initialize(&authorized, &lockup, &rent)
|
||||
}
|
||||
StakeInstruction::Authorize(authorized_pubkey, stake_authorize) => {
|
||||
instruction_context.check_number_of_instruction_accounts(3)?;
|
||||
let require_custodian_for_locked_stake_authorize = invoke_context
|
||||
.feature_set
|
||||
.is_active(&feature_set::require_custodian_for_locked_stake_authorize::id());
|
||||
|
||||
if require_custodian_for_locked_stake_authorize {
|
||||
let clock = get_sysvar_with_account_check2::clock(
|
||||
let clock = get_sysvar_with_account_check::clock(
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::Authorize::Clock as usize,
|
||||
)?;
|
||||
let custodian = keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account
|
||||
+ instruction_account_indices::Authorize::Custodian as usize,
|
||||
)
|
||||
let _current_authority =
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?;
|
||||
let custodian =
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 3)
|
||||
.ok()
|
||||
.map(|ka| ka.unsigned_key());
|
||||
|
||||
|
@ -178,27 +84,19 @@ pub fn process_instruction(
|
|||
}
|
||||
}
|
||||
StakeInstruction::AuthorizeWithSeed(args) => {
|
||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||
let authority_base = keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account
|
||||
+ instruction_account_indices::AuthorizeWithSeed::AuthorityBase as usize,
|
||||
)?;
|
||||
let authority_base =
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
||||
let require_custodian_for_locked_stake_authorize = invoke_context
|
||||
.feature_set
|
||||
.is_active(&feature_set::require_custodian_for_locked_stake_authorize::id());
|
||||
|
||||
if require_custodian_for_locked_stake_authorize {
|
||||
let clock = get_sysvar_with_account_check2::clock(
|
||||
let clock = get_sysvar_with_account_check::clock(
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::AuthorizeWithSeed::Clock as usize,
|
||||
)?;
|
||||
let custodian = keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account
|
||||
+ instruction_account_indices::AuthorizeWithSeed::Custodian as usize,
|
||||
)
|
||||
let custodian =
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 3)
|
||||
.ok()
|
||||
.map(|ka| ka.unsigned_key());
|
||||
|
||||
|
@ -226,28 +124,17 @@ pub fn process_instruction(
|
|||
}
|
||||
}
|
||||
StakeInstruction::DelegateStake => {
|
||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||
let vote = keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account
|
||||
+ instruction_account_indices::DelegateStake::VoteAccount as usize,
|
||||
)?;
|
||||
let clock = get_sysvar_with_account_check2::clock(
|
||||
let vote = keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
||||
let clock = get_sysvar_with_account_check::clock(
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::DelegateStake::Clock as usize,
|
||||
)?;
|
||||
let stake_history = get_sysvar_with_account_check2::stake_history(
|
||||
let stake_history = get_sysvar_with_account_check::stake_history(
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 3)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::DelegateStake::StakeHistory as usize,
|
||||
)?;
|
||||
instruction_context.check_number_of_instruction_accounts(5)?;
|
||||
let config_account = keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account
|
||||
+ instruction_account_indices::DelegateStake::ConfigAccount as usize,
|
||||
)?;
|
||||
let config_account =
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 4)?;
|
||||
if !config::check_id(config_account.unsigned_key()) {
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
|
@ -256,28 +143,20 @@ pub fn process_instruction(
|
|||
me.delegate(vote, &clock, &stake_history, &config, &signers)
|
||||
}
|
||||
StakeInstruction::Split(lamports) => {
|
||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||
let split_stake = &keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account + instruction_account_indices::Split::SplitTo as usize,
|
||||
)?;
|
||||
let split_stake =
|
||||
&keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
||||
me.split(lamports, split_stake, &signers)
|
||||
}
|
||||
StakeInstruction::Merge => {
|
||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||
let source_stake = &keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account + instruction_account_indices::Merge::MergeFrom as usize,
|
||||
)?;
|
||||
let clock = get_sysvar_with_account_check2::clock(
|
||||
let source_stake =
|
||||
&keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
||||
let clock = get_sysvar_with_account_check::clock(
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::Merge::Clock as usize,
|
||||
)?;
|
||||
let stake_history = get_sysvar_with_account_check2::stake_history(
|
||||
let stake_history = get_sysvar_with_account_check::stake_history(
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 3)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::Merge::StakeHistory as usize,
|
||||
)?;
|
||||
me.merge(
|
||||
invoke_context,
|
||||
|
@ -288,46 +167,28 @@ pub fn process_instruction(
|
|||
)
|
||||
}
|
||||
StakeInstruction::Withdraw(lamports) => {
|
||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||
let to = &keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account
|
||||
+ instruction_account_indices::Withdraw::Recipient as usize,
|
||||
)?;
|
||||
let clock = get_sysvar_with_account_check2::clock(
|
||||
let to = &keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
||||
let clock = get_sysvar_with_account_check::clock(
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::Withdraw::Clock as usize,
|
||||
)?;
|
||||
let stake_history = get_sysvar_with_account_check2::stake_history(
|
||||
let stake_history = get_sysvar_with_account_check::stake_history(
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 3)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::Withdraw::StakeHistory as usize,
|
||||
)?;
|
||||
instruction_context.check_number_of_instruction_accounts(5)?;
|
||||
me.withdraw(
|
||||
lamports,
|
||||
to,
|
||||
&clock,
|
||||
&stake_history,
|
||||
keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account
|
||||
+ instruction_account_indices::Withdraw::WithdrawAuthority as usize,
|
||||
)?,
|
||||
keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account
|
||||
+ instruction_account_indices::Withdraw::Custodian as usize,
|
||||
)
|
||||
.ok(),
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 4)?,
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 5).ok(),
|
||||
)
|
||||
}
|
||||
StakeInstruction::Deactivate => {
|
||||
let clock = get_sysvar_with_account_check2::clock(
|
||||
let clock = get_sysvar_with_account_check::clock(
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::Deactivate::Clock as usize,
|
||||
)?;
|
||||
me.deactivate(&clock, &signers)
|
||||
}
|
||||
|
@ -340,29 +201,20 @@ pub fn process_instruction(
|
|||
.feature_set
|
||||
.is_active(&feature_set::vote_stake_checked_instructions::id())
|
||||
{
|
||||
instruction_context.check_number_of_instruction_accounts(4)?;
|
||||
let authorized = Authorized {
|
||||
staker: *keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account
|
||||
+ instruction_account_indices::InitializeChecked::AuthorizedStaker
|
||||
as usize,
|
||||
)?
|
||||
staker: *keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?
|
||||
.unsigned_key(),
|
||||
withdrawer: *keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account
|
||||
+ instruction_account_indices::InitializeChecked::AuthorizedWithdrawer
|
||||
as usize,
|
||||
first_instruction_account + 3,
|
||||
)?
|
||||
.signer_key()
|
||||
.ok_or(InstructionError::MissingRequiredSignature)?,
|
||||
};
|
||||
|
||||
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 + 1)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::InitializeChecked::Rent as usize,
|
||||
)?;
|
||||
me.initialize(&authorized, &Lockup::default(), &rent)
|
||||
} else {
|
||||
|
@ -374,24 +226,18 @@ pub fn process_instruction(
|
|||
.feature_set
|
||||
.is_active(&feature_set::vote_stake_checked_instructions::id())
|
||||
{
|
||||
let clock = get_sysvar_with_account_check2::clock(
|
||||
let clock = get_sysvar_with_account_check::clock(
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::AuthorizeChecked::Clock as usize,
|
||||
)?;
|
||||
instruction_context.check_number_of_instruction_accounts(4)?;
|
||||
let authorized_pubkey = &keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account
|
||||
+ instruction_account_indices::AuthorizeChecked::Authorized as usize,
|
||||
)?
|
||||
let _current_authority =
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?;
|
||||
let authorized_pubkey =
|
||||
&keyed_account_at_index(keyed_accounts, first_instruction_account + 3)?
|
||||
.signer_key()
|
||||
.ok_or(InstructionError::MissingRequiredSignature)?;
|
||||
let custodian = keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account
|
||||
+ instruction_account_indices::AuthorizeChecked::Custodian as usize,
|
||||
)
|
||||
let custodian =
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 4)
|
||||
.ok()
|
||||
.map(|ka| ka.unsigned_key());
|
||||
|
||||
|
@ -412,32 +258,18 @@ pub fn process_instruction(
|
|||
.feature_set
|
||||
.is_active(&feature_set::vote_stake_checked_instructions::id())
|
||||
{
|
||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||
let authority_base = keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account
|
||||
+ instruction_account_indices::AuthorizeCheckedWithSeed::AuthorityBase
|
||||
as usize,
|
||||
)?;
|
||||
let clock = get_sysvar_with_account_check2::clock(
|
||||
let authority_base =
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
||||
let clock = get_sysvar_with_account_check::clock(
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::AuthorizeCheckedWithSeed::Clock as usize,
|
||||
)?;
|
||||
instruction_context.check_number_of_instruction_accounts(4)?;
|
||||
let authorized_pubkey = &keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account
|
||||
+ instruction_account_indices::AuthorizeCheckedWithSeed::Authorized
|
||||
as usize,
|
||||
)?
|
||||
let authorized_pubkey =
|
||||
&keyed_account_at_index(keyed_accounts, first_instruction_account + 3)?
|
||||
.signer_key()
|
||||
.ok_or(InstructionError::MissingRequiredSignature)?;
|
||||
let custodian = keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account
|
||||
+ instruction_account_indices::AuthorizeCheckedWithSeed::Custodian as usize,
|
||||
)
|
||||
let custodian =
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 4)
|
||||
.ok()
|
||||
.map(|ka| ka.unsigned_key());
|
||||
|
||||
|
@ -460,11 +292,9 @@ pub fn process_instruction(
|
|||
.feature_set
|
||||
.is_active(&feature_set::vote_stake_checked_instructions::id())
|
||||
{
|
||||
let custodian = if let Ok(custodian) = keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account
|
||||
+ instruction_account_indices::SetLockupChecked::Custodian as usize,
|
||||
) {
|
||||
let custodian = if let Ok(custodian) =
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 2)
|
||||
{
|
||||
Some(
|
||||
*custodian
|
||||
.signer_key()
|
||||
|
|
|
@ -5,157 +5,87 @@ use {
|
|||
log::*,
|
||||
solana_metrics::inc_new_counter_info,
|
||||
solana_program_runtime::{
|
||||
invoke_context::InvokeContext, sysvar_cache::get_sysvar_with_account_check2,
|
||||
invoke_context::InvokeContext, sysvar_cache::get_sysvar_with_account_check,
|
||||
},
|
||||
solana_sdk::{feature_set, instruction::InstructionError, program_utils::limited_deserialize},
|
||||
solana_sdk::{
|
||||
feature_set,
|
||||
instruction::InstructionError,
|
||||
keyed_account::{get_signers, keyed_account_at_index, KeyedAccount},
|
||||
program_utils::limited_deserialize,
|
||||
pubkey::Pubkey,
|
||||
sysvar::rent::Rent,
|
||||
},
|
||||
std::collections::HashSet,
|
||||
};
|
||||
|
||||
pub mod instruction_account_indices {
|
||||
pub enum InitializeAccount {
|
||||
VoteAccount = 0,
|
||||
Rent = 1,
|
||||
Clock = 2,
|
||||
}
|
||||
|
||||
pub enum Authorize {
|
||||
VoteAccount = 0,
|
||||
Clock = 1,
|
||||
}
|
||||
|
||||
pub enum UpdateValidatorIdentity {
|
||||
VoteAccount = 0,
|
||||
Node = 1,
|
||||
}
|
||||
|
||||
pub enum UpdateCommission {
|
||||
VoteAccount = 0,
|
||||
}
|
||||
|
||||
pub enum Vote {
|
||||
VoteAccount = 0,
|
||||
SlotHashes = 1,
|
||||
Clock = 2,
|
||||
}
|
||||
|
||||
pub enum UpdateVoteState {
|
||||
VoteAccount = 0,
|
||||
}
|
||||
|
||||
pub enum Withdraw {
|
||||
VoteAccount = 0,
|
||||
Recipient = 1,
|
||||
}
|
||||
|
||||
pub enum AuthorizeChecked {
|
||||
VoteAccount = 0,
|
||||
Clock = 1,
|
||||
// Ignores = 2,
|
||||
Voter = 3,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_instruction(
|
||||
_first_instruction_account: usize,
|
||||
first_instruction_account: usize,
|
||||
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()?;
|
||||
|
||||
trace!("process_instruction: {:?}", data);
|
||||
trace!("keyed_accounts: {:?}", keyed_accounts);
|
||||
|
||||
{
|
||||
let vote_account =
|
||||
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||
if vote_account.get_owner() != &id() {
|
||||
let me = &mut keyed_account_at_index(keyed_accounts, first_instruction_account)?;
|
||||
if me.owner()? != id() {
|
||||
return Err(InstructionError::InvalidAccountOwner);
|
||||
}
|
||||
}
|
||||
|
||||
let signers = instruction_context.get_signers(transaction_context);
|
||||
let signers: HashSet<Pubkey> = get_signers(&keyed_accounts[first_instruction_account..]);
|
||||
match limited_deserialize(data)? {
|
||||
VoteInstruction::InitializeAccount(vote_init) => {
|
||||
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 + 1)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::InitializeAccount::Rent as usize,
|
||||
)?;
|
||||
{
|
||||
// Verify rent exemption
|
||||
let vote_account = instruction_context.try_borrow_instruction_account(
|
||||
transaction_context,
|
||||
instruction_account_indices::InitializeAccount::VoteAccount as usize,
|
||||
)?;
|
||||
if !rent.is_exempt(vote_account.get_lamports(), vote_account.get_data().len()) {
|
||||
return Err(InstructionError::InsufficientFunds);
|
||||
}
|
||||
}
|
||||
let _clock = get_sysvar_with_account_check2::clock(
|
||||
verify_rent_exemption(me, &rent)?;
|
||||
let clock = get_sysvar_with_account_check::clock(
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::InitializeAccount::Clock as usize,
|
||||
)?;
|
||||
vote_state::initialize_account(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
&signers,
|
||||
instruction_account_indices::InitializeAccount::VoteAccount as usize,
|
||||
&vote_init,
|
||||
)
|
||||
vote_state::initialize_account(me, &vote_init, &signers, &clock)
|
||||
}
|
||||
VoteInstruction::Authorize(voter_pubkey, vote_authorize) => {
|
||||
let _clock = get_sysvar_with_account_check2::clock(
|
||||
let clock = get_sysvar_with_account_check::clock(
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::Authorize::Clock as usize,
|
||||
)?;
|
||||
vote_state::authorize(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
&signers,
|
||||
instruction_account_indices::Authorize::VoteAccount as usize,
|
||||
me,
|
||||
&voter_pubkey,
|
||||
vote_authorize,
|
||||
&signers,
|
||||
&clock,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
}
|
||||
VoteInstruction::UpdateValidatorIdentity => {
|
||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||
vote_state::update_validator_identity(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
VoteInstruction::UpdateValidatorIdentity => vote_state::update_validator_identity(
|
||||
me,
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?.unsigned_key(),
|
||||
&signers,
|
||||
instruction_account_indices::UpdateValidatorIdentity::VoteAccount as usize,
|
||||
instruction_context.get_instruction_account_key(
|
||||
transaction_context,
|
||||
instruction_account_indices::UpdateValidatorIdentity::Node as usize,
|
||||
)?,
|
||||
)
|
||||
}
|
||||
VoteInstruction::UpdateCommission(commission) => vote_state::update_commission(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
&signers,
|
||||
instruction_account_indices::UpdateCommission::VoteAccount as usize,
|
||||
commission,
|
||||
),
|
||||
VoteInstruction::UpdateCommission(commission) => {
|
||||
vote_state::update_commission(me, commission, &signers)
|
||||
}
|
||||
VoteInstruction::Vote(vote) | VoteInstruction::VoteSwitch(vote, _) => {
|
||||
inc_new_counter_info!("vote-native", 1);
|
||||
let _slot_hashes = get_sysvar_with_account_check2::slot_hashes(
|
||||
let slot_hashes = get_sysvar_with_account_check::slot_hashes(
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::Vote::SlotHashes as usize,
|
||||
)?;
|
||||
let _clock = get_sysvar_with_account_check2::clock(
|
||||
let clock = get_sysvar_with_account_check::clock(
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::Vote::Clock as usize,
|
||||
)?;
|
||||
vote_state::process_vote(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
&signers,
|
||||
instruction_account_indices::Vote::VoteAccount as usize,
|
||||
me,
|
||||
&slot_hashes,
|
||||
&clock,
|
||||
&vote,
|
||||
&signers,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
}
|
||||
VoteInstruction::UpdateVoteState(vote_state_update)
|
||||
|
@ -165,26 +95,47 @@ pub fn process_instruction(
|
|||
.is_active(&feature_set::allow_votes_to_directly_update_vote_state::id())
|
||||
{
|
||||
inc_new_counter_info!("vote-state-native", 1);
|
||||
let sysvar_cache = invoke_context.get_sysvar_cache();
|
||||
let slot_hashes = sysvar_cache.get_slot_hashes()?;
|
||||
let clock = sysvar_cache.get_clock()?;
|
||||
vote_state::process_vote_state_update(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
&signers,
|
||||
instruction_account_indices::UpdateVoteState::VoteAccount as usize,
|
||||
me,
|
||||
slot_hashes.slot_hashes(),
|
||||
&clock,
|
||||
vote_state_update,
|
||||
&signers,
|
||||
)
|
||||
} else {
|
||||
Err(InstructionError::InvalidInstructionData)
|
||||
}
|
||||
}
|
||||
VoteInstruction::Withdraw(lamports) => {
|
||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||
let to = keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
||||
let rent_sysvar = if invoke_context
|
||||
.feature_set
|
||||
.is_active(&feature_set::reject_non_rent_exempt_vote_withdraws::id())
|
||||
{
|
||||
Some(invoke_context.get_sysvar_cache().get_rent()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let clock_if_feature_active = if invoke_context
|
||||
.feature_set
|
||||
.is_active(&feature_set::reject_vote_account_close_unless_zero_credit_epoch::id())
|
||||
{
|
||||
Some(invoke_context.get_sysvar_cache().get_clock()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
vote_state::withdraw(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
&signers,
|
||||
instruction_account_indices::Withdraw::VoteAccount as usize,
|
||||
instruction_account_indices::Withdraw::Recipient as usize,
|
||||
me,
|
||||
lamports,
|
||||
to,
|
||||
&signers,
|
||||
rent_sysvar.as_deref(),
|
||||
clock_if_feature_active.as_deref(),
|
||||
)
|
||||
}
|
||||
VoteInstruction::AuthorizeChecked(vote_authorize) => {
|
||||
|
@ -192,28 +143,21 @@ pub fn process_instruction(
|
|||
.feature_set
|
||||
.is_active(&feature_set::vote_stake_checked_instructions::id())
|
||||
{
|
||||
instruction_context.check_number_of_instruction_accounts(4)?;
|
||||
if !instruction_context.is_signer(
|
||||
instruction_context.get_number_of_program_accounts()
|
||||
+ instruction_account_indices::AuthorizeChecked::Voter as usize,
|
||||
)? {
|
||||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
let _clock = get_sysvar_with_account_check2::clock(
|
||||
let voter_pubkey =
|
||||
&keyed_account_at_index(keyed_accounts, first_instruction_account + 3)?
|
||||
.signer_key()
|
||||
.ok_or(InstructionError::MissingRequiredSignature)?;
|
||||
let clock = get_sysvar_with_account_check::clock(
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?,
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::AuthorizeChecked::Clock as usize,
|
||||
)?;
|
||||
vote_state::authorize(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
&signers,
|
||||
instruction_account_indices::AuthorizeChecked::VoteAccount as usize,
|
||||
instruction_context.get_instruction_account_key(
|
||||
transaction_context,
|
||||
instruction_account_indices::AuthorizeChecked::Voter as usize,
|
||||
)?,
|
||||
me,
|
||||
voter_pubkey,
|
||||
vote_authorize,
|
||||
&signers,
|
||||
&clock,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
} else {
|
||||
Err(InstructionError::InvalidInstructionData)
|
||||
|
@ -222,6 +166,17 @@ pub fn process_instruction(
|
|||
}
|
||||
}
|
||||
|
||||
fn verify_rent_exemption(
|
||||
keyed_account: &KeyedAccount,
|
||||
rent: &Rent,
|
||||
) -> Result<(), InstructionError> {
|
||||
if !rent.is_exempt(keyed_account.lamports()?, keyed_account.data_len()?) {
|
||||
Err(InstructionError::InsufficientFunds)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use {
|
||||
|
@ -246,10 +201,9 @@ mod tests {
|
|||
feature_set::FeatureSet,
|
||||
hash::Hash,
|
||||
instruction::{AccountMeta, Instruction},
|
||||
pubkey::Pubkey,
|
||||
sysvar::{self, clock::Clock, rent::Rent, slot_hashes::SlotHashes},
|
||||
sysvar::{self, clock::Clock, slot_hashes::SlotHashes},
|
||||
},
|
||||
std::{collections::HashSet, str::FromStr},
|
||||
std::str::FromStr,
|
||||
};
|
||||
|
||||
fn create_default_account() -> AccountSharedData {
|
||||
|
|
|
@ -5,19 +5,19 @@ use {
|
|||
bincode::{deserialize, serialize_into, serialized_size, ErrorKind},
|
||||
log::*,
|
||||
serde_derive::{Deserialize, Serialize},
|
||||
solana_program_runtime::invoke_context::InvokeContext,
|
||||
solana_sdk::{
|
||||
account::{AccountSharedData, ReadableAccount, WritableAccount},
|
||||
account_utils::State,
|
||||
clock::{Epoch, Slot, UnixTimestamp},
|
||||
epoch_schedule::MAX_LEADER_SCHEDULE_EPOCH_OFFSET,
|
||||
feature_set::{self, filter_votes_outside_slot_hashes, FeatureSet},
|
||||
hash::Hash,
|
||||
instruction::InstructionError,
|
||||
keyed_account::KeyedAccount,
|
||||
pubkey::Pubkey,
|
||||
rent::Rent,
|
||||
slot_hashes::SlotHash,
|
||||
sysvar::clock::Clock,
|
||||
transaction_context::{BorrowedAccount, InstructionContext},
|
||||
},
|
||||
std::{
|
||||
cmp::Ordering,
|
||||
|
@ -1165,24 +1165,19 @@ impl VoteState {
|
|||
/// but will implicitly withdraw authorization from the previously authorized
|
||||
/// key
|
||||
pub fn authorize<S: std::hash::BuildHasher>(
|
||||
invoke_context: &InvokeContext,
|
||||
instruction_context: &InstructionContext,
|
||||
signers: &HashSet<Pubkey, S>,
|
||||
vote_account_index: usize,
|
||||
vote_account: &KeyedAccount,
|
||||
authorized: &Pubkey,
|
||||
vote_authorize: VoteAuthorize,
|
||||
signers: &HashSet<Pubkey, S>,
|
||||
clock: &Clock,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut vote_account = instruction_context
|
||||
.try_borrow_instruction_account(invoke_context.transaction_context, vote_account_index)?;
|
||||
let clock = invoke_context.get_sysvar_cache().get_clock()?;
|
||||
let mut vote_state: VoteState = vote_account
|
||||
.get_state::<VoteStateVersions>()?
|
||||
.convert_to_current();
|
||||
let mut vote_state: VoteState =
|
||||
State::<VoteStateVersions>::state(vote_account)?.convert_to_current();
|
||||
|
||||
match vote_authorize {
|
||||
VoteAuthorize::Voter => {
|
||||
let authorized_withdrawer_signer = if invoke_context
|
||||
.feature_set
|
||||
let authorized_withdrawer_signer = if feature_set
|
||||
.is_active(&feature_set::vote_withdraw_authority_may_change_authorized_voter::id())
|
||||
{
|
||||
verify_authorized_signer(&vote_state.authorized_withdrawer, signers).is_ok()
|
||||
|
@ -1216,17 +1211,12 @@ pub fn authorize<S: std::hash::BuildHasher>(
|
|||
|
||||
/// Update the node_pubkey, requires signature of the authorized voter
|
||||
pub fn update_validator_identity<S: std::hash::BuildHasher>(
|
||||
invoke_context: &InvokeContext,
|
||||
instruction_context: &InstructionContext,
|
||||
signers: &HashSet<Pubkey, S>,
|
||||
vote_account_index: usize,
|
||||
vote_account: &KeyedAccount,
|
||||
node_pubkey: &Pubkey,
|
||||
signers: &HashSet<Pubkey, S>,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut vote_account = instruction_context
|
||||
.try_borrow_instruction_account(invoke_context.transaction_context, vote_account_index)?;
|
||||
let mut vote_state: VoteState = vote_account
|
||||
.get_state::<VoteStateVersions>()?
|
||||
.convert_to_current();
|
||||
let mut vote_state: VoteState =
|
||||
State::<VoteStateVersions>::state(vote_account)?.convert_to_current();
|
||||
|
||||
// current authorized withdrawer must say "yay"
|
||||
verify_authorized_signer(&vote_state.authorized_withdrawer, signers)?;
|
||||
|
@ -1241,17 +1231,12 @@ pub fn update_validator_identity<S: std::hash::BuildHasher>(
|
|||
|
||||
/// Update the vote account's commission
|
||||
pub fn update_commission<S: std::hash::BuildHasher>(
|
||||
invoke_context: &InvokeContext,
|
||||
instruction_context: &InstructionContext,
|
||||
signers: &HashSet<Pubkey, S>,
|
||||
vote_account_index: usize,
|
||||
vote_account: &KeyedAccount,
|
||||
commission: u8,
|
||||
signers: &HashSet<Pubkey, S>,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut vote_account = instruction_context
|
||||
.try_borrow_instruction_account(invoke_context.transaction_context, vote_account_index)?;
|
||||
let mut vote_state: VoteState = vote_account
|
||||
.get_state::<VoteStateVersions>()?
|
||||
.convert_to_current();
|
||||
let mut vote_state: VoteState =
|
||||
State::<VoteStateVersions>::state(vote_account)?.convert_to_current();
|
||||
|
||||
// current authorized withdrawer must say "yay"
|
||||
verify_authorized_signer(&vote_state.authorized_withdrawer, signers)?;
|
||||
|
@ -1274,42 +1259,20 @@ fn verify_authorized_signer<S: std::hash::BuildHasher>(
|
|||
|
||||
/// Withdraw funds from the vote account
|
||||
pub fn withdraw<S: std::hash::BuildHasher>(
|
||||
invoke_context: &InvokeContext,
|
||||
instruction_context: &InstructionContext,
|
||||
signers: &HashSet<Pubkey, S>,
|
||||
vote_account_index: usize,
|
||||
recipient_account_index: usize,
|
||||
vote_account: &KeyedAccount,
|
||||
lamports: u64,
|
||||
to_account: &KeyedAccount,
|
||||
signers: &HashSet<Pubkey, S>,
|
||||
rent_sysvar: Option<&Rent>,
|
||||
clock: Option<&Clock>,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut vote_account = instruction_context
|
||||
.try_borrow_instruction_account(invoke_context.transaction_context, vote_account_index)?;
|
||||
|
||||
let rent_sysvar = if invoke_context
|
||||
.feature_set
|
||||
.is_active(&feature_set::reject_non_rent_exempt_vote_withdraws::id())
|
||||
{
|
||||
Some(invoke_context.get_sysvar_cache().get_rent()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let clock = if invoke_context
|
||||
.feature_set
|
||||
.is_active(&feature_set::reject_vote_account_close_unless_zero_credit_epoch::id())
|
||||
{
|
||||
Some(invoke_context.get_sysvar_cache().get_clock()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let vote_state: VoteState = vote_account
|
||||
.get_state::<VoteStateVersions>()?
|
||||
.convert_to_current();
|
||||
let vote_state: VoteState =
|
||||
State::<VoteStateVersions>::state(vote_account)?.convert_to_current();
|
||||
|
||||
verify_authorized_signer(&vote_state.authorized_withdrawer, signers)?;
|
||||
|
||||
let remaining_balance = vote_account
|
||||
.get_lamports()
|
||||
.lamports()?
|
||||
.checked_sub(lamports)
|
||||
.ok_or(InstructionError::InsufficientFunds)?;
|
||||
|
||||
|
@ -1332,19 +1295,18 @@ pub fn withdraw<S: std::hash::BuildHasher>(
|
|||
vote_account.set_state(&VoteStateVersions::new_current(VoteState::default()))?;
|
||||
}
|
||||
} else if let Some(rent_sysvar) = rent_sysvar {
|
||||
let min_rent_exempt_balance = rent_sysvar.minimum_balance(vote_account.get_data().len());
|
||||
let min_rent_exempt_balance = rent_sysvar.minimum_balance(vote_account.data_len()?);
|
||||
if remaining_balance < min_rent_exempt_balance {
|
||||
return Err(InstructionError::InsufficientFunds);
|
||||
}
|
||||
}
|
||||
|
||||
vote_account.checked_sub_lamports(lamports)?;
|
||||
drop(vote_account);
|
||||
let mut recipient_account = instruction_context.try_borrow_instruction_account(
|
||||
invoke_context.transaction_context,
|
||||
recipient_account_index,
|
||||
)?;
|
||||
recipient_account.checked_add_lamports(lamports)?;
|
||||
vote_account
|
||||
.try_account_ref_mut()?
|
||||
.checked_sub_lamports(lamports)?;
|
||||
to_account
|
||||
.try_account_ref_mut()?
|
||||
.checked_add_lamports(lamports)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1352,19 +1314,15 @@ pub fn withdraw<S: std::hash::BuildHasher>(
|
|||
/// Assumes that the account is being init as part of a account creation or balance transfer and
|
||||
/// that the transaction must be signed by the staker's keys
|
||||
pub fn initialize_account<S: std::hash::BuildHasher>(
|
||||
invoke_context: &InvokeContext,
|
||||
instruction_context: &InstructionContext,
|
||||
signers: &HashSet<Pubkey, S>,
|
||||
vote_account_index: usize,
|
||||
vote_account: &KeyedAccount,
|
||||
vote_init: &VoteInit,
|
||||
signers: &HashSet<Pubkey, S>,
|
||||
clock: &Clock,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut vote_account = instruction_context
|
||||
.try_borrow_instruction_account(invoke_context.transaction_context, vote_account_index)?;
|
||||
let clock = invoke_context.get_sysvar_cache().get_clock()?;
|
||||
if vote_account.get_data().len() != VoteState::size_of() {
|
||||
if vote_account.data_len()? != VoteState::size_of() {
|
||||
return Err(InstructionError::InvalidAccountData);
|
||||
}
|
||||
let versioned = vote_account.get_state::<VoteStateVersions>()?;
|
||||
let versioned = State::<VoteStateVersions>::state(vote_account)?;
|
||||
|
||||
if !versioned.is_uninitialized() {
|
||||
return Err(InstructionError::AccountAlreadyInitialized);
|
||||
|
@ -1374,16 +1332,16 @@ pub fn initialize_account<S: std::hash::BuildHasher>(
|
|||
verify_authorized_signer(&vote_init.node_pubkey, signers)?;
|
||||
|
||||
vote_account.set_state(&VoteStateVersions::new_current(VoteState::new(
|
||||
vote_init, &clock,
|
||||
vote_init, clock,
|
||||
)))
|
||||
}
|
||||
|
||||
fn verify_and_get_vote_state<S: std::hash::BuildHasher>(
|
||||
vote_account: &BorrowedAccount,
|
||||
vote_account: &KeyedAccount,
|
||||
clock: &Clock,
|
||||
signers: &HashSet<Pubkey, S>,
|
||||
) -> Result<VoteState, InstructionError> {
|
||||
let versioned = vote_account.get_state::<VoteStateVersions>()?;
|
||||
let versioned = State::<VoteStateVersions>::state(vote_account)?;
|
||||
|
||||
if versioned.is_uninitialized() {
|
||||
return Err(InstructionError::UninitializedAccount);
|
||||
|
@ -1397,25 +1355,16 @@ fn verify_and_get_vote_state<S: std::hash::BuildHasher>(
|
|||
}
|
||||
|
||||
pub fn process_vote<S: std::hash::BuildHasher>(
|
||||
invoke_context: &InvokeContext,
|
||||
instruction_context: &InstructionContext,
|
||||
signers: &HashSet<Pubkey, S>,
|
||||
vote_account_index: usize,
|
||||
vote_account: &KeyedAccount,
|
||||
slot_hashes: &[SlotHash],
|
||||
clock: &Clock,
|
||||
vote: &Vote,
|
||||
signers: &HashSet<Pubkey, S>,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut vote_account = instruction_context
|
||||
.try_borrow_instruction_account(invoke_context.transaction_context, vote_account_index)?;
|
||||
let sysvar_cache = invoke_context.get_sysvar_cache();
|
||||
let slot_hashes = sysvar_cache.get_slot_hashes()?;
|
||||
let clock = sysvar_cache.get_clock()?;
|
||||
let mut vote_state = verify_and_get_vote_state(&vote_account, &clock, signers)?;
|
||||
let mut vote_state = verify_and_get_vote_state(vote_account, clock, signers)?;
|
||||
|
||||
vote_state.process_vote(
|
||||
vote,
|
||||
slot_hashes.slot_hashes(),
|
||||
clock.epoch,
|
||||
Some(&invoke_context.feature_set),
|
||||
)?;
|
||||
vote_state.process_vote(vote, slot_hashes, clock.epoch, Some(feature_set))?;
|
||||
if let Some(timestamp) = vote.timestamp {
|
||||
vote.slots
|
||||
.iter()
|
||||
|
@ -1427,19 +1376,14 @@ pub fn process_vote<S: std::hash::BuildHasher>(
|
|||
}
|
||||
|
||||
pub fn process_vote_state_update<S: std::hash::BuildHasher>(
|
||||
invoke_context: &InvokeContext,
|
||||
instruction_context: &InstructionContext,
|
||||
signers: &HashSet<Pubkey, S>,
|
||||
vote_account_index: usize,
|
||||
vote_account: &KeyedAccount,
|
||||
slot_hashes: &[SlotHash],
|
||||
clock: &Clock,
|
||||
mut vote_state_update: VoteStateUpdate,
|
||||
signers: &HashSet<Pubkey, S>,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut vote_account = instruction_context
|
||||
.try_borrow_instruction_account(invoke_context.transaction_context, vote_account_index)?;
|
||||
let sysvar_cache = invoke_context.get_sysvar_cache();
|
||||
let slot_hashes = sysvar_cache.get_slot_hashes()?;
|
||||
let clock = sysvar_cache.get_clock()?;
|
||||
let mut vote_state = verify_and_get_vote_state(&vote_account, &clock, signers)?;
|
||||
vote_state.check_update_vote_state_slots_are_valid(&mut vote_state_update, &slot_hashes)?;
|
||||
let mut vote_state = verify_and_get_vote_state(vote_account, clock, signers)?;
|
||||
vote_state.check_update_vote_state_slots_are_valid(&mut vote_state_update, slot_hashes)?;
|
||||
vote_state.process_new_vote_state(
|
||||
vote_state_update.lockouts,
|
||||
vote_state_update.root,
|
||||
|
|
|
@ -1,25 +1,53 @@
|
|||
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 fn advance_nonce_account(
|
||||
invoke_context: &InvokeContext,
|
||||
instruction_context: &InstructionContext,
|
||||
pub trait NonceKeyedAccount {
|
||||
fn advance_nonce_account(
|
||||
&self,
|
||||
signers: &HashSet<Pubkey>,
|
||||
nonce_account_index: usize,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut account = instruction_context
|
||||
.try_borrow_instruction_account(invoke_context.transaction_context, nonce_account_index)?;
|
||||
invoke_context: &InvokeContext,
|
||||
) -> Result<(), InstructionError>;
|
||||
fn withdraw_nonce_account(
|
||||
&self,
|
||||
lamports: u64,
|
||||
to: &KeyedAccount,
|
||||
rent: &Rent,
|
||||
signers: &HashSet<Pubkey>,
|
||||
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<Pubkey>,
|
||||
invoke_context: &InvokeContext,
|
||||
) -> Result<(), InstructionError>;
|
||||
}
|
||||
|
||||
impl<'a> NonceKeyedAccount for KeyedAccount<'a> {
|
||||
fn advance_nonce_account(
|
||||
&self,
|
||||
signers: &HashSet<Pubkey>,
|
||||
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());
|
||||
|
@ -27,17 +55,17 @@ pub fn advance_nonce_account(
|
|||
if invoke_context
|
||||
.feature_set
|
||||
.is_active(&nonce_must_be_writable::id())
|
||||
&& !account.is_writable()
|
||||
&& !self.is_writable()
|
||||
{
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Advance nonce account: Account {} must be writeable",
|
||||
account.get_key()
|
||||
self.unsigned_key()
|
||||
);
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
|
||||
let state = account.get_state::<Versions>()?.convert_to_current();
|
||||
let state = AccountUtilsState::<Versions>::state(self)?.convert_to_current();
|
||||
match state {
|
||||
State::Initialized(data) => {
|
||||
if !signers.contains(&data.authority) {
|
||||
|
@ -65,13 +93,13 @@ pub fn advance_nonce_account(
|
|||
recent_blockhash,
|
||||
invoke_context.lamports_per_signature,
|
||||
);
|
||||
account.set_state(&Versions::new_current(State::Initialized(new_data)))
|
||||
self.set_state(&Versions::new_current(State::Initialized(new_data)))
|
||||
}
|
||||
_ => {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Advance nonce account: Account {} state is invalid",
|
||||
account.get_key()
|
||||
self.unsigned_key()
|
||||
);
|
||||
Err(nonce_to_instruction_error(
|
||||
NonceError::BadAccountState,
|
||||
|
@ -79,19 +107,16 @@ pub fn advance_nonce_account(
|
|||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn withdraw_nonce_account(
|
||||
invoke_context: &InvokeContext,
|
||||
instruction_context: &InstructionContext,
|
||||
signers: &HashSet<Pubkey>,
|
||||
nonce_account_index: usize,
|
||||
withdraw_to_account_index: usize,
|
||||
fn withdraw_nonce_account(
|
||||
&self,
|
||||
lamports: u64,
|
||||
to: &KeyedAccount,
|
||||
rent: &Rent,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut nonce_account = instruction_context
|
||||
.try_borrow_instruction_account(invoke_context.transaction_context, nonce_account_index)?;
|
||||
signers: &HashSet<Pubkey>,
|
||||
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());
|
||||
|
@ -99,31 +124,31 @@ pub fn withdraw_nonce_account(
|
|||
if invoke_context
|
||||
.feature_set
|
||||
.is_active(&nonce_must_be_writable::id())
|
||||
&& !nonce_account.is_writable()
|
||||
&& !self.is_writable()
|
||||
{
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Withdraw nonce account: Account {} must be writeable",
|
||||
nonce_account.get_key()
|
||||
self.unsigned_key()
|
||||
);
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
|
||||
let signer = match nonce_account.get_state::<Versions>()?.convert_to_current() {
|
||||
let signer = match AccountUtilsState::<Versions>::state(self)?.convert_to_current() {
|
||||
State::Uninitialized => {
|
||||
if lamports > nonce_account.get_lamports() {
|
||||
if lamports > self.lamports()? {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Withdraw nonce account: insufficient lamports {}, need {}",
|
||||
nonce_account.get_lamports(),
|
||||
self.lamports()?,
|
||||
lamports,
|
||||
);
|
||||
return Err(InstructionError::InsufficientFunds);
|
||||
}
|
||||
*nonce_account.get_key()
|
||||
*self.unsigned_key()
|
||||
}
|
||||
State::Initialized(ref data) => {
|
||||
if lamports == nonce_account.get_lamports() {
|
||||
if lamports == self.lamports()? {
|
||||
if data.blockhash == invoke_context.blockhash {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
|
@ -134,15 +159,15 @@ pub fn withdraw_nonce_account(
|
|||
merge_nonce_error_into_system_error,
|
||||
));
|
||||
}
|
||||
nonce_account.set_state(&Versions::new_current(State::Uninitialized))?;
|
||||
self.set_state(&Versions::new_current(State::Uninitialized))?;
|
||||
} else {
|
||||
let min_balance = rent.minimum_balance(nonce_account.get_data().len());
|
||||
let min_balance = rent.minimum_balance(self.data_len()?);
|
||||
let amount = checked_add(lamports, min_balance)?;
|
||||
if amount > nonce_account.get_lamports() {
|
||||
if amount > self.lamports()? {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Withdraw nonce account: insufficient lamports {}, need {}",
|
||||
nonce_account.get_lamports(),
|
||||
self.lamports()?,
|
||||
amount,
|
||||
);
|
||||
return Err(InstructionError::InsufficientFunds);
|
||||
|
@ -161,26 +186,28 @@ pub fn withdraw_nonce_account(
|
|||
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)?;
|
||||
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)?,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initialize_nonce_account(
|
||||
invoke_context: &InvokeContext,
|
||||
instruction_context: &InstructionContext,
|
||||
nonce_account_index: usize,
|
||||
fn initialize_nonce_account(
|
||||
&self,
|
||||
nonce_authority: &Pubkey,
|
||||
rent: &Rent,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut account = instruction_context
|
||||
.try_borrow_instruction_account(invoke_context.transaction_context, nonce_account_index)?;
|
||||
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());
|
||||
|
@ -188,24 +215,24 @@ pub fn initialize_nonce_account(
|
|||
if invoke_context
|
||||
.feature_set
|
||||
.is_active(&nonce_must_be_writable::id())
|
||||
&& !account.is_writable()
|
||||
&& !self.is_writable()
|
||||
{
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Initialize nonce account: Account {} must be writeable",
|
||||
account.get_key()
|
||||
self.unsigned_key()
|
||||
);
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
|
||||
match account.get_state::<Versions>()?.convert_to_current() {
|
||||
match AccountUtilsState::<Versions>::state(self)?.convert_to_current() {
|
||||
State::Uninitialized => {
|
||||
let min_balance = rent.minimum_balance(account.get_data().len());
|
||||
if account.get_lamports() < min_balance {
|
||||
let min_balance = rent.minimum_balance(self.data_len()?);
|
||||
if self.lamports()? < min_balance {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Initialize nonce account: insufficient lamports {}, need {}",
|
||||
account.get_lamports(),
|
||||
self.lamports()?,
|
||||
min_balance
|
||||
);
|
||||
return Err(InstructionError::InsufficientFunds);
|
||||
|
@ -215,13 +242,13 @@ pub fn initialize_nonce_account(
|
|||
invoke_context.blockhash,
|
||||
invoke_context.lamports_per_signature,
|
||||
);
|
||||
account.set_state(&Versions::new_current(State::Initialized(data)))
|
||||
self.set_state(&Versions::new_current(State::Initialized(data)))
|
||||
}
|
||||
_ => {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Initialize nonce account: Account {} state is invalid",
|
||||
account.get_key()
|
||||
self.unsigned_key()
|
||||
);
|
||||
Err(nonce_to_instruction_error(
|
||||
NonceError::BadAccountState,
|
||||
|
@ -229,17 +256,14 @@ pub fn initialize_nonce_account(
|
|||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn authorize_nonce_account(
|
||||
invoke_context: &InvokeContext,
|
||||
instruction_context: &InstructionContext,
|
||||
signers: &HashSet<Pubkey>,
|
||||
nonce_account_index: usize,
|
||||
fn authorize_nonce_account(
|
||||
&self,
|
||||
nonce_authority: &Pubkey,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut account = instruction_context
|
||||
.try_borrow_instruction_account(invoke_context.transaction_context, nonce_account_index)?;
|
||||
signers: &HashSet<Pubkey>,
|
||||
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());
|
||||
|
@ -247,17 +271,17 @@ pub fn authorize_nonce_account(
|
|||
if invoke_context
|
||||
.feature_set
|
||||
.is_active(&nonce_must_be_writable::id())
|
||||
&& !account.is_writable()
|
||||
&& !self.is_writable()
|
||||
{
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Authorize nonce account: Account {} must be writeable",
|
||||
account.get_key()
|
||||
self.unsigned_key()
|
||||
);
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
|
||||
match account.get_state::<Versions>()?.convert_to_current() {
|
||||
match AccountUtilsState::<Versions>::state(self)?.convert_to_current() {
|
||||
State::Initialized(data) => {
|
||||
if !signers.contains(&data.authority) {
|
||||
ic_msg!(
|
||||
|
@ -272,13 +296,13 @@ pub fn authorize_nonce_account(
|
|||
data.blockhash,
|
||||
data.get_lamports_per_signature(),
|
||||
);
|
||||
account.set_state(&Versions::new_current(State::Initialized(new_data)))
|
||||
self.set_state(&Versions::new_current(State::Initialized(new_data)))
|
||||
}
|
||||
_ => {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Authorize nonce account: Account {} state is invalid",
|
||||
account.get_key()
|
||||
self.unsigned_key()
|
||||
);
|
||||
Err(nonce_to_instruction_error(
|
||||
NonceError::BadAccountState,
|
||||
|
@ -286,6 +310,7 @@ pub fn authorize_nonce_account(
|
|||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -304,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
|
||||
|
@ -350,9 +378,6 @@ mod test {
|
|||
};
|
||||
}
|
||||
|
||||
const NONCE_ACCOUNT_INDEX: usize = 0;
|
||||
const WITHDRAW_TO_ACCOUNT_INDEX: usize = 1;
|
||||
|
||||
macro_rules! set_invoke_context_blockhash {
|
||||
($invoke_context:expr, $seed:expr) => {
|
||||
$invoke_context.blockhash = hash(&bincode::serialize(&$seed).unwrap());
|
||||
|
@ -392,13 +417,8 @@ 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,
|
||||
)
|
||||
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)
|
||||
|
@ -416,12 +436,8 @@ 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,
|
||||
)
|
||||
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)
|
||||
|
@ -439,12 +455,8 @@ 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,
|
||||
)
|
||||
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)
|
||||
|
@ -470,14 +482,13 @@ 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,
|
||||
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
|
||||
|
@ -513,13 +524,8 @@ 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,
|
||||
)
|
||||
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)
|
||||
|
@ -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,
|
||||
)
|
||||
invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX]
|
||||
.initialize_nonce_account(&authorized, &rent, &invoke_context)
|
||||
.unwrap();
|
||||
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(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,
|
||||
)
|
||||
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,
|
||||
)
|
||||
invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX]
|
||||
.initialize_nonce_account(&authorized, &rent, &invoke_context)
|
||||
.unwrap();
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -713,14 +684,13 @@ 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,
|
||||
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
|
||||
|
@ -763,14 +733,13 @@ 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,
|
||||
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,14 +766,13 @@ 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,
|
||||
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,14 +800,13 @@ 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,
|
||||
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
|
||||
|
@ -860,14 +827,13 @@ 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,
|
||||
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
|
||||
|
@ -906,13 +872,8 @@ 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,
|
||||
)
|
||||
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)
|
||||
|
@ -935,14 +896,13 @@ 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,
|
||||
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
|
||||
|
@ -969,14 +929,13 @@ 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,
|
||||
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
|
||||
|
@ -1013,13 +972,8 @@ 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,
|
||||
)
|
||||
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)
|
||||
|
@ -1028,14 +982,13 @@ 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,
|
||||
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,13 +1008,8 @@ 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,
|
||||
)
|
||||
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
|
||||
|
@ -1071,14 +1019,13 @@ 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,
|
||||
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,13 +1045,8 @@ 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,
|
||||
)
|
||||
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)
|
||||
|
@ -1114,14 +1056,13 @@ 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,
|
||||
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,13 +1082,8 @@ 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,
|
||||
)
|
||||
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)
|
||||
|
@ -1157,14 +1093,13 @@ 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,
|
||||
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,
|
||||
)
|
||||
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,13 +1206,8 @@ 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,
|
||||
)
|
||||
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(
|
||||
|
@ -1305,13 +1215,8 @@ mod test {
|
|||
invoke_context.blockhash,
|
||||
invoke_context.lamports_per_signature,
|
||||
);
|
||||
authorize_nonce_account(
|
||||
&invoke_context,
|
||||
instruction_context,
|
||||
&signers,
|
||||
NONCE_ACCOUNT_INDEX,
|
||||
&authority,
|
||||
)
|
||||
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)
|
||||
|
@ -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,
|
||||
)
|
||||
invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX]
|
||||
.initialize_nonce_account(&authorized, &rent, &invoke_context)
|
||||
.unwrap();
|
||||
let result = authorize_nonce_account(
|
||||
&invoke_context,
|
||||
instruction_context,
|
||||
&signers,
|
||||
NONCE_ACCOUNT_INDEX,
|
||||
&authorized,
|
||||
);
|
||||
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,13 +1293,8 @@ 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,
|
||||
)
|
||||
invoke_context.get_keyed_accounts().unwrap()[1 + NONCE_ACCOUNT_INDEX]
|
||||
.initialize_nonce_account(&authorized, &rent, &invoke_context)
|
||||
.unwrap();
|
||||
assert!(verify_nonce_account(
|
||||
&transaction_context
|
||||
|
@ -1458,13 +1343,8 @@ 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(),
|
||||
)
|
||||
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(
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
use {
|
||||
crate::nonce_keyed_account::{
|
||||
advance_nonce_account, authorize_nonce_account, initialize_nonce_account,
|
||||
withdraw_nonce_account,
|
||||
},
|
||||
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},
|
||||
account::{AccountSharedData, ReadableAccount, WritableAccount},
|
||||
account_utils::StateMut,
|
||||
feature_set,
|
||||
instruction::InstructionError,
|
||||
keyed_account::{get_signers, keyed_account_at_index, KeyedAccount},
|
||||
nonce,
|
||||
program_utils::limited_deserialize,
|
||||
pubkey::Pubkey,
|
||||
|
@ -19,7 +17,6 @@ use {
|
|||
NonceError, SystemError, SystemInstruction, MAX_PERMITTED_DATA_LENGTH,
|
||||
},
|
||||
system_program,
|
||||
transaction_context::{BorrowedAccount, InstructionContext},
|
||||
},
|
||||
std::collections::HashSet,
|
||||
};
|
||||
|
@ -70,11 +67,11 @@ impl Address {
|
|||
}
|
||||
|
||||
fn allocate(
|
||||
invoke_context: &InvokeContext,
|
||||
signers: &HashSet<Pubkey>,
|
||||
account: &mut BorrowedAccount,
|
||||
account: &mut AccountSharedData,
|
||||
address: &Address,
|
||||
space: u64,
|
||||
signers: &HashSet<Pubkey>,
|
||||
invoke_context: &InvokeContext,
|
||||
) -> Result<(), InstructionError> {
|
||||
if !address.is_signer(signers) {
|
||||
ic_msg!(
|
||||
|
@ -87,7 +84,7 @@ fn allocate(
|
|||
|
||||
// if it looks like the `to` account is already in use, bail
|
||||
// (note that the id check is also enforced by message_processor)
|
||||
if !account.get_data().is_empty() || !system_program::check_id(account.get_owner()) {
|
||||
if !account.data().is_empty() || !system_program::check_id(account.owner()) {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Allocate: account {:?} already in use",
|
||||
|
@ -106,20 +103,20 @@ fn allocate(
|
|||
return Err(SystemError::InvalidAccountDataLength.into());
|
||||
}
|
||||
|
||||
account.set_data(vec![0; space as usize].as_slice());
|
||||
account.set_data(vec![0; space as usize]);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn assign(
|
||||
invoke_context: &InvokeContext,
|
||||
signers: &HashSet<Pubkey>,
|
||||
account: &mut BorrowedAccount,
|
||||
account: &mut AccountSharedData,
|
||||
address: &Address,
|
||||
owner: &Pubkey,
|
||||
signers: &HashSet<Pubkey>,
|
||||
invoke_context: &InvokeContext,
|
||||
) -> Result<(), InstructionError> {
|
||||
// no work to do, just return
|
||||
if account.get_owner() == owner {
|
||||
if account.owner() == owner {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
@ -128,38 +125,36 @@ fn assign(
|
|||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
|
||||
account.set_owner(&owner.to_bytes());
|
||||
account.set_owner(*owner);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn allocate_and_assign(
|
||||
invoke_context: &InvokeContext,
|
||||
signers: &HashSet<Pubkey>,
|
||||
to_account: &mut BorrowedAccount,
|
||||
to: &mut AccountSharedData,
|
||||
to_address: &Address,
|
||||
space: u64,
|
||||
owner: &Pubkey,
|
||||
signers: &HashSet<Pubkey>,
|
||||
invoke_context: &InvokeContext,
|
||||
) -> Result<(), InstructionError> {
|
||||
allocate(invoke_context, signers, to_account, to_address, space)?;
|
||||
assign(invoke_context, signers, to_account, to_address, owner)
|
||||
allocate(to, to_address, space, signers, invoke_context)?;
|
||||
assign(to, to_address, owner, signers, invoke_context)
|
||||
}
|
||||
|
||||
fn create_account(
|
||||
invoke_context: &InvokeContext,
|
||||
instruction_context: &InstructionContext,
|
||||
signers: &HashSet<Pubkey>,
|
||||
from_account_index: usize,
|
||||
to_account_index: usize,
|
||||
from: &KeyedAccount,
|
||||
to: &KeyedAccount,
|
||||
to_address: &Address,
|
||||
lamports: u64,
|
||||
space: u64,
|
||||
owner: &Pubkey,
|
||||
signers: &HashSet<Pubkey>,
|
||||
invoke_context: &InvokeContext,
|
||||
) -> Result<(), InstructionError> {
|
||||
// if it looks like the `to` account is already in use, bail
|
||||
{
|
||||
let mut to_account = instruction_context
|
||||
.try_borrow_instruction_account(invoke_context.transaction_context, to_account_index)?;
|
||||
if to_account.get_lamports() > 0 {
|
||||
let to = &mut to.try_account_ref_mut()?;
|
||||
if to.lamports() > 0 {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Create Account: account {:?} already in use",
|
||||
|
@ -167,60 +162,42 @@ fn create_account(
|
|||
);
|
||||
return Err(SystemError::AccountAlreadyInUse.into());
|
||||
}
|
||||
allocate_and_assign(
|
||||
invoke_context,
|
||||
signers,
|
||||
&mut to_account,
|
||||
to_address,
|
||||
space,
|
||||
owner,
|
||||
)?;
|
||||
|
||||
allocate_and_assign(to, to_address, space, owner, signers, invoke_context)?;
|
||||
}
|
||||
transfer(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
from_account_index,
|
||||
to_account_index,
|
||||
lamports,
|
||||
)
|
||||
transfer(from, to, lamports, invoke_context)
|
||||
}
|
||||
|
||||
fn transfer_verified(
|
||||
invoke_context: &InvokeContext,
|
||||
instruction_context: &InstructionContext,
|
||||
from_account_index: usize,
|
||||
to_account_index: usize,
|
||||
from: &KeyedAccount,
|
||||
to: &KeyedAccount,
|
||||
lamports: u64,
|
||||
invoke_context: &InvokeContext,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut from_account = instruction_context
|
||||
.try_borrow_instruction_account(invoke_context.transaction_context, from_account_index)?;
|
||||
if !from_account.get_data().is_empty() {
|
||||
if !from.data_is_empty()? {
|
||||
ic_msg!(invoke_context, "Transfer: `from` must not carry data");
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
if lamports > from_account.get_lamports() {
|
||||
if lamports > from.lamports()? {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Transfer: insufficient lamports {}, need {}",
|
||||
from_account.get_lamports(),
|
||||
from.lamports()?,
|
||||
lamports
|
||||
);
|
||||
return Err(SystemError::ResultWithNegativeLamports.into());
|
||||
}
|
||||
from_account.checked_sub_lamports(lamports)?;
|
||||
drop(from_account);
|
||||
let mut to_account = instruction_context
|
||||
.try_borrow_instruction_account(invoke_context.transaction_context, to_account_index)?;
|
||||
to_account.checked_add_lamports(lamports)?;
|
||||
|
||||
from.try_account_ref_mut()?.checked_sub_lamports(lamports)?;
|
||||
to.try_account_ref_mut()?.checked_add_lamports(lamports)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn transfer(
|
||||
invoke_context: &InvokeContext,
|
||||
instruction_context: &InstructionContext,
|
||||
from_account_index: usize,
|
||||
to_account_index: usize,
|
||||
from: &KeyedAccount,
|
||||
to: &KeyedAccount,
|
||||
lamports: u64,
|
||||
invoke_context: &InvokeContext,
|
||||
) -> Result<(), InstructionError> {
|
||||
if !invoke_context
|
||||
.feature_set
|
||||
|
@ -230,38 +207,26 @@ fn transfer(
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
if !instruction_context
|
||||
.is_signer(instruction_context.get_number_of_program_accounts() + from_account_index)?
|
||||
{
|
||||
if from.signer_key().is_none() {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Transfer: `from` account {} must sign",
|
||||
instruction_context.get_instruction_account_key(
|
||||
invoke_context.transaction_context,
|
||||
from_account_index
|
||||
)?,
|
||||
from.unsigned_key()
|
||||
);
|
||||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
|
||||
transfer_verified(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
from_account_index,
|
||||
to_account_index,
|
||||
lamports,
|
||||
)
|
||||
transfer_verified(from, to, lamports, invoke_context)
|
||||
}
|
||||
|
||||
fn transfer_with_seed(
|
||||
invoke_context: &InvokeContext,
|
||||
instruction_context: &InstructionContext,
|
||||
from_account_index: usize,
|
||||
from_base_account_index: usize,
|
||||
to_account_index: usize,
|
||||
from: &KeyedAccount,
|
||||
from_base: &KeyedAccount,
|
||||
from_seed: &str,
|
||||
from_owner: &Pubkey,
|
||||
to: &KeyedAccount,
|
||||
lamports: u64,
|
||||
invoke_context: &InvokeContext,
|
||||
) -> Result<(), InstructionError> {
|
||||
if !invoke_context
|
||||
.feature_set
|
||||
|
@ -271,136 +236,61 @@ fn transfer_with_seed(
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
let from_base_key = instruction_context
|
||||
.get_instruction_account_key(invoke_context.transaction_context, from_base_account_index)?;
|
||||
if !instruction_context
|
||||
.is_signer(instruction_context.get_number_of_program_accounts() + from_base_account_index)?
|
||||
{
|
||||
if from_base.signer_key().is_none() {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Transfer: 'from' account {:?} must sign",
|
||||
from_base_key,
|
||||
from_base
|
||||
);
|
||||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
|
||||
let from_key = instruction_context
|
||||
.get_instruction_account_key(invoke_context.transaction_context, from_account_index)?;
|
||||
let address_from_seed = Pubkey::create_with_seed(from_base_key, from_seed, from_owner)?;
|
||||
if *from_key != address_from_seed {
|
||||
let address_from_seed =
|
||||
Pubkey::create_with_seed(from_base.unsigned_key(), from_seed, from_owner)?;
|
||||
if *from.unsigned_key() != address_from_seed {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Transfer: 'from' address {} does not match derived address {}",
|
||||
from_key,
|
||||
address_from_seed,
|
||||
from.unsigned_key(),
|
||||
address_from_seed
|
||||
);
|
||||
return Err(SystemError::AddressWithSeedMismatch.into());
|
||||
}
|
||||
|
||||
transfer_verified(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
from_account_index,
|
||||
to_account_index,
|
||||
lamports,
|
||||
)
|
||||
}
|
||||
|
||||
pub mod instruction_account_indices {
|
||||
pub enum CreateAccount {
|
||||
From = 0,
|
||||
To = 1,
|
||||
}
|
||||
|
||||
pub enum CreateAccountWithSeed {
|
||||
From = 0,
|
||||
To = 1,
|
||||
}
|
||||
|
||||
pub enum Assign {
|
||||
Account = 0,
|
||||
}
|
||||
|
||||
pub enum Transfer {
|
||||
From = 0,
|
||||
To = 1,
|
||||
}
|
||||
|
||||
pub enum TransferWithSeed {
|
||||
From = 0,
|
||||
Base = 1,
|
||||
To = 2,
|
||||
}
|
||||
|
||||
pub enum AdvanceNonceAccount {
|
||||
Nonce = 0,
|
||||
RecentBlockhashes = 1,
|
||||
}
|
||||
|
||||
pub enum WithdrawNonceAccount {
|
||||
From = 0,
|
||||
To = 1,
|
||||
RecentBlockhashes = 2,
|
||||
Rent = 3,
|
||||
}
|
||||
|
||||
pub enum InitializeNonceAccount {
|
||||
Nonce = 0,
|
||||
RecentBlockhashes = 1,
|
||||
Rent = 2,
|
||||
}
|
||||
|
||||
pub enum AuthorizeNonceAccount {
|
||||
Nonce = 0,
|
||||
}
|
||||
|
||||
pub enum Allocate {
|
||||
Account = 0,
|
||||
}
|
||||
|
||||
pub enum AllocateWithSeed {
|
||||
Account = 0,
|
||||
}
|
||||
|
||||
pub enum AssignWithSeed {
|
||||
Account = 0,
|
||||
}
|
||||
transfer_verified(from, to, lamports, invoke_context)
|
||||
}
|
||||
|
||||
pub fn process_instruction(
|
||||
_first_instruction_account: usize,
|
||||
first_instruction_account: usize,
|
||||
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,
|
||||
space,
|
||||
owner,
|
||||
} => {
|
||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||
let to_key = instruction_context.get_instruction_account_key(
|
||||
invoke_context.transaction_context,
|
||||
instruction_account_indices::CreateAccount::To as usize,
|
||||
)?;
|
||||
let to_address = Address::create(to_key, None, invoke_context)?;
|
||||
let from = keyed_account_at_index(keyed_accounts, first_instruction_account)?;
|
||||
let to = keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
||||
let to_address = Address::create(to.unsigned_key(), None, invoke_context)?;
|
||||
create_account(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
&signers,
|
||||
instruction_account_indices::CreateAccount::From as usize,
|
||||
instruction_account_indices::CreateAccount::To as usize,
|
||||
from,
|
||||
to,
|
||||
&to_address,
|
||||
lamports,
|
||||
space,
|
||||
&owner,
|
||||
&signers,
|
||||
invoke_context,
|
||||
)
|
||||
}
|
||||
SystemInstruction::CreateAccountWithSeed {
|
||||
|
@ -410,66 +300,59 @@ pub fn process_instruction(
|
|||
space,
|
||||
owner,
|
||||
} => {
|
||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||
let to_key = instruction_context.get_instruction_account_key(
|
||||
invoke_context.transaction_context,
|
||||
instruction_account_indices::CreateAccountWithSeed::To as usize,
|
||||
)?;
|
||||
let to_address = Address::create(to_key, Some((&base, &seed, &owner)), invoke_context)?;
|
||||
create_account(
|
||||
let from = keyed_account_at_index(keyed_accounts, first_instruction_account)?;
|
||||
let to = keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
||||
let to_address = Address::create(
|
||||
to.unsigned_key(),
|
||||
Some((&base, &seed, &owner)),
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
&signers,
|
||||
instruction_account_indices::CreateAccountWithSeed::From as usize,
|
||||
instruction_account_indices::CreateAccountWithSeed::To as usize,
|
||||
)?;
|
||||
create_account(
|
||||
from,
|
||||
to,
|
||||
&to_address,
|
||||
lamports,
|
||||
space,
|
||||
&owner,
|
||||
&signers,
|
||||
invoke_context,
|
||||
)
|
||||
}
|
||||
SystemInstruction::Assign { owner } => {
|
||||
let mut account = instruction_context.try_borrow_instruction_account(
|
||||
invoke_context.transaction_context,
|
||||
instruction_account_indices::Assign::Account as usize,
|
||||
)?;
|
||||
let address = Address::create(account.get_key(), None, invoke_context)?;
|
||||
assign(invoke_context, &signers, &mut account, &address, &owner)
|
||||
let keyed_account = keyed_account_at_index(keyed_accounts, first_instruction_account)?;
|
||||
let mut account = keyed_account.try_account_ref_mut()?;
|
||||
let address = Address::create(keyed_account.unsigned_key(), None, invoke_context)?;
|
||||
assign(&mut account, &address, &owner, &signers, invoke_context)
|
||||
}
|
||||
SystemInstruction::Transfer { lamports } => {
|
||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||
transfer(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::Transfer::From as usize,
|
||||
instruction_account_indices::Transfer::To as usize,
|
||||
lamports,
|
||||
)
|
||||
let from = keyed_account_at_index(keyed_accounts, first_instruction_account)?;
|
||||
let to = keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
||||
transfer(from, to, lamports, invoke_context)
|
||||
}
|
||||
SystemInstruction::TransferWithSeed {
|
||||
lamports,
|
||||
from_seed,
|
||||
from_owner,
|
||||
} => {
|
||||
instruction_context.check_number_of_instruction_accounts(3)?;
|
||||
let from = keyed_account_at_index(keyed_accounts, first_instruction_account)?;
|
||||
let base = keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
||||
let to = keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?;
|
||||
transfer_with_seed(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::TransferWithSeed::From as usize,
|
||||
instruction_account_indices::TransferWithSeed::Base as usize,
|
||||
instruction_account_indices::TransferWithSeed::To as usize,
|
||||
from,
|
||||
base,
|
||||
&from_seed,
|
||||
&from_owner,
|
||||
to,
|
||||
lamports,
|
||||
invoke_context,
|
||||
)
|
||||
}
|
||||
SystemInstruction::AdvanceNonceAccount => {
|
||||
instruction_context.check_number_of_instruction_accounts(1)?;
|
||||
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,
|
||||
instruction_account_indices::AdvanceNonceAccount::RecentBlockhashes as usize,
|
||||
)?;
|
||||
if recent_blockhashes.is_empty() {
|
||||
ic_msg!(
|
||||
|
@ -478,43 +361,28 @@ pub fn process_instruction(
|
|||
);
|
||||
return Err(NonceError::NoRecentBlockhashes.into());
|
||||
}
|
||||
advance_nonce_account(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
&signers,
|
||||
instruction_account_indices::AdvanceNonceAccount::Nonce as usize,
|
||||
)
|
||||
me.advance_nonce_account(&signers, invoke_context)
|
||||
}
|
||||
SystemInstruction::WithdrawNonceAccount(lamports) => {
|
||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||
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,
|
||||
instruction_account_indices::WithdrawNonceAccount::RecentBlockhashes as usize,
|
||||
)?;
|
||||
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,
|
||||
instruction_account_indices::WithdrawNonceAccount::Rent as usize,
|
||||
)?;
|
||||
withdraw_nonce_account(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
&signers,
|
||||
instruction_account_indices::WithdrawNonceAccount::From as usize,
|
||||
instruction_account_indices::WithdrawNonceAccount::To as usize,
|
||||
lamports,
|
||||
&rent,
|
||||
)
|
||||
me.withdraw_nonce_account(lamports, to, &rent, &signers, invoke_context)
|
||||
}
|
||||
SystemInstruction::InitializeNonceAccount(authorized) => {
|
||||
instruction_context.check_number_of_instruction_accounts(1)?;
|
||||
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,
|
||||
instruction_account_indices::InitializeNonceAccount::RecentBlockhashes as usize,
|
||||
)?;
|
||||
if recent_blockhashes.is_empty() {
|
||||
ic_msg!(
|
||||
|
@ -523,36 +391,21 @@ 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,
|
||||
instruction_account_indices::InitializeNonceAccount::Rent as usize,
|
||||
)?;
|
||||
initialize_nonce_account(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
instruction_account_indices::InitializeNonceAccount::Nonce as usize,
|
||||
&authorized,
|
||||
&rent,
|
||||
)
|
||||
me.initialize_nonce_account(&authorized, &rent, invoke_context)
|
||||
}
|
||||
SystemInstruction::AuthorizeNonceAccount(nonce_authority) => {
|
||||
instruction_context.check_number_of_instruction_accounts(1)?;
|
||||
authorize_nonce_account(
|
||||
invoke_context,
|
||||
instruction_context,
|
||||
&signers,
|
||||
instruction_account_indices::AuthorizeNonceAccount::Nonce as usize,
|
||||
&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 mut account = instruction_context.try_borrow_instruction_account(
|
||||
invoke_context.transaction_context,
|
||||
instruction_account_indices::Allocate::Account as usize,
|
||||
)?;
|
||||
let address = Address::create(account.get_key(), None, invoke_context)?;
|
||||
allocate(invoke_context, &signers, &mut account, &address, space)
|
||||
let keyed_account = keyed_account_at_index(keyed_accounts, first_instruction_account)?;
|
||||
let mut account = keyed_account.try_account_ref_mut()?;
|
||||
let address = Address::create(keyed_account.unsigned_key(), None, invoke_context)?;
|
||||
allocate(&mut account, &address, space, &signers, invoke_context)
|
||||
}
|
||||
SystemInstruction::AllocateWithSeed {
|
||||
base,
|
||||
|
@ -560,35 +413,31 @@ pub fn process_instruction(
|
|||
space,
|
||||
owner,
|
||||
} => {
|
||||
let mut account = instruction_context.try_borrow_instruction_account(
|
||||
invoke_context.transaction_context,
|
||||
instruction_account_indices::AllocateWithSeed::Account as usize,
|
||||
)?;
|
||||
let keyed_account = keyed_account_at_index(keyed_accounts, first_instruction_account)?;
|
||||
let mut account = keyed_account.try_account_ref_mut()?;
|
||||
let address = Address::create(
|
||||
account.get_key(),
|
||||
keyed_account.unsigned_key(),
|
||||
Some((&base, &seed, &owner)),
|
||||
invoke_context,
|
||||
)?;
|
||||
allocate_and_assign(
|
||||
invoke_context,
|
||||
&signers,
|
||||
&mut account,
|
||||
&address,
|
||||
space,
|
||||
&owner,
|
||||
&signers,
|
||||
invoke_context,
|
||||
)
|
||||
}
|
||||
SystemInstruction::AssignWithSeed { base, seed, owner } => {
|
||||
let mut account = instruction_context.try_borrow_instruction_account(
|
||||
invoke_context.transaction_context,
|
||||
instruction_account_indices::AssignWithSeed::Account as usize,
|
||||
)?;
|
||||
let keyed_account = keyed_account_at_index(keyed_accounts, first_instruction_account)?;
|
||||
let mut account = keyed_account.try_account_ref_mut()?;
|
||||
let address = Address::create(
|
||||
account.get_key(),
|
||||
keyed_account.unsigned_key(),
|
||||
Some((&base, &seed, &owner)),
|
||||
invoke_context,
|
||||
)?;
|
||||
assign(invoke_context, &signers, &mut account, &address, &owner)
|
||||
assign(&mut account, &address, &owner, &signers, invoke_context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue