Add program_ids() methods

Added CompiledInstruction::program_id() so that we don't need to pass
around instruction indexes just for Message::program_id().

Also added Message.program_ids() that returns a slice so that we
can move those pubkeys into Message::account_keys.
This commit is contained in:
Greg Fitzgerald
2019-04-02 16:02:57 -06:00
parent 025b4f90de
commit 4c0bc1fd88
6 changed files with 31 additions and 25 deletions

View File

@ -402,7 +402,7 @@ impl StorageStage {
// the storage_keys with their signatures // the storage_keys with their signatures
for tx in entry.transactions { for tx in entry.transactions {
let message = tx.message(); let message = tx.message();
for (i, program_id) in message.program_ids.iter().enumerate() { for (i, program_id) in message.program_ids().iter().enumerate() {
if solana_storage_api::check_id(&program_id) { if solana_storage_api::check_id(&program_id) {
match deserialize(&message.instructions[i].data) { match deserialize(&message.instructions[i].data) {
Ok(StorageInstruction::SubmitMiningProof { Ok(StorageInstruction::SubmitMiningProof {

View File

@ -707,11 +707,11 @@ impl AccountsDB {
.instructions .instructions
.iter() .iter()
.map(|ix| { .map(|ix| {
if message.program_ids.len() <= ix.program_ids_index as usize { if message.program_ids().len() <= ix.program_ids_index as usize {
error_counters.account_not_found += 1; error_counters.account_not_found += 1;
return Err(TransactionError::AccountNotFound); return Err(TransactionError::AccountNotFound);
} }
let program_id = message.program_ids[ix.program_ids_index as usize]; let program_id = message.program_ids()[ix.program_ids_index as usize];
self.load_executable_accounts(fork, &program_id, error_counters) self.load_executable_accounts(fork, &program_id, error_counters)
}) })
.collect() .collect()

View File

@ -1,7 +1,7 @@
use crate::native_loader; use crate::native_loader;
use crate::system_instruction_processor; use crate::system_instruction_processor;
use solana_sdk::account::{create_keyed_accounts, Account, KeyedAccount}; use solana_sdk::account::{create_keyed_accounts, Account, KeyedAccount};
use solana_sdk::instruction::InstructionError; use solana_sdk::instruction::{CompiledInstruction, InstructionError};
use solana_sdk::message::Message; use solana_sdk::message::Message;
use solana_sdk::pubkey::Pubkey; use solana_sdk::pubkey::Pubkey;
use solana_sdk::system_program; use solana_sdk::system_program;
@ -118,15 +118,15 @@ impl MessageProcessor {
fn process_instruction( fn process_instruction(
&self, &self,
message: &Message, message: &Message,
instruction_index: usize, instruction: &CompiledInstruction,
executable_accounts: &mut [(Pubkey, Account)], executable_accounts: &mut [(Pubkey, Account)],
program_accounts: &mut [&mut Account], program_accounts: &mut [&mut Account],
tick_height: u64, tick_height: u64,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
let program_id = message.program_id(instruction_index); let program_id = instruction.program_id(message.program_ids());
let mut keyed_accounts = create_keyed_accounts(executable_accounts); let mut keyed_accounts = create_keyed_accounts(executable_accounts);
let mut keyed_accounts2: Vec<_> = message.instructions[instruction_index] let mut keyed_accounts2: Vec<_> = instruction
.accounts .accounts
.iter() .iter()
.map(|&index| { .map(|&index| {
@ -144,7 +144,7 @@ impl MessageProcessor {
return process_instruction( return process_instruction(
&program_id, &program_id,
&mut keyed_accounts[1..], &mut keyed_accounts[1..],
&message.instructions[instruction_index].data, &instruction.data,
tick_height, tick_height,
); );
} }
@ -153,7 +153,7 @@ impl MessageProcessor {
native_loader::entrypoint( native_loader::entrypoint(
&program_id, &program_id,
&mut keyed_accounts, &mut keyed_accounts,
&message.instructions[instruction_index].data, &instruction.data,
tick_height, tick_height,
) )
} }
@ -165,12 +165,12 @@ impl MessageProcessor {
fn execute_instruction( fn execute_instruction(
&self, &self,
message: &Message, message: &Message,
instruction_index: usize, instruction: &CompiledInstruction,
executable_accounts: &mut [(Pubkey, Account)], executable_accounts: &mut [(Pubkey, Account)],
program_accounts: &mut [&mut Account], program_accounts: &mut [&mut Account],
tick_height: u64, tick_height: u64,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
let program_id = message.program_id(instruction_index); let program_id = instruction.program_id(message.program_ids());
// TODO: the runtime should be checking read/write access to memory // TODO: the runtime should be checking read/write access to memory
// we are trusting the hard-coded programs not to clobber or allocate // we are trusting the hard-coded programs not to clobber or allocate
let pre_total: u64 = program_accounts.iter().map(|a| a.lamports).sum(); let pre_total: u64 = program_accounts.iter().map(|a| a.lamports).sum();
@ -181,7 +181,7 @@ impl MessageProcessor {
self.process_instruction( self.process_instruction(
message, message,
instruction_index, instruction,
executable_accounts, executable_accounts,
program_accounts, program_accounts,
tick_height, tick_height,
@ -224,7 +224,7 @@ impl MessageProcessor {
.map_err(|err| TransactionError::InstructionError(instruction_index as u8, err))?; .map_err(|err| TransactionError::InstructionError(instruction_index as u8, err))?;
self.execute_instruction( self.execute_instruction(
message, message,
instruction_index, instruction,
executable_accounts, executable_accounts,
&mut program_accounts, &mut program_accounts,
tick_height, tick_height,

View File

@ -129,4 +129,8 @@ impl CompiledInstruction {
accounts, accounts,
} }
} }
pub fn program_id<'a>(&self, program_ids: &'a [Pubkey]) -> &'a Pubkey {
&program_ids[self.program_ids_index as usize]
}
} }

View File

@ -83,7 +83,7 @@ pub struct Message {
/// All the program id keys used to execute this transaction's instructions /// All the program id keys used to execute this transaction's instructions
#[serde(with = "short_vec")] #[serde(with = "short_vec")]
pub program_ids: Vec<Pubkey>, program_ids: Vec<Pubkey>,
/// Programs that will be executed in sequence and committed in one atomic transaction if all /// Programs that will be executed in sequence and committed in one atomic transaction if all
/// succeed. /// succeed.
@ -123,9 +123,8 @@ impl Message {
) )
} }
pub fn program_id(&self, instruction_index: usize) -> &Pubkey { pub fn program_ids(&self) -> &[Pubkey] {
let program_ids_index = self.instructions[instruction_index].program_ids_index; &self.program_ids
&self.program_ids[program_ids_index as usize]
} }
} }

View File

@ -145,9 +145,6 @@ impl Transaction {
} }
} }
} }
pub fn program_id(&self, instruction_index: usize) -> &Pubkey {
self.message().program_id(instruction_index)
}
/// Return a message containing all data that should be signed. /// Return a message containing all data that should be signed.
pub fn message(&self) -> &Message { pub fn message(&self) -> &Message {
@ -185,7 +182,7 @@ impl Transaction {
pub fn verify_refs(&self) -> bool { pub fn verify_refs(&self) -> bool {
let message = self.message(); let message = self.message();
for instruction in &message.instructions { for instruction in &message.instructions {
if (instruction.program_ids_index as usize) >= message.program_ids.len() { if (instruction.program_ids_index as usize) >= message.program_ids().len() {
return false; return false;
} }
for account_index in &instruction.accounts { for account_index in &instruction.accounts {
@ -207,6 +204,12 @@ mod tests {
use bincode::{deserialize, serialize, serialized_size}; use bincode::{deserialize, serialize, serialized_size};
use std::mem::size_of; use std::mem::size_of;
fn get_program_id(tx: &Transaction, instruction_index: usize) -> &Pubkey {
let message = tx.message();
let instruction = &message.instructions[instruction_index];
instruction.program_id(message.program_ids())
}
#[test] #[test]
fn test_refs() { fn test_refs() {
let key = Keypair::new(); let key = Keypair::new();
@ -245,8 +248,8 @@ mod tests {
assert_eq!(tx.key(0, 2), None); assert_eq!(tx.key(0, 2), None);
assert_eq!(tx.signer_key(0, 2), None); assert_eq!(tx.signer_key(0, 2), None);
assert_eq!(*tx.program_id(0), prog1); assert_eq!(*get_program_id(&tx, 0), prog1);
assert_eq!(*tx.program_id(1), prog2); assert_eq!(*get_program_id(&tx, 1), prog2);
} }
#[test] #[test]
fn test_refs_invalid_program_id() { fn test_refs_invalid_program_id() {
@ -272,7 +275,7 @@ mod tests {
vec![Pubkey::default()], vec![Pubkey::default()],
instructions, instructions,
); );
assert_eq!(*tx.program_id(0), Pubkey::default()); assert_eq!(*get_program_id(&tx, 0), Pubkey::default());
assert!(!tx.verify_refs()); assert!(!tx.verify_refs());
} }
@ -350,7 +353,7 @@ mod tests {
+ (tx.message.account_keys.len() * size_of::<Pubkey>()) + (tx.message.account_keys.len() * size_of::<Pubkey>())
+ blockhash_size + blockhash_size
+ len_size + len_size
+ (tx.message.program_ids.len() * size_of::<Pubkey>()) + (tx.message.program_ids().len() * size_of::<Pubkey>())
+ len_size + len_size
+ expected_instruction_size; + expected_instruction_size;
assert_eq!(expected_transaction_size, 214); assert_eq!(expected_transaction_size, 214);