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
for tx in entry.transactions {
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) {
match deserialize(&message.instructions[i].data) {
Ok(StorageInstruction::SubmitMiningProof {

View File

@ -707,11 +707,11 @@ impl AccountsDB {
.instructions
.iter()
.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;
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)
})
.collect()

View File

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

View File

@ -129,4 +129,8 @@ impl CompiledInstruction {
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
#[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
/// succeed.
@ -123,9 +123,8 @@ impl Message {
)
}
pub fn program_id(&self, instruction_index: usize) -> &Pubkey {
let program_ids_index = self.instructions[instruction_index].program_ids_index;
&self.program_ids[program_ids_index as usize]
pub fn program_ids(&self) -> &[Pubkey] {
&self.program_ids
}
}

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.
pub fn message(&self) -> &Message {
@ -185,7 +182,7 @@ impl Transaction {
pub fn verify_refs(&self) -> bool {
let message = self.message();
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;
}
for account_index in &instruction.accounts {
@ -207,6 +204,12 @@ mod tests {
use bincode::{deserialize, serialize, serialized_size};
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]
fn test_refs() {
let key = Keypair::new();
@ -245,8 +248,8 @@ mod tests {
assert_eq!(tx.key(0, 2), None);
assert_eq!(tx.signer_key(0, 2), None);
assert_eq!(*tx.program_id(0), prog1);
assert_eq!(*tx.program_id(1), prog2);
assert_eq!(*get_program_id(&tx, 0), prog1);
assert_eq!(*get_program_id(&tx, 1), prog2);
}
#[test]
fn test_refs_invalid_program_id() {
@ -272,7 +275,7 @@ mod tests {
vec![Pubkey::default()],
instructions,
);
assert_eq!(*tx.program_id(0), Pubkey::default());
assert_eq!(*get_program_id(&tx, 0), Pubkey::default());
assert!(!tx.verify_refs());
}
@ -350,7 +353,7 @@ mod tests {
+ (tx.message.account_keys.len() * size_of::<Pubkey>())
+ blockhash_size
+ len_size
+ (tx.message.program_ids.len() * size_of::<Pubkey>())
+ (tx.message.program_ids().len() * size_of::<Pubkey>())
+ len_size
+ expected_instruction_size;
assert_eq!(expected_transaction_size, 214);