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:
Alexander Meißner
2022-03-16 11:30:01 +01:00
committed by GitHub
parent 44ab660172
commit 584ac80b1e
7 changed files with 1211 additions and 1900 deletions

File diff suppressed because it is too large Load Diff

View File

@ -5,29 +5,33 @@ use {
bincode::deserialize, bincode::deserialize,
solana_program_runtime::{ic_msg, invoke_context::InvokeContext}, solana_program_runtime::{ic_msg, invoke_context::InvokeContext},
solana_sdk::{ 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, pubkey::Pubkey,
}, },
std::collections::BTreeSet, std::collections::BTreeSet,
}; };
pub fn process_instruction( pub fn process_instruction(
_first_instruction_account: usize, first_instruction_account: usize,
data: &[u8], data: &[u8],
invoke_context: &mut InvokeContext, invoke_context: &mut InvokeContext,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
let transaction_context = &invoke_context.transaction_context; let keyed_accounts = invoke_context.get_keyed_accounts()?;
let instruction_context = transaction_context.get_current_instruction_context()?;
let key_list: ConfigKeys = limited_deserialize(data)?; 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 current_data: ConfigKeys = {
let config_account = let config_account = config_keyed_account.try_account_ref_mut()?;
instruction_context.try_borrow_instruction_account(transaction_context, 0)?; if config_account.owner() != &crate::id() {
if config_account.get_owner() != &crate::id() {
return Err(InstructionError::InvalidAccountOwner); return Err(InstructionError::InvalidAccountOwner);
} }
deserialize(config_account.get_data()).map_err(|err| { deserialize(config_account.data()).map_err(|err| {
ic_msg!( ic_msg!(
invoke_context, invoke_context,
"Unable to deserialize config account: {}", "Unable to deserialize config account: {}",
@ -46,7 +50,7 @@ pub fn process_instruction(
if current_signer_keys.is_empty() { if current_signer_keys.is_empty() {
// Config account keypair must be a signer on account initialization, // Config account keypair must be a signer on account initialization,
// or when no signers specified in Config data // 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); return Err(InstructionError::MissingRequiredSignature);
} }
} }
@ -54,10 +58,9 @@ pub fn process_instruction(
let mut counter = 0; let mut counter = 0;
for (signer, _) in key_list.keys.iter().filter(|(_, is_signer)| *is_signer) { for (signer, _) in key_list.keys.iter().filter(|(_, is_signer)| *is_signer) {
counter += 1; counter += 1;
if signer != instruction_context.get_instruction_account_key(transaction_context, 0)? { if signer != config_keyed_account.unsigned_key() {
let is_signer = instruction_context let signer_account =
.is_signer(instruction_context.get_number_of_program_accounts() + counter) keyed_account_at_index(keyed_accounts, counter + 1).map_err(|_| {
.map_err(|_| {
ic_msg!( ic_msg!(
invoke_context, invoke_context,
"account {:?} is not in account list", "account {:?} is not in account list",
@ -65,7 +68,8 @@ pub fn process_instruction(
); );
InstructionError::MissingRequiredSignature InstructionError::MissingRequiredSignature
})?; })?;
if !is_signer { let signer_key = signer_account.signer_key();
if signer_key.is_none() {
ic_msg!( ic_msg!(
invoke_context, invoke_context,
"account {:?} signer_key().is_none()", "account {:?} signer_key().is_none()",
@ -73,9 +77,7 @@ pub fn process_instruction(
); );
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
} }
if instruction_context.get_instruction_account_key(transaction_context, counter)? if signer_key.unwrap() != signer {
!= signer
{
ic_msg!( ic_msg!(
invoke_context, invoke_context,
"account[{:?}].signer_key() does not match Config data)", "account[{:?}].signer_key() does not match Config data)",
@ -94,9 +96,7 @@ pub fn process_instruction(
); );
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
} }
} else if !instruction_context } else if config_keyed_account.signer_key().is_none() {
.is_signer(instruction_context.get_number_of_program_accounts())?
{
ic_msg!(invoke_context, "account[0].signer_key().is_none()"); ic_msg!(invoke_context, "account[0].signer_key().is_none()");
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
} }
@ -125,13 +125,15 @@ pub fn process_instruction(
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
} }
let mut config_account = if config_keyed_account.data_len()? < data.len() {
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
if config_account.get_data().len() < data.len() {
ic_msg!(invoke_context, "instruction data too large"); ic_msg!(invoke_context, "instruction data too large");
return Err(InstructionError::InvalidInstructionData); 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(()) Ok(())
} }
@ -144,7 +146,7 @@ mod tests {
serde_derive::{Deserialize, Serialize}, serde_derive::{Deserialize, Serialize},
solana_program_runtime::invoke_context::mock_process_instruction, solana_program_runtime::invoke_context::mock_process_instruction,
solana_sdk::{ solana_sdk::{
account::{AccountSharedData, ReadableAccount}, account::AccountSharedData,
instruction::AccountMeta, instruction::AccountMeta,
pubkey::Pubkey, pubkey::Pubkey,
signature::{Keypair, Signer}, signature::{Keypair, Signer},

View File

@ -7,12 +7,12 @@ use {
crate::{config, stake_state::StakeAccount}, crate::{config, stake_state::StakeAccount},
log::*, log::*,
solana_program_runtime::{ 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::{ solana_sdk::{
feature_set, feature_set,
instruction::InstructionError, instruction::InstructionError,
keyed_account::keyed_account_at_index, keyed_account::{get_signers, keyed_account_at_index},
program_utils::limited_deserialize, program_utils::limited_deserialize,
stake::{ stake::{
instruction::StakeInstruction, instruction::StakeInstruction,
@ -23,140 +23,46 @@ 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( pub fn process_instruction(
first_instruction_account: usize, first_instruction_account: usize,
data: &[u8], data: &[u8],
invoke_context: &mut InvokeContext, invoke_context: &mut InvokeContext,
) -> Result<(), InstructionError> { ) -> 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 keyed_accounts = invoke_context.get_keyed_accounts()?;
trace!("process_instruction: {:?}", data); trace!("process_instruction: {:?}", data);
trace!("keyed_accounts: {:?}", keyed_accounts);
let me = &keyed_account_at_index(keyed_accounts, first_instruction_account)?; let me = &keyed_account_at_index(keyed_accounts, first_instruction_account)?;
if me.owner()? != id() { if me.owner()? != id() {
return Err(InstructionError::InvalidAccountOwner); 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)? { match limited_deserialize(data)? {
StakeInstruction::Initialize(authorized, lockup) => { 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, invoke_context,
instruction_context,
instruction_account_indices::Initialize::Rent as usize,
)?; )?;
me.initialize(&authorized, &lockup, &rent) me.initialize(&authorized, &lockup, &rent)
} }
StakeInstruction::Authorize(authorized_pubkey, stake_authorize) => { StakeInstruction::Authorize(authorized_pubkey, stake_authorize) => {
instruction_context.check_number_of_instruction_accounts(3)?;
let require_custodian_for_locked_stake_authorize = invoke_context let require_custodian_for_locked_stake_authorize = invoke_context
.feature_set .feature_set
.is_active(&feature_set::require_custodian_for_locked_stake_authorize::id()); .is_active(&feature_set::require_custodian_for_locked_stake_authorize::id());
if require_custodian_for_locked_stake_authorize { 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, invoke_context,
instruction_context,
instruction_account_indices::Authorize::Clock as usize,
)?; )?;
let custodian = keyed_account_at_index( let _current_authority =
keyed_accounts, keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?;
first_instruction_account let custodian =
+ instruction_account_indices::Authorize::Custodian as usize, keyed_account_at_index(keyed_accounts, first_instruction_account + 3)
) .ok()
.ok() .map(|ka| ka.unsigned_key());
.map(|ka| ka.unsigned_key());
me.authorize( me.authorize(
&signers, &signers,
@ -178,29 +84,21 @@ pub fn process_instruction(
} }
} }
StakeInstruction::AuthorizeWithSeed(args) => { StakeInstruction::AuthorizeWithSeed(args) => {
instruction_context.check_number_of_instruction_accounts(2)?; let authority_base =
let authority_base = keyed_account_at_index( keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
keyed_accounts,
first_instruction_account
+ instruction_account_indices::AuthorizeWithSeed::AuthorityBase as usize,
)?;
let require_custodian_for_locked_stake_authorize = invoke_context let require_custodian_for_locked_stake_authorize = invoke_context
.feature_set .feature_set
.is_active(&feature_set::require_custodian_for_locked_stake_authorize::id()); .is_active(&feature_set::require_custodian_for_locked_stake_authorize::id());
if require_custodian_for_locked_stake_authorize { 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, invoke_context,
instruction_context,
instruction_account_indices::AuthorizeWithSeed::Clock as usize,
)?; )?;
let custodian = keyed_account_at_index( let custodian =
keyed_accounts, keyed_account_at_index(keyed_accounts, first_instruction_account + 3)
first_instruction_account .ok()
+ instruction_account_indices::AuthorizeWithSeed::Custodian as usize, .map(|ka| ka.unsigned_key());
)
.ok()
.map(|ka| ka.unsigned_key());
me.authorize_with_seed( me.authorize_with_seed(
authority_base, authority_base,
@ -226,28 +124,17 @@ pub fn process_instruction(
} }
} }
StakeInstruction::DelegateStake => { StakeInstruction::DelegateStake => {
instruction_context.check_number_of_instruction_accounts(2)?; let vote = keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
let vote = keyed_account_at_index( let clock = get_sysvar_with_account_check::clock(
keyed_accounts, keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?,
first_instruction_account
+ instruction_account_indices::DelegateStake::VoteAccount as usize,
)?;
let clock = get_sysvar_with_account_check2::clock(
invoke_context, 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, 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()) { if !config::check_id(config_account.unsigned_key()) {
return Err(InstructionError::InvalidArgument); return Err(InstructionError::InvalidArgument);
} }
@ -256,28 +143,20 @@ pub fn process_instruction(
me.delegate(vote, &clock, &stake_history, &config, &signers) me.delegate(vote, &clock, &stake_history, &config, &signers)
} }
StakeInstruction::Split(lamports) => { StakeInstruction::Split(lamports) => {
instruction_context.check_number_of_instruction_accounts(2)?; let split_stake =
let split_stake = &keyed_account_at_index( &keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
keyed_accounts,
first_instruction_account + instruction_account_indices::Split::SplitTo as usize,
)?;
me.split(lamports, split_stake, &signers) me.split(lamports, split_stake, &signers)
} }
StakeInstruction::Merge => { StakeInstruction::Merge => {
instruction_context.check_number_of_instruction_accounts(2)?; let source_stake =
let source_stake = &keyed_account_at_index( &keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
keyed_accounts, let clock = get_sysvar_with_account_check::clock(
first_instruction_account + instruction_account_indices::Merge::MergeFrom as usize, keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?,
)?;
let clock = get_sysvar_with_account_check2::clock(
invoke_context, 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, invoke_context,
instruction_context,
instruction_account_indices::Merge::StakeHistory as usize,
)?; )?;
me.merge( me.merge(
invoke_context, invoke_context,
@ -288,46 +167,28 @@ pub fn process_instruction(
) )
} }
StakeInstruction::Withdraw(lamports) => { StakeInstruction::Withdraw(lamports) => {
instruction_context.check_number_of_instruction_accounts(2)?; let to = &keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
let to = &keyed_account_at_index( let clock = get_sysvar_with_account_check::clock(
keyed_accounts, keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?,
first_instruction_account
+ instruction_account_indices::Withdraw::Recipient as usize,
)?;
let clock = get_sysvar_with_account_check2::clock(
invoke_context, 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, invoke_context,
instruction_context,
instruction_account_indices::Withdraw::StakeHistory as usize,
)?; )?;
instruction_context.check_number_of_instruction_accounts(5)?;
me.withdraw( me.withdraw(
lamports, lamports,
to, to,
&clock, &clock,
&stake_history, &stake_history,
keyed_account_at_index( keyed_account_at_index(keyed_accounts, first_instruction_account + 4)?,
keyed_accounts, keyed_account_at_index(keyed_accounts, first_instruction_account + 5).ok(),
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(),
) )
} }
StakeInstruction::Deactivate => { 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, invoke_context,
instruction_context,
instruction_account_indices::Deactivate::Clock as usize,
)?; )?;
me.deactivate(&clock, &signers) me.deactivate(&clock, &signers)
} }
@ -340,29 +201,20 @@ pub fn process_instruction(
.feature_set .feature_set
.is_active(&feature_set::vote_stake_checked_instructions::id()) .is_active(&feature_set::vote_stake_checked_instructions::id())
{ {
instruction_context.check_number_of_instruction_accounts(4)?;
let authorized = Authorized { let authorized = Authorized {
staker: *keyed_account_at_index( staker: *keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?
keyed_accounts, .unsigned_key(),
first_instruction_account
+ instruction_account_indices::InitializeChecked::AuthorizedStaker
as usize,
)?
.unsigned_key(),
withdrawer: *keyed_account_at_index( withdrawer: *keyed_account_at_index(
keyed_accounts, keyed_accounts,
first_instruction_account first_instruction_account + 3,
+ instruction_account_indices::InitializeChecked::AuthorizedWithdrawer
as usize,
)? )?
.signer_key() .signer_key()
.ok_or(InstructionError::MissingRequiredSignature)?, .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, invoke_context,
instruction_context,
instruction_account_indices::InitializeChecked::Rent as usize,
)?; )?;
me.initialize(&authorized, &Lockup::default(), &rent) me.initialize(&authorized, &Lockup::default(), &rent)
} else { } else {
@ -374,26 +226,20 @@ pub fn process_instruction(
.feature_set .feature_set
.is_active(&feature_set::vote_stake_checked_instructions::id()) .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, invoke_context,
instruction_context,
instruction_account_indices::AuthorizeChecked::Clock as usize,
)?; )?;
instruction_context.check_number_of_instruction_accounts(4)?; let _current_authority =
let authorized_pubkey = &keyed_account_at_index( keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?;
keyed_accounts, let authorized_pubkey =
first_instruction_account &keyed_account_at_index(keyed_accounts, first_instruction_account + 3)?
+ instruction_account_indices::AuthorizeChecked::Authorized as usize, .signer_key()
)? .ok_or(InstructionError::MissingRequiredSignature)?;
.signer_key() let custodian =
.ok_or(InstructionError::MissingRequiredSignature)?; keyed_account_at_index(keyed_accounts, first_instruction_account + 4)
let custodian = keyed_account_at_index( .ok()
keyed_accounts, .map(|ka| ka.unsigned_key());
first_instruction_account
+ instruction_account_indices::AuthorizeChecked::Custodian as usize,
)
.ok()
.map(|ka| ka.unsigned_key());
me.authorize( me.authorize(
&signers, &signers,
@ -412,34 +258,20 @@ pub fn process_instruction(
.feature_set .feature_set
.is_active(&feature_set::vote_stake_checked_instructions::id()) .is_active(&feature_set::vote_stake_checked_instructions::id())
{ {
instruction_context.check_number_of_instruction_accounts(2)?; let authority_base =
let authority_base = keyed_account_at_index( keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
keyed_accounts, let clock = get_sysvar_with_account_check::clock(
first_instruction_account keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?,
+ instruction_account_indices::AuthorizeCheckedWithSeed::AuthorityBase
as usize,
)?;
let clock = get_sysvar_with_account_check2::clock(
invoke_context, invoke_context,
instruction_context,
instruction_account_indices::AuthorizeCheckedWithSeed::Clock as usize,
)?; )?;
instruction_context.check_number_of_instruction_accounts(4)?; let authorized_pubkey =
let authorized_pubkey = &keyed_account_at_index( &keyed_account_at_index(keyed_accounts, first_instruction_account + 3)?
keyed_accounts, .signer_key()
first_instruction_account .ok_or(InstructionError::MissingRequiredSignature)?;
+ instruction_account_indices::AuthorizeCheckedWithSeed::Authorized let custodian =
as usize, keyed_account_at_index(keyed_accounts, first_instruction_account + 4)
)? .ok()
.signer_key() .map(|ka| ka.unsigned_key());
.ok_or(InstructionError::MissingRequiredSignature)?;
let custodian = keyed_account_at_index(
keyed_accounts,
first_instruction_account
+ instruction_account_indices::AuthorizeCheckedWithSeed::Custodian as usize,
)
.ok()
.map(|ka| ka.unsigned_key());
me.authorize_with_seed( me.authorize_with_seed(
authority_base, authority_base,
@ -460,11 +292,9 @@ pub fn process_instruction(
.feature_set .feature_set
.is_active(&feature_set::vote_stake_checked_instructions::id()) .is_active(&feature_set::vote_stake_checked_instructions::id())
{ {
let custodian = if let Ok(custodian) = keyed_account_at_index( let custodian = if let Ok(custodian) =
keyed_accounts, keyed_account_at_index(keyed_accounts, first_instruction_account + 2)
first_instruction_account {
+ instruction_account_indices::SetLockupChecked::Custodian as usize,
) {
Some( Some(
*custodian *custodian
.signer_key() .signer_key()

View File

@ -5,157 +5,87 @@ use {
log::*, log::*,
solana_metrics::inc_new_counter_info, solana_metrics::inc_new_counter_info,
solana_program_runtime::{ 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( pub fn process_instruction(
_first_instruction_account: usize, first_instruction_account: usize,
data: &[u8], data: &[u8],
invoke_context: &mut InvokeContext, invoke_context: &mut InvokeContext,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
let transaction_context = &invoke_context.transaction_context; let keyed_accounts = invoke_context.get_keyed_accounts()?;
let instruction_context = transaction_context.get_current_instruction_context()?;
trace!("process_instruction: {:?}", data); trace!("process_instruction: {:?}", data);
trace!("keyed_accounts: {:?}", keyed_accounts);
{ let me = &mut keyed_account_at_index(keyed_accounts, first_instruction_account)?;
let vote_account = if me.owner()? != id() {
instruction_context.try_borrow_instruction_account(transaction_context, 0)?; return Err(InstructionError::InvalidAccountOwner);
if vote_account.get_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)? { match limited_deserialize(data)? {
VoteInstruction::InitializeAccount(vote_init) => { 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, invoke_context,
instruction_context,
instruction_account_indices::InitializeAccount::Rent as usize,
)?; )?;
{ verify_rent_exemption(me, &rent)?;
// Verify rent exemption let clock = get_sysvar_with_account_check::clock(
let vote_account = instruction_context.try_borrow_instruction_account( keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?,
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(
invoke_context, invoke_context,
instruction_context,
instruction_account_indices::InitializeAccount::Clock as usize,
)?; )?;
vote_state::initialize_account( vote_state::initialize_account(me, &vote_init, &signers, &clock)
invoke_context,
instruction_context,
&signers,
instruction_account_indices::InitializeAccount::VoteAccount as usize,
&vote_init,
)
} }
VoteInstruction::Authorize(voter_pubkey, vote_authorize) => { 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, invoke_context,
instruction_context,
instruction_account_indices::Authorize::Clock as usize,
)?; )?;
vote_state::authorize( vote_state::authorize(
invoke_context, me,
instruction_context,
&signers,
instruction_account_indices::Authorize::VoteAccount as usize,
&voter_pubkey, &voter_pubkey,
vote_authorize, vote_authorize,
)
}
VoteInstruction::UpdateValidatorIdentity => {
instruction_context.check_number_of_instruction_accounts(2)?;
vote_state::update_validator_identity(
invoke_context,
instruction_context,
&signers, &signers,
instruction_account_indices::UpdateValidatorIdentity::VoteAccount as usize, &clock,
instruction_context.get_instruction_account_key( &invoke_context.feature_set,
transaction_context,
instruction_account_indices::UpdateValidatorIdentity::Node as usize,
)?,
) )
} }
VoteInstruction::UpdateCommission(commission) => vote_state::update_commission( VoteInstruction::UpdateValidatorIdentity => vote_state::update_validator_identity(
invoke_context, me,
instruction_context, keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?.unsigned_key(),
&signers, &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, _) => { VoteInstruction::Vote(vote) | VoteInstruction::VoteSwitch(vote, _) => {
inc_new_counter_info!("vote-native", 1); 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, 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, invoke_context,
instruction_context,
instruction_account_indices::Vote::Clock as usize,
)?; )?;
vote_state::process_vote( vote_state::process_vote(
invoke_context, me,
instruction_context, &slot_hashes,
&signers, &clock,
instruction_account_indices::Vote::VoteAccount as usize,
&vote, &vote,
&signers,
&invoke_context.feature_set,
) )
} }
VoteInstruction::UpdateVoteState(vote_state_update) 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()) .is_active(&feature_set::allow_votes_to_directly_update_vote_state::id())
{ {
inc_new_counter_info!("vote-state-native", 1); 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( vote_state::process_vote_state_update(
invoke_context, me,
instruction_context, slot_hashes.slot_hashes(),
&signers, &clock,
instruction_account_indices::UpdateVoteState::VoteAccount as usize,
vote_state_update, vote_state_update,
&signers,
) )
} else { } else {
Err(InstructionError::InvalidInstructionData) Err(InstructionError::InvalidInstructionData)
} }
} }
VoteInstruction::Withdraw(lamports) => { 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( vote_state::withdraw(
invoke_context, me,
instruction_context,
&signers,
instruction_account_indices::Withdraw::VoteAccount as usize,
instruction_account_indices::Withdraw::Recipient as usize,
lamports, lamports,
to,
&signers,
rent_sysvar.as_deref(),
clock_if_feature_active.as_deref(),
) )
} }
VoteInstruction::AuthorizeChecked(vote_authorize) => { VoteInstruction::AuthorizeChecked(vote_authorize) => {
@ -192,28 +143,21 @@ pub fn process_instruction(
.feature_set .feature_set
.is_active(&feature_set::vote_stake_checked_instructions::id()) .is_active(&feature_set::vote_stake_checked_instructions::id())
{ {
instruction_context.check_number_of_instruction_accounts(4)?; let voter_pubkey =
if !instruction_context.is_signer( &keyed_account_at_index(keyed_accounts, first_instruction_account + 3)?
instruction_context.get_number_of_program_accounts() .signer_key()
+ instruction_account_indices::AuthorizeChecked::Voter as usize, .ok_or(InstructionError::MissingRequiredSignature)?;
)? { let clock = get_sysvar_with_account_check::clock(
return Err(InstructionError::MissingRequiredSignature); keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?,
}
let _clock = get_sysvar_with_account_check2::clock(
invoke_context, invoke_context,
instruction_context,
instruction_account_indices::AuthorizeChecked::Clock as usize,
)?; )?;
vote_state::authorize( vote_state::authorize(
invoke_context, me,
instruction_context, voter_pubkey,
&signers,
instruction_account_indices::AuthorizeChecked::VoteAccount as usize,
instruction_context.get_instruction_account_key(
transaction_context,
instruction_account_indices::AuthorizeChecked::Voter as usize,
)?,
vote_authorize, vote_authorize,
&signers,
&clock,
&invoke_context.feature_set,
) )
} else { } else {
Err(InstructionError::InvalidInstructionData) 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)] #[cfg(test)]
mod tests { mod tests {
use { use {
@ -246,10 +201,9 @@ mod tests {
feature_set::FeatureSet, feature_set::FeatureSet,
hash::Hash, hash::Hash,
instruction::{AccountMeta, Instruction}, instruction::{AccountMeta, Instruction},
pubkey::Pubkey, sysvar::{self, clock::Clock, slot_hashes::SlotHashes},
sysvar::{self, clock::Clock, rent::Rent, slot_hashes::SlotHashes},
}, },
std::{collections::HashSet, str::FromStr}, std::str::FromStr,
}; };
fn create_default_account() -> AccountSharedData { fn create_default_account() -> AccountSharedData {

View File

@ -5,19 +5,19 @@ use {
bincode::{deserialize, serialize_into, serialized_size, ErrorKind}, bincode::{deserialize, serialize_into, serialized_size, ErrorKind},
log::*, log::*,
serde_derive::{Deserialize, Serialize}, serde_derive::{Deserialize, Serialize},
solana_program_runtime::invoke_context::InvokeContext,
solana_sdk::{ solana_sdk::{
account::{AccountSharedData, ReadableAccount, WritableAccount}, account::{AccountSharedData, ReadableAccount, WritableAccount},
account_utils::State,
clock::{Epoch, Slot, UnixTimestamp}, clock::{Epoch, Slot, UnixTimestamp},
epoch_schedule::MAX_LEADER_SCHEDULE_EPOCH_OFFSET, epoch_schedule::MAX_LEADER_SCHEDULE_EPOCH_OFFSET,
feature_set::{self, filter_votes_outside_slot_hashes, FeatureSet}, feature_set::{self, filter_votes_outside_slot_hashes, FeatureSet},
hash::Hash, hash::Hash,
instruction::InstructionError, instruction::InstructionError,
keyed_account::KeyedAccount,
pubkey::Pubkey, pubkey::Pubkey,
rent::Rent, rent::Rent,
slot_hashes::SlotHash, slot_hashes::SlotHash,
sysvar::clock::Clock, sysvar::clock::Clock,
transaction_context::{BorrowedAccount, InstructionContext},
}, },
std::{ std::{
cmp::Ordering, cmp::Ordering,
@ -1165,24 +1165,19 @@ impl VoteState {
/// but will implicitly withdraw authorization from the previously authorized /// but will implicitly withdraw authorization from the previously authorized
/// key /// key
pub fn authorize<S: std::hash::BuildHasher>( pub fn authorize<S: std::hash::BuildHasher>(
invoke_context: &InvokeContext, vote_account: &KeyedAccount,
instruction_context: &InstructionContext,
signers: &HashSet<Pubkey, S>,
vote_account_index: usize,
authorized: &Pubkey, authorized: &Pubkey,
vote_authorize: VoteAuthorize, vote_authorize: VoteAuthorize,
signers: &HashSet<Pubkey, S>,
clock: &Clock,
feature_set: &FeatureSet,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
let mut vote_account = instruction_context let mut vote_state: VoteState =
.try_borrow_instruction_account(invoke_context.transaction_context, vote_account_index)?; State::<VoteStateVersions>::state(vote_account)?.convert_to_current();
let clock = invoke_context.get_sysvar_cache().get_clock()?;
let mut vote_state: VoteState = vote_account
.get_state::<VoteStateVersions>()?
.convert_to_current();
match vote_authorize { match vote_authorize {
VoteAuthorize::Voter => { VoteAuthorize::Voter => {
let authorized_withdrawer_signer = if invoke_context let authorized_withdrawer_signer = if feature_set
.feature_set
.is_active(&feature_set::vote_withdraw_authority_may_change_authorized_voter::id()) .is_active(&feature_set::vote_withdraw_authority_may_change_authorized_voter::id())
{ {
verify_authorized_signer(&vote_state.authorized_withdrawer, signers).is_ok() 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 /// Update the node_pubkey, requires signature of the authorized voter
pub fn update_validator_identity<S: std::hash::BuildHasher>( pub fn update_validator_identity<S: std::hash::BuildHasher>(
invoke_context: &InvokeContext, vote_account: &KeyedAccount,
instruction_context: &InstructionContext,
signers: &HashSet<Pubkey, S>,
vote_account_index: usize,
node_pubkey: &Pubkey, node_pubkey: &Pubkey,
signers: &HashSet<Pubkey, S>,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
let mut vote_account = instruction_context let mut vote_state: VoteState =
.try_borrow_instruction_account(invoke_context.transaction_context, vote_account_index)?; State::<VoteStateVersions>::state(vote_account)?.convert_to_current();
let mut vote_state: VoteState = vote_account
.get_state::<VoteStateVersions>()?
.convert_to_current();
// current authorized withdrawer must say "yay" // current authorized withdrawer must say "yay"
verify_authorized_signer(&vote_state.authorized_withdrawer, signers)?; 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 /// Update the vote account's commission
pub fn update_commission<S: std::hash::BuildHasher>( pub fn update_commission<S: std::hash::BuildHasher>(
invoke_context: &InvokeContext, vote_account: &KeyedAccount,
instruction_context: &InstructionContext,
signers: &HashSet<Pubkey, S>,
vote_account_index: usize,
commission: u8, commission: u8,
signers: &HashSet<Pubkey, S>,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
let mut vote_account = instruction_context let mut vote_state: VoteState =
.try_borrow_instruction_account(invoke_context.transaction_context, vote_account_index)?; State::<VoteStateVersions>::state(vote_account)?.convert_to_current();
let mut vote_state: VoteState = vote_account
.get_state::<VoteStateVersions>()?
.convert_to_current();
// current authorized withdrawer must say "yay" // current authorized withdrawer must say "yay"
verify_authorized_signer(&vote_state.authorized_withdrawer, signers)?; 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 /// Withdraw funds from the vote account
pub fn withdraw<S: std::hash::BuildHasher>( pub fn withdraw<S: std::hash::BuildHasher>(
invoke_context: &InvokeContext, vote_account: &KeyedAccount,
instruction_context: &InstructionContext,
signers: &HashSet<Pubkey, S>,
vote_account_index: usize,
recipient_account_index: usize,
lamports: u64, lamports: u64,
to_account: &KeyedAccount,
signers: &HashSet<Pubkey, S>,
rent_sysvar: Option<&Rent>,
clock: Option<&Clock>,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
let mut vote_account = instruction_context let vote_state: VoteState =
.try_borrow_instruction_account(invoke_context.transaction_context, vote_account_index)?; State::<VoteStateVersions>::state(vote_account)?.convert_to_current();
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();
verify_authorized_signer(&vote_state.authorized_withdrawer, signers)?; verify_authorized_signer(&vote_state.authorized_withdrawer, signers)?;
let remaining_balance = vote_account let remaining_balance = vote_account
.get_lamports() .lamports()?
.checked_sub(lamports) .checked_sub(lamports)
.ok_or(InstructionError::InsufficientFunds)?; .ok_or(InstructionError::InsufficientFunds)?;
@ -1332,19 +1295,18 @@ pub fn withdraw<S: std::hash::BuildHasher>(
vote_account.set_state(&VoteStateVersions::new_current(VoteState::default()))?; vote_account.set_state(&VoteStateVersions::new_current(VoteState::default()))?;
} }
} else if let Some(rent_sysvar) = rent_sysvar { } 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 { if remaining_balance < min_rent_exempt_balance {
return Err(InstructionError::InsufficientFunds); return Err(InstructionError::InsufficientFunds);
} }
} }
vote_account.checked_sub_lamports(lamports)?; vote_account
drop(vote_account); .try_account_ref_mut()?
let mut recipient_account = instruction_context.try_borrow_instruction_account( .checked_sub_lamports(lamports)?;
invoke_context.transaction_context, to_account
recipient_account_index, .try_account_ref_mut()?
)?; .checked_add_lamports(lamports)?;
recipient_account.checked_add_lamports(lamports)?;
Ok(()) 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 /// 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 /// that the transaction must be signed by the staker's keys
pub fn initialize_account<S: std::hash::BuildHasher>( pub fn initialize_account<S: std::hash::BuildHasher>(
invoke_context: &InvokeContext, vote_account: &KeyedAccount,
instruction_context: &InstructionContext,
signers: &HashSet<Pubkey, S>,
vote_account_index: usize,
vote_init: &VoteInit, vote_init: &VoteInit,
signers: &HashSet<Pubkey, S>,
clock: &Clock,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
let mut vote_account = instruction_context if vote_account.data_len()? != VoteState::size_of() {
.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() {
return Err(InstructionError::InvalidAccountData); return Err(InstructionError::InvalidAccountData);
} }
let versioned = vote_account.get_state::<VoteStateVersions>()?; let versioned = State::<VoteStateVersions>::state(vote_account)?;
if !versioned.is_uninitialized() { if !versioned.is_uninitialized() {
return Err(InstructionError::AccountAlreadyInitialized); return Err(InstructionError::AccountAlreadyInitialized);
@ -1374,16 +1332,16 @@ pub fn initialize_account<S: std::hash::BuildHasher>(
verify_authorized_signer(&vote_init.node_pubkey, signers)?; verify_authorized_signer(&vote_init.node_pubkey, signers)?;
vote_account.set_state(&VoteStateVersions::new_current(VoteState::new( 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>( fn verify_and_get_vote_state<S: std::hash::BuildHasher>(
vote_account: &BorrowedAccount, vote_account: &KeyedAccount,
clock: &Clock, clock: &Clock,
signers: &HashSet<Pubkey, S>, signers: &HashSet<Pubkey, S>,
) -> Result<VoteState, InstructionError> { ) -> Result<VoteState, InstructionError> {
let versioned = vote_account.get_state::<VoteStateVersions>()?; let versioned = State::<VoteStateVersions>::state(vote_account)?;
if versioned.is_uninitialized() { if versioned.is_uninitialized() {
return Err(InstructionError::UninitializedAccount); 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>( pub fn process_vote<S: std::hash::BuildHasher>(
invoke_context: &InvokeContext, vote_account: &KeyedAccount,
instruction_context: &InstructionContext, slot_hashes: &[SlotHash],
signers: &HashSet<Pubkey, S>, clock: &Clock,
vote_account_index: usize,
vote: &Vote, vote: &Vote,
signers: &HashSet<Pubkey, S>,
feature_set: &FeatureSet,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
let mut vote_account = instruction_context let mut vote_state = verify_and_get_vote_state(vote_account, clock, signers)?;
.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.process_vote( vote_state.process_vote(vote, slot_hashes, clock.epoch, Some(feature_set))?;
vote,
slot_hashes.slot_hashes(),
clock.epoch,
Some(&invoke_context.feature_set),
)?;
if let Some(timestamp) = vote.timestamp { if let Some(timestamp) = vote.timestamp {
vote.slots vote.slots
.iter() .iter()
@ -1427,19 +1376,14 @@ pub fn process_vote<S: std::hash::BuildHasher>(
} }
pub fn process_vote_state_update<S: std::hash::BuildHasher>( pub fn process_vote_state_update<S: std::hash::BuildHasher>(
invoke_context: &InvokeContext, vote_account: &KeyedAccount,
instruction_context: &InstructionContext, slot_hashes: &[SlotHash],
signers: &HashSet<Pubkey, S>, clock: &Clock,
vote_account_index: usize,
mut vote_state_update: VoteStateUpdate, mut vote_state_update: VoteStateUpdate,
signers: &HashSet<Pubkey, S>,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
let mut vote_account = instruction_context let mut vote_state = verify_and_get_vote_state(vote_account, clock, signers)?;
.try_borrow_instruction_account(invoke_context.transaction_context, vote_account_index)?; vote_state.check_update_vote_state_slots_are_valid(&mut vote_state_update, slot_hashes)?;
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)?;
vote_state.process_new_vote_state( vote_state.process_new_vote_state(
vote_state_update.lockouts, vote_state_update.lockouts,
vote_state_update.root, vote_state_update.root,

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,15 @@
use { use {
crate::nonce_keyed_account::{ crate::nonce_keyed_account::NonceKeyedAccount,
advance_nonce_account, authorize_nonce_account, initialize_nonce_account,
withdraw_nonce_account,
},
log::*, log::*,
solana_program_runtime::{ 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::{ solana_sdk::{
account::{AccountSharedData, ReadableAccount}, account::{AccountSharedData, ReadableAccount, WritableAccount},
account_utils::StateMut, account_utils::StateMut,
feature_set, feature_set,
instruction::InstructionError, instruction::InstructionError,
keyed_account::{get_signers, keyed_account_at_index, KeyedAccount},
nonce, nonce,
program_utils::limited_deserialize, program_utils::limited_deserialize,
pubkey::Pubkey, pubkey::Pubkey,
@ -19,7 +17,6 @@ use {
NonceError, SystemError, SystemInstruction, MAX_PERMITTED_DATA_LENGTH, NonceError, SystemError, SystemInstruction, MAX_PERMITTED_DATA_LENGTH,
}, },
system_program, system_program,
transaction_context::{BorrowedAccount, InstructionContext},
}, },
std::collections::HashSet, std::collections::HashSet,
}; };
@ -70,11 +67,11 @@ impl Address {
} }
fn allocate( fn allocate(
invoke_context: &InvokeContext, account: &mut AccountSharedData,
signers: &HashSet<Pubkey>,
account: &mut BorrowedAccount,
address: &Address, address: &Address,
space: u64, space: u64,
signers: &HashSet<Pubkey>,
invoke_context: &InvokeContext,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
if !address.is_signer(signers) { if !address.is_signer(signers) {
ic_msg!( ic_msg!(
@ -87,7 +84,7 @@ fn allocate(
// if it looks like the `to` account is already in use, bail // if it looks like the `to` account is already in use, bail
// (note that the id check is also enforced by message_processor) // (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!( ic_msg!(
invoke_context, invoke_context,
"Allocate: account {:?} already in use", "Allocate: account {:?} already in use",
@ -106,20 +103,20 @@ fn allocate(
return Err(SystemError::InvalidAccountDataLength.into()); return Err(SystemError::InvalidAccountDataLength.into());
} }
account.set_data(vec![0; space as usize].as_slice()); account.set_data(vec![0; space as usize]);
Ok(()) Ok(())
} }
fn assign( fn assign(
invoke_context: &InvokeContext, account: &mut AccountSharedData,
signers: &HashSet<Pubkey>,
account: &mut BorrowedAccount,
address: &Address, address: &Address,
owner: &Pubkey, owner: &Pubkey,
signers: &HashSet<Pubkey>,
invoke_context: &InvokeContext,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
// no work to do, just return // no work to do, just return
if account.get_owner() == owner { if account.owner() == owner {
return Ok(()); return Ok(());
} }
@ -128,38 +125,36 @@ fn assign(
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
} }
account.set_owner(&owner.to_bytes()); account.set_owner(*owner);
Ok(()) Ok(())
} }
fn allocate_and_assign( fn allocate_and_assign(
invoke_context: &InvokeContext, to: &mut AccountSharedData,
signers: &HashSet<Pubkey>,
to_account: &mut BorrowedAccount,
to_address: &Address, to_address: &Address,
space: u64, space: u64,
owner: &Pubkey, owner: &Pubkey,
signers: &HashSet<Pubkey>,
invoke_context: &InvokeContext,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
allocate(invoke_context, signers, to_account, to_address, space)?; allocate(to, to_address, space, signers, invoke_context)?;
assign(invoke_context, signers, to_account, to_address, owner) assign(to, to_address, owner, signers, invoke_context)
} }
fn create_account( fn create_account(
invoke_context: &InvokeContext, from: &KeyedAccount,
instruction_context: &InstructionContext, to: &KeyedAccount,
signers: &HashSet<Pubkey>,
from_account_index: usize,
to_account_index: usize,
to_address: &Address, to_address: &Address,
lamports: u64, lamports: u64,
space: u64, space: u64,
owner: &Pubkey, owner: &Pubkey,
signers: &HashSet<Pubkey>,
invoke_context: &InvokeContext,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
// if it looks like the `to` account is already in use, bail // if it looks like the `to` account is already in use, bail
{ {
let mut to_account = instruction_context let to = &mut to.try_account_ref_mut()?;
.try_borrow_instruction_account(invoke_context.transaction_context, to_account_index)?; if to.lamports() > 0 {
if to_account.get_lamports() > 0 {
ic_msg!( ic_msg!(
invoke_context, invoke_context,
"Create Account: account {:?} already in use", "Create Account: account {:?} already in use",
@ -167,60 +162,42 @@ fn create_account(
); );
return Err(SystemError::AccountAlreadyInUse.into()); return Err(SystemError::AccountAlreadyInUse.into());
} }
allocate_and_assign(
invoke_context, allocate_and_assign(to, to_address, space, owner, signers, invoke_context)?;
signers,
&mut to_account,
to_address,
space,
owner,
)?;
} }
transfer( transfer(from, to, lamports, invoke_context)
invoke_context,
instruction_context,
from_account_index,
to_account_index,
lamports,
)
} }
fn transfer_verified( fn transfer_verified(
invoke_context: &InvokeContext, from: &KeyedAccount,
instruction_context: &InstructionContext, to: &KeyedAccount,
from_account_index: usize,
to_account_index: usize,
lamports: u64, lamports: u64,
invoke_context: &InvokeContext,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
let mut from_account = instruction_context if !from.data_is_empty()? {
.try_borrow_instruction_account(invoke_context.transaction_context, from_account_index)?;
if !from_account.get_data().is_empty() {
ic_msg!(invoke_context, "Transfer: `from` must not carry data"); ic_msg!(invoke_context, "Transfer: `from` must not carry data");
return Err(InstructionError::InvalidArgument); return Err(InstructionError::InvalidArgument);
} }
if lamports > from_account.get_lamports() { if lamports > from.lamports()? {
ic_msg!( ic_msg!(
invoke_context, invoke_context,
"Transfer: insufficient lamports {}, need {}", "Transfer: insufficient lamports {}, need {}",
from_account.get_lamports(), from.lamports()?,
lamports lamports
); );
return Err(SystemError::ResultWithNegativeLamports.into()); return Err(SystemError::ResultWithNegativeLamports.into());
} }
from_account.checked_sub_lamports(lamports)?;
drop(from_account); from.try_account_ref_mut()?.checked_sub_lamports(lamports)?;
let mut to_account = instruction_context to.try_account_ref_mut()?.checked_add_lamports(lamports)?;
.try_borrow_instruction_account(invoke_context.transaction_context, to_account_index)?;
to_account.checked_add_lamports(lamports)?;
Ok(()) Ok(())
} }
fn transfer( fn transfer(
invoke_context: &InvokeContext, from: &KeyedAccount,
instruction_context: &InstructionContext, to: &KeyedAccount,
from_account_index: usize,
to_account_index: usize,
lamports: u64, lamports: u64,
invoke_context: &InvokeContext,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
if !invoke_context if !invoke_context
.feature_set .feature_set
@ -230,38 +207,26 @@ fn transfer(
return Ok(()); return Ok(());
} }
if !instruction_context if from.signer_key().is_none() {
.is_signer(instruction_context.get_number_of_program_accounts() + from_account_index)?
{
ic_msg!( ic_msg!(
invoke_context, invoke_context,
"Transfer: `from` account {} must sign", "Transfer: `from` account {} must sign",
instruction_context.get_instruction_account_key( from.unsigned_key()
invoke_context.transaction_context,
from_account_index
)?,
); );
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
} }
transfer_verified( transfer_verified(from, to, lamports, invoke_context)
invoke_context,
instruction_context,
from_account_index,
to_account_index,
lamports,
)
} }
fn transfer_with_seed( fn transfer_with_seed(
invoke_context: &InvokeContext, from: &KeyedAccount,
instruction_context: &InstructionContext, from_base: &KeyedAccount,
from_account_index: usize,
from_base_account_index: usize,
to_account_index: usize,
from_seed: &str, from_seed: &str,
from_owner: &Pubkey, from_owner: &Pubkey,
to: &KeyedAccount,
lamports: u64, lamports: u64,
invoke_context: &InvokeContext,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
if !invoke_context if !invoke_context
.feature_set .feature_set
@ -271,136 +236,61 @@ fn transfer_with_seed(
return Ok(()); return Ok(());
} }
let from_base_key = instruction_context if from_base.signer_key().is_none() {
.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)?
{
ic_msg!( ic_msg!(
invoke_context, invoke_context,
"Transfer: 'from' account {:?} must sign", "Transfer: 'from' account {:?} must sign",
from_base_key, from_base
); );
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
} }
let from_key = instruction_context let address_from_seed =
.get_instruction_account_key(invoke_context.transaction_context, from_account_index)?; Pubkey::create_with_seed(from_base.unsigned_key(), from_seed, from_owner)?;
let address_from_seed = Pubkey::create_with_seed(from_base_key, from_seed, from_owner)?; if *from.unsigned_key() != address_from_seed {
if *from_key != address_from_seed {
ic_msg!( ic_msg!(
invoke_context, invoke_context,
"Transfer: 'from' address {} does not match derived address {}", "Transfer: 'from' address {} does not match derived address {}",
from_key, from.unsigned_key(),
address_from_seed, address_from_seed
); );
return Err(SystemError::AddressWithSeedMismatch.into()); return Err(SystemError::AddressWithSeedMismatch.into());
} }
transfer_verified( transfer_verified(from, to, lamports, invoke_context)
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,
}
} }
pub fn process_instruction( pub fn process_instruction(
_first_instruction_account: usize, first_instruction_account: usize,
instruction_data: &[u8], instruction_data: &[u8],
invoke_context: &mut InvokeContext, invoke_context: &mut InvokeContext,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
let transaction_context = &invoke_context.transaction_context; let keyed_accounts = invoke_context.get_keyed_accounts()?;
let instruction_context = transaction_context.get_current_instruction_context()?;
let instruction = limited_deserialize(instruction_data)?; let instruction = limited_deserialize(instruction_data)?;
trace!("process_instruction: {:?}", instruction); 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 { match instruction {
SystemInstruction::CreateAccount { SystemInstruction::CreateAccount {
lamports, lamports,
space, space,
owner, owner,
} => { } => {
instruction_context.check_number_of_instruction_accounts(2)?; let from = keyed_account_at_index(keyed_accounts, first_instruction_account)?;
let to_key = instruction_context.get_instruction_account_key( let to = keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
invoke_context.transaction_context, let to_address = Address::create(to.unsigned_key(), None, invoke_context)?;
instruction_account_indices::CreateAccount::To as usize,
)?;
let to_address = Address::create(to_key, None, invoke_context)?;
create_account( create_account(
invoke_context, from,
instruction_context, to,
&signers,
instruction_account_indices::CreateAccount::From as usize,
instruction_account_indices::CreateAccount::To as usize,
&to_address, &to_address,
lamports, lamports,
space, space,
&owner, &owner,
&signers,
invoke_context,
) )
} }
SystemInstruction::CreateAccountWithSeed { SystemInstruction::CreateAccountWithSeed {
@ -410,66 +300,59 @@ pub fn process_instruction(
space, space,
owner, owner,
} => { } => {
instruction_context.check_number_of_instruction_accounts(2)?; let from = keyed_account_at_index(keyed_accounts, first_instruction_account)?;
let to_key = instruction_context.get_instruction_account_key( let to = keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
invoke_context.transaction_context, let to_address = Address::create(
instruction_account_indices::CreateAccountWithSeed::To as usize, to.unsigned_key(),
)?; Some((&base, &seed, &owner)),
let to_address = Address::create(to_key, Some((&base, &seed, &owner)), invoke_context)?;
create_account(
invoke_context, invoke_context,
instruction_context, )?;
&signers, create_account(
instruction_account_indices::CreateAccountWithSeed::From as usize, from,
instruction_account_indices::CreateAccountWithSeed::To as usize, to,
&to_address, &to_address,
lamports, lamports,
space, space,
&owner, &owner,
&signers,
invoke_context,
) )
} }
SystemInstruction::Assign { owner } => { SystemInstruction::Assign { owner } => {
let mut account = instruction_context.try_borrow_instruction_account( let keyed_account = keyed_account_at_index(keyed_accounts, first_instruction_account)?;
invoke_context.transaction_context, let mut account = keyed_account.try_account_ref_mut()?;
instruction_account_indices::Assign::Account as usize, let address = Address::create(keyed_account.unsigned_key(), None, invoke_context)?;
)?; assign(&mut account, &address, &owner, &signers, invoke_context)
let address = Address::create(account.get_key(), None, invoke_context)?;
assign(invoke_context, &signers, &mut account, &address, &owner)
} }
SystemInstruction::Transfer { lamports } => { SystemInstruction::Transfer { lamports } => {
instruction_context.check_number_of_instruction_accounts(2)?; let from = keyed_account_at_index(keyed_accounts, first_instruction_account)?;
transfer( let to = keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
invoke_context, transfer(from, to, lamports, invoke_context)
instruction_context,
instruction_account_indices::Transfer::From as usize,
instruction_account_indices::Transfer::To as usize,
lamports,
)
} }
SystemInstruction::TransferWithSeed { SystemInstruction::TransferWithSeed {
lamports, lamports,
from_seed, from_seed,
from_owner, 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( transfer_with_seed(
invoke_context, from,
instruction_context, base,
instruction_account_indices::TransferWithSeed::From as usize,
instruction_account_indices::TransferWithSeed::Base as usize,
instruction_account_indices::TransferWithSeed::To as usize,
&from_seed, &from_seed,
&from_owner, &from_owner,
to,
lamports, lamports,
invoke_context,
) )
} }
SystemInstruction::AdvanceNonceAccount => { SystemInstruction::AdvanceNonceAccount => {
instruction_context.check_number_of_instruction_accounts(1)?; let me = &mut keyed_account_at_index(keyed_accounts, first_instruction_account)?;
#[allow(deprecated)] #[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, invoke_context,
instruction_context,
instruction_account_indices::AdvanceNonceAccount::RecentBlockhashes as usize,
)?; )?;
if recent_blockhashes.is_empty() { if recent_blockhashes.is_empty() {
ic_msg!( ic_msg!(
@ -478,43 +361,28 @@ pub fn process_instruction(
); );
return Err(NonceError::NoRecentBlockhashes.into()); return Err(NonceError::NoRecentBlockhashes.into());
} }
advance_nonce_account( me.advance_nonce_account(&signers, invoke_context)
invoke_context,
instruction_context,
&signers,
instruction_account_indices::AdvanceNonceAccount::Nonce as usize,
)
} }
SystemInstruction::WithdrawNonceAccount(lamports) => { 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)] #[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, 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, invoke_context,
instruction_context,
instruction_account_indices::WithdrawNonceAccount::Rent as usize,
)?; )?;
withdraw_nonce_account( me.withdraw_nonce_account(lamports, to, &rent, &signers, invoke_context)
invoke_context,
instruction_context,
&signers,
instruction_account_indices::WithdrawNonceAccount::From as usize,
instruction_account_indices::WithdrawNonceAccount::To as usize,
lamports,
&rent,
)
} }
SystemInstruction::InitializeNonceAccount(authorized) => { 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)] #[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, invoke_context,
instruction_context,
instruction_account_indices::InitializeNonceAccount::RecentBlockhashes as usize,
)?; )?;
if recent_blockhashes.is_empty() { if recent_blockhashes.is_empty() {
ic_msg!( ic_msg!(
@ -523,36 +391,21 @@ pub fn process_instruction(
); );
return Err(NonceError::NoRecentBlockhashes.into()); 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, invoke_context,
instruction_context,
instruction_account_indices::InitializeNonceAccount::Rent as usize,
)?; )?;
initialize_nonce_account( me.initialize_nonce_account(&authorized, &rent, invoke_context)
invoke_context,
instruction_context,
instruction_account_indices::InitializeNonceAccount::Nonce as usize,
&authorized,
&rent,
)
} }
SystemInstruction::AuthorizeNonceAccount(nonce_authority) => { SystemInstruction::AuthorizeNonceAccount(nonce_authority) => {
instruction_context.check_number_of_instruction_accounts(1)?; let me = &mut keyed_account_at_index(keyed_accounts, first_instruction_account)?;
authorize_nonce_account( me.authorize_nonce_account(&nonce_authority, &signers, invoke_context)
invoke_context,
instruction_context,
&signers,
instruction_account_indices::AuthorizeNonceAccount::Nonce as usize,
&nonce_authority,
)
} }
SystemInstruction::Allocate { space } => { SystemInstruction::Allocate { space } => {
let mut account = instruction_context.try_borrow_instruction_account( let keyed_account = keyed_account_at_index(keyed_accounts, first_instruction_account)?;
invoke_context.transaction_context, let mut account = keyed_account.try_account_ref_mut()?;
instruction_account_indices::Allocate::Account as usize, let address = Address::create(keyed_account.unsigned_key(), None, invoke_context)?;
)?; allocate(&mut account, &address, space, &signers, invoke_context)
let address = Address::create(account.get_key(), None, invoke_context)?;
allocate(invoke_context, &signers, &mut account, &address, space)
} }
SystemInstruction::AllocateWithSeed { SystemInstruction::AllocateWithSeed {
base, base,
@ -560,35 +413,31 @@ pub fn process_instruction(
space, space,
owner, owner,
} => { } => {
let mut account = instruction_context.try_borrow_instruction_account( let keyed_account = keyed_account_at_index(keyed_accounts, first_instruction_account)?;
invoke_context.transaction_context, let mut account = keyed_account.try_account_ref_mut()?;
instruction_account_indices::AllocateWithSeed::Account as usize,
)?;
let address = Address::create( let address = Address::create(
account.get_key(), keyed_account.unsigned_key(),
Some((&base, &seed, &owner)), Some((&base, &seed, &owner)),
invoke_context, invoke_context,
)?; )?;
allocate_and_assign( allocate_and_assign(
invoke_context,
&signers,
&mut account, &mut account,
&address, &address,
space, space,
&owner, &owner,
&signers,
invoke_context,
) )
} }
SystemInstruction::AssignWithSeed { base, seed, owner } => { SystemInstruction::AssignWithSeed { base, seed, owner } => {
let mut account = instruction_context.try_borrow_instruction_account( let keyed_account = keyed_account_at_index(keyed_accounts, first_instruction_account)?;
invoke_context.transaction_context, let mut account = keyed_account.try_account_ref_mut()?;
instruction_account_indices::AssignWithSeed::Account as usize,
)?;
let address = Address::create( let address = Address::create(
account.get_key(), keyed_account.unsigned_key(),
Some((&base, &seed, &owner)), Some((&base, &seed, &owner)),
invoke_context, invoke_context,
)?; )?;
assign(invoke_context, &signers, &mut account, &address, &owner) assign(&mut account, &address, &owner, &signers, invoke_context)
} }
} }
} }