Skip to content

MempoolTxsDetector is only fed with mempool txs.#901

Open
ZanCorDX wants to merge 3 commits intodevelopfrom
dx/private-txs
Open

MempoolTxsDetector is only fed with mempool txs.#901
ZanCorDX wants to merge 3 commits intodevelopfrom
dx/private-txs

Conversation

@ZanCorDX
Copy link
Collaborator

📝 Summary

MempoolTxsDetector used to consider as mempool any MempoolTx but those coming from eth_sendRawTransaction should not be considered as mempool.
MempoolTxsDetector was changed, now it's a long lived object.
We insert txs into MempoolTxsDetector on the read mempool tasks and clean it on the OrderPool to avoid leaks.

✅ I have completed the following steps:

  • Run make lint
  • Run make test
  • Added tests (if applicable)

@ZanCorDX ZanCorDX requested a review from dvush as a code owner March 20, 2026 19:23
@claude
Copy link
Contributor

claude bot commented Mar 20, 2026

Claude finished @ZanCorDX's task in 1m 15s —— View job


PR Review: MempoolTxsDetector refactor

  • Read diff and changed files
  • Analyze code for bugs, edge cases, and concurrency issues
  • Post review findings

Summary

The refactoring direction is sound — making MempoolTxsDetector a long-lived shared object and feeding it only from actual mempool sources (not eth_sendRawTransaction) is the right approach. The removal of ReplaceableOrderStreamSniffer simplifies the pipeline nicely.

Issues found

  1. Bug — leak in try_send_to_orderpool (mod.rs:555): add_tx is called before the orderpool send, so if the send fails the hash leaks in the DashSet forever (never cleaned by head_updated). The txpool_fetcher.rs path correctly adds only on success — this path should match.

  2. block_building_helper_stats_logger.rs still treats all txs as mempool (lines 98-101): A fresh local MempoolTxsDetector is created and all Order::Tx are added to it — including private txs. This defeats the purpose of the PR for stats logging. Should likely use the shared detector from BlockBuildingContext.

See inline comments for details.

Comment on lines +98 to +101
let mempool_txs_detector = MempoolTxsDetector::new();
for sim_order in &orders {
order_id_to_order.insert(sim_order.id(), sim_order.clone());
mempool_txs_detector.add_tx(&sim_order.order);
if let Order::Tx(mempool_tx) = sim_order.order.as_ref() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This creates a fresh MempoolTxsDetector and feeds it all Order::Tx orders — including private txs from eth_sendRawTransaction. This contradicts the PR's goal of distinguishing mempool txs from private txs.

Should this use the shared MempoolTxsDetector from BlockBuildingContext (i.e. block_ctx.mempool_tx_detector) instead of constructing a local one?

}
};

let tx = MempoolTx::new(tx_with_blobs);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: unrelated whitespace change (blank line removed). Consider reverting to keep the diff focused.

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
@claude
Copy link
Contributor

claude bot commented Mar 20, 2026

Claude finished @ZanCorDX's task in 1m 54s —— View job


PR Review: MempoolTxsDetector refactor (re-review after sync)

  • Read updated diff and changed files
  • Check if previous review issues were addressed
  • Post review findings

Summary

The second commit (4c5b074) attempted to address the try_send_to_orderpool bug from the first review, but introduced a new issue:

Issues

  1. Bug — duplicated code in try_send_to_orderpool (mod.rs:555-566): The new code with add_tx/remove_tx was added but the old code block was not removed, resulting in duplicated logic. This will fail to compile since tx is moved into MempoolTx::new(tx) on the first block and then reused on the second block. See inline comment.

  2. block_building_helper_stats_logger.rs still creates a local detector (lines 98-104): A fresh MempoolTxsDetector is created and all Order::Tx hashes are added — including private txs. This still misclassifies private txs as mempool txs for stats purposes. See inline comment.

Comment on lines 98 to 104
let mempool_txs_detector = MempoolTxsDetector::new();
for sim_order in &orders {
order_id_to_order.insert(sim_order.id(), sim_order.clone());
mempool_txs_detector.add_tx(&sim_order.order);
if let Order::Tx(mempool_tx) = sim_order.order.as_ref() {
mempool_txs_detector.add_tx(mempool_tx.tx_with_blobs.hash());
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still creates a fresh local MempoolTxsDetector and adds all Order::Tx — including private txs from eth_sendRawTransaction. This means stats logging will misclassify private txs as mempool txs, defeating the purpose of this PR for the stats path.

Should use the shared detector from BlockBuildingContext (accessible via self.block_building_helper) instead of constructing a local one.

Comment on lines +555 to +561
mempool_detector.add_tx(tx.hash());
let order = Order::Tx(MempoolTx::new(tx));
let command = ReplaceableOrderPoolCommand::Order(Arc::new(order));
if let Err(e) = orderpool_sender.send(command).await {
mempool_detector.remove_tx(tx.hash());
error!("Error sending order to orderpool: {:#}", e);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The new code block (lines 555-561) was added but the old code block (lines 562-566) was not removed. This duplicates the logic and will fail to compile — tx is moved into MempoolTx::new(tx) on line 556, making lines 559 (tx.hash()) and 562 (MempoolTx::new(tx)) invalid.

Fix: remove lines 562-566 (the old code) and save the hash before moving tx:

let hash = tx.hash();
mempool_detector.add_tx(hash);
let order = Order::Tx(MempoolTx::new(tx));
let command = ReplaceableOrderPoolCommand::Order(Arc::new(order));
if let Err(e) = orderpool_sender.send(command).await {
    mempool_detector.remove_tx(hash);
    error!("Error sending order to orderpool: {:#}", e);
}

@claude
Copy link
Contributor

claude bot commented Mar 20, 2026

Claude finished @ZanCorDX's task in 1m 20s —— View job


PR Review: MempoolTxsDetector refactor (re-review after latest sync)

  • Read updated diff and changed files
  • Check if previous review issues were addressed
  • Post review findings

Summary

The latest commit (23e866a) addressed both issues from previous reviews:

  1. try_send_to_orderpool bug — fixed. The duplicated code block is gone. The hash is now captured before moving tx, add_tx is called before send, and remove_tx is called on failure. Clean pattern.

  2. block_building_helper_stats_logger.rs — fixed. Now uses the shared MempoolTxsDetector from BlockBuildingContext instead of creating a local one that misclassified private txs.

Remaining issue

Backtest path still adds all Order::Tx as mempool (backtest/execute.rs:104-108): The @Pending comment acknowledges this, but backtest_prepare_orders_from_building_context still treats every Order::Tx as a mempool tx — including private txs. This means backtest stats will misclassify private txs as mempool txs. Not a blocker if backtest data doesn't currently include private txs, but worth tracking.

Nit

  • txpool_fetcher.rs:73: Unrelated whitespace removal (blank line between }; and let tx = ...). Minor, but keeping diffs focused helps reviewers.

Overall the core changes look correct. The refactoring direction is sound — the shared long-lived MempoolTxsDetector fed only from mempool sources, with cleanup in OrderPool::head_updated, is a clean approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant