@@ -30,13 +30,6 @@ type p2pHandler interface {
3030 ProcessDataRange (ctx context.Context , fromHeight , toHeight uint64 ) []common.DAHeightEvent
3131}
3232
33- const (
34- // maxRetriesBeforeHalt is the maximum number of retries against the execution client before halting the syncer.
35- maxRetriesBeforeHalt = 3
36- // maxRetriesTimeout is the maximum time to wait for a retry before halting the syncer.
37- maxRetriesTimeout = time .Second * 10
38- )
39-
4033// Syncer handles block synchronization from DA and P2P sources.
4134type Syncer struct {
4235 // Core components
@@ -76,10 +69,9 @@ type Syncer struct {
7669 logger zerolog.Logger
7770
7871 // Lifecycle
79- ctx context.Context
80- cancel context.CancelFunc
81- wg sync.WaitGroup
82- retriesBeforeHalt map [uint64 ]uint64
72+ ctx context.Context
73+ cancel context.CancelFunc
74+ wg sync.WaitGroup
8375}
8476
8577// NewSyncer creates a new block syncer
@@ -98,21 +90,20 @@ func NewSyncer(
9890 errorCh chan <- error ,
9991) * Syncer {
10092 return & Syncer {
101- store : store ,
102- exec : exec ,
103- da : da ,
104- cache : cache ,
105- metrics : metrics ,
106- config : config ,
107- genesis : genesis ,
108- options : options ,
109- headerStore : headerStore ,
110- dataStore : dataStore ,
111- lastStateMtx : & sync.RWMutex {},
112- heightInCh : make (chan common.DAHeightEvent , 10_000 ),
113- errorCh : errorCh ,
114- logger : logger .With ().Str ("component" , "syncer" ).Logger (),
115- retriesBeforeHalt : make (map [uint64 ]uint64 ),
93+ store : store ,
94+ exec : exec ,
95+ da : da ,
96+ cache : cache ,
97+ metrics : metrics ,
98+ config : config ,
99+ genesis : genesis ,
100+ options : options ,
101+ headerStore : headerStore ,
102+ dataStore : dataStore ,
103+ lastStateMtx : & sync.RWMutex {},
104+ heightInCh : make (chan common.DAHeightEvent , 10_000 ),
105+ errorCh : errorCh ,
106+ logger : logger .With ().Str ("component" , "syncer" ).Logger (),
116107 }
117108}
118109
@@ -489,19 +480,11 @@ func (s *Syncer) applyBlock(header types.Header, data *types.Data, currentState
489480
490481 // Execute transactions
491482 ctx := context .WithValue (s .ctx , types .HeaderContextKey , header )
492- newAppHash , _ , err := s .exec .ExecuteTxs (ctx , rawTxs , header .Height (),
493- header .Time (), currentState .AppHash )
483+ newAppHash , err := s .executeTxsWithRetry (ctx , rawTxs , header , currentState )
494484 if err != nil {
495- s .retriesBeforeHalt [header .Height ()]++
496- if s .retriesBeforeHalt [header .Height ()] > maxRetriesBeforeHalt {
497- s .sendCriticalError (fmt .Errorf ("failed to execute transactions: %w" , err ))
498- return types.State {}, fmt .Errorf ("failed to execute transactions: %w" , err )
499- }
500-
501- time .Sleep (maxRetriesTimeout ) // sleep before retrying
502- return types.State {}, fmt .Errorf ("failed to execute transactions (retry %d / %d): %w" , s .retriesBeforeHalt [header .Height ()], maxRetriesBeforeHalt , err )
485+ s .sendCriticalError (fmt .Errorf ("failed to execute transactions: %w" , err ))
486+ return types.State {}, fmt .Errorf ("failed to execute transactions: %w" , err )
503487 }
504- delete (s .retriesBeforeHalt , header .Height ())
505488
506489 // Create new state
507490 newState , err := currentState .NextState (header , newAppHash )
@@ -512,6 +495,35 @@ func (s *Syncer) applyBlock(header types.Header, data *types.Data, currentState
512495 return newState , nil
513496}
514497
498+ // executeTxsWithRetry executes transactions with retry logic
499+ func (s * Syncer ) executeTxsWithRetry (ctx context.Context , rawTxs [][]byte , header types.Header , currentState types.State ) ([]byte , error ) {
500+ for attempt := 1 ; attempt <= common .MaxRetriesBeforeHalt ; attempt ++ {
501+ newAppHash , _ , err := s .exec .ExecuteTxs (ctx , rawTxs , header .Height (), header .Time (), currentState .AppHash )
502+ if err != nil {
503+ if attempt == common .MaxRetriesBeforeHalt {
504+ return nil , fmt .Errorf ("failed to execute transactions: %w" , err )
505+ }
506+
507+ s .logger .Error ().Err (err ).
508+ Int ("attempt" , attempt ).
509+ Int ("max_attempts" , common .MaxRetriesBeforeHalt ).
510+ Uint64 ("height" , header .Height ()).
511+ Msg ("failed to execute transactions, retrying" )
512+
513+ select {
514+ case <- time .After (common .MaxRetriesTimeout ):
515+ continue
516+ case <- s .ctx .Done ():
517+ return nil , fmt .Errorf ("context cancelled during retry: %w" , s .ctx .Err ())
518+ }
519+ }
520+
521+ return newAppHash , nil
522+ }
523+
524+ return nil , nil
525+ }
526+
515527// validateBlock validates a synced block
516528func (s * Syncer ) validateBlock (
517529 lastState types.State ,
0 commit comments