eth/downloader: short-circuit synchronise once partial-state sync is complete

beaconBackfiller.resume() already returns early when partialSyncComplete
is set, so in normal CL-driven operation the downloader never reaches
synchronise after the initial partial-state sync finishes. Add the same
guard at the synchronise entry point as defense in depth: any future
caller of synchronise (tests, other wiring) inherits the invariant
that partial-state nodes do not run full downloader cycles after
initial sync, even if the resume path is bypassed.

The check is cheap (one atomic.Load) and sits on the cold path, so the
impact on normal full-sync users is nil.
This commit is contained in:
CPerezz 2026-04-18 20:24:28 +02:00
parent e0c5cff4df
commit be19e2c67e
No known key found for this signature in database
GPG key ID: 62045F34B97177DD

View file

@ -389,6 +389,18 @@ func (d *Downloader) synchronise(beaconPing chan struct{}) (err error) {
}
defer d.synchronising.Store(false)
// Partial-state nodes must not run a downloader cycle once the initial
// sync has completed; every live block arrives via the Engine API's
// newPayload path and is processed with ApplyBALAndComputeRoot. Running
// the downloader here would try to download + (re-)execute blocks
// against storage we intentionally don't have. beaconBackfiller.resume
// already guards this at a higher layer; this check is defense in depth
// for any other caller of synchronise (tests, future wiring).
if d.partialFilter != nil && d.partialSyncComplete.Load() {
log.Debug("Partial state: sync complete, skipping downloader cycle")
return nil
}
// Post a user notification of the sync (only once per session)
if d.notified.CompareAndSwap(false, true) {
log.Info("Block synchronisation started")