Skip to content

Commit

Permalink
Refactor: Removes Rc from Refcell<AccountSharedData> in the progr…
Browse files Browse the repository at this point in the history
…am-runtime (solana-labs#21927)

* Removes Rc from Rc<RefCell<AccountSharedData>> in the program-runtime.

* Adjusts tests in bpf_loader, system_instruction_processor, config_processor, vote_instruction and stake_instruction
  • Loading branch information
Lichtso authored Dec 17, 2021
1 parent 56ec524 commit 66fa8f9
Show file tree
Hide file tree
Showing 11 changed files with 2,885 additions and 2,320 deletions.
156 changes: 80 additions & 76 deletions program-runtime/src/invoke_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use {
std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc, sync::Arc},
};

pub type TransactionAccountRefCell = (Pubkey, Rc<RefCell<AccountSharedData>>);
pub type TransactionAccountRefCell = (Pubkey, RefCell<AccountSharedData>);
pub type TransactionAccountRefCells = Vec<TransactionAccountRefCell>;

pub type ProcessInstructionWithContext =
Expand Down Expand Up @@ -841,50 +841,38 @@ pub struct MockInvokeContextPreparation {
pub fn prepare_mock_invoke_context(
program_indices: &[usize],
instruction_data: &[u8],
keyed_accounts: &[(bool, bool, Pubkey, Rc<RefCell<AccountSharedData>>)],
transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
instruction_accounts: Vec<AccountMeta>,
) -> MockInvokeContextPreparation {
#[allow(clippy::type_complexity)]
let (accounts, mut metas): (TransactionAccountRefCells, Vec<AccountMeta>) = keyed_accounts
.iter()
.map(|(is_signer, is_writable, pubkey, account)| {
(
(*pubkey, account.clone()),
AccountMeta {
pubkey: *pubkey,
is_signer: *is_signer,
is_writable: *is_writable,
},
)
})
.unzip();
let transaction_accounts: TransactionAccountRefCells = transaction_accounts
.into_iter()
.map(|(pubkey, account)| (pubkey, RefCell::new(account)))
.collect();
let program_id = if let Some(program_index) = program_indices.last() {
accounts[*program_index].0
transaction_accounts[*program_index].0
} else {
Pubkey::default()
};
for program_index in program_indices.iter().rev() {
metas.remove(*program_index);
}
let message = Message::new(
&[Instruction::new_with_bytes(
program_id,
instruction_data,
metas,
instruction_accounts,
)],
None,
);
let account_indices: Vec<usize> = message
.account_keys
.iter()
.map(|search_key| {
accounts
transaction_accounts
.iter()
.position(|(key, _account)| key == search_key)
.unwrap_or(accounts.len())
.unwrap_or(transaction_accounts.len())
})
.collect();
MockInvokeContextPreparation {
accounts,
accounts: transaction_accounts,
message,
account_indices,
}
Expand All @@ -896,27 +884,31 @@ pub fn with_mock_invoke_context<R, F: FnMut(&mut InvokeContext) -> R>(
mut callback: F,
) -> R {
let program_indices = vec![0, 1];
let keyed_accounts = [
let transaction_accounts = vec![
(
false,
false,
loader_id,
AccountSharedData::new_ref(0, 0, &solana_sdk::native_loader::id()),
AccountSharedData::new(0, 0, &solana_sdk::native_loader::id()),
),
(
false,
false,
Pubkey::new_unique(),
AccountSharedData::new_ref(1, 0, &loader_id),
AccountSharedData::new(1, 0, &loader_id),
),
(
false,
false,
Pubkey::new_unique(),
AccountSharedData::new_ref(2, account_size, &Pubkey::new_unique()),
AccountSharedData::new(2, account_size, &Pubkey::new_unique()),
),
];
let preparation = prepare_mock_invoke_context(&program_indices, &[], &keyed_accounts);
let instruction_accounts = vec![AccountMeta {
pubkey: transaction_accounts[2].0,
is_signer: false,
is_writable: false,
}];
let preparation = prepare_mock_invoke_context(
&program_indices,
&[],
transaction_accounts,
instruction_accounts,
);
let mut invoke_context = InvokeContext::new_mock(&preparation.accounts, &[]);
invoke_context
.push(
Expand All @@ -933,38 +925,60 @@ pub fn mock_process_instruction_with_sysvars(
loader_id: &Pubkey,
mut program_indices: Vec<usize>,
instruction_data: &[u8],
keyed_accounts: &[(bool, bool, Pubkey, Rc<RefCell<AccountSharedData>>)],
transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
instruction_accounts: Vec<AccountMeta>,
expected_result: Result<(), InstructionError>,
sysvars: &[(Pubkey, Vec<u8>)],
process_instruction: ProcessInstructionWithContext,
) -> Result<(), InstructionError> {
let mut preparation =
prepare_mock_invoke_context(&program_indices, instruction_data, keyed_accounts);
let processor_account = AccountSharedData::new_ref(0, 0, &solana_sdk::native_loader::id());
) -> Vec<AccountSharedData> {
let mut preparation = prepare_mock_invoke_context(
&program_indices,
instruction_data,
transaction_accounts,
instruction_accounts,
);
let processor_account = RefCell::new(AccountSharedData::new(
0,
0,
&solana_sdk::native_loader::id(),
));
program_indices.insert(0, preparation.accounts.len());
preparation.accounts.push((*loader_id, processor_account));
let mut invoke_context = InvokeContext::new_mock(&preparation.accounts, &[]);
invoke_context.sysvars = sysvars;
invoke_context.push(
&preparation.message,
&preparation.message.instructions[0],
&program_indices,
&preparation.account_indices,
)?;
process_instruction(1, instruction_data, &mut invoke_context)
let result = invoke_context
.push(
&preparation.message,
&preparation.message.instructions[0],
&program_indices,
&preparation.account_indices,
)
.and_then(|_| process_instruction(1, instruction_data, &mut invoke_context));
preparation.accounts.pop();
assert_eq!(result, expected_result);
preparation
.accounts
.into_iter()
.map(|(_key, account)| account.into_inner())
.collect()
}

pub fn mock_process_instruction(
loader_id: &Pubkey,
program_indices: Vec<usize>,
instruction_data: &[u8],
keyed_accounts: &[(bool, bool, Pubkey, Rc<RefCell<AccountSharedData>>)],
transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
instruction_accounts: Vec<AccountMeta>,
expected_result: Result<(), InstructionError>,
process_instruction: ProcessInstructionWithContext,
) -> Result<(), InstructionError> {
) -> Vec<AccountSharedData> {
mock_process_instruction_with_sysvars(
loader_id,
program_indices,
instruction_data,
keyed_accounts,
transaction_accounts,
instruction_accounts,
expected_result,
&[],
process_instruction,
)
Expand Down Expand Up @@ -1076,22 +1090,18 @@ mod tests {
invoke_stack.push(solana_sdk::pubkey::new_rand());
accounts.push((
solana_sdk::pubkey::new_rand(),
Rc::new(RefCell::new(AccountSharedData::new(
i as u64,
1,
&invoke_stack[i],
))),
RefCell::new(AccountSharedData::new(i as u64, 1, &invoke_stack[i])),
));
metas.push(AccountMeta::new(accounts[i].0, false));
}
for program_id in invoke_stack.iter() {
accounts.push((
*program_id,
Rc::new(RefCell::new(AccountSharedData::new(
RefCell::new(AccountSharedData::new(
1,
1,
&solana_sdk::pubkey::Pubkey::default(),
))),
)),
));
metas.push(AccountMeta::new(*program_id, false));
}
Expand Down Expand Up @@ -1178,7 +1188,7 @@ mod tests {
fn test_invoke_context_verify() {
let accounts = vec![(
solana_sdk::pubkey::new_rand(),
Rc::new(RefCell::new(AccountSharedData::default())),
RefCell::new(AccountSharedData::default()),
)];
let message = Message::new(
&[Instruction::new_with_bincode(
Expand Down Expand Up @@ -1216,20 +1226,17 @@ mod tests {
program_account.set_executable(true);

let accounts = vec![
(solana_sdk::pubkey::new_rand(), RefCell::new(owned_account)),
(
solana_sdk::pubkey::new_rand(),
Rc::new(RefCell::new(owned_account)),
RefCell::new(not_owned_account),
),
(
solana_sdk::pubkey::new_rand(),
Rc::new(RefCell::new(not_owned_account)),
RefCell::new(readonly_account),
),
(
solana_sdk::pubkey::new_rand(),
Rc::new(RefCell::new(readonly_account)),
),
(caller_program_id, Rc::new(RefCell::new(loader_account))),
(callee_program_id, Rc::new(RefCell::new(program_account))),
(caller_program_id, RefCell::new(loader_account)),
(callee_program_id, RefCell::new(program_account)),
];
let account_indices = [0, 1, 2];
let program_indices = [3, 4];
Expand Down Expand Up @@ -1346,20 +1353,17 @@ mod tests {
program_account.set_executable(true);

let accounts = vec![
(solana_sdk::pubkey::new_rand(), RefCell::new(owned_account)),
(
solana_sdk::pubkey::new_rand(),
Rc::new(RefCell::new(owned_account)),
),
(
solana_sdk::pubkey::new_rand(),
Rc::new(RefCell::new(not_owned_account)),
RefCell::new(not_owned_account),
),
(
solana_sdk::pubkey::new_rand(),
Rc::new(RefCell::new(readonly_account)),
RefCell::new(readonly_account),
),
(caller_program_id, Rc::new(RefCell::new(loader_account))),
(callee_program_id, Rc::new(RefCell::new(program_account))),
(caller_program_id, RefCell::new(loader_account)),
(callee_program_id, RefCell::new(program_account)),
];
let program_indices = [3];
let metas = vec![
Expand Down Expand Up @@ -1441,11 +1445,11 @@ mod tests {
let accounts = vec![
(
solana_sdk::pubkey::new_rand(),
Rc::new(RefCell::new(AccountSharedData::default())),
RefCell::new(AccountSharedData::default()),
),
(
crate::neon_evm_program::id(),
Rc::new(RefCell::new(AccountSharedData::default())),
RefCell::new(AccountSharedData::default()),
),
];

Expand Down
Loading

0 comments on commit 66fa8f9

Please sign in to comment.