Refactor: Remove KeyedAccounts (2) (#22274)
* Adds InstructionContext::get_signers(). Improves error messages when modifying borrowed accounts. * Removes keyed_accounts from InvokeContext tests. * Removes keyed_accounts from message_processor.rs * Removes keyed_accounts from bank.rs * Removes keyed_accounts from bpf serialization.
This commit is contained in:
committed by
GitHub
parent
c1995c647b
commit
9f63493789
@@ -6285,7 +6285,6 @@ pub(crate) mod tests {
|
||||
genesis_config::create_genesis_config,
|
||||
hash,
|
||||
instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
|
||||
keyed_account::keyed_account_at_index,
|
||||
message::{Message, MessageHeader},
|
||||
nonce,
|
||||
poh_config::PohConfig,
|
||||
@@ -6737,63 +6736,6 @@ pub(crate) mod tests {
|
||||
assert_eq!(bank_with_success_txs_hash, bank_hash);
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum MockInstruction {
|
||||
Deduction,
|
||||
}
|
||||
|
||||
fn mock_process_instruction(
|
||||
first_instruction_account: usize,
|
||||
data: &[u8],
|
||||
invoke_context: &mut InvokeContext,
|
||||
) -> result::Result<(), InstructionError> {
|
||||
let keyed_accounts = invoke_context.get_keyed_accounts()?;
|
||||
if let Ok(instruction) = bincode::deserialize(data) {
|
||||
match instruction {
|
||||
MockInstruction::Deduction => {
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?
|
||||
.account
|
||||
.borrow_mut()
|
||||
.checked_add_lamports(1)?;
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?
|
||||
.account
|
||||
.borrow_mut()
|
||||
.checked_sub_lamports(1)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(InstructionError::InvalidInstructionData)
|
||||
}
|
||||
}
|
||||
|
||||
fn create_mock_transaction(
|
||||
payer: &Keypair,
|
||||
keypair1: &Keypair,
|
||||
keypair2: &Keypair,
|
||||
read_only_keypair: &Keypair,
|
||||
mock_program_id: Pubkey,
|
||||
recent_blockhash: Hash,
|
||||
) -> Transaction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(payer.pubkey(), true),
|
||||
AccountMeta::new(keypair1.pubkey(), true),
|
||||
AccountMeta::new(keypair2.pubkey(), true),
|
||||
AccountMeta::new_readonly(read_only_keypair.pubkey(), false),
|
||||
];
|
||||
let deduct_instruction = Instruction::new_with_bincode(
|
||||
mock_program_id,
|
||||
&MockInstruction::Deduction,
|
||||
account_metas,
|
||||
);
|
||||
Transaction::new_signed_with_payer(
|
||||
&[deduct_instruction],
|
||||
Some(&payer.pubkey()),
|
||||
&[payer, keypair1, keypair2],
|
||||
recent_blockhash,
|
||||
)
|
||||
}
|
||||
|
||||
fn store_accounts_for_rent_test(
|
||||
bank: &Bank,
|
||||
keypairs: &mut Vec<Keypair>,
|
||||
@@ -6893,7 +6835,6 @@ pub(crate) mod tests {
|
||||
fn create_child_bank_for_rent_test(
|
||||
root_bank: &Arc<Bank>,
|
||||
genesis_config: &GenesisConfig,
|
||||
mock_program_id: Pubkey,
|
||||
) -> Bank {
|
||||
let mut bank = Bank::new_from_parent(
|
||||
root_bank,
|
||||
@@ -6905,8 +6846,6 @@ pub(crate) mod tests {
|
||||
) as u64,
|
||||
);
|
||||
bank.rent_collector.slots_per_year = 421_812.0;
|
||||
bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction);
|
||||
|
||||
bank
|
||||
}
|
||||
|
||||
@@ -7305,11 +7244,7 @@ pub(crate) mod tests {
|
||||
};
|
||||
|
||||
let root_bank = Arc::new(Bank::new_for_tests(&genesis_config));
|
||||
let bank = create_child_bank_for_rent_test(
|
||||
&root_bank,
|
||||
&genesis_config,
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
);
|
||||
let bank = create_child_bank_for_rent_test(&root_bank, &genesis_config);
|
||||
|
||||
let account_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let account_balance = 1;
|
||||
@@ -7339,6 +7274,35 @@ pub(crate) mod tests {
|
||||
solana_logger::setup();
|
||||
let mock_program_id = Pubkey::new(&[2u8; 32]);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum MockInstruction {
|
||||
Deduction,
|
||||
}
|
||||
|
||||
fn mock_process_instruction(
|
||||
_first_instruction_account: usize,
|
||||
data: &[u8],
|
||||
invoke_context: &mut InvokeContext,
|
||||
) -> result::Result<(), InstructionError> {
|
||||
let transaction_context = &invoke_context.transaction_context;
|
||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||
if let Ok(instruction) = bincode::deserialize(data) {
|
||||
match instruction {
|
||||
MockInstruction::Deduction => {
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.checked_add_lamports(1)?;
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 2)?
|
||||
.checked_sub_lamports(1)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(InstructionError::InvalidInstructionData)
|
||||
}
|
||||
}
|
||||
|
||||
let (mut genesis_config, _mint_keypair) = create_genesis_config(10);
|
||||
let mut keypairs: Vec<Keypair> = Vec::with_capacity(14);
|
||||
for _i in 0..14 {
|
||||
@@ -7356,7 +7320,8 @@ pub(crate) mod tests {
|
||||
// we must ensure lazy rent collection doens't get broken!
|
||||
root_bank.restore_old_behavior_for_fragile_tests();
|
||||
let root_bank = Arc::new(root_bank);
|
||||
let bank = create_child_bank_for_rent_test(&root_bank, &genesis_config, mock_program_id);
|
||||
let mut bank = create_child_bank_for_rent_test(&root_bank, &genesis_config);
|
||||
bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction);
|
||||
|
||||
assert_eq!(bank.last_blockhash(), genesis_config.hash());
|
||||
|
||||
@@ -7413,12 +7378,21 @@ pub(crate) mod tests {
|
||||
genesis_config.hash(),
|
||||
);
|
||||
|
||||
let t6 = create_mock_transaction(
|
||||
&keypairs[10],
|
||||
&keypairs[11],
|
||||
&keypairs[12],
|
||||
&keypairs[13],
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(keypairs[10].pubkey(), true),
|
||||
AccountMeta::new(keypairs[11].pubkey(), true),
|
||||
AccountMeta::new(keypairs[12].pubkey(), true),
|
||||
AccountMeta::new_readonly(keypairs[13].pubkey(), false),
|
||||
];
|
||||
let deduct_instruction = Instruction::new_with_bincode(
|
||||
mock_program_id,
|
||||
&MockInstruction::Deduction,
|
||||
account_metas,
|
||||
);
|
||||
let t6 = Transaction::new_signed_with_payer(
|
||||
&[deduct_instruction],
|
||||
Some(&keypairs[10].pubkey()),
|
||||
&[&keypairs[10], &keypairs[11], &keypairs[12]],
|
||||
genesis_config.hash(),
|
||||
);
|
||||
|
||||
@@ -11491,23 +11465,24 @@ pub(crate) mod tests {
|
||||
let mut bank = Bank::new_for_tests(&genesis_config);
|
||||
|
||||
fn mock_process_instruction(
|
||||
first_instruction_account: usize,
|
||||
_first_instruction_account: usize,
|
||||
data: &[u8],
|
||||
invoke_context: &mut InvokeContext,
|
||||
) -> result::Result<(), InstructionError> {
|
||||
let keyed_accounts = invoke_context.get_keyed_accounts()?;
|
||||
let transaction_context = &invoke_context.transaction_context;
|
||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||
let lamports = data[0] as u64;
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?
|
||||
.try_account_ref_mut()?
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 2)?
|
||||
.checked_sub_lamports(lamports)?;
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?
|
||||
.try_account_ref_mut()?
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.checked_add_lamports(lamports)?;
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account)?
|
||||
.try_account_ref_mut()?
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 0)?
|
||||
.checked_sub_lamports(lamports)?;
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?
|
||||
.try_account_ref_mut()?
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.checked_add_lamports(lamports)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -12022,14 +11997,15 @@ pub(crate) mod tests {
|
||||
#[test]
|
||||
fn test_same_program_id_uses_unqiue_executable_accounts() {
|
||||
fn nested_processor(
|
||||
first_instruction_account: usize,
|
||||
_first_instruction_account: usize,
|
||||
_data: &[u8],
|
||||
invoke_context: &mut InvokeContext,
|
||||
) -> result::Result<(), InstructionError> {
|
||||
let keyed_accounts = invoke_context.get_keyed_accounts()?;
|
||||
let account = keyed_account_at_index(keyed_accounts, first_instruction_account)?;
|
||||
assert_eq!(42, account.lamports().unwrap());
|
||||
account.try_account_ref_mut()?.checked_add_lamports(1)?;
|
||||
let transaction_context = &invoke_context.transaction_context;
|
||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||
let _ = instruction_context
|
||||
.try_borrow_account(transaction_context, 1)?
|
||||
.checked_add_lamports(1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -14761,15 +14737,15 @@ pub(crate) mod tests {
|
||||
let mut bank = Bank::new_for_tests(&genesis_config);
|
||||
|
||||
fn mock_ix_processor(
|
||||
first_instruction_account: usize,
|
||||
_first_instruction_account: usize,
|
||||
_data: &[u8],
|
||||
invoke_context: &mut InvokeContext,
|
||||
) -> std::result::Result<(), InstructionError> {
|
||||
use solana_sdk::account::WritableAccount;
|
||||
let keyed_accounts = invoke_context.get_keyed_accounts()?;
|
||||
let data = keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
||||
data.try_account_ref_mut()?.data_as_mut_slice()[0] = 5;
|
||||
Ok(())
|
||||
let transaction_context = &invoke_context.transaction_context;
|
||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.set_data(&[0; 40])
|
||||
}
|
||||
|
||||
let program_id = solana_sdk::pubkey::new_rand();
|
||||
@@ -14780,7 +14756,6 @@ pub(crate) mod tests {
|
||||
let blockhash_sysvar = sysvar::clock::id();
|
||||
#[allow(deprecated)]
|
||||
let orig_lamports = bank.get_account(&sysvar::clock::id()).unwrap().lamports();
|
||||
info!("{:?}", bank.get_account(&sysvar::clock::id()));
|
||||
let tx = system_transaction::transfer(&mint_keypair, &blockhash_sysvar, 10, blockhash);
|
||||
assert_eq!(
|
||||
bank.process_transaction(&tx),
|
||||
@@ -14793,7 +14768,6 @@ pub(crate) mod tests {
|
||||
bank.get_account(&sysvar::clock::id()).unwrap().lamports(),
|
||||
orig_lamports
|
||||
);
|
||||
info!("{:?}", bank.get_account(&sysvar::clock::id()));
|
||||
|
||||
let accounts = vec![
|
||||
AccountMeta::new(mint_keypair.pubkey(), true),
|
||||
|
@@ -160,7 +160,6 @@ mod tests {
|
||||
solana_sdk::{
|
||||
account::{AccountSharedData, ReadableAccount},
|
||||
instruction::{AccountMeta, Instruction, InstructionError},
|
||||
keyed_account::keyed_account_at_index,
|
||||
message::Message,
|
||||
native_loader::{self, create_loadable_account_for_test},
|
||||
secp256k1_instruction::new_secp256k1_instruction,
|
||||
@@ -182,36 +181,33 @@ mod tests {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum MockSystemInstruction {
|
||||
Correct,
|
||||
AttemptCredit { lamports: u64 },
|
||||
AttemptDataChange { data: u8 },
|
||||
TransferLamports { lamports: u64 },
|
||||
ChangeData { data: u8 },
|
||||
}
|
||||
|
||||
fn mock_system_process_instruction(
|
||||
first_instruction_account: usize,
|
||||
_first_instruction_account: usize,
|
||||
data: &[u8],
|
||||
invoke_context: &mut InvokeContext,
|
||||
) -> Result<(), InstructionError> {
|
||||
let keyed_accounts = invoke_context.get_keyed_accounts()?;
|
||||
let transaction_context = &invoke_context.transaction_context;
|
||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||
if let Ok(instruction) = bincode::deserialize(data) {
|
||||
match instruction {
|
||||
MockSystemInstruction::Correct => Ok(()),
|
||||
MockSystemInstruction::AttemptCredit { lamports } => {
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account)?
|
||||
.account
|
||||
.borrow_mut()
|
||||
MockSystemInstruction::TransferLamports { lamports } => {
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 0)?
|
||||
.checked_sub_lamports(lamports)?;
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?
|
||||
.account
|
||||
.borrow_mut()
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.checked_add_lamports(lamports)?;
|
||||
Ok(())
|
||||
}
|
||||
// Change data in a read-only account
|
||||
MockSystemInstruction::AttemptDataChange { data } => {
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?
|
||||
.account
|
||||
.borrow_mut()
|
||||
.set_data(vec![data]);
|
||||
MockSystemInstruction::ChangeData { data } => {
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.set_data(&[data])?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -293,7 +289,7 @@ mod tests {
|
||||
let message = Message::new(
|
||||
&[Instruction::new_with_bincode(
|
||||
mock_system_program_id,
|
||||
&MockSystemInstruction::AttemptCredit { lamports: 50 },
|
||||
&MockSystemInstruction::TransferLamports { lamports: 50 },
|
||||
account_metas.clone(),
|
||||
)],
|
||||
Some(transaction_context.get_key_of_account_at_index(0)),
|
||||
@@ -326,7 +322,7 @@ mod tests {
|
||||
let message = Message::new(
|
||||
&[Instruction::new_with_bincode(
|
||||
mock_system_program_id,
|
||||
&MockSystemInstruction::AttemptDataChange { data: 50 },
|
||||
&MockSystemInstruction::ChangeData { data: 50 },
|
||||
account_metas,
|
||||
)],
|
||||
Some(transaction_context.get_key_of_account_at_index(0)),
|
||||
@@ -367,67 +363,49 @@ mod tests {
|
||||
}
|
||||
|
||||
fn mock_system_process_instruction(
|
||||
first_instruction_account: usize,
|
||||
_first_instruction_account: usize,
|
||||
data: &[u8],
|
||||
invoke_context: &mut InvokeContext,
|
||||
) -> Result<(), InstructionError> {
|
||||
let keyed_accounts = invoke_context.get_keyed_accounts()?;
|
||||
let transaction_context = &invoke_context.transaction_context;
|
||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||
let mut to_account =
|
||||
instruction_context.try_borrow_instruction_account(transaction_context, 1)?;
|
||||
if let Ok(instruction) = bincode::deserialize(data) {
|
||||
match instruction {
|
||||
MockSystemInstruction::BorrowFail => {
|
||||
let from_account =
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account)?
|
||||
.try_account_ref_mut()?;
|
||||
let dup_account =
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?
|
||||
.try_account_ref_mut()?;
|
||||
if from_account.lamports() != dup_account.lamports() {
|
||||
let from_account = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 0)?;
|
||||
let dup_account = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 2)?;
|
||||
if from_account.get_lamports() != dup_account.get_lamports() {
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
MockSystemInstruction::MultiBorrowMut => {
|
||||
let from_lamports = {
|
||||
let from_account =
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account)?
|
||||
.try_account_ref_mut()?;
|
||||
from_account.lamports()
|
||||
};
|
||||
let dup_lamports = {
|
||||
let dup_account = keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account + 2,
|
||||
)?
|
||||
.try_account_ref_mut()?;
|
||||
dup_account.lamports()
|
||||
};
|
||||
if from_lamports != dup_lamports {
|
||||
let lamports_a = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 0)?
|
||||
.get_lamports();
|
||||
let lamports_b = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 2)?
|
||||
.get_lamports();
|
||||
if lamports_a != lamports_b {
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
MockSystemInstruction::DoWork { lamports, data } => {
|
||||
{
|
||||
let mut to_account = keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account + 1,
|
||||
)?
|
||||
.try_account_ref_mut()?;
|
||||
let mut dup_account = keyed_account_at_index(
|
||||
keyed_accounts,
|
||||
first_instruction_account + 2,
|
||||
)?
|
||||
.try_account_ref_mut()?;
|
||||
dup_account.checked_sub_lamports(lamports)?;
|
||||
to_account.checked_add_lamports(lamports)?;
|
||||
dup_account.set_data(vec![data]);
|
||||
}
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account)?
|
||||
.try_account_ref_mut()?
|
||||
.checked_sub_lamports(lamports)?;
|
||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?
|
||||
.try_account_ref_mut()?
|
||||
.checked_add_lamports(lamports)?;
|
||||
let mut dup_account = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 2)?;
|
||||
dup_account.checked_sub_lamports(lamports)?;
|
||||
to_account.checked_add_lamports(lamports)?;
|
||||
dup_account.set_data(&[data])?;
|
||||
drop(dup_account);
|
||||
let mut from_account = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 0)?;
|
||||
from_account.checked_sub_lamports(lamports)?;
|
||||
to_account.checked_add_lamports(lamports)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -528,7 +506,7 @@ mod tests {
|
||||
);
|
||||
assert!(result.is_ok());
|
||||
|
||||
// Do work on the same account but at different location in keyed_accounts[]
|
||||
// Do work on the same transaction account but at different instruction accounts
|
||||
let message = Message::new(
|
||||
&[Instruction::new_with_bincode(
|
||||
mock_program_id,
|
||||
|
Reference in New Issue
Block a user