@@ -3,6 +3,7 @@ package executing
33import (
44 "bytes"
55 "context"
6+ "encoding/binary"
67 "errors"
78 "fmt"
89 "reflect"
@@ -551,23 +552,41 @@ func (e *Executor) ProduceBlock(ctx context.Context) error {
551552 // production to fail, but it does run in the critical path and may add
552553 // some latency when large ranges are pruned.
553554 if e .config .Node .PruningEnabled && e .config .Node .PruningKeepRecent > 0 && e .config .Node .PruningInterval > 0 {
554- if newHeight % e .config .Node .PruningInterval == 0 {
555- // Compute the prune floor: all heights <= targetHeight are candidates
556- // for pruning of header/data/signature/index entries.
557- if newHeight > e .config .Node .PruningKeepRecent {
558- targetHeight := newHeight - e .config .Node .PruningKeepRecent
559- if err := e .store .PruneBlocks (e .ctx , targetHeight ); err != nil {
560- e .logger .Error ().Err (err ).Uint64 ("target_height" , targetHeight ).Msg ("failed to prune old block data" )
555+ interval := e .config .Node .PruningInterval
556+ // Only attempt pruning when we're exactly at an interval boundary.
557+ if newHeight % interval == 0 && newHeight > e .config .Node .PruningKeepRecent {
558+ targetHeight := newHeight - e .config .Node .PruningKeepRecent
559+
560+ // Determine the DA-included floor for pruning, so we never prune
561+ // beyond what has been confirmed in DA.
562+ var daIncludedHeight uint64
563+ meta , err := e .store .GetMetadata (e .ctx , store .DAIncludedHeightKey )
564+ if err == nil && len (meta ) == 8 {
565+ daIncludedHeight = binary .LittleEndian .Uint64 (meta )
566+ }
567+
568+ // If nothing is known to be DA-included yet, skip pruning.
569+ if daIncludedHeight == 0 {
570+ // Nothing known to be DA-included yet; skip pruning.
571+ } else {
572+ if targetHeight > daIncludedHeight {
573+ targetHeight = daIncludedHeight
561574 }
562575
563- // If the execution client exposes execution-metadata pruning,
564- // prune ExecMeta using the same target height. This keeps EVM
565- // execution metadata aligned with ev-node's block store pruning
566- // while remaining a no-op for execution environments that don't
567- // implement ExecMetaPruner (e.g. ABCI-based executors).
568- if pruner , ok := e .exec .(coreexecutor.ExecMetaPruner ); ok {
569- if err := pruner .PruneExecMeta (e .ctx , targetHeight ); err != nil {
570- e .logger .Error ().Err (err ).Uint64 ("target_height" , targetHeight ).Msg ("failed to prune execution metadata" )
576+ if targetHeight > 0 {
577+ if err := e .store .PruneBlocks (e .ctx , targetHeight ); err != nil {
578+ return fmt .Errorf ("failed to prune old block data: %w" , err )
579+ }
580+
581+ // If the execution client exposes execution-metadata pruning,
582+ // prune ExecMeta using the same target height. This keeps
583+ // execution-layer metadata aligned with
584+ // ev-node's block store pruning while remaining a no-op for
585+ // execution environments that don't implement ExecMetaPruner yet.
586+ if pruner , ok := e .exec .(coreexecutor.ExecMetaPruner ); ok {
587+ if err := pruner .PruneExecMeta (e .ctx , targetHeight ); err != nil {
588+ return fmt .Errorf ("failed to prune execution metadata: %w" , err )
589+ }
571590 }
572591 }
573592 }
0 commit comments