Skip to content

Simplify the driver's mempool configuration - #5113

Open
jmg-duarte wants to merge 8 commits into
mainfrom
jmgd/submission-receiver
Open

jmg-duarte wants to merge 8 commits into
mainfrom
jmgd/submission-receiver

Conversation

@jmg-duarte

@jmg-duarte jmg-duarte commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Description

Continues the clean up of the submission configuration started in #5110.

Today a driver can send a settlement to private relays and public nodes at the same time. Settlements that interact with AMMs (or have EIP-1271 orders) go only to the relay; fully internalized settlements race on all of them. That mix is hard to reason about.

From now on a driver has exactly one receiver: either a set of public nodes or one private relay. Every settlement takes that route. — this simplifies our logic and for most cases this is existing behavior, for mainnet we'll be moving to builders exclusively so it will be unified; as for BNB, please check the respective section.

[submission.public-mempool]
urls = ["https://node-1", "https://node-2"]

# or

[submission.private-relay]
url = "http://mevblocker-proxy..."
mines-reverting-txs = false

BNB

BNB is the only network where this changes routing in a way we care about (mainnet moves to builders). BNB becomes blink only. Over the last 30 days:

  • 96.5% of settlements already went to blink only
  • 3.5% raced blink against the public nodes, and the public nodes won 99.3% of those races

So those 3.5% lose a faster route, roughly one block each. We accept that for now; once builder support lands can we replace blink with builders on BNB to win that latency back.

Most (~96%) of blocks are built by BlockRazor and 48Club, and there's 4 more builders we can add to get nearly 100% coverage (Dune query):
image

How to validate the numbers

Every public node records one outcome per settlement: Disabled when the settlement went to blink only, anything else when it raced.

Share of raced settlements (3.5%; blink only is the remainder):

sum(increase(driver_mempool_submission{network="bnb", mempool="Mempool(ovh1)", result!="Disabled"}[30d]))
/
sum(increase(driver_mempool_submission{network="bnb", mempool="Mempool(ovh1)"}[30d]))
image

Share of races won by a public node (99.3%):

sum(increase(driver_mempool_submission{network="bnb", mempool!="Mempool(blink)", result="Success"}[30d]))
/
sum(increase(driver_mempool_submission{network="bnb", mempool="Mempool(ovh1)", result!="Disabled"}[30d]))
image

A "win" is the route whose tx got mined, not a polling artifact: each mempool signs its own tx, so the hashes differ and only one lands. Check it in the driver debug logs, e.g. one settlement on 2026-10-16 09:29:41Z where ovh1, alchemy and blink each submitted a different hash and alchemy's was mined:

network:bnb AND pod:"bnb-driver-prod-liquidity-5d69865d89-gr9hh" AND "checking if tx is confirmed"
| fields _time, parsed.spans.mempool.kind, parsed.fields.hash

(time range 2026-10-16T09:29:40Z to 09:29:46Z)

Changes

  • Replace [[submission.mempool]] with exactly one of [submission.public-mempool] (many URLs) or [submission.private-relay] (one URL)
  • Reject unknown keys in both receivers; [submission] is now required
  • Drop the per-mempool name, mempools are named after the URL host in logs and metrics
  • Remove the per-settlement routing: may_revert, Solution::revertable, Mempools::is_disabled, Error::Disabled
  • Update example.toml, the playground and e2e configs and the driver test setup

Breaking config change, deployed in lockstep with the infra PR.

How to test

Existing tests, plus new config parsing tests. Driver and e2e submission::local_node_* tests pass.

@jmg-duarte
jmg-duarte requested a review from a team as a code owner October 16, 2026 10:28
@claude

claude Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @jmg-duarte's task in 3m 19s —— View job


PR Review: Simplify the driver's mempool configuration

Reviewed against origin/jmgd/submission-tip-params. The refactor is clean and well-scoped: the Receiver enum models the "exactly one receiver" invariant nicely, the per-settlement routing (revertable/may_revert/is_disabled/Error::Disabled) is removed consistently, and there are no dangling references to the removed items. Config-parsing tests cover the important accept/reject cases.

Two minor points, posted inline:

  • tests/setup/mod.rs:529-530 — orphaned doc comment left behind from the removed mempools field, now dangling above rpc_args.
  • infra/config/file/mod.rs:157-160 — naming each public-mempool node by host_str() collides when two URLs share a host (e.g. same host, different port), silently merging their logs/metrics. Low-probability but relevant now that public-mempool takes many URLs.

Neither is blocking.

Notes checked and considered fine
  • serde(flatten) + deny_unknown_fields on SubmissionConfig: deny_unknown_fields is effectively a no-op on the outer struct when combined with flatten, but the externally-tagged Receiver enum and its per-variant deny_unknown_fields still reject the cases the tests target, so behavior matches the PR's intent.
  • RevertProtection mapping preserved: public-mempool → Disabled (= old default mines-reverting-txs = true), private-relay honors mines-reverting-txs. reverts_can_get_mined() simulation-skip logic still wired correctly.
  • Metric label values change from explicit names (Mempool(blink)) to hostnames — acknowledged as a breaking change deployed in lockstep with infra.
· branch `jmgd/submission-receiver`

Comment thread crates/driver/src/tests/setup/mod.rs Outdated
Comment on lines +157 to +160
name: match url.host_str() {
Some(host) => host.to_owned(),
None => format!("mempool_{index}"),
},

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.

Minor: with public-mempool now taking many URLs, naming each mempool purely by host_str() means two nodes that share a host but differ by port or path (e.g. http://localhost:8545 and http://localhost:8546) collapse to the same name. That name is the Mempool(<name>) label used in logs and the driver_mempool_submission metric (Display at infra/mempool/mod.rs:82), so their stats/logs would silently merge and the per-node race breakdown in the PR description would be unattributable. Distinct providers usually have distinct hosts so this is unlikely in practice, but it's worth either disambiguating (e.g. include port, or fall back to index on duplicate names) or at least being aware of it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Claude rightfully notes that this isn't a problem in practice because we're not running nodes on localhost in staging or prod

@jmg-duarte
jmg-duarte force-pushed the jmgd/submission-receiver branch 2 times, most recently from c3514cf to 5017daa Compare October 16, 2026 11:08
Comment thread crates/driver/src/infra/config/file/mod.rs
Comment thread crates/driver/src/infra/config/file/mod.rs Outdated
@jmg-duarte
jmg-duarte marked this pull request as draft October 16, 2026 11:41
@jmg-duarte
jmg-duarte force-pushed the jmgd/submission-receiver branch from 5017daa to 4bc6316 Compare October 16, 2026 12:55
@jmg-duarte
jmg-duarte force-pushed the jmgd/submission-receiver branch from 4bc6316 to 46a643b Compare October 16, 2026 12:57
@jmg-duarte
jmg-duarte marked this pull request as ready for review October 16, 2026 12:59
@claude

claude Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @jmg-duarte's task in 2m 29s —— View job


PR Review: Simplify the driver's mempool configuration

Reviewed against origin/jmgd/submission-tip-params. The "exactly one receiver" model is clean and the removal of per-settlement routing (revertable/may_revert/is_disabled/Error::Disabled/domain RevertProtection) is consistent — no dangling references, the simulation-skip (reverts_can_get_mined) and metric/notify paths are correctly rewired, and the config-parsing tests cover the accept/reject cases. The orphaned doc comment flagged in the earlier review is already resolved in the current diff.

One point posted inline:

  • infra/config/file/mod.rs:141-142 — #[serde(flatten)] silently disables deny_unknown_fields on SubmissionConfig, so typos in top-level [submission] keys are no longer rejected (they were before this PR). The per-variant deny_unknown_fields still guards inside public-mempool/private-relay. Likely an acceptable tradeoff for the desired TOML syntax, but worth being aware of.

Not blocking. Nice cleanup overall.

  • Read the full diff
  • Analyze config parsing & domain changes
  • Post inline findings
  • Summary
    · branch jmgd/submission-receiver

Comment thread crates/driver/src/infra/config/file/mod.rs
jmg-duarte and others added 2 commits October 16, 2026 14:10
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Base automatically changed from jmgd/submission-tip-params to main October 16, 2026 13:25
jmg-duarte and others added 2 commits October 16, 2026 14:52
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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