From 4307ee86f86dd9814323f45e5a64a46441e645a9 Mon Sep 17 00:00:00 2001 From: SillyZir Date: Wed, 12 Aug 2026 11:57:13 -0400 Subject: [PATCH] eth/syncer: only synthesize finalized/safe markers with an explicit sync target (#35433) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #35418. After a restart, the syncer sets the finalized marker to head−64 and the safe marker to head−32 on every downloader sync event, ignoring epoch boundaries. Since this service is registered unconditionally and `api_backend` serves `CurrentFinalBlock()` verbatim, `eth_getBlockByNumber("finalized")` can return a mid-epoch block that was never finalized and can still be reorged. The synthesized markers exist to make `finalized`/`safe` usable when no consensus client is attached. This change scopes them to exactly that case: they are only set when an explicit sync target has been specified (`--synctarget`), which is the only mode where no CL supplies real checkpoints. Normal nodes now never override consensus-client checkpoints. `TestSyncerDoesNotInventFinalityMarkers` syncs a node to head with no CL finality input and asserts the chain's finalized/safe markers stay unset; it fails on master (finalized invented at head−64) and passes with this change. --------- Co-authored-by: SillyZir <269283839+SillyZir@users.noreply.github.com> Co-authored-by: Jonny Rhea <5555162+jrhea@users.noreply.github.com> Co-authored-by: rjl493456442 --- eth/syncer/syncer.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/eth/syncer/syncer.go b/eth/syncer/syncer.go index dfe4b80e93..12987c9cae 100644 --- a/eth/syncer/syncer.go +++ b/eth/syncer/syncer.go @@ -159,10 +159,14 @@ func (s *Syncer) run() { } head := s.backend.BlockChain().CurrentHeader() - if head != nil { + if target != nil && head != nil { // Set the finalized and safe markers relative to the current head. // The finalized marker is set two epochs behind the target, // and the safe marker is set one epoch behind the target. + // + // Note, the markers are only synthesized if a sync target has + // been explicitly specified, in which case no consensus client + // is attached to supply the real ones. if header := s.backend.BlockChain().GetHeaderByNumber(head.Number.Uint64() - params.EpochLength*2); header != nil { if final := s.backend.BlockChain().CurrentFinalBlock(); final == nil || final.Number.Cmp(header.Number) < 0 { s.backend.BlockChain().SetFinalized(header)