Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Refactor instruction compilation and update message account key ordering #23729

Merged
merged 4 commits into from
Mar 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions cli-output/src/cli_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2776,10 +2776,10 @@ mod tests {

let expected_msg = "AwECBwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDgTl3Dqh9\
F19Wo1Rmw0x+zMuNipG07jeiXfYPW4/Js5QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE\
BAQEBAYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBQUFBQUFBQUFBQUFBQUFBQUF\
BQUFBQUFBQUFBQUFBQUGp9UXGSxWjuCKhF9z0peIzwNcMUWyGrNE2AYuqUAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcH\
BwcCBgMDBQIEBAAAAAYCAQQMAgAAACoAAAAAAAAA"
BAQEBAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBgYGBgYGBgYGBgYGBgYGBgYG\
BgYGBgYGBgYGBgYGBgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAan1RcZLFaO\
4IqEX3PSl4jPA1wxRbIas0TYBi6pQAAABwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcH\
BwcCBQMEBgIEBAAAAAUCAQMMAgAAACoAAAAAAAAA"
.to_string();
let config = ReturnSignersConfig {
dump_transaction_message: true,
Expand Down
82 changes: 49 additions & 33 deletions runtime/src/message_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ mod tests {
solana_sdk::{
account::{AccountSharedData, ReadableAccount},
instruction::{AccountMeta, Instruction, InstructionError},
message::Message,
message::{AccountKeys, Message},
native_loader::{self, create_loadable_account_for_test},
pubkey::Pubkey,
secp256k1_instruction::new_secp256k1_instruction,
Expand Down Expand Up @@ -219,7 +219,10 @@ mod tests {
}
}

let mock_system_program_id = Pubkey::new(&[2u8; 32]);
let writable_pubkey = Pubkey::new_unique();
let readonly_pubkey = Pubkey::new_unique();
let mock_system_program_id = Pubkey::new_unique();

let rent_collector = RentCollector::default();
let builtin_programs = &[BuiltinProgram {
program_id: mock_system_program_id,
Expand All @@ -228,11 +231,11 @@ mod tests {

let accounts = vec![
(
solana_sdk::pubkey::new_rand(),
writable_pubkey,
AccountSharedData::new(100, 1, &mock_system_program_id),
),
(
solana_sdk::pubkey::new_rand(),
readonly_pubkey,
AccountSharedData::new(0, 1, &mock_system_program_id),
),
(
Expand All @@ -243,24 +246,25 @@ mod tests {
let mut transaction_context = TransactionContext::new(accounts, 1, 3);
let program_indices = vec![vec![2]];
let executors = Rc::new(RefCell::new(Executors::default()));
let account_keys = transaction_context.get_keys_of_accounts().to_vec();
let account_metas = vec![
AccountMeta::new(
*transaction_context.get_key_of_account_at_index(0).unwrap(),
true,
),
AccountMeta::new_readonly(
*transaction_context.get_key_of_account_at_index(1).unwrap(),
false,
),
AccountMeta::new(writable_pubkey, true),
AccountMeta::new_readonly(readonly_pubkey, false),
];

let message = SanitizedMessage::Legacy(Message::new(
&[Instruction::new_with_bincode(
mock_system_program_id,
&MockSystemInstruction::Correct,
account_metas.clone(),
)],
Some(transaction_context.get_key_of_account_at_index(0).unwrap()),
let message = SanitizedMessage::Legacy(Message::new_with_compiled_instructions(
1,
0,
2,
account_keys.clone(),
Hash::default(),
AccountKeys::new(&account_keys, None).compile_instructions(&[
Instruction::new_with_bincode(
mock_system_program_id,
&MockSystemInstruction::Correct,
account_metas.clone(),
),
]),
));
let sysvar_cache = SysvarCache::default();
let result = MessageProcessor::process_message(
Expand Down Expand Up @@ -297,13 +301,19 @@ mod tests {
0
);

let message = SanitizedMessage::Legacy(Message::new(
&[Instruction::new_with_bincode(
mock_system_program_id,
&MockSystemInstruction::TransferLamports { lamports: 50 },
account_metas.clone(),
)],
Some(transaction_context.get_key_of_account_at_index(0).unwrap()),
let message = SanitizedMessage::Legacy(Message::new_with_compiled_instructions(
1,
0,
2,
account_keys.clone(),
Hash::default(),
AccountKeys::new(&account_keys, None).compile_instructions(&[
Instruction::new_with_bincode(
mock_system_program_id,
&MockSystemInstruction::TransferLamports { lamports: 50 },
account_metas.clone(),
),
]),
));
let result = MessageProcessor::process_message(
builtin_programs,
Expand All @@ -329,13 +339,19 @@ mod tests {
))
);

let message = SanitizedMessage::Legacy(Message::new(
&[Instruction::new_with_bincode(
mock_system_program_id,
&MockSystemInstruction::ChangeData { data: 50 },
account_metas,
)],
Some(transaction_context.get_key_of_account_at_index(0).unwrap()),
let message = SanitizedMessage::Legacy(Message::new_with_compiled_instructions(
1,
0,
2,
account_keys.clone(),
Hash::default(),
AccountKeys::new(&account_keys, None).compile_instructions(&[
Instruction::new_with_bincode(
mock_system_program_id,
&MockSystemInstruction::ChangeData { data: 50 },
account_metas,
),
]),
));
let result = MessageProcessor::process_message(
builtin_programs,
Expand Down
35 changes: 33 additions & 2 deletions sdk/program/src/message/account_keys.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use {
crate::{message::v0::LoadedAddresses, pubkey::Pubkey},
std::ops::Index,
crate::{
instruction::{CompiledInstruction, Instruction},
message::v0::LoadedAddresses,
pubkey::Pubkey,
},
std::{collections::BTreeMap, ops::Index},
};

/// Collection of static and dynamically loaded keys used to load accounts
Expand Down Expand Up @@ -75,6 +79,33 @@ impl<'a> AccountKeys<'a> {
pub fn iter(&self) -> impl Iterator<Item = &'a Pubkey> {
self.key_segment_iter().flatten()
}

/// Compile instructions using the order of account keys to determine
/// compiled instruction account indexes.
pub fn compile_instructions(&self, instructions: &[Instruction]) -> Vec<CompiledInstruction> {
let account_index_map: BTreeMap<&Pubkey, u8> = BTreeMap::from_iter(
self.iter()
.enumerate()
.map(|(index, key)| (key, index as u8)),
);

instructions
.iter()
.map(|ix| {
let accounts: Vec<u8> = ix
.accounts
.iter()
.map(|account_meta| *account_index_map.get(&account_meta.pubkey).unwrap())
.collect();

CompiledInstruction {
program_id_index: *account_index_map.get(&ix.program_id).unwrap(),
data: ix.data.clone(),
accounts,
}
})
.collect()
}
}

#[cfg(test)]
Expand Down
Loading