fix(server): guard uint64 subtractions in timing-games getHeader budget - #908
Open
SashaMIT wants to merge 1 commit into
Open
fix(server): guard uint64 subtractions in timing-games getHeader budget#908SashaMIT wants to merge 1 commit into
SashaMIT wants to merge 1 commit into
Conversation
In handleTimingGamesGetHeader both operands of delayMs = TargetFirstRequestMs - msIntoSlot are uint64. Whenever the consensus client calls getHeader later than target_first_request_ms into the slot (the common case), the subtraction wraps to ~2^64, delayMs > 0 passes, and timeoutLeftMs -= delayMs INCREASES the remaining budget by (msIntoSlot - target) - defeating the late-in-slot deadline the budget was computed against and letting header requests run past it. The inverse path (target beyond remaining budget) could pre-expire every request. Guard the wrap (only subtract when msIntoSlot < target) and clamp the budget decrement at zero.
There was a problem hiding this comment.
Pull request overview
This PR fixes an unsigned integer underflow in handleTimingGamesGetHeader by guarding uint64 subtractions when calculating the initial timing-games delay and clamping the timeout budget reduction to avoid wraparound that could defeat the late-in-slot deadline.
Changes:
- Guard
TargetFirstRequestMs - msIntoSlotby only subtracting whenmsIntoSlot < TargetFirstRequestMs. - Clamp the timeout budget decrement to prevent
timeoutLeftMsfrom wrapping.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+209
to
+213
| } else { | ||
| // The target time is already at/past the budget end: nothing left. | ||
| timeoutLeftMs = 0 | ||
| } | ||
| time.Sleep(time.Duration(delayMs) * time.Millisecond) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
In
handleTimingGamesGetHeader:Both operands are unsigned. Whenever the consensus client calls getHeader later than
target_first_request_msinto the slot — the common case with the repo's own example config (target_first_request_ms: 200) — the subtraction wraps to ~2^64. ThedelayMs > 0check then passes on the wrapped value, andtimeoutLeftMs -= delayMswraps in the opposite direction, i.e. it increases the remaining budget by(msIntoSlot - target).The budget was deliberately computed as
min(timeoutGetHeaderMs, lateInSlotTimeMs - msIntoSlot)so header requests stop at the late-in-slot deadline; the wrap silently defeats that bound and lets requests run past it. The symmetric case (target beyond the remaining budget) could zero/pre-expire requests instead.Fix
msIntoSlot < TargetFirstRequestMs(the wrap is then impossible).Tests
go build ./...andgo test ./server/pass. The changed block is inside the per-relay timing-games path; no interface changes.Made with Cursor
Made with Cursor