@@ -69,9 +69,17 @@ var errSyncReorged = errors.New("sync reorged")
6969// might still be propagating.
7070var errTerminated = errors .New ("terminated" )
7171
72- // errReorgDenied is returned if an attempt is made to extend the beacon chain
73- // with a new header, but it does not link up to the existing sync.
74- var errReorgDenied = errors .New ("non-forced head reorg denied" )
72+ // errChainReorged is an internal helper error to signal that the header chain
73+ // of the current sync cycle was (partially) reorged.
74+ var errChainReorged = errors .New ("chain reorged" )
75+
76+ // errChainGapped is an internal helper error to signal that the header chain
77+ // of the current sync cycle is gaped with the one advertised by consensus client.
78+ var errChainGapped = errors .New ("chain gapped" )
79+
80+ // errChainForked is an internal helper error to signal that the header chain
81+ // of the current sync cycle is forked with the one advertised by consensus client.
82+ var errChainForked = errors .New ("chain forked" )
7583
7684func init () {
7785 // Tuning parameters is nice, but the scratch space must be assignable in
@@ -271,9 +279,9 @@ func (s *skeleton) startup() {
271279 newhead , err := s .sync (head )
272280 switch {
273281 case err == errSyncLinked :
274- // Sync cycle linked up to the genesis block. Tear down the loop
275- // and restart it so, it can properly notify the backfiller. Don't
276- // account a new head.
282+ // Sync cycle linked up to the genesis block, or the existent chain
283+ // segment. Tear down the loop and restart it so, it can properly
284+ // notify the backfiller. Don't account a new head.
277285 head = nil
278286
279287 case err == errSyncMerged :
@@ -457,15 +465,16 @@ func (s *skeleton) sync(head *types.Header) (*types.Header, error) {
457465 // we don't seamlessly integrate reorgs to keep things simple. If the
458466 // network starts doing many mini reorgs, it might be worthwhile handling
459467 // a limited depth without an error.
460- if reorged := s .processNewHead (event .header , event .final , event . force ); reorged {
468+ if err := s .processNewHead (event .header , event .final ); err != nil {
461469 // If a reorg is needed, and we're forcing the new head, signal
462470 // the syncer to tear down and start over. Otherwise, drop the
463471 // non-force reorg.
464472 if event .force {
465473 event .errc <- nil // forced head reorg accepted
474+ log .Info ("Restart sync cycle" , "reason" , err )
466475 return event .header , errSyncReorged
467476 }
468- event .errc <- errReorgDenied
477+ event .errc <- err
469478 continue
470479 }
471480 event .errc <- nil // head extension accepted
@@ -610,7 +619,7 @@ func (s *skeleton) saveSyncStatus(db ethdb.KeyValueWriter) {
610619// accepts and integrates it into the skeleton or requests a reorg. Upon reorg,
611620// the syncer will tear itself down and restart with a fresh head. It is simpler
612621// to reconstruct the sync state than to mutate it and hope for the best.
613- func (s * skeleton ) processNewHead (head * types.Header , final * types.Header , force bool ) bool {
622+ func (s * skeleton ) processNewHead (head * types.Header , final * types.Header ) error {
614623 // If a new finalized block was announced, update the sync process independent
615624 // of what happens with the sync head below
616625 if final != nil {
@@ -631,26 +640,17 @@ func (s *skeleton) processNewHead(head *types.Header, final *types.Header, force
631640 // once more, ignore it instead of tearing down sync for a noop.
632641 if lastchain .Head == lastchain .Tail {
633642 if current := rawdb .ReadSkeletonHeader (s .db , number ); current .Hash () == head .Hash () {
634- return false
643+ return nil
635644 }
636645 }
637646 // Not a noop / double head announce, abort with a reorg
638- if force {
639- log .Warn ("Beacon chain reorged" , "tail" , lastchain .Tail , "head" , lastchain .Head , "newHead" , number )
640- }
641- return true
647+ return fmt .Errorf ("%w, tail: %d, head: %d, newHead: %d" , errChainReorged , lastchain .Tail , lastchain .Head , number )
642648 }
643649 if lastchain .Head + 1 < number {
644- if force {
645- log .Warn ("Beacon chain gapped" , "head" , lastchain .Head , "newHead" , number )
646- }
647- return true
650+ return fmt .Errorf ("%w, head: %d, newHead: %d" , errChainGapped , lastchain .Head , number )
648651 }
649652 if parent := rawdb .ReadSkeletonHeader (s .db , number - 1 ); parent .Hash () != head .ParentHash {
650- if force {
651- log .Warn ("Beacon chain forked" , "ancestor" , number - 1 , "hash" , parent .Hash (), "want" , head .ParentHash )
652- }
653- return true
653+ return fmt .Errorf ("%w, ancestor: %d, hash: %s, want: %s" , errChainForked , number - 1 , parent .Hash (), head .ParentHash )
654654 }
655655 // New header seems to be in the last subchain range. Unwind any extra headers
656656 // from the chain tip and insert the new head. We won't delete any trimmed
@@ -666,7 +666,7 @@ func (s *skeleton) processNewHead(head *types.Header, final *types.Header, force
666666 if err := batch .Write (); err != nil {
667667 log .Crit ("Failed to write skeleton sync status" , "err" , err )
668668 }
669- return false
669+ return nil
670670}
671671
672672// assignTasks attempts to match idle peers to pending header retrievals.
0 commit comments