Feature: TransactionContext, InstructionContext and BorrowedAccount (#21706)

* Adds TransactionContext, InstructionContext and BorrowedAccount.

* Redirects the usage of accounts in InvokeContext through TransactionContext.
Also use the types declared in transaction_context.rs everywhere.

* Adjusts all affected tests.
This commit is contained in:
Alexander Meißner
2021-12-27 18:49:32 +01:00
committed by GitHub
parent bb97c8fdcd
commit a06646631c
14 changed files with 926 additions and 530 deletions

View File

@ -323,6 +323,7 @@ mod tests {
bpf_loader,
entrypoint::deserialize,
instruction::AccountMeta,
transaction_context::TransactionContext,
},
std::{
cell::RefCell,
@ -452,7 +453,8 @@ mod tests {
let program_indices = [0];
let preparation =
prepare_mock_invoke_context(transaction_accounts.clone(), instruction_accounts);
let mut invoke_context = InvokeContext::new_mock(&preparation.transaction_accounts, &[]);
let transaction_context = TransactionContext::new(preparation.transaction_accounts, 1);
let mut invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
invoke_context
.push(&preparation.instruction_accounts, &program_indices)
.unwrap();

View File

@ -5,7 +5,7 @@ use {
alloc::Alloc,
solana_program_runtime::{
ic_logger_msg, ic_msg,
invoke_context::{ComputeMeter, InstructionAccount, InvokeContext},
invoke_context::{ComputeMeter, InvokeContext},
stable_log,
},
solana_rbpf::{
@ -41,6 +41,7 @@ use {
Secp256k1RecoverError, SECP256K1_PUBLIC_KEY_LENGTH, SECP256K1_SIGNATURE_LENGTH,
},
sysvar::{self, Sysvar, SysvarId},
transaction_context::InstructionAccount,
},
std::{
alloc::Layout,
@ -2214,8 +2215,12 @@ where
accounts.push((*program_account_index, None));
for instruction_account in instruction_accounts.iter() {
let account = invoke_context.get_account_at_index(instruction_account.index);
let account_key = invoke_context.get_account_key_at_index(instruction_account.index);
let account = invoke_context
.transaction_context
.get_account_at_index(instruction_account.index);
let account_key = invoke_context
.transaction_context
.get_key_of_account_at_index(instruction_account.index);
if account.borrow().executable() {
// Use the known account
accounts.push((instruction_account.index, None));
@ -2396,6 +2401,7 @@ fn call<'a, 'b: 'a>(
for (callee_account_index, caller_account) in accounts.iter_mut() {
if let Some(caller_account) = caller_account {
let callee_account = invoke_context
.transaction_context
.get_account_at_index(*callee_account_index)
.borrow();
*caller_account.lamports = callee_account.lamports();
@ -2669,6 +2675,7 @@ mod tests {
},
solana_sdk::{
account::AccountSharedData, bpf_loader, fee_calculator::FeeCalculator, hash::hashv,
transaction_context::TransactionContext,
},
std::str::FromStr,
};
@ -2979,9 +2986,11 @@ mod tests {
#[should_panic(expected = "UserError(SyscallError(Panic(\"Gaggablaghblagh!\", 42, 84)))")]
fn test_syscall_sol_panic() {
let program_id = Pubkey::new_unique();
let program_account = RefCell::new(AccountSharedData::new(0, 0, &bpf_loader::id()));
let accounts = [(program_id, program_account)];
let mut invoke_context = InvokeContext::new_mock(&accounts, &[]);
let transaction_context = TransactionContext::new(
vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))],
1,
);
let mut invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
invoke_context.push(&[], &[0]).unwrap();
let mut syscall_panic = SyscallPanic {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
@ -3050,9 +3059,11 @@ mod tests {
#[test]
fn test_syscall_sol_log() {
let program_id = Pubkey::new_unique();
let program_account = RefCell::new(AccountSharedData::new(0, 0, &bpf_loader::id()));
let accounts = [(program_id, program_account)];
let mut invoke_context = InvokeContext::new_mock(&accounts, &[]);
let transaction_context = TransactionContext::new(
vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))],
1,
);
let mut invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
invoke_context.push(&[], &[0]).unwrap();
let mut syscall_sol_log = SyscallLog {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
@ -3148,9 +3159,11 @@ mod tests {
#[test]
fn test_syscall_sol_log_u64() {
let program_id = Pubkey::new_unique();
let program_account = RefCell::new(AccountSharedData::new(0, 0, &bpf_loader::id()));
let accounts = [(program_id, program_account)];
let mut invoke_context = InvokeContext::new_mock(&accounts, &[]);
let transaction_context = TransactionContext::new(
vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))],
1,
);
let mut invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
invoke_context.push(&[], &[0]).unwrap();
let cost = invoke_context.get_compute_budget().log_64_units;
let mut syscall_sol_log_u64 = SyscallLogU64 {
@ -3184,9 +3197,11 @@ mod tests {
#[test]
fn test_syscall_sol_pubkey() {
let program_id = Pubkey::new_unique();
let program_account = RefCell::new(AccountSharedData::new(0, 0, &bpf_loader::id()));
let accounts = [(program_id, program_account)];
let mut invoke_context = InvokeContext::new_mock(&accounts, &[]);
let transaction_context = TransactionContext::new(
vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))],
1,
);
let mut invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
invoke_context.push(&[], &[0]).unwrap();
let cost = invoke_context.get_compute_budget().log_pubkey_units;
let mut syscall_sol_pubkey = SyscallLogPubkey {
@ -3390,10 +3405,14 @@ mod tests {
fn test_syscall_sha256() {
let config = Config::default();
let program_id = Pubkey::new_unique();
let program_account =
RefCell::new(AccountSharedData::new(0, 0, &bpf_loader_deprecated::id()));
let accounts = [(program_id, program_account)];
let mut invoke_context = InvokeContext::new_mock(&accounts, &[]);
let transaction_context = TransactionContext::new(
vec![(
program_id,
AccountSharedData::new(0, 0, &bpf_loader_deprecated::id()),
)],
1,
);
let mut invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
invoke_context.push(&[], &[0]).unwrap();
let bytes1 = "Gaggablaghblagh!";
@ -3511,11 +3530,55 @@ mod tests {
}
#[test]
#[allow(deprecated)]
fn test_syscall_get_sysvar() {
let config = Config::default();
let src_clock = Clock {
slot: 1,
epoch_start_timestamp: 2,
epoch: 3,
leader_schedule_epoch: 4,
unix_timestamp: 5,
};
let mut data_clock = vec![];
bincode::serialize_into(&mut data_clock, &src_clock).unwrap();
let src_epochschedule = EpochSchedule {
slots_per_epoch: 1,
leader_schedule_slot_offset: 2,
warmup: false,
first_normal_epoch: 3,
first_normal_slot: 4,
};
let mut data_epochschedule = vec![];
bincode::serialize_into(&mut data_epochschedule, &src_epochschedule).unwrap();
let src_fees = Fees {
fee_calculator: FeeCalculator {
lamports_per_signature: 1,
},
};
let mut data_fees = vec![];
bincode::serialize_into(&mut data_fees, &src_fees).unwrap();
let src_rent = Rent {
lamports_per_byte_year: 1,
exemption_threshold: 2.0,
burn_percent: 3,
};
let mut data_rent = vec![];
bincode::serialize_into(&mut data_rent, &src_rent).unwrap();
let sysvars = [
(sysvar::clock::id(), data_clock),
(sysvar::epoch_schedule::id(), data_epochschedule),
(sysvar::fees::id(), data_fees),
(sysvar::rent::id(), data_rent),
];
let program_id = Pubkey::new_unique();
let program_account = RefCell::new(AccountSharedData::new(0, 0, &bpf_loader::id()));
let accounts = [(program_id, program_account)];
let transaction_context = TransactionContext::new(
vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))],
1,
);
let mut invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
invoke_context.sysvars = &sysvars;
invoke_context.push(&[], &[0]).unwrap();
// Test clock sysvar
{
@ -3536,20 +3599,6 @@ mod tests {
&config,
)
.unwrap();
let src_clock = Clock {
slot: 1,
epoch_start_timestamp: 2,
epoch: 3,
leader_schedule_epoch: 4,
unix_timestamp: 5,
};
let mut data = vec![];
bincode::serialize_into(&mut data, &src_clock).unwrap();
let mut invoke_context = InvokeContext::new_mock(&accounts, &[]);
let sysvars = [(sysvar::clock::id(), data)];
invoke_context.sysvars = &sysvars;
invoke_context.push(&[], &[0]).unwrap();
let mut syscall = SyscallGetClockSysvar {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
};
@ -3579,20 +3628,6 @@ mod tests {
&config,
)
.unwrap();
let src_epochschedule = EpochSchedule {
slots_per_epoch: 1,
leader_schedule_slot_offset: 2,
warmup: false,
first_normal_epoch: 3,
first_normal_slot: 4,
};
let mut data = vec![];
bincode::serialize_into(&mut data, &src_epochschedule).unwrap();
let mut invoke_context = InvokeContext::new_mock(&accounts, &[]);
let sysvars = [(sysvar::epoch_schedule::id(), data)];
invoke_context.sysvars = &sysvars;
invoke_context.push(&[], &[0]).unwrap();
let mut syscall = SyscallGetEpochScheduleSysvar {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
};
@ -3612,7 +3647,6 @@ mod tests {
}
// Test fees sysvar
#[allow(deprecated)]
{
let got_fees = Fees::default();
let got_fees_va = 0x100000000;
@ -3631,18 +3665,6 @@ mod tests {
&config,
)
.unwrap();
let src_fees = Fees {
fee_calculator: FeeCalculator {
lamports_per_signature: 1,
},
};
let mut data = vec![];
bincode::serialize_into(&mut data, &src_fees).unwrap();
let mut invoke_context = InvokeContext::new_mock(&accounts, &[]);
let sysvars = [(sysvar::fees::id(), data)];
invoke_context.sysvars = &sysvars;
invoke_context.push(&[], &[0]).unwrap();
let mut syscall = SyscallGetFeesSysvar {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
};
@ -3672,18 +3694,6 @@ mod tests {
&config,
)
.unwrap();
let src_rent = Rent {
lamports_per_byte_year: 1,
exemption_threshold: 2.0,
burn_percent: 3,
};
let mut data = vec![];
bincode::serialize_into(&mut data, &src_rent).unwrap();
let mut invoke_context = InvokeContext::new_mock(&accounts, &[]);
let sysvars = [(sysvar::rent::id(), data)];
invoke_context.sysvars = &sysvars;
invoke_context.push(&[], &[0]).unwrap();
let mut syscall = SyscallGetRentSysvar {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
};
@ -3812,9 +3822,11 @@ mod tests {
// These tests duplicate the direct tests in solana_program::pubkey
let program_id = Pubkey::new_unique();
let program_account = RefCell::new(AccountSharedData::new(0, 0, &bpf_loader::id()));
let accounts = [(program_id, program_account)];
let mut invoke_context = InvokeContext::new_mock(&accounts, &[]);
let transaction_context = TransactionContext::new(
vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))],
1,
);
let mut invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
invoke_context.push(&[], &[0]).unwrap();
let address = bpf_loader_upgradeable::id();
@ -3922,9 +3934,11 @@ mod tests {
#[test]
fn test_find_program_address() {
let program_id = Pubkey::new_unique();
let program_account = RefCell::new(AccountSharedData::new(0, 0, &bpf_loader::id()));
let accounts = [(program_id, program_account)];
let mut invoke_context = InvokeContext::new_mock(&accounts, &[]);
let transaction_context = TransactionContext::new(
vec![(program_id, AccountSharedData::new(0, 0, &bpf_loader::id()))],
1,
);
let mut invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
invoke_context.push(&[], &[0]).unwrap();
let cost = invoke_context
.get_compute_budget()