@@ -31,6 +31,9 @@ type p2pHandler interface {
3131 ProcessDataRange (ctx context.Context , fromHeight , toHeight uint64 ) []common.DAHeightEvent
3232}
3333
34+ // maxRetriesBeforeHalt is the maximum number of retries against the execution client before halting the syncer.
35+ const maxRetriesBeforeHalt = 3
36+
3437// Syncer handles block synchronization from DA and P2P sources.
3538type Syncer struct {
3639 // Core components
@@ -70,9 +73,10 @@ type Syncer struct {
7073 logger zerolog.Logger
7174
7275 // Lifecycle
73- ctx context.Context
74- cancel context.CancelFunc
75- wg sync.WaitGroup
76+ ctx context.Context
77+ cancel context.CancelFunc
78+ wg sync.WaitGroup
79+ retriesBeforeHalt map [uint64 ]uint64
7680}
7781
7882// NewSyncer creates a new block syncer
@@ -91,20 +95,21 @@ func NewSyncer(
9195 errorCh chan <- error ,
9296) * Syncer {
9397 return & Syncer {
94- store : store ,
95- exec : exec ,
96- da : da ,
97- cache : cache ,
98- metrics : metrics ,
99- config : config ,
100- genesis : genesis ,
101- options : options ,
102- headerStore : headerStore ,
103- dataStore : dataStore ,
104- lastStateMtx : & sync.RWMutex {},
105- heightInCh : make (chan common.DAHeightEvent , 10_000 ),
106- errorCh : errorCh ,
107- logger : logger .With ().Str ("component" , "syncer" ).Logger (),
98+ store : store ,
99+ exec : exec ,
100+ da : da ,
101+ cache : cache ,
102+ metrics : metrics ,
103+ config : config ,
104+ genesis : genesis ,
105+ options : options ,
106+ headerStore : headerStore ,
107+ dataStore : dataStore ,
108+ lastStateMtx : & sync.RWMutex {},
109+ heightInCh : make (chan common.DAHeightEvent , 10_000 ),
110+ errorCh : errorCh ,
111+ logger : logger .With ().Str ("component" , "syncer" ).Logger (),
112+ retriesBeforeHalt : make (map [uint64 ]uint64 ),
108113 }
109114}
110115
@@ -470,9 +475,15 @@ func (s *Syncer) applyBlock(header types.Header, data *types.Data, currentState
470475 newAppHash , _ , err := s .exec .ExecuteTxs (ctx , rawTxs , header .Height (),
471476 header .Time (), currentState .AppHash )
472477 if err != nil {
473- s .sendCriticalError (fmt .Errorf ("failed to execute transactions: %w" , err ))
474- return types.State {}, fmt .Errorf ("failed to execute transactions: %w" , err )
478+ s .retriesBeforeHalt [header .Height ()]++
479+ if s .retriesBeforeHalt [header .Height ()] > maxRetriesBeforeHalt {
480+ s .sendCriticalError (fmt .Errorf ("failed to execute transactions: %w" , err ))
481+ return types.State {}, fmt .Errorf ("failed to execute transactions: %w" , err )
482+ }
483+
484+ return types.State {}, fmt .Errorf ("failed to execute transactions (retry %d / %d): %w" , s .retriesBeforeHalt [header .Height ()], maxRetriesBeforeHalt , err )
475485 }
486+ delete (s .retriesBeforeHalt , header .Height ())
476487
477488 // Create new state
478489 newState , err := currentState .NextState (header , newAppHash )
0 commit comments