Skip to content

Leios prototype: Fix PastHorizon errors in syncing - #2252

Merged
ch1bo merged 2 commits into
leios-prototypefrom
ch1bo/leios-announcement-past-horizon
Aug 29, 2026
Merged

Leios prototype: Fix PastHorizon errors in syncing#2252
ch1bo merged 2 commits into
leios-prototypefrom
ch1bo/leios-announcement-past-horizon

Conversation

@ch1bo

@ch1bo ch1bo commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Should fix or at least improve the situation with input-output-hk/ouroboros-leios#1039 and input-output-hk/ouroboros-leios#998. Both issues had various reports with PastHorizon or forecast range errors.

When syncing a testnet on preparing a release I got stuck multiple times and the root cause was the connection going down because of the LeiosNotify handler throwIOing the PastHorizon error result during judgeHeaderArrival. I also noticed that we use the immutable tip to do time converstions, but the volatile one would have a slightly longer range and so switched to that.

I did not see nodes using this fix get stuck so far.

ch1bo and others added 2 commits August 29, 2026 23:16
'announcementValidity' reuses ChainSync's in-future check to date an
announced EB, and threw whatever it returned. A syncing node cannot place
the network's current slot on a wall clock, so every announcement from a
caught-up peer raised 'PastHorizon', killed the per-peer handler and shut
the peer down. With no peer surviving to serve headers, ChainSync stopped,
no announcements arrived via rollforward, and chain selection froze until
the node was restarted -- 148 such disconnects in one 29-minute stall.

The stock ChainSync client calls the same 'judgeHeaderArrival' and reads
'PastHorizon' as "cannot judge yet", blocking for a newer ledger state.
Only the Leios copy turned it into a disconnect.

So the verdict is now 'VerdictIgnore', the path 'StaleOCIN' already takes:
accepted from the peer, neither processed nor relayed. A /far-future/ slot
is a different matter -- that one is the peer lying, and
'handleHeaderArrival' still disconnects them.

'TraceLeiosAnnouncementPastHorizon' records the slot, and only the slot: a
'PastHorizonException' renders as a couple of kilobytes of era summary, and
this fires once per announcement.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The in-future check was judging against the immutable tip, whose forecast
horizon early in a sync is tiny: the summary in one PastHorizon carried six
eras collapsed at slot 0 and the last ending at slot 21600, against an
announced slot of 1971193. Nearly every announcement was undatable, and the
preceding commit could only ignore them.

The volatile tip forecasts as far as we have any right to, so the same
announcements become datable and are accepted instead. On the testnet that
is the difference between ~150 announcements per run reaching a verdict of
'VerdictIgnore' and 1126 reaching 'VerdictProcess', with a residue of 4 --
all at the true chain tip, which a node 1.4M slots behind genuinely cannot
place.

'validateAnnouncementHeader' keeps the immutable tip: an opcert revocation
should only count once it cannot be rolled back. The two states are read in
one 'atomically' so they cannot describe different chains, and the
signature now names which is which.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ch1bo
ch1bo requested a review from nfrisby August 29, 2026 21:38
@ch1bo ch1bo added the Leios label Aug 29, 2026
@ch1bo

ch1bo commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

Merging to release and tag a node with this (for further validation on the testnet). Hope to get your feedback on the change still @nfrisby

@ch1bo
ch1bo merged commit 1820edf into leios-prototype Aug 29, 2026
4 of 24 checks passed
@ch1bo
ch1bo deleted the ch1bo/leios-announcement-past-horizon branch August 29, 2026 21:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant