Skip to content

fix(op-reth): evict definitively-invalid interop txs on revalidation#21447

Merged
ajsutton merged 17 commits into
developfrom
aj/fix/op-reth-interop-evict-invalid-on-revalidation
Jun 23, 2026
Merged

fix(op-reth): evict definitively-invalid interop txs on revalidation#21447
ajsutton merged 17 commits into
developfrom
aj/fix/op-reth-interop-evict-invalid-on-revalidation

Conversation

@ajsutton

@ajsutton ajsutton commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Three related fixes to the interop txpool revalidation/eviction sweep, all in maintain.rs.

1. Evict on a definitive invalid verdict. The sweep gated eviction on reth's is_bad_transaction() — a peer-penalization predicate that's false for ValidationError(_). A definitive invalid verdict from the interop filter (InvalidEntry/Rejected) was therefore never evicted and stayed buildable until its ~2h cached deadline. Adds a dedicated InvalidCrossTx::is_now_invalid() and uses it in the sweep: evict on a decisive invalid verdict, retain on transient/non-decisive outcomes (quorum miss, timeout, data-unavailable, disagreement) so a flapping or unreachable interop filter can't drain the pool. Failsafe stays handled by the whole-pool eviction; reth's is_bad_transaction() is unchanged.

2. Revalidate non-propagatable interop txs. The sweep iterated pool.pooled_transactions(), which filters out propagate=false txs. Non-propagatable interop txs (Private origin, e.g. from eth_sendRawTransactionConditional) were never revalidated or evicted, yet the builder still selects them via best_transactions() (no propagate filter) — a permanent eviction blind spot. Now scans pool.all_transactions() at all interop sites (failsafe eviction, stale scan, poll_failsafe).

3. Evict all interop txs on reorg. The maintenance loop handled only Commit notifications and silently dropped Reorg. A local-chain reorg can invalidate the initiating message a pooled cross-chain executing tx depends on (and source-chain reorgs are not observable here at all), leaving the dependent tx pooled and buildable. The loop now matches on the event and the Reorg arm evicts all interop txs from the pool. The scan-and-remove logic is extracted into evict_all_interop_txs, shared by the reorg arm, the failsafe path, and poll_failsafe. The OpPool 30s reorg-window admission filter is kept: it suppresses re-admission of interop txs via gossip or block reinjection while the chain settles.

The revalidation sweep is extracted into a testable function; tests drive a real pool against a mock interop-filter endpoint and cover the eviction decision across origin × verdict, plus reorg eviction (incl. a non-propagatable Private-origin tx) and the failsafe-on-commit branch.

@ajsutton ajsutton force-pushed the aj/fix/op-reth-interop-evict-invalid-on-revalidation branch 2 times, most recently from a914013 to dc4f32f Compare June 16, 2026 23:46
@ajsutton ajsutton marked this pull request as ready for review June 17, 2026 00:16
@ajsutton ajsutton requested a review from a team as a code owner June 17, 2026 00:16
@ajsutton ajsutton force-pushed the aj/fix/op-reth-interop-evict-invalid-on-revalidation branch from 21fc30d to 2ef0019 Compare June 17, 2026 02:32
@einar-oplabs einar-oplabs self-assigned this Jun 18, 2026

@einar-oplabs einar-oplabs left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I requested changes because I think it is important we keep the tests super fast.

Let me know if I can help out with something.

Comment thread rust/op-reth/crates/txpool/src/error.rs
Comment thread rust/op-reth/crates/txpool/src/error.rs
Comment thread rust/op-reth/crates/txpool/src/maintain.rs Outdated
Comment thread rust/op-reth/crates/txpool/src/maintain.rs Outdated
Comment thread rust/op-reth/crates/txpool/src/maintain.rs Outdated
Comment thread rust/op-reth/crates/txpool/src/maintain.rs Outdated
Comment thread rust/op-reth/crates/txpool/src/maintain.rs Outdated
Comment thread rust/op-reth/crates/txpool/src/maintain.rs Outdated
@wiz-0f98cca50a

wiz-0f98cca50a Bot commented Jun 18, 2026

Copy link
Copy Markdown

Wiz Scan Summary

Scanner Findings
Vulnerability Finding Vulnerabilities 12 High 5 Medium 6 Low
Data Finding Sensitive Data -
Secret Finding Secrets -
IaC Misconfiguration IaC Misconfigurations -
SAST Finding SAST Findings -
Software Management Finding Software Management Findings -
Total 12 High 5 Medium 6 Low

View scan details in Wiz

To detect these findings earlier in the dev lifecycle, try using Wiz Code VS Code Extension.

@ajsutton ajsutton requested a review from einar-oplabs June 19, 2026 01:02

@einar-oplabs einar-oplabs left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this is a huge improvement 👍

My main point in this round is that we should probably make the type signatures of the InteropFilter as simple as possible. Unless we have a good reason to pass streams and box futures around and track life times of transactions, let's keep it simple.

Let me know if you want me to help with anything.

Comment thread rust/op-reth/crates/txpool/src/error.rs
Comment thread rust/op-reth/crates/txpool/src/maintain.rs Outdated
Comment thread rust/op-reth/crates/txpool/src/maintain.rs
Comment thread rust/op-reth/crates/txpool/src/maintain.rs
Comment thread rust/op-reth/crates/txpool/src/maintain.rs Outdated
Comment thread rust/op-reth/crates/txpool/src/maintain.rs Outdated
Comment thread rust/op-reth/crates/txpool/src/maintain.rs
Comment thread rust/op-reth/crates/txpool/src/maintain.rs Outdated
Comment thread rust/op-reth/crates/txpool/src/maintain.rs Outdated
Comment thread rust/op-reth/crates/txpool/src/maintain.rs Outdated
@ajsutton ajsutton force-pushed the aj/fix/op-reth-interop-evict-invalid-on-revalidation branch from 91efe99 to f673a2a Compare June 21, 2026 23:36

@einar-oplabs einar-oplabs left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it is in a good state now. Added some minor points about naming.

Comment thread rust/op-reth/crates/txpool/src/interop_filter/client.rs
Comment thread rust/op-reth/crates/txpool/src/maintain.rs
Comment thread rust/op-reth/crates/txpool/src/interop_filter/client.rs Outdated

@einar-oplabs einar-oplabs left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One more thing.

Comment thread rust/op-reth/crates/txpool/src/interop_filter/client.rs Outdated
@ajsutton ajsutton enabled auto-merge June 22, 2026 23:08
@ajsutton ajsutton force-pushed the aj/fix/op-reth-interop-evict-invalid-on-revalidation branch from a5abec4 to 3eb19bf Compare June 22, 2026 23:19
@ajsutton ajsutton added this pull request to the merge queue Jun 22, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Jun 22, 2026
ajsutton added 12 commits June 22, 2026 20:00
The interop txpool revalidation sweep gated eviction on reth's
`is_bad_transaction()`, which is true only for `CrossChainTxPreInterop`
and false for `ValidationError(_)`. A definitive invalid verdict from the
interop filter (`InvalidEntry`/`Rejected`) therefore stayed buildable
until its ~2h cached deadline expired.

`is_bad_transaction()` answers reth's peer-penalization question, a
different concern from "is this tx now invalid and must be evicted". Add a
dedicated `InvalidCrossTx::is_now_invalid()` predicate and use it in the
revalidation sweep: evict on a decisive invalid verdict, retain on
transient/non-decisive outcomes (quorum miss, timeout, data-unavailable,
disagreement) so a flapping or unreachable interop filter cannot drain the
pool. Failsafe stays handled by the whole-pool eviction. reth's
peer-penalization predicate is left unchanged.
The interop revalidation/eviction sweep iterated `pool.pooled_transactions()`,
which filters out `propagate=false` transactions. Non-propagatable interop txs
(`Private` origin, e.g. from `eth_sendRawTransactionConditional`) were therefore
never revalidated or evicted, yet the builder still selects them via
`best_transactions()` (no propagate filter) — a permanent eviction blind spot.

Scan `pool.all_transactions()` (pending/basefee/queued, no propagate filter) at
the three interop sites: the failsafe eviction in `maintain_transaction_pool_interop`,
the stale scan in `revalidate_stale_interop_txs`, and the eviction in `poll_failsafe`.

Adds a regression test that admits a `Private`-origin interop tx and asserts the
sweep evicts it on a definitive invalid verdict (fails on baseline).
The interop txpool maintenance loop handled only `Commit` notifications and
silently dropped `Reorg`. A local-chain reorg can invalidate the initiating
message a pooled cross-chain executing tx depends on (and source-chain reorgs
are not observable here at all), leaving the dependent tx pooled and buildable.

Handle `Reorg` by evicting all interop txs from the pool. Extract the
scan-and-remove logic into `evict_all_interop_txs`, shared by the reorg arm,
the failsafe path, and `poll_failsafe`.

The OpPool reorg-window admission filter is kept: it suppresses re-admission of
interop txs via gossip or block reinjection while the chain settles.
@ajsutton ajsutton force-pushed the aj/fix/op-reth-interop-evict-invalid-on-revalidation branch from 3eb19bf to 0a21ba9 Compare June 23, 2026 00:03
@ajsutton ajsutton enabled auto-merge June 23, 2026 00:19
@ajsutton ajsutton added this pull request to the merge queue Jun 23, 2026
Merged via the queue into develop with commit bdcf49a Jun 23, 2026
128 checks passed
@ajsutton ajsutton deleted the aj/fix/op-reth-interop-evict-invalid-on-revalidation branch June 23, 2026 01:09
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.

2 participants