msg-validation: round-timeout validation refactoring#2811
msg-validation: round-timeout validation refactoring#2811iurii-ssv wants to merge 11 commits intomsgval-lowest-roundfrom
Conversation
Codecov Report❌ Patch coverage is
☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Greptile SummaryThis PR refactors the QBFT round-timeout validation logic: it extracts a shared Confidence Score: 5/5Safe to merge — all changes are correct, well-tested, and the edge-case fix is validated by targeted boundary tests. The No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["roundBelongsToAllowedSpread(role, round, receivedAt)"] --> B["estimatedRoundAt(role, timeIntoSlot)\n→ EstimatedRoundAt(role, slotDuration, timeIntoSlot)"]
B --> C["elapsed = timeIntoSlot - round1HeadStart(role)"]
C --> D{elapsed < 0?}
D -- yes --> E["return FirstRound"]
D -- no --> F{"elapsed < quickEnd?\nquickEnd = T × QuickTimeout"}
F -- yes --> G["return FirstRound + elapsed/QuickTimeout\n(quick phase: rounds 1..T)"]
F -- no --> H["slowElapsed = elapsed − quickEnd\nreturn FirstRound + T + slowElapsed/SlowTimeout\n(slow phase: rounds T+1…)"]
E & G & H --> I["estimatedRound"]
I --> J{"estimatedRound > allowedRoundsInPast (=2)?"}
J -- no --> K["lowestAllowed = FirstRound\n✅ edge-case fix: was ≥, now >"]
J -- yes --> L["lowestAllowed = estimatedRound − allowedRoundsInPast"]
K & L --> M["highestAllowed = estimatedRound + allowedRoundsInFuture"]
M --> N{role == Proposer?}
N -- yes --> O["lowestAllowed = FirstRound\nhighestAllowed = FirstRound + 1"]
N -- no --> P["keep computed bounds"]
O & P --> Q{"msg.Round in\n[lowestAllowed, highestAllowed]?"}
Q -- yes --> R["✅ Accept"]
Q -- no --> S["❌ ErrEstimatedRoundNotInAllowedSpread"]
Reviews (3): Last reviewed commit: "clean up" | Re-trigger Greptile |
c0216bd to
91dde2c
Compare
280961e to
09f3eb0
Compare
|
@greptile pls re-review |
| // Round T+2 ends at headStart + T * quick + 2 * slow | ||
| // | ||
| // Every role has its own dedicated headStart duration. | ||
| func (o TimeoutOptions) roundTimeoutOffset(role spectypes.RunnerRole, slotDuration time.Duration, round specqbft.Round) time.Duration { |
There was a problem hiding this comment.
I'm not sure that 'offset' describes the duration very well
There was a problem hiding this comment.
WDYT about renaming roundTimeoutOffset->roundTimeoutSlotOffset / roundTimeoutIntoSlot ? Or do you have some other name in mind
Or maybe we could name it just roundTimeout to keep consistent/similar to RoundTimer.RoundTimeout
There was a problem hiding this comment.
Maybe something like RoundTimeoutAfter?
There was a problem hiding this comment.
After part doesn't quite describe it, how about roundTimeoutForRound ?
Builds on top of #2807 to clean up the message-validation code related to validating QBFT Rounds:
Resolves https://github.com/ssvlabs/ssv-node-board/issues/1002