* 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:
@ -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();
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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(
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user