@@ -511,12 +511,10 @@ func (e *Executor) ProduceBlock(ctx context.Context) error {
511511 }
512512 header .Signature = signature
513513
514- if err := e .blockProducer .ValidateBlock (ctx , currentState , header , data ); err != nil {
515- e .sendCriticalError (fmt .Errorf ("failed to validate block: %w" , err ))
516- e .logger .Error ().Err (err ).Msg ("CRITICAL: Permanent block validation error - halting block production" )
517- return fmt .Errorf ("failed to validate block: %w" , err )
518- }
514+ // ValidateBlock is only needed for blocks we didn't produce (syncer path).
515+ // On the sequencer, we just built this block — skip self-validation.
519516
517+ // Prepare store batch synchronously. Only the commit is deferred.
520518 batch , err := e .store .NewBatch (ctx )
521519 if err != nil {
522520 return fmt .Errorf ("failed to create batch: %w" , err )
@@ -565,11 +563,12 @@ func (e *Executor) ProduceBlock(ctx context.Context) error {
565563 }
566564 }
567565
566+ // Commit synchronously — DA submitter reads store height.
568567 if err := batch .Commit (); err != nil {
569568 return fmt .Errorf ("failed to commit batch: %w" , err )
570569 }
571570
572- // Update in-memory state after successful commit
571+ // Update in-memory state after successful commit.
573572 e .setLastState (newState )
574573
575574 // Cache this block for the next CreateBlock call (avoids 2 store reads).
@@ -582,18 +581,19 @@ func (e *Executor) ProduceBlock(ctx context.Context) error {
582581 }
583582 e .lastBlockMu .Unlock ()
584583
585- // broadcast header and data to P2P network
586- g , broadcastCtx := errgroup .WithContext (e .ctx )
587- g .Go (func () error {
588- return e .headerBroadcaster .WriteToStoreAndBroadcast (broadcastCtx , & types.P2PSignedHeader {SignedHeader : header })
589- })
590- g .Go (func () error {
591- return e .dataBroadcaster .WriteToStoreAndBroadcast (broadcastCtx , & types.P2PData {Data : data })
592- })
593- if err := g .Wait (); err != nil {
594- e .logger .Error ().Err (err ).Msg ("failed to broadcast header and/data" )
595- // don't fail block production on broadcast error
596- }
584+ // P2P broadcast is fire-and-forget — doesn't block next block production.
585+ go func () {
586+ g , broadcastCtx := errgroup .WithContext (e .ctx )
587+ g .Go (func () error {
588+ return e .headerBroadcaster .WriteToStoreAndBroadcast (broadcastCtx , & types.P2PSignedHeader {SignedHeader : header })
589+ })
590+ g .Go (func () error {
591+ return e .dataBroadcaster .WriteToStoreAndBroadcast (broadcastCtx , & types.P2PData {Data : data })
592+ })
593+ if err := g .Wait (); err != nil {
594+ e .logger .Error ().Err (err ).Msg ("failed to broadcast header and/data" )
595+ }
596+ }()
597597
598598 e .recordBlockMetrics (newState , data )
599599
0 commit comments