Fix transaction logs and inner ixs for leader nodes (backport #18395) (#18448)

* Fix transaction logs and inner ixs for leader nodes (#18395)

* Fix transaction logs and inner ixs for leader nodes

* Fix cpi log storage flag

(cherry picked from commit 5dd399dafa)

# Conflicts:
#	runtime/src/bank.rs

* resolve conflict

Co-authored-by: Justin Starry <justin@solana.com>
This commit is contained in:
mergify[bot]
2021-07-06 23:04:19 +00:00
committed by GitHub
parent 75a2b66206
commit 6afeaac7a5
4 changed files with 65 additions and 77 deletions

View File

@ -1199,7 +1199,7 @@ pub struct TransactionStatusBatch {
pub balances: TransactionBalancesSet, pub balances: TransactionBalancesSet,
pub token_balances: TransactionTokenBalancesSet, pub token_balances: TransactionTokenBalancesSet,
pub inner_instructions: Option<Vec<Option<InnerInstructionsList>>>, pub inner_instructions: Option<Vec<Option<InnerInstructionsList>>>,
pub transaction_logs: Option<Vec<TransactionLogMessages>>, pub transaction_logs: Option<Vec<Option<TransactionLogMessages>>>,
pub rent_debits: Vec<RentDebits>, pub rent_debits: Vec<RentDebits>,
} }
@ -1218,7 +1218,7 @@ impl TransactionStatusSender {
balances: TransactionBalancesSet, balances: TransactionBalancesSet,
token_balances: TransactionTokenBalancesSet, token_balances: TransactionTokenBalancesSet,
inner_instructions: Vec<Option<InnerInstructionsList>>, inner_instructions: Vec<Option<InnerInstructionsList>>,
transaction_logs: Vec<TransactionLogMessages>, transaction_logs: Vec<Option<TransactionLogMessages>>,
rent_debits: Vec<RentDebits>, rent_debits: Vec<RentDebits>,
) { ) {
let slot = bank.slot(); let slot = bank.slot();

View File

@ -292,26 +292,24 @@ fn process_transaction_and_record_inner(
let signature = tx.signatures.get(0).unwrap().clone(); let signature = tx.signatures.get(0).unwrap().clone();
let txs = vec![tx]; let txs = vec![tx];
let tx_batch = bank.prepare_batch(txs.iter()); let tx_batch = bank.prepare_batch(txs.iter());
let (mut results, _, mut inner, _transaction_logs) = bank.load_execute_and_commit_transactions( let (mut results, _, mut inner_instructions, _transaction_logs) = bank
&tx_batch, .load_execute_and_commit_transactions(
MAX_PROCESSING_AGE, &tx_batch,
false, MAX_PROCESSING_AGE,
true, false,
false, true,
&mut ExecuteTimings::default(), false,
); &mut ExecuteTimings::default(),
let inner_instructions = if inner.is_empty() { );
Some(vec![vec![]])
} else {
inner.swap_remove(0)
};
let result = results let result = results
.fee_collection_results .fee_collection_results
.swap_remove(0) .swap_remove(0)
.and_then(|_| bank.get_signature_status(&signature).unwrap()); .and_then(|_| bank.get_signature_status(&signature).unwrap());
( (
result, result,
inner_instructions.expect("cpi recording should be enabled"), inner_instructions
.swap_remove(0)
.expect("cpi recording should be enabled"),
) )
} }
@ -329,8 +327,8 @@ fn execute_transactions(bank: &Bank, txs: &[Transaction]) -> Vec<ConfirmedTransa
post_balances, post_balances,
.. ..
}, },
mut inner_instructions, inner_instructions,
mut transaction_logs, transaction_logs,
) = bank.load_execute_and_commit_transactions( ) = bank.load_execute_and_commit_transactions(
&batch, &batch,
std::usize::MAX, std::usize::MAX,
@ -341,13 +339,6 @@ fn execute_transactions(bank: &Bank, txs: &[Transaction]) -> Vec<ConfirmedTransa
); );
let tx_post_token_balances = collect_token_balances(&bank, &batch, &mut mint_decimals); let tx_post_token_balances = collect_token_balances(&bank, &batch, &mut mint_decimals);
for _ in 0..(txs.len() - transaction_logs.len()) {
transaction_logs.push(vec![]);
}
for _ in 0..(txs.len() - inner_instructions.len()) {
inner_instructions.push(None);
}
izip!( izip!(
txs.iter(), txs.iter(),
execution_results.into_iter(), execution_results.into_iter(),
@ -395,7 +386,7 @@ fn execute_transactions(bank: &Bank, txs: &[Transaction]) -> Vec<ConfirmedTransa
pre_token_balances: Some(pre_token_balances), pre_token_balances: Some(pre_token_balances),
post_token_balances: Some(post_token_balances), post_token_balances: Some(post_token_balances),
inner_instructions, inner_instructions,
log_messages: Some(log_messages), log_messages,
rewards: None, rewards: None,
}; };

View File

@ -74,12 +74,13 @@ impl TransactionStatusService {
} else { } else {
Box::new(std::iter::repeat_with(|| None)) Box::new(std::iter::repeat_with(|| None))
}; };
let transaction_logs_iter: Box<dyn Iterator<Item = TransactionLogMessages>> = let transaction_logs_iter: Box<
if let Some(transaction_logs) = transaction_logs { dyn Iterator<Item = Option<TransactionLogMessages>>,
Box::new(transaction_logs.into_iter()) > = if let Some(transaction_logs) = transaction_logs {
} else { Box::new(transaction_logs.into_iter())
Box::new(std::iter::repeat_with(Vec::new)) } else {
}; Box::new(std::iter::repeat_with(|| None))
};
for ( for (
transaction, transaction,
(status, nonce_rollback), (status, nonce_rollback),
@ -125,7 +126,6 @@ impl TransactionStatusService {
.collect() .collect()
}); });
let log_messages = Some(log_messages);
let pre_token_balances = Some(pre_token_balances); let pre_token_balances = Some(pre_token_balances);
let post_token_balances = Some(post_token_balances); let post_token_balances = Some(post_token_balances);
let rewards = Some( let rewards = Some(

View File

@ -2670,9 +2670,7 @@ impl Bank {
); );
let transaction_result = executed[0].0.clone().map(|_| ()); let transaction_result = executed[0].0.clone().map(|_| ());
let log_messages = log_messages let log_messages = log_messages.get(0).cloned().flatten().unwrap_or_default();
.get(0)
.map_or(vec![], |messages| messages.to_vec());
let post_transaction_accounts = loaded_accounts let post_transaction_accounts = loaded_accounts
.into_iter() .into_iter()
.next() .next()
@ -2995,17 +2993,22 @@ impl Bank {
Ok(()) Ok(())
} }
fn collect_log_messages(
log_collector: Option<Rc<LogCollector>>,
) -> Option<TransactionLogMessages> {
log_collector.and_then(|log_collector| Rc::try_unwrap(log_collector).map(Into::into).ok())
}
fn compile_recorded_instructions( fn compile_recorded_instructions(
inner_instructions: &mut Vec<Option<InnerInstructionsList>>,
instruction_recorders: Option<Vec<InstructionRecorder>>, instruction_recorders: Option<Vec<InstructionRecorder>>,
message: &Message, message: &Message,
) { ) -> Option<InnerInstructionsList> {
inner_instructions.push(instruction_recorders.map(|instruction_recorders| { instruction_recorders.map(|instruction_recorders| {
instruction_recorders instruction_recorders
.into_iter() .into_iter()
.map(|r| r.compile_instructions(message)) .map(|r| r.compile_instructions(message))
.collect() .collect()
})); })
} }
/// Get any cached executors needed by the transaction /// Get any cached executors needed by the transaction
@ -3072,7 +3075,7 @@ impl Bank {
Vec<TransactionLoadResult>, Vec<TransactionLoadResult>,
Vec<TransactionExecutionResult>, Vec<TransactionExecutionResult>,
Vec<Option<InnerInstructionsList>>, Vec<Option<InnerInstructionsList>>,
Vec<TransactionLogMessages>, Vec<Option<TransactionLogMessages>>,
Vec<usize>, Vec<usize>,
u64, u64,
u64, u64,
@ -3121,7 +3124,8 @@ impl Bank {
let mut signature_count: u64 = 0; let mut signature_count: u64 = 0;
let mut inner_instructions: Vec<Option<InnerInstructionsList>> = let mut inner_instructions: Vec<Option<InnerInstructionsList>> =
Vec::with_capacity(hashed_txs.len()); Vec::with_capacity(hashed_txs.len());
let mut transaction_log_messages = Vec::with_capacity(hashed_txs.len()); let mut transaction_log_messages: Vec<Option<Vec<String>>> =
Vec::with_capacity(hashed_txs.len());
let bpf_compute_budget = self let bpf_compute_budget = self
.bpf_compute_budget .bpf_compute_budget
.unwrap_or_else(BpfComputeBudget::new); .unwrap_or_else(BpfComputeBudget::new);
@ -3130,7 +3134,11 @@ impl Bank {
.iter_mut() .iter_mut()
.zip(hashed_txs.as_transactions_iter()) .zip(hashed_txs.as_transactions_iter())
.map(|(accs, tx)| match accs { .map(|(accs, tx)| match accs {
(Err(e), _nonce_rollback) => (Err(e.clone()), None), (Err(e), _nonce_rollback) => {
inner_instructions.push(None);
transaction_log_messages.push(None);
(Err(e.clone()), None)
}
(Ok(loaded_transaction), nonce_rollback) => { (Ok(loaded_transaction), nonce_rollback) => {
signature_count += u64::from(tx.message().header.num_required_signatures); signature_count += u64::from(tx.message().header.num_required_signatures);
let executors = self.get_executors(&tx.message, &loaded_transaction.loaders); let executors = self.get_executors(&tx.message, &loaded_transaction.loaders);
@ -3173,20 +3181,11 @@ impl Bank {
&self.ancestors, &self.ancestors,
); );
if enable_log_recording { transaction_log_messages.push(Self::collect_log_messages(log_collector));
let log_messages: TransactionLogMessages = inner_instructions.push(Self::compile_recorded_instructions(
Rc::try_unwrap(log_collector.unwrap_or_default())
.unwrap_or_default()
.into();
transaction_log_messages.push(log_messages);
}
Self::compile_recorded_instructions(
&mut inner_instructions,
instruction_recorders, instruction_recorders,
&tx.message, &tx.message,
); ));
if let Err(e) = Self::refcells_to_accounts( if let Err(e) = Self::refcells_to_accounts(
&mut loaded_transaction.accounts, &mut loaded_transaction.accounts,
@ -3272,7 +3271,6 @@ impl Bank {
} }
let is_vote = is_simple_vote_transaction(tx); let is_vote = is_simple_vote_transaction(tx);
let store = match transaction_log_collector_config.filter { let store = match transaction_log_collector_config.filter {
TransactionLogCollectorFilter::All => !is_vote || mentioned_address, TransactionLogCollectorFilter::All => !is_vote || mentioned_address,
TransactionLogCollectorFilter::AllWithVotes => true, TransactionLogCollectorFilter::AllWithVotes => true,
@ -3281,12 +3279,14 @@ impl Bank {
}; };
if store { if store {
transaction_log_collector.logs.push(TransactionLogInfo { if let Some(log_messages) = transaction_log_messages.get(i).cloned().flatten() {
signature: tx.signatures[0], transaction_log_collector.logs.push(TransactionLogInfo {
result: r.clone(), signature: tx.signatures[0],
is_vote, result: r.clone(),
log_messages: transaction_log_messages.get(i).cloned().unwrap_or_default(), is_vote,
}); log_messages,
});
}
} }
} }
@ -4045,7 +4045,7 @@ impl Bank {
TransactionResults, TransactionResults,
TransactionBalancesSet, TransactionBalancesSet,
Vec<Option<InnerInstructionsList>>, Vec<Option<InnerInstructionsList>>,
Vec<TransactionLogMessages>, Vec<Option<TransactionLogMessages>>,
) { ) {
let pre_balances = if collect_balances { let pre_balances = if collect_balances {
self.collect_balances(batch) self.collect_balances(batch)
@ -10143,9 +10143,11 @@ pub(crate) mod tests {
&mut ExecuteTimings::default(), &mut ExecuteTimings::default(),
); );
assert!(inner_instructions[0].iter().all(|ix| ix.is_empty())); assert!(inner_instructions.iter().all(Option::is_none));
assert_eq!(transaction_logs.len(), 0); assert!(transaction_logs.iter().all(Option::is_none));
assert_eq!(inner_instructions.len(), 3);
assert_eq!(transaction_logs.len(), 3);
assert_eq!(transaction_balances_set.pre_balances.len(), 3); assert_eq!(transaction_balances_set.pre_balances.len(), 3);
assert_eq!(transaction_balances_set.post_balances.len(), 3); assert_eq!(transaction_balances_set.post_balances.len(), 3);
@ -12934,7 +12936,9 @@ pub(crate) mod tests {
let success_sig = tx0.signatures[0]; let success_sig = tx0.signatures[0];
let tx1 = system_transaction::transfer(&sender1, &recipient1, 110, blockhash); // Should produce insufficient funds log let tx1 = system_transaction::transfer(&sender1, &recipient1, 110, blockhash); // Should produce insufficient funds log
let failure_sig = tx1.signatures[0]; let failure_sig = tx1.signatures[0];
let txs = vec![tx1, tx0]; let mut invalid_tx = system_transaction::transfer(&sender1, &recipient1, 10, blockhash);
invalid_tx.message.header.num_required_signatures = 0; // this tx won't be processed because it has no signers
let txs = vec![invalid_tx, tx1, tx0];
let batch = bank.prepare_batch(txs.iter()); let batch = bank.prepare_batch(txs.iter());
let log_results = bank let log_results = bank
@ -12947,17 +12951,10 @@ pub(crate) mod tests {
&mut ExecuteTimings::default(), &mut ExecuteTimings::default(),
) )
.3; .3;
assert_eq!(log_results.len(), 2); assert_eq!(log_results.len(), 3);
assert!(log_results[0] assert!(log_results[0].as_ref().is_none());
.clone() assert!(log_results[1].as_ref().unwrap()[2].contains(&"failed".to_string()));
.pop() assert!(log_results[2].as_ref().unwrap()[1].contains(&"success".to_string()));
.unwrap()
.contains(&"failed".to_string()));
assert!(log_results[1]
.clone()
.pop()
.unwrap()
.contains(&"success".to_string()));
let stored_logs = &bank.transaction_log_collector.read().unwrap().logs; let stored_logs = &bank.transaction_log_collector.read().unwrap().logs;
let success_log_info = stored_logs let success_log_info = stored_logs