eth: re-schedule skeleton sync if it's not linked with local chain

This commit is contained in:
Gary Rong 2025-12-17 12:12:10 +08:00
parent 374be93068
commit af8e152501
2 changed files with 28 additions and 2 deletions

View file

@ -1,4 +1,4 @@
// Copyright 20222 The go-ethereum Authors // Copyright 2025 The go-ethereum Authors
// This file is part of the go-ethereum library. // This file is part of the go-ethereum library.
// //
// The go-ethereum library is free software: you can redistribute it and/or modify // The go-ethereum library is free software: you can redistribute it and/or modify

View file

@ -64,6 +64,12 @@ var errSyncMerged = errors.New("sync merged")
// should abort and restart with the new state. // should abort and restart with the new state.
var errSyncReorged = errors.New("sync reorged") var errSyncReorged = errors.New("sync reorged")
// errSyncTrimmed is an internal helper error to signal that the local chain
// has been trimmed (e.g, via debug_setHead explicitly) and the skeleton chain
// is no longer linked with the local chain. In this case, the skeleton sync
// should be re-scheduled again.
var errSyncTrimmed = errors.New("sync trimmed")
// errTerminated is returned if the sync mechanism was terminated for this run of // errTerminated is returned if the sync mechanism was terminated for this run of
// the process. This is usually the case when Geth is shutting down and some events // the process. This is usually the case when Geth is shutting down and some events
// might still be propagating. // might still be propagating.
@ -296,6 +302,11 @@ func (s *skeleton) startup() {
// head to force a cleanup. // head to force a cleanup.
head = newhead head = newhead
case err == errSyncTrimmed:
// The skeleton chain is not linked with the local chain anymore,
// restart the sync.
head = nil
case err == errTerminated: case err == errTerminated:
// Sync was requested to be terminated from within, stop and // Sync was requested to be terminated from within, stop and
// return (no need to pass a message, was already done internally) // return (no need to pass a message, was already done internally)
@ -486,7 +497,21 @@ func (s *skeleton) sync(head *types.Header) (*types.Header, error) {
// is still running, it will pick it up. If it already terminated, // is still running, it will pick it up. If it already terminated,
// a new cycle needs to be spun up. // a new cycle needs to be spun up.
if linked { if linked {
s.filler.resume() linked = len(s.progress.Subchains) == 1 &&
rawdb.HasHeader(s.db, s.progress.Subchains[0].Next, s.scratchHead) &&
rawdb.HasBody(s.db, s.progress.Subchains[0].Next, s.scratchHead) &&
rawdb.HasReceipts(s.db, s.progress.Subchains[0].Next, s.scratchHead)
if linked {
// The skeleton chain has been extended and is still linked with the local
// chain, try to re-schedule the backfiller if it's already terminated.
s.filler.resume()
} else {
// The skeleton chain is no longer linked to the local chain for some reason
// (e.g. debug_setHead was used to trim the local chain). Re-schedule the
// skeleton sync to fill the chain gap.
return nil, errSyncTrimmed
}
} }
case req := <-requestFails: case req := <-requestFails:
@ -669,6 +694,7 @@ func (s *skeleton) processNewHead(head *types.Header, final *types.Header) error
if err := batch.Write(); err != nil { if err := batch.Write(); err != nil {
log.Crit("Failed to write skeleton sync status", "err", err) log.Crit("Failed to write skeleton sync status", "err", err)
} }
log.Debug("Extended beacon header chain", "number", head.Number, "hash", head.Hash())
return nil return nil
} }