uint64 underflow in getHeader msIntoSlot: request arriving before slot start silently skips all relays

Open Beginner friendly
#902 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
72/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
go
Domain
api, backend

Research direction

Read server/get_header.go at the msIntoSlot calculation around line 65 and the late-in-slot guard around line 86, then trace RecordMsIntoSlot. Verify behavior for a request just before slot start and after the change; done means early requests are not skipped, relay querying remains possible, and the exported metric no longer records a wrapped value.

Written by the indexing model from the issue text.

Description

Summary

getHeader computes msIntoSlot with unsigned arithmetic (server/get_header.go:65):

msIntoSlot := uint64(time.Now().UTC().UnixMilli()) - slotStartTimestamp*1000

If the CL's getHeader request arrives even 1ms before slot start — sub-ms scheduling jitter between a VC and BN is enough — the subtraction underflows to ~2^64. The late-in-slot guard at line 86 then sees msIntoSlot >= lateInSlotTimeMs, concludes the request is hopelessly late, and returns 204 without querying any relay. The CL falls back to a locally built block and the proposer silently loses the MEV reward. This happens with timing games disabled — the guard is always active.

Production occurrence (mainnet, v1.12, Lighthouse v8.1.3)

Slot 14479147, request arrived 94µs before slot start:

time="2026-06-04T11:49:46.999Z" level=info msg="getHeader request start - 18446744073709551615 milliseconds into slot 14479147" ... slot=14479147 ua=Lighthouse/v8.1.3-176cce5 version=1.12
time="2026-06-04T11:49:46.999Z" level=warning msg="getHeader request skipped because we are already past the lateInSlotTimeMs deadline" lateInSlotTimeMs=2000 msIntoSlot=18446744073709551615
time="2026-06-04T11:49:46.999Z" level=info msg="no bid received"

18446744073709551615 = 2^64−1, i.e. −1ms wrapped. Lighthouse logged Builder error when requesting payload ... falling back to local execution client and proposed a vanilla block. All relays had bids for the slot and the registration was current — the auction was never attempted.

Across our fleet we count ~38 occurrences since deploying v1.12 in early March (the wrapped observation adds exactly 2^64 to mev_boost_millisec_into_slot_sum, which makes the signature easy to detect retroactively). All produced locally-built blocks; none missed.

Suggested fix

Compute with signed ints and clamp negatives to zero ("very early in slot" = full time budget), mirroring how mev-boost-relay handled its analogous underflow after the 2023 disclosure. #900 fixes a sibling underflow in the timing-games delay path but does not cover this one — with a wrapped msIntoSlot the line-86 guard returns before that code is reached.

Also worth noting: RecordMsIntoSlot exports the wrapped value into the histogram, so the metric is corrupted by the same bug.

Happy to provide more logs/metrics if useful.

Dominant language
Go
Stars
1.4k
Forks
292
PR merge metrics
No merged PRs in 30d

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from flashbots/mev-boost

All issues in flashbots/mev-boost

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.