diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index ccd1f0b3bd..5e10cc2320 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -614,7 +614,7 @@ pub struct TransactionLogCollectorConfig { pub filter: TransactionLogCollectorFilter, } -#[derive(AbiExample, Clone, Debug)] +#[derive(AbiExample, Clone, Debug, PartialEq)] pub struct TransactionLogInfo { pub signature: Signature, pub result: Result<()>, @@ -633,6 +633,23 @@ pub struct TransactionLogCollector { pub mentioned_address_map: HashMap>, } +impl TransactionLogCollector { + pub fn get_logs_for_address( + &self, + address: Option<&Pubkey>, + ) -> Option> { + match address { + None => Some(self.logs.clone()), + Some(address) => self.mentioned_address_map.get(address).map(|log_indices| { + log_indices + .iter() + .filter_map(|i| self.logs.get(*i).cloned()) + .collect() + }), + } + } +} + pub trait NonceRollbackInfo { fn nonce_address(&self) -> &Pubkey; fn nonce_account(&self) -> &AccountSharedData; @@ -3854,10 +3871,7 @@ impl Bank { if Self::can_commit(r) // Skip log collection for unprocessed transactions && transaction_log_collector_config.filter != TransactionLogCollectorFilter::None { - let mut transaction_log_collector = self.transaction_log_collector.write().unwrap(); - let transaction_log_index = transaction_log_collector.logs.len(); - - let mut mentioned_address = false; + let mut filtered_mentioned_addresses = Vec::new(); if !transaction_log_collector_config .mentioned_addresses .is_empty() @@ -3867,32 +3881,42 @@ impl Bank { .mentioned_addresses .contains(key) { - transaction_log_collector - .mentioned_address_map - .entry(*key) - .or_default() - .push(transaction_log_index); - mentioned_address = true; + filtered_mentioned_addresses.push(*key); } } } let is_vote = is_simple_vote_transaction(tx); let store = match transaction_log_collector_config.filter { - TransactionLogCollectorFilter::All => !is_vote || mentioned_address, + TransactionLogCollectorFilter::All => { + !is_vote || !filtered_mentioned_addresses.is_empty() + } TransactionLogCollectorFilter::AllWithVotes => true, TransactionLogCollectorFilter::None => false, - TransactionLogCollectorFilter::OnlyMentionedAddresses => mentioned_address, + TransactionLogCollectorFilter::OnlyMentionedAddresses => { + !filtered_mentioned_addresses.is_empty() + } }; if store { if let Some(log_messages) = transaction_log_messages.get(i).cloned().flatten() { + let mut transaction_log_collector = + self.transaction_log_collector.write().unwrap(); + let transaction_log_index = transaction_log_collector.logs.len(); + transaction_log_collector.logs.push(TransactionLogInfo { signature: tx.signatures[0], result: r.clone(), is_vote, log_messages, }); + for key in filtered_mentioned_addresses.into_iter() { + transaction_log_collector + .mentioned_address_map + .entry(key) + .or_default() + .push(transaction_log_index); + } } } } @@ -5047,20 +5071,10 @@ impl Bank { &self, address: Option<&Pubkey>, ) -> Option> { - let transaction_log_collector = self.transaction_log_collector.read().unwrap(); - - match address { - None => Some(transaction_log_collector.logs.clone()), - Some(address) => transaction_log_collector - .mentioned_address_map - .get(address) - .map(|log_indices| { - log_indices - .iter() - .map(|i| transaction_log_collector.logs[*i].clone()) - .collect() - }), - } + self.transaction_log_collector + .read() + .unwrap() + .get_logs_for_address(address) } pub fn get_all_accounts_modified_since_parent(&self) -> Vec<(Pubkey, AccountSharedData)> { @@ -14409,4 +14423,19 @@ pub(crate) mod tests { let tx = Transaction::new(&[&mint_keypair], message, bank.last_blockhash()); bank.process_transaction(&tx).unwrap(); } + + #[test] + fn test_transaction_log_collector_get_logs_for_address() { + let address = Pubkey::new_unique(); + let mut mentioned_address_map = HashMap::new(); + mentioned_address_map.insert(address, vec![0]); + let transaction_log_collector = TransactionLogCollector { + mentioned_address_map, + ..TransactionLogCollector::default() + }; + assert_eq!( + transaction_log_collector.get_logs_for_address(Some(&address)), + Some(Vec::::new()), + ); + } }