Refactor: Cleanup InvokeContext (#20785)
* Move blockhash and fee_calculator in ThisInvokeContext instead of using a reference. * Moves tx_wide_compute_cap into InvokeContext::push(). * Adds ThisInvokeContext::new_mock() constructor. * Adds missing loader account in uses of MockInvokeContext. * Use keyed_account_at_index() when accessing keyed_accounts. * Makes sysvar interface consistent between ThisInvokeContext and MockInvokeContext, in order to add InvokeContext::get_sysvars(). * Adds InvokeContext::set_blockhash() and InvokeContext ::set_fee_calculator(). * Adds new_mock_with_features. * Makes ancestors optional in ThisInvokeContext. * Adds prepare_mock_invoke_context() and mock_process_instruction().
This commit is contained in:
committed by
GitHub
parent
0ac89841bf
commit
97c2732d02
@ -94,8 +94,28 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
||||
.write_u64::<LittleEndian>(ARMSTRONG_LIMIT)
|
||||
.unwrap();
|
||||
inner_iter.write_u64::<LittleEndian>(0).unwrap();
|
||||
|
||||
let loader_id = bpf_loader::id();
|
||||
let mut invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
|
||||
let program_id = solana_sdk::pubkey::new_rand();
|
||||
let accounts = [
|
||||
(
|
||||
program_id,
|
||||
RefCell::new(AccountSharedData::new(0, 0, &loader_id)),
|
||||
),
|
||||
(
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
RefCell::new(AccountSharedData::new(
|
||||
1,
|
||||
10000001,
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
)),
|
||||
),
|
||||
];
|
||||
let keyed_accounts: Vec<_> = accounts
|
||||
.iter()
|
||||
.map(|(key, account)| solana_sdk::keyed_account::KeyedAccount::new(&key, false, &account))
|
||||
.collect();
|
||||
let mut invoke_context = MockInvokeContext::new(&program_id, keyed_accounts);
|
||||
|
||||
let elf = load_elf("bench_alu").unwrap();
|
||||
let mut executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||
@ -254,29 +274,35 @@ fn bench_create_vm(bencher: &mut Bencher) {
|
||||
fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
||||
const BUDGET: u64 = 200_000;
|
||||
let loader_id = bpf_loader::id();
|
||||
let program_id = solana_sdk::pubkey::new_rand();
|
||||
|
||||
let accounts = [RefCell::new(AccountSharedData::new(
|
||||
1,
|
||||
10000001,
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
))];
|
||||
let keys = [solana_sdk::pubkey::new_rand()];
|
||||
let keyed_accounts: Vec<_> = keys
|
||||
let accounts = [
|
||||
(
|
||||
program_id,
|
||||
RefCell::new(AccountSharedData::new(0, 0, &loader_id)),
|
||||
),
|
||||
(
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
RefCell::new(AccountSharedData::new(
|
||||
1,
|
||||
10000001,
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
)),
|
||||
),
|
||||
];
|
||||
let keyed_accounts: Vec<_> = accounts
|
||||
.iter()
|
||||
.zip(&accounts)
|
||||
.map(|(key, account)| solana_sdk::keyed_account::KeyedAccount::new(&key, false, &account))
|
||||
.collect();
|
||||
let instruction_data = vec![0u8];
|
||||
|
||||
let mut invoke_context = MockInvokeContext::new(&loader_id, keyed_accounts);
|
||||
let mut invoke_context = MockInvokeContext::new(&program_id, keyed_accounts);
|
||||
invoke_context.compute_meter.remaining = BUDGET;
|
||||
|
||||
// Serialize account data
|
||||
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
||||
let (mut serialized, account_lengths) = serialize_parameters(
|
||||
&loader_id,
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
keyed_accounts,
|
||||
&program_id,
|
||||
&invoke_context.get_keyed_accounts().unwrap()[1..],
|
||||
&instruction_data,
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -192,24 +192,23 @@ fn upgrade_bpf_program(
|
||||
|
||||
fn run_program(
|
||||
name: &str,
|
||||
loader_id: &Pubkey,
|
||||
program_id: &Pubkey,
|
||||
parameter_accounts: Vec<KeyedAccount>,
|
||||
instruction_data: &[u8],
|
||||
) -> Result<u64, InstructionError> {
|
||||
let path = create_bpf_path(name);
|
||||
let mut file = File::open(path).unwrap();
|
||||
|
||||
let mut file = File::open(create_bpf_path(name)).unwrap();
|
||||
let mut data = vec![];
|
||||
file.read_to_end(&mut data).unwrap();
|
||||
let loader_id = bpf_loader::id();
|
||||
|
||||
let mut invoke_context = MockInvokeContext::new(&program_id, parameter_accounts);
|
||||
let (parameter_bytes, account_lengths) = serialize_parameters(
|
||||
&loader_id,
|
||||
program_id,
|
||||
¶meter_accounts,
|
||||
&invoke_context.get_keyed_accounts().unwrap()[1..],
|
||||
&instruction_data,
|
||||
)
|
||||
.unwrap();
|
||||
let mut invoke_context = MockInvokeContext::new(&loader_id, parameter_accounts);
|
||||
let compute_meter = invoke_context.get_compute_meter();
|
||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||
|
||||
@ -1405,11 +1404,17 @@ fn assert_instruction_count() {
|
||||
let mut passed = true;
|
||||
println!("\n {:36} expected actual diff", "BPF program");
|
||||
for program in programs.iter() {
|
||||
let loader_id = bpf_loader::id();
|
||||
let program_id = Pubkey::new_unique();
|
||||
let key = Pubkey::new_unique();
|
||||
let mut program_account = RefCell::new(AccountSharedData::new(0, 0, &loader_id));
|
||||
let mut account = RefCell::new(AccountSharedData::default());
|
||||
let parameter_accounts = vec![KeyedAccount::new(&key, false, &mut account)];
|
||||
let count = run_program(program.0, &program_id, parameter_accounts, &[]).unwrap();
|
||||
let parameter_accounts = vec![
|
||||
KeyedAccount::new(&program_id, false, &mut program_account),
|
||||
KeyedAccount::new(&key, false, &mut account),
|
||||
];
|
||||
let count =
|
||||
run_program(program.0, &loader_id, &program_id, parameter_accounts, &[]).unwrap();
|
||||
let diff: i64 = count as i64 - program.1 as i64;
|
||||
println!(
|
||||
" {:36} {:8} {:6} {:+5} ({:+3.0}%)",
|
||||
|
@ -3335,7 +3335,8 @@ mod tests {
|
||||
let mut data = vec![];
|
||||
bincode::serialize_into(&mut data, &src_clock).unwrap();
|
||||
invoke_context
|
||||
.sysvars
|
||||
.get_sysvars()
|
||||
.borrow_mut()
|
||||
.push((sysvar::clock::id(), Some(Rc::new(data))));
|
||||
|
||||
let mut syscall = SyscallGetClockSysvar {
|
||||
@ -3380,7 +3381,8 @@ mod tests {
|
||||
let mut data = vec![];
|
||||
bincode::serialize_into(&mut data, &src_epochschedule).unwrap();
|
||||
invoke_context
|
||||
.sysvars
|
||||
.get_sysvars()
|
||||
.borrow_mut()
|
||||
.push((sysvar::epoch_schedule::id(), Some(Rc::new(data))));
|
||||
|
||||
let mut syscall = SyscallGetEpochScheduleSysvar {
|
||||
@ -3432,7 +3434,8 @@ mod tests {
|
||||
let mut data = vec![];
|
||||
bincode::serialize_into(&mut data, &src_fees).unwrap();
|
||||
invoke_context
|
||||
.sysvars
|
||||
.get_sysvars()
|
||||
.borrow_mut()
|
||||
.push((sysvar::fees::id(), Some(Rc::new(data))));
|
||||
|
||||
let mut syscall = SyscallGetFeesSysvar {
|
||||
@ -3475,7 +3478,8 @@ mod tests {
|
||||
let mut data = vec![];
|
||||
bincode::serialize_into(&mut data, &src_rent).unwrap();
|
||||
invoke_context
|
||||
.sysvars
|
||||
.get_sysvars()
|
||||
.borrow_mut()
|
||||
.push((sysvar::rent::id(), Some(Rc::new(data))));
|
||||
|
||||
let mut syscall = SyscallGetRentSysvar {
|
||||
|
@ -54,20 +54,19 @@ pub fn process_instruction(
|
||||
}
|
||||
|
||||
let mut counter = 0;
|
||||
let mut keyed_accounts_iter = keyed_accounts.iter().skip(2);
|
||||
for (signer, _) in key_list.keys.iter().filter(|(_, is_signer)| *is_signer) {
|
||||
counter += 1;
|
||||
if signer != config_keyed_account.unsigned_key() {
|
||||
let signer_account = keyed_accounts_iter.next();
|
||||
if signer_account.is_none() {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"account {:?} is not in account list",
|
||||
signer
|
||||
);
|
||||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
let signer_key = signer_account.unwrap().signer_key();
|
||||
let signer_account =
|
||||
keyed_account_at_index(keyed_accounts, counter + 1).map_err(|_| {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"account {:?} is not in account list",
|
||||
signer,
|
||||
);
|
||||
InstructionError::MissingRequiredSignature
|
||||
})?;
|
||||
let signer_key = signer_account.signer_key();
|
||||
if signer_key.is_none() {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
|
@ -37,7 +37,7 @@ pub fn process_instruction(
|
||||
return Err(InstructionError::InvalidAccountOwner);
|
||||
}
|
||||
|
||||
let signers = get_signers(&keyed_accounts[1..]);
|
||||
let signers = get_signers(&keyed_accounts[first_instruction_account..]);
|
||||
match limited_deserialize(data)? {
|
||||
StakeInstruction::Initialize(authorized, lockup) => me.initialize(
|
||||
&authorized,
|
||||
@ -330,7 +330,7 @@ mod tests {
|
||||
account::{self, Account, AccountSharedData, WritableAccount},
|
||||
instruction::{AccountMeta, Instruction},
|
||||
keyed_account::create_keyed_accounts_unified,
|
||||
process_instruction::{mock_set_sysvar, MockInvokeContext},
|
||||
process_instruction::MockInvokeContext,
|
||||
pubkey::Pubkey,
|
||||
rent::Rent,
|
||||
stake::{
|
||||
@ -338,7 +338,7 @@ mod tests {
|
||||
instruction::{self, LockupArgs},
|
||||
state::{Authorized, Lockup, StakeAuthorize},
|
||||
},
|
||||
sysvar::stake_history::StakeHistory,
|
||||
sysvar::{stake_history::StakeHistory, Sysvar},
|
||||
};
|
||||
use std::{cell::RefCell, rc::Rc, str::FromStr};
|
||||
|
||||
@ -442,12 +442,12 @@ mod tests {
|
||||
&processor_id,
|
||||
create_keyed_accounts_unified(&keyed_accounts),
|
||||
);
|
||||
mock_set_sysvar(
|
||||
&mut invoke_context,
|
||||
sysvar::clock::id(),
|
||||
sysvar::clock::Clock::default(),
|
||||
)
|
||||
.unwrap();
|
||||
let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of());
|
||||
bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap();
|
||||
invoke_context
|
||||
.get_sysvars()
|
||||
.borrow_mut()
|
||||
.push((sysvar::clock::id(), Some(Rc::new(data))));
|
||||
super::process_instruction(1, &instruction.data, &mut invoke_context)
|
||||
}
|
||||
}
|
||||
@ -1100,11 +1100,11 @@ mod tests {
|
||||
];
|
||||
let mut invoke_context =
|
||||
MockInvokeContext::new(&id(), create_keyed_accounts_unified(&keyed_accounts));
|
||||
let clock = Clock::default();
|
||||
let mut data = vec![];
|
||||
bincode::serialize_into(&mut data, &clock).unwrap();
|
||||
let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of());
|
||||
bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap();
|
||||
invoke_context
|
||||
.sysvars
|
||||
.get_sysvars()
|
||||
.borrow_mut()
|
||||
.push((sysvar::clock::id(), Some(Rc::new(data))));
|
||||
|
||||
assert_eq!(
|
||||
|
@ -322,7 +322,7 @@ pub fn process_instruction(
|
||||
return Err(InstructionError::InvalidAccountOwner);
|
||||
}
|
||||
|
||||
let signers: HashSet<Pubkey> = get_signers(&keyed_accounts[1..]);
|
||||
let signers: HashSet<Pubkey> = get_signers(&keyed_accounts[first_instruction_account..]);
|
||||
match limited_deserialize(data)? {
|
||||
VoteInstruction::InitializeAccount(vote_init) => {
|
||||
verify_rent_exemption(
|
||||
|
Reference in New Issue
Block a user