@@ -44,7 +44,14 @@ const BLOCK_HASH_CACHE_SIZE: NonZeroUsize = match NonZeroUsize::new(256) {
4444/// - Cumulative gas used by all transactions
4545/// - Logs emitted by each transaction
4646/// - Total transaction fees collected (gas_used × effective_gas_price)
47- type ProcessTransactionsResult = ( Vec < TransactionReceipt > , u64 , Vec < Vec < Log > > , U256 ) ;
47+ /// - Executed transaction bytes (only transactions with receipts, not skipped ones)
48+ type ProcessTransactionsResult = (
49+ Vec < TransactionReceipt > ,
50+ u64 ,
51+ Vec < Vec < Log > > ,
52+ U256 ,
53+ Vec < Bytes > ,
54+ ) ;
4855
4956/// ExecutionLayer trait defines the interface for block execution.
5057///
@@ -345,6 +352,7 @@ impl<P: Provider + Clone> ExecutionEngine<P> {
345352 let mut cumulative_gas_used = 0u64 ;
346353 let mut all_logs = Vec :: new ( ) ;
347354 let mut total_fees = U256 :: ZERO ;
355+ let mut executed_tx_bytes = Vec :: new ( ) ;
348356
349357 // Sort transactions by (sender, nonce) to ensure correct execution order
350358 // This prevents NonceTooLow errors when txs from same sender arrive out of order
@@ -503,6 +511,7 @@ impl<P: Provider + Clone> ExecutionEngine<P> {
503511
504512 receipts. push ( receipt) ;
505513 all_logs. push ( tx_result. logs ) ;
514+ executed_tx_bytes. push ( tx_bytes. clone ( ) ) ;
506515 }
507516
508517 // Finalize EVM to extract journal changes
@@ -531,7 +540,13 @@ impl<P: Provider + Clone> ExecutionEngine<P> {
531540 ) ;
532541 }
533542
534- Ok ( ( receipts, cumulative_gas_used, all_logs, total_fees) )
543+ Ok ( (
544+ receipts,
545+ cumulative_gas_used,
546+ all_logs,
547+ total_fees,
548+ executed_tx_bytes,
549+ ) )
535550 }
536551
537552 /// Compute or retrieve state root based on block number.
@@ -566,12 +581,14 @@ impl<P: Provider + Clone> ExecutionLayer for ExecutionEngine<P> {
566581 self . validate_block ( & input) ?;
567582
568583 // Process all transactions and collect fees
569- let ( receipts, gas_used, all_logs, total_fees) = self . process_transactions (
570- & input. transactions ,
571- input. block_number ,
572- input. timestamp ,
573- input. parent_hash ,
574- ) ?;
584+ // executed_tx_bytes contains only transactions that actually executed (have receipts)
585+ let ( receipts, gas_used, all_logs, total_fees, executed_tx_bytes) = self
586+ . process_transactions (
587+ & input. transactions ,
588+ input. block_number ,
589+ input. timestamp ,
590+ input. parent_hash ,
591+ ) ?;
575592
576593 if !total_fees. is_zero ( ) {
577594 tracing:: info!(
@@ -665,6 +682,7 @@ impl<P: Provider + Clone> ExecutionLayer for ExecutionEngine<P> {
665682 block_hash,
666683 receipts,
667684 logs_bloom,
685+ executed_transactions : executed_tx_bytes,
668686 } )
669687 }
670688
@@ -958,6 +976,7 @@ mod tests {
958976 block_hash : B256 :: ZERO ,
959977 receipts : vec ! [ ] ,
960978 logs_bloom : Bloom :: ZERO ,
979+ executed_transactions : vec ! [ ] ,
961980 } ;
962981
963982 let sealed = engine
@@ -1018,6 +1037,7 @@ mod tests {
10181037 block_hash : B256 :: ZERO ,
10191038 receipts : vec ! [ ] ,
10201039 logs_bloom : Bloom :: ZERO ,
1040+ executed_transactions : vec ! [ ] ,
10211041 } ;
10221042
10231043 let sealed = engine
0 commit comments