Refactor: Remove KeyedAccount from program runtime (#22226)

* Makes error handling in BorrowedAccount optional.
Adds BorrowedAccount ::get_rent_epoch().
Exposes InstructionContext::get_index_in_transaction().
Turns accounts and account_keys into pinned boxed slices.

* Introduces "unsafe" to InvokeContext::push().

* Turns &TransactionContext into &mut TransactionContext in InvokeContext.

* Push and pop InstructionContext in InvokeContext.
Makes test_process_cross_program and test_native_invoke symmetric.
Removes the borrow check from test_invoke_context_verify.

* Removes keyed_accounts from prepare_instruction()

* Removes usage of invoke_stack.

* Removes keyed_accounts from program-test.

* Removes caller_write_privileges.

* Removes keyed_accounts from BPF parameter (de-)serialization.
This commit is contained in:
Alexander Meißner
2022-01-03 23:30:56 +01:00
committed by GitHub
parent 672fed04cb
commit 73e6038986
18 changed files with 847 additions and 805 deletions

View File

@ -3561,9 +3561,9 @@ impl Bank {
let mut transaction_accounts = Vec::new();
std::mem::swap(&mut loaded_transaction.accounts, &mut transaction_accounts);
let transaction_context = TransactionContext::new(
let mut transaction_context = TransactionContext::new(
transaction_accounts,
compute_budget.max_invoke_depth,
compute_budget.max_invoke_depth.saturating_add(1),
);
let instruction_recorder = if enable_cpi_recording {
@ -3588,7 +3588,7 @@ impl Bank {
&self.builtin_programs.vec,
legacy_message,
&loaded_transaction.program_indices,
&transaction_context,
&mut transaction_context,
self.rent_collector.rent,
log_collector.clone(),
executors.clone(),
@ -10401,7 +10401,7 @@ pub(crate) mod tests {
_instruction_data: &[u8],
invoke_context: &mut InvokeContext,
) -> std::result::Result<(), InstructionError> {
let program_id = invoke_context.get_caller()?;
let program_id = invoke_context.transaction_context.get_program_key()?;
if mock_vote_program_id() != *program_id {
return Err(InstructionError::IncorrectProgramId);
}

View File

@ -19,12 +19,12 @@ fn process_instruction_with_program_logging(
invoke_context: &mut InvokeContext,
) -> Result<(), InstructionError> {
let logger = invoke_context.get_log_collector();
let program_id = invoke_context.get_caller()?;
let program_id = invoke_context.transaction_context.get_program_key()?;
stable_log::program_invoke(&logger, program_id, invoke_context.invoke_depth());
let result = process_instruction(first_instruction_account, instruction_data, invoke_context);
let program_id = invoke_context.get_caller()?;
let program_id = invoke_context.transaction_context.get_program_key()?;
match &result {
Ok(()) => stable_log::program_success(&logger, program_id),
Err(err) => stable_log::program_failure(&logger, program_id, err),

View File

@ -53,7 +53,7 @@ impl MessageProcessor {
builtin_programs: &[BuiltinProgram],
message: &Message,
program_indices: &[Vec<usize>],
transaction_context: &TransactionContext,
transaction_context: &mut TransactionContext,
rent: Rent,
log_collector: Option<Rc<RefCell<LogCollector>>>,
executors: Rc<RefCell<Executors>>,
@ -132,7 +132,6 @@ impl MessageProcessor {
let result = invoke_context.process_instruction(
&instruction.data,
&instruction_accounts,
None,
program_indices,
&mut compute_units_consumed,
);
@ -242,7 +241,7 @@ mod tests {
create_loadable_account_for_test("mock_system_program"),
),
];
let transaction_context = TransactionContext::new(accounts, 1);
let mut transaction_context = TransactionContext::new(accounts, 1);
let program_indices = vec![vec![2]];
let executors = Rc::new(RefCell::new(Executors::default()));
let account_metas = vec![
@ -262,7 +261,7 @@ mod tests {
builtin_programs,
&message,
&program_indices,
&transaction_context,
&mut transaction_context,
rent_collector.rent,
None,
executors.clone(),
@ -303,7 +302,7 @@ mod tests {
builtin_programs,
&message,
&program_indices,
&transaction_context,
&mut transaction_context,
rent_collector.rent,
None,
executors.clone(),
@ -336,7 +335,7 @@ mod tests {
builtin_programs,
&message,
&program_indices,
&transaction_context,
&mut transaction_context,
rent_collector.rent,
None,
executors,
@ -458,7 +457,7 @@ mod tests {
create_loadable_account_for_test("mock_system_program"),
),
];
let transaction_context = TransactionContext::new(accounts, 1);
let mut transaction_context = TransactionContext::new(accounts, 1);
let program_indices = vec![vec![2]];
let executors = Rc::new(RefCell::new(Executors::default()));
let account_metas = vec![
@ -480,7 +479,7 @@ mod tests {
builtin_programs,
&message,
&program_indices,
&transaction_context,
&mut transaction_context,
rent_collector.rent,
None,
executors.clone(),
@ -514,7 +513,7 @@ mod tests {
builtin_programs,
&message,
&program_indices,
&transaction_context,
&mut transaction_context,
rent_collector.rent,
None,
executors.clone(),
@ -545,7 +544,7 @@ mod tests {
builtin_programs,
&message,
&program_indices,
&transaction_context,
&mut transaction_context,
rent_collector.rent,
None,
executors,
@ -602,7 +601,7 @@ mod tests {
(secp256k1_program::id(), secp256k1_account),
(mock_program_id, mock_program_account),
];
let transaction_context = TransactionContext::new(accounts, 1);
let mut transaction_context = TransactionContext::new(accounts, 1);
let message = Message::new(
&[
@ -618,7 +617,7 @@ mod tests {
builtin_programs,
&message,
&[vec![0], vec![1]],
&transaction_context,
&mut transaction_context,
RentCollector::default().rent,
None,
Rc::new(RefCell::new(Executors::default())),

View File

@ -334,8 +334,8 @@ mod test {
where
F: FnMut(&mut InvokeContext, &KeyedAccount),
{
let transaction_context = TransactionContext::new(Vec::new(), 1);
let mut invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let pubkey = Pubkey::new_unique();
let account = create_account(lamports);
let keyed_account = KeyedAccount::new(&pubkey, signer, &account);

View File

@ -675,8 +675,8 @@ mod tests {
#[test]
fn test_address_create_with_seed_mismatch() {
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let from = Pubkey::new_unique();
let seed = "dull boy";
let to = Pubkey::new_unique();
@ -690,8 +690,8 @@ mod tests {
#[test]
fn test_create_account_with_seed_missing_sig() {
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let new_owner = Pubkey::new(&[9; 32]);
let from = Pubkey::new_unique();
let seed = "dull boy";
@ -721,8 +721,8 @@ mod tests {
#[test]
fn test_create_with_zero_lamports() {
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// create account with zero lamports transferred
let new_owner = Pubkey::new(&[9; 32]);
let from = Pubkey::new_unique();
@ -756,8 +756,8 @@ mod tests {
#[test]
fn test_create_negative_lamports() {
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Attempt to create account with more lamports than remaining in from_account
let new_owner = Pubkey::new(&[9; 32]);
let from = Pubkey::new_unique();
@ -781,8 +781,8 @@ mod tests {
#[test]
fn test_request_more_than_allowed_data_length() {
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let from_account = RefCell::new(AccountSharedData::new(100, 0, &system_program::id()));
let from = Pubkey::new_unique();
let to_account = RefCell::new(AccountSharedData::new(0, 0, &system_program::id()));
@ -829,8 +829,8 @@ mod tests {
#[test]
fn test_create_already_in_use() {
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Attempt to create system account in account already owned by another program
let new_owner = Pubkey::new(&[9; 32]);
let from = Pubkey::new_unique();
@ -898,8 +898,8 @@ mod tests {
#[test]
fn test_create_unsigned() {
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Attempt to create an account without signing the transfer
let new_owner = Pubkey::new(&[9; 32]);
let from = Pubkey::new_unique();
@ -954,8 +954,8 @@ mod tests {
#[test]
fn test_create_sysvar_invalid_id_with_feature() {
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Attempt to create system account in account already owned by another program
let from = Pubkey::new_unique();
let from_account = RefCell::new(AccountSharedData::new(100, 0, &system_program::id()));
@ -989,8 +989,8 @@ mod tests {
feature_set
.inactive
.insert(feature_set::rent_for_sysvars::id());
let transaction_context = TransactionContext::new(Vec::new(), 1);
let mut invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context.feature_set = Arc::new(feature_set);
// Attempt to create system account in account already owned by another program
let from = Pubkey::new_unique();
@ -1017,8 +1017,8 @@ mod tests {
#[test]
fn test_create_data_populated() {
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Attempt to create system account in account with populated data
let new_owner = Pubkey::new(&[9; 32]);
let from = Pubkey::new_unique();
@ -1051,8 +1051,8 @@ mod tests {
#[test]
fn test_create_from_account_is_nonce_fail() {
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let nonce = Pubkey::new_unique();
let nonce_account = RefCell::new(
AccountSharedData::new_data(
@ -1090,8 +1090,8 @@ mod tests {
#[test]
fn test_assign() {
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let new_owner = Pubkey::new(&[9; 32]);
let pubkey = Pubkey::new_unique();
let mut account = AccountSharedData::new(100, 0, &system_program::id());
@ -1133,8 +1133,8 @@ mod tests {
#[test]
fn test_assign_to_sysvar_with_feature() {
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let new_owner = sysvar::id();
let from = Pubkey::new_unique();
let mut from_account = AccountSharedData::new(100, 0, &system_program::id());
@ -1160,8 +1160,8 @@ mod tests {
feature_set
.inactive
.insert(feature_set::rent_for_sysvars::id());
let transaction_context = TransactionContext::new(Vec::new(), 1);
let mut invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context.feature_set = Arc::new(feature_set);
let new_owner = sysvar::id();
let from = Pubkey::new_unique();
@ -1212,8 +1212,8 @@ mod tests {
#[test]
fn test_transfer_lamports() {
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let from = Pubkey::new_unique();
let from_account = RefCell::new(AccountSharedData::new(100, 0, &Pubkey::new(&[2; 32]))); // account owner should not matter
let to = Pubkey::new(&[3; 32]);
@ -1251,8 +1251,8 @@ mod tests {
#[test]
fn test_transfer_with_seed() {
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let base = Pubkey::new_unique();
let base_account = RefCell::new(AccountSharedData::new(100, 0, &Pubkey::new(&[2; 32]))); // account owner should not matter
let from_base_keyed_account = KeyedAccount::new(&base, true, &base_account);
@ -1312,8 +1312,8 @@ mod tests {
#[test]
fn test_transfer_lamports_from_nonce_account_fail() {
let transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&transaction_context, &[]);
let mut transaction_context = TransactionContext::new(Vec::new(), 1);
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
let from = Pubkey::new_unique();
let from_account = RefCell::new(
AccountSharedData::new_data(