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:
Alexander Meißner
2022-01-05 09:39:37 +01:00
committed by GitHub
parent c1995c647b
commit 9f63493789
5 changed files with 223 additions and 266 deletions

View File

@@ -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),

View File

@@ -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,