Skip to content

[LLM Draft] Fetch: single-flight in-flight RPC slot fetches (tighter reimpl of #1070)#1072

Draft
msooseth wants to merge 1 commit into
mainfrom
rpc-slot-singleflight-simplified
Draft

[LLM Draft] Fetch: single-flight in-flight RPC slot fetches (tighter reimpl of #1070)#1072
msooseth wants to merge 1 commit into
mainfrom
rpc-slot-singleflight-simplified

Conversation

@msooseth

Copy link
Copy Markdown
Collaborator

Summary

Reduces redundant RPC load when multiple workers race on the same uncached storage slot, by giving slot fetches single-flight semantics: concurrent callers on the same (block, address, slot) share one eth_getStorageAt request instead of each issuing their own.

This is a tighter reimplementation of #1070. Same behavior and same RPC-count reduction, but the single-flight logic is a generic, mask-safe singleFlight combinator plus a reused lookupSlotCache, instead of a dedicated owner/waiter ADT and several one-shot helpers.

What changed

  • Route oracle slot reads through fetchSlotWithCache — the PleaseFetchSlot branch in oracle no longer hand-rolls its own cache-check/fetch/populate; it calls the shared cache path (which now also respects the failed-slot cache).
  • singleFlight — a generic "run an action at most once per key, share the result" combinator. The owner runs the action, fills an MVar, and removes the key; waiters block on that MVar. Wrapped in mask with try, so the owner clears the key and wakes waiters even on (async) exception — a failed fetch is retried by the next caller rather than deadlocking.
  • lookupSlotCache — the success/failure cache lookup, factored out and reused on both the fast path (cache hit, no lock) and the post-claim recheck (an owner may have just populated the cache).
  • fetchSlotWithCacheUsingfetchSlotWithCache with the underlying RPC injected, so the concurrency tests drive it deterministically with no network.

The in-flight key includes the resolved block, so reads at different fork blocks stay isolated (BlockNumber gains an Ord instance for the map key).

Note on FetchStatus for waiters

Waiters return the owner's FetchSuccess val Fresh as-is (this version drops the Fresh -> Cached relabel that #1070 applied to waiters). Inside hevm this is invisible — the oracle ignores the status. The actual RPC still fires exactly once; only the per-caller Fresh/Cached label differs for the threads that waited.

Motivation

During Echidna fork fuzzing, workers can race on the same uncached storage slot. Before this change each worker could issue its own identical eth_getStorageAt before the first result populated the cache, causing avoidable duplicate RPC traffic and quickly hitting provider call limits.

Testing

  • Full test suite passes; StorageTests group (5 tests) green.
  • Four new deterministic concurrency tests (injected fetcher, no network):
    • concurrent fetches of the same slot ⇒ underlying fetch fires once, all 8 callers get the right value
    • concurrent fetches of different slots ⇒ not merged (one fetch per slot)
    • owner error wakes all waiters and clears the in-flight entry (a later retry fetches again)
    • owner exception wakes all waiters and clears the in-flight entry (a later retry throws again)

Checklist

  • tested locally
  • added automated tests
  • updated the docs
  • updated the changelog

🤖 Generated with Claude Code

Concurrent workers racing on the same uncached (block, addr, slot) used to
each issue an identical eth_getStorageAt before the first result populated the
cache. Route oracle slot reads through fetchSlotWithCache and add single-flight
tracking keyed by resolved block, address, and slot, so concurrent callers wait
for one shared fetch.

This is a tighter reimplementation of the approach in #1070: the single-flight
logic is a generic, mask-safe `singleFlight` combinator plus a reused
`lookupSlotCache`, instead of a dedicated owner/waiter ADT and several helpers.
The owner clears the key and wakes waiters even on (async) exception, so a
failed fetch is retried by the next caller rather than deadlocking.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@msooseth

Copy link
Copy Markdown
Collaborator Author

Fully LLM-written, total YOLO, no manual review AT ALL yet. Will need 2 people to reivew.

@msooseth msooseth changed the title Fetch: single-flight in-flight RPC slot fetches (tighter reimpl of #1070) [LLM Draft] Fetch: single-flight in-flight RPC slot fetches (tighter reimpl of #1070) Jun 18, 2026
@msooseth msooseth marked this pull request as draft June 18, 2026 08:47
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