Skip to content

fix(simulator): rewrite wss/ws RPC URL to https/http for fork backend#129

Merged
0xfandom merged 1 commit into
developfrom
fix/simulator-fork-rpc-scheme
May 11, 2026
Merged

fix(simulator): rewrite wss/ws RPC URL to https/http for fork backend#129
0xfandom merged 1 commit into
developfrom
fix/simulator-fork-rpc-scheme

Conversation

@0xfandom

Copy link
Copy Markdown
Collaborator

Problem

The revm-backed fork backend issues one-shot eth_getStorageAt / eth_getBalance requests via AlloyDB's HTTP transport. ETH_RPC_URL, however, is shared with the streaming subscription path (newHeads, logs, pending tx) which requires a wss:// / ws:// scheme for the persistent connection.

Without normalisation, ProviderBuilder::new().connect_http(parsed) on a wss URL fails every detected cycle with:

ERROR aether_simulator: RPC EVM transact error error=database error: Transport error: builder error for url (wss://eth-mainnet.g.alchemy.com/v2/<key>)

Floods the log on every block (10-50 errors/sec when detection is active). Mempool tracking (analytical predictors) is unaffected, but the regular block-by-block arb validation path is silently broken.

This surfaced after ETH_RPC_URL was flipped from https to wss to engage Alchemy alchemy_pendingTransactions + newHeads over WebSocket for the PR #118 mempool work. Pre-existing bug — was lurking the whole time, only visible once the env var changed scheme.

Fix

Add normalize_to_http_scheme(url: &str) -> String which rewrites wss:// -> https:// and ws:// -> http:// literally, leaving host / path / query intact. Apply at the boundary between config.rpc_url and the ProviderBuilder::connect_http call in AetherEngine::new.

let http_url = normalize_to_http_scheme(url_str);
let parsed: url::Url = http_url.parse()?;
let provider = ProviderBuilder::new().connect_http(parsed);

Why HTTP, not WS-backed fork

revm itself is transport-agnostic — it consumes a Database trait and AlloyDB wraps any alloy Provider. WS-backed fork works, but isn't preferred:

Aspect HTTP fork WS-backed fork
Concurrent reads Native parallel Multiplexed through one socket
Per-sim latency (50-200 slot fetches) ~50ms ~150-300ms
Rate limits Separate from subscription budget Shares budget with streaming
Connection state Stateless, retries cheap Persistent, needs reconnect plumbing
revm convention Canonical (Foundry, Anvil, every tutorial) Atypical
Anvil compatibility Native Some versions wonky

Scheme rewrite gives operators a single ETH_RPC_URL env var while routing each consumer to the transport it actually wants.

Why a literal rewrite

Alchemy, Infura, and QuickNode all expose both transports on the same hostname + path differing only in scheme:

  • wss://eth-mainnet.g.alchemy.com/v2/<key>
  • https://eth-mainnet.g.alchemy.com/v2/<key>

No new env var, no config-file changes, no operator coordination required.

Unknown schemes

IPC paths (ipc:///tmp/reth.ipc), file URLs, anything not ws(s) — pass through unchanged. Downstream parser surfaces a clear error rather than silently miscast.

Side-effect: clippy fix

Develop's crates/grpc-server/src/metrics.rs doc-list continuation lines under sim_evm_fallback_total were indented to 24 spaces. Rust 1.94's clippy::doc_overindented_list_items lint rejects them under -D warnings. Dedented to 4 spaces — required to keep cargo clippy --workspace -- -D warnings green for the new tests.

Tests

6 unit tests covering all scheme cases:

  • wss:// -> https://
  • ws:// -> http://
  • https:// unchanged
  • http:// unchanged
  • ipc:// (unknown scheme) unchanged
  • Query string + path preservation

488 workspace tests pass. cargo clippy --workspace -- -D warnings clean.

Impact

  • Unblocks main-detection EVM sim when operator sets ETH_RPC_URL=wss://...
  • No behaviour change when ETH_RPC_URL is already https://...
  • No env var changes, no config-file changes
  • Mempool tracking pipeline unaffected (uses analytical predictors, never touched the fork)

Verification

Before (capture log on PR #118 branch):

ERROR aether_simulator: RPC EVM transact error error=database error: Transport error: builder error for url (wss://...)

... repeated 10-50 times/sec.

After (with this fix on ETH_RPC_URL=wss://...):

INFO aether_rust::engine: RPC provider created for fork simulation original=wss://eth-mainnet.g.alchemy.com/v2/<key> fork_url=https://eth-mainnet.g.alchemy.com/v2/<key>

No Transport error lines.

The revm-backed fork backend issues one-shot `eth_getStorageAt` /
`eth_getBalance` requests via AlloyDB's HTTP transport. `ETH_RPC_URL`,
however, is shared with the streaming subscription path (newHeads,
logs, pending tx) which requires a `wss://` / `ws://` scheme for the
persistent connection.

Without normalisation, `connect_http` on a wss URL fails every
detected cycle with `Transport error: builder error for url (wss://...)`
and floods the log on each block. Mempool tracking (analytical
predictors) is unaffected, but the regular block-by-block arb
validation path is silently broken.

Fix: add `normalize_to_http_scheme` which rewrites `wss://` -> `https://`
and `ws://` -> `http://` literally, leaving host / path / query intact.
Apply at the boundary between `config.rpc_url` and the
`ProviderBuilder::connect_http` call. Major providers (Alchemy, Infura,
QuickNode) expose both transports on the same hostname so the rewritten
URL routes to the correct endpoint. Operators keep a single env var.

Unknown schemes (`ipc://`, `file://`, etc.) pass through unchanged so
downstream parser surfaces a clear error rather than a silent miscast.

Also dedents `sim_evm_fallback_total` doc-list continuation lines from
24 spaces to 4 to satisfy `-D clippy::doc_overindented_list_items` --
required to keep `cargo clippy --workspace -- -D warnings` green on
rust 1.94.

Tests: 6 unit tests covering wss, ws, https, http, unknown-scheme, and
query-string preservation. 488 workspace tests, clippy clean.
@vercel

vercel Bot commented May 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
aether Ready Ready Preview, Comment May 11, 2026 11:44am
aether-63xv Ready Ready Preview, Comment May 11, 2026 11:44am

@0xfandom 0xfandom merged commit fc3b1af into develop May 11, 2026
3 checks passed
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