Optimize Message::is_non_loader_key method (#18579)

This commit is contained in:
Justin Starry 2021-07-12 10:42:22 -05:00 committed by GitHub
parent 12aa238eb1
commit e806d31224
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 25 additions and 51 deletions

View File

@ -201,7 +201,7 @@ pub fn write_transaction<W: io::Write>(
} }
let mut fee_payer_index = None; let mut fee_payer_index = None;
for (account_index, account) in message.account_keys.iter().enumerate() { for (account_index, account) in message.account_keys.iter().enumerate() {
if fee_payer_index.is_none() && message.is_non_loader_key(account, account_index) { if fee_payer_index.is_none() && message.is_non_loader_key(account_index) {
fee_payer_index = Some(account_index) fee_payer_index = Some(account_index)
} }
writeln!( writeln!(

View File

@ -28,7 +28,7 @@ use solana_sdk::{
fee_calculator::FeeCalculator, fee_calculator::FeeCalculator,
genesis_config::ClusterType, genesis_config::ClusterType,
hash::Hash, hash::Hash,
message::{Message, MessageProgramIdsCache}, message::Message,
native_loader, nonce, native_loader, nonce,
pubkey::Pubkey, pubkey::Pubkey,
transaction::Result, transaction::Result,
@ -208,12 +208,11 @@ impl Accounts {
let mut tx_rent: TransactionRent = 0; let mut tx_rent: TransactionRent = 0;
let mut accounts = Vec::with_capacity(message.account_keys.len()); let mut accounts = Vec::with_capacity(message.account_keys.len());
let mut account_deps = Vec::with_capacity(message.account_keys.len()); let mut account_deps = Vec::with_capacity(message.account_keys.len());
let mut key_check = MessageProgramIdsCache::new(message);
let mut rent_debits = RentDebits::default(); let mut rent_debits = RentDebits::default();
let rent_for_sysvars = feature_set.is_active(&feature_set::rent_for_sysvars::id()); let rent_for_sysvars = feature_set.is_active(&feature_set::rent_for_sysvars::id());
for (i, key) in message.account_keys.iter().enumerate() { for (i, key) in message.account_keys.iter().enumerate() {
let account = if key_check.is_non_loader_key(key, i) { let account = if message.is_non_loader_key(i) {
if payer_index.is_none() { if payer_index.is_none() {
payer_index = Some(i); payer_index = Some(i);
} }
@ -981,7 +980,7 @@ impl Accounts {
let mut fee_payer_index = None; let mut fee_payer_index = None;
for (i, (key, account)) in (0..message.account_keys.len()) for (i, (key, account)) in (0..message.account_keys.len())
.zip(loaded_transaction.accounts.iter_mut()) .zip(loaded_transaction.accounts.iter_mut())
.filter(|(i, (key, _account))| message.is_non_loader_key(key, *i)) .filter(|(i, _account)| message.is_non_loader_key(*i))
{ {
let is_nonce_account = prepare_if_nonce_account( let is_nonce_account = prepare_if_nonce_account(
account, account,

View File

@ -632,7 +632,7 @@ impl NonceRollbackFull {
} = partial; } = partial;
let fee_payer = (0..message.account_keys.len()).find_map(|i| { let fee_payer = (0..message.account_keys.len()).find_map(|i| {
if let Some((k, a)) = &accounts.get(i) { if let Some((k, a)) = &accounts.get(i) {
if message.is_non_loader_key(k, i) { if message.is_non_loader_key(i) {
return Some((k, a)); return Some((k, a));
} }
} }

View File

@ -240,26 +240,6 @@ impl Sanitize for Message {
Ok(()) Ok(())
} }
} }
pub struct MessageProgramIdsCache<'a> {
program_ids: Option<Vec<&'a Pubkey>>,
message: &'a Message,
}
impl<'a> MessageProgramIdsCache<'a> {
pub fn new(message: &'a Message) -> Self {
Self {
program_ids: None,
message,
}
}
pub fn is_non_loader_key(&mut self, key: &Pubkey, key_index: usize) -> bool {
if self.program_ids.is_none() {
self.program_ids = Some(self.message.program_ids());
}
self.message
.is_non_loader_key_internal(self.program_ids.as_ref().unwrap(), key, key_index)
}
}
impl Message { impl Message {
pub fn new_with_compiled_instructions( pub fn new_with_compiled_instructions(
@ -356,28 +336,28 @@ impl Message {
.collect() .collect()
} }
pub fn is_key_passed_to_program(&self, index: usize) -> bool { pub fn is_key_passed_to_program(&self, key_index: usize) -> bool {
if let Ok(index) = u8::try_from(index) { if let Ok(key_index) = u8::try_from(key_index) {
for ix in self.instructions.iter() { self.instructions
if ix.accounts.contains(&index) { .iter()
return true; .any(|ix| ix.accounts.contains(&key_index))
} } else {
} false
} }
false
} }
pub(crate) fn is_non_loader_key_internal( pub fn is_key_called_as_program(&self, key_index: usize) -> bool {
&self, if let Ok(key_index) = u8::try_from(key_index) {
program_ids: &[&Pubkey], self.instructions
key: &Pubkey, .iter()
key_index: usize, .any(|ix| ix.program_id_index == key_index)
) -> bool { } else {
!program_ids.contains(&key) || self.is_key_passed_to_program(key_index) false
}
} }
pub fn is_non_loader_key(&self, key: &Pubkey, key_index: usize) -> bool { pub fn is_non_loader_key(&self, key_index: usize) -> bool {
self.is_non_loader_key_internal(&self.program_ids(), key, key_index) !self.is_key_called_as_program(key_index) || self.is_key_passed_to_program(key_index)
} }
pub fn program_position(&self, index: usize) -> Option<usize> { pub fn program_position(&self, index: usize) -> Option<usize> {
@ -1029,14 +1009,9 @@ mod tests {
Hash::default(), Hash::default(),
instructions, instructions,
); );
let mut helper = MessageProgramIdsCache::new(&message); assert!(message.is_non_loader_key(0));
assert!(message.is_non_loader_key(1));
assert!(message.is_non_loader_key(&key0, 0)); assert!(!message.is_non_loader_key(2));
assert!(message.is_non_loader_key(&key1, 1));
assert!(!message.is_non_loader_key(&loader2, 2));
assert!(helper.is_non_loader_key(&key0, 0));
assert!(helper.is_non_loader_key(&key1, 1));
assert!(!helper.is_non_loader_key(&loader2, 2));
} }
#[test] #[test]