Skip to content

Commit 178cdef

Browse files
committed
fix: only remove executed txs from mempool pending map
1 parent 6a49012 commit 178cdef

File tree

4 files changed

+44
-12
lines changed

4 files changed

+44
-12
lines changed

crates/execution/src/engine.rs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

crates/execution/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@ mod tests {
593593
block_hash: B256::ZERO,
594594
receipts: vec![],
595595
logs_bloom: Bloom::ZERO,
596+
executed_transactions: vec![],
596597
};
597598

598599
let sealed = execution_layer

crates/execution/src/types.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,14 @@ pub struct ExecutionResult {
351351

352352
/// Logs bloom filter.
353353
pub logs_bloom: Bloom,
354+
355+
/// Raw bytes of transactions that actually executed (have receipts).
356+
///
357+
/// This excludes transactions that were skipped due to nonce errors
358+
/// (NonceTooLow, NonceTooHigh). Used by the node to properly clean up
359+
/// the mempool pending map - only executed transactions should be removed.
360+
#[serde(default)]
361+
pub executed_transactions: Vec<Bytes>,
354362
}
355363

356364
/// Transaction receipt.

crates/node/src/execution_bridge.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -353,9 +353,8 @@ impl ExecutionBridge {
353353
let timestamp = execution_cut.timestamp;
354354
let parent_hash = execution_cut.parent_hash;
355355

356-
// Capture all transactions BEFORE they're consumed by execution.
357-
// These will be stored by the node for eth_getTransactionByHash queries.
358-
let executed_transactions: Vec<Bytes> = execution_cut
356+
// Collect all transactions for the block input
357+
let all_transactions: Vec<Bytes> = execution_cut
359358
.cars
360359
.iter()
361360
.flat_map(|car| car.transactions.iter().cloned())
@@ -365,7 +364,7 @@ impl ExecutionBridge {
365364
let block_input = BlockInput {
366365
block_number: execution_cut.block_number,
367366
timestamp: execution_cut.timestamp,
368-
transactions: executed_transactions.clone(),
367+
transactions: all_transactions,
369368
parent_hash: execution_cut.parent_hash,
370369
gas_limit: execution_cut.gas_limit,
371370
base_fee_per_gas: execution_cut.base_fee_per_gas,
@@ -400,6 +399,10 @@ impl ExecutionBridge {
400399
"Block hash updated"
401400
);
402401

402+
// Use executed_transactions from the execution result - this only contains
403+
// transactions that actually executed (have receipts), not skipped ones
404+
let executed_transactions = result.executed_transactions.clone();
405+
403406
Ok(BlockExecutionResult {
404407
execution_result: result,
405408
block_hash: new_block_hash,

0 commit comments

Comments
 (0)