Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions block/internal/common/replay.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,11 @@ func (s *Replayer) SyncToHeight(ctx context.Context, targetHeight uint64) error
Uint64("exec_layer_height", execHeight).
Msg("execution layer height check")

// If execution layer is ahead, skip syncing and continue. This can happen if execution
// progressed independently (e.g. after manual intervention). We log it for visibility but
// do not treat it as fatal.
// If execution layer is ahead, we cannot proceed safely as this indicates state divergence.
// The execution layer must be rolled back before the node can continue.
if execHeight > targetHeight {
s.logger.Warn().
Uint64("target_height", targetHeight).
Uint64("exec_layer_height", execHeight).
Msg("execution layer is ahead of target height - skipping replay")
return nil
return fmt.Errorf("execution layer height (%d) ahead of target height (%d): manually rollback execution layer to height %d",
execHeight, targetHeight, targetHeight)
}

// If execution layer is behind, sync the missing blocks
Expand Down
7 changes: 4 additions & 3 deletions block/internal/common/replay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,16 @@ func TestReplayer_SyncToHeight_ExecutorAhead(t *testing.T) {

syncer := NewReplayer(mockStore, mockExec, gen, logger)

// Setup: target height is 100, execution layer is at 101 (unexpected!)
// Setup: execution layer is ahead of target (indicates state divergence)
targetHeight := uint64(100)
execHeight := uint64(101)

mockExec.On("GetLatestHeight", mock.Anything).Return(execHeight, nil)

// Execute sync - should just log and continue without error
// Should return error to prevent proceeding with divergent state
err := syncer.SyncToHeight(ctx, targetHeight)
require.NoError(t, err)
require.Error(t, err)
require.Contains(t, err.Error(), "ahead of target height")

// No replay should be attempted
mockExec.AssertNotCalled(t, "ExecuteTxs", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything)
Expand Down
Loading