Skip to content

Commit 40aae3b

Browse files
committed
code cleanups
1 parent 2326ae3 commit 40aae3b

3 files changed

Lines changed: 75 additions & 26 deletions

File tree

pkg/sequencers/based/sequencer.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -128,16 +128,11 @@ func (s *BasedSequencer) GetNextBatch(ctx context.Context, req coresequencer.Get
128128
// If we have no cached transactions or we've consumed all from the current DA epoch,
129129
// fetch the next DA epoch
130130
if daHeight > 0 && (len(s.currentBatchTxs) == 0 || s.checkpoint.TxIndex >= uint64(len(s.currentBatchTxs))) {
131-
daEndTime, daEndHeight, err := s.fetchNextDAEpoch(ctx, req.MaxBytes)
131+
daEndHeight, err := s.fetchNextDAEpoch(ctx, req.MaxBytes)
132132
if err != nil {
133133
return nil, err
134134
}
135135
daHeight = daEndHeight
136-
137-
if daEndTime.After(s.currentDAEndTime) {
138-
s.currentDAEndTime = daEndTime
139-
}
140-
s.currentEpochTxCount = uint64(len(s.currentBatchTxs))
141136
}
142137

143138
// Get remaining transactions from checkpoint position
@@ -242,7 +237,7 @@ func (s *BasedSequencer) getMaxGas(ctx context.Context) uint64 {
242237
}
243238

244239
// fetchNextDAEpoch fetches transactions from the next DA epoch
245-
func (s *BasedSequencer) fetchNextDAEpoch(ctx context.Context, maxBytes uint64) (time.Time, uint64, error) {
240+
func (s *BasedSequencer) fetchNextDAEpoch(ctx context.Context, maxBytes uint64) (uint64, error) {
246241
currentDAHeight := s.checkpoint.DAHeight
247242

248243
s.logger.Debug().
@@ -254,16 +249,16 @@ func (s *BasedSequencer) fetchNextDAEpoch(ctx context.Context, maxBytes uint64)
254249
if err != nil {
255250
// Check if forced inclusion is not configured
256251
if errors.Is(err, block.ErrForceInclusionNotConfigured) {
257-
return time.Time{}, 0, block.ErrForceInclusionNotConfigured
252+
return 0, block.ErrForceInclusionNotConfigured
258253
} else if errors.Is(err, datypes.ErrHeightFromFuture) {
259254
// If we get a height from future error, stay at current position
260255
// We'll retry the same height on the next call until DA produces that block
261256
s.logger.Debug().
262257
Uint64("da_height", currentDAHeight).
263258
Msg("DA height from future, waiting for DA to produce block")
264-
return time.Time{}, 0, nil
259+
return 0, nil
265260
}
266-
return time.Time{}, 0, fmt.Errorf("failed to retrieve forced inclusion transactions: %w", err)
261+
return 0, fmt.Errorf("failed to retrieve forced inclusion transactions: %w", err)
267262
}
268263

269264
// Validate and filter transactions by size
@@ -292,8 +287,13 @@ func (s *BasedSequencer) fetchNextDAEpoch(ctx context.Context, maxBytes uint64)
292287

293288
// Cache the transactions for this DA epoch
294289
s.currentBatchTxs = validTxs
290+
s.currentEpochTxCount = uint64(len(validTxs))
291+
292+
if daEndTime := forcedTxsEvent.Timestamp.UTC(); daEndTime.After(s.currentDAEndTime) {
293+
s.currentDAEndTime = daEndTime
294+
}
295295

296-
return forcedTxsEvent.Timestamp.UTC(), forcedTxsEvent.EndDaHeight, nil
296+
return forcedTxsEvent.EndDaHeight, nil
297297
}
298298

299299
// VerifyBatch verifies a batch of transactions

pkg/sequencers/single/sequencer.go

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,17 @@ func NewSequencer(
8484
executor execution.Executor,
8585
) (*Sequencer, error) {
8686
s := &Sequencer{
87-
db: db,
88-
logger: logger,
89-
daClient: daClient,
90-
cfg: cfg,
91-
batchTime: cfg.Node.BlockTime.Duration,
92-
Id: id,
93-
queue: NewBatchQueue(db, "batches", maxQueueSize),
94-
checkpointStore: seqcommon.NewCheckpointStore(db, ds.NewKey("/single/checkpoint")),
95-
genesis: genesis,
96-
executor: executor,
87+
db: db,
88+
logger: logger,
89+
daClient: daClient,
90+
cfg: cfg,
91+
batchTime: cfg.Node.BlockTime.Duration,
92+
Id: id,
93+
queue: NewBatchQueue(db, "batches", maxQueueSize),
94+
checkpointStore: seqcommon.NewCheckpointStore(db, ds.NewKey("/single/checkpoint")),
95+
genesis: genesis,
96+
currentDAEndTime: genesis.StartTime,
97+
executor: executor,
9798
}
9899
s.SetDAHeight(genesis.DAStartHeight) // default value, will be overridden by executor or submitter
99100
s.daStartHeight.Store(genesis.DAStartHeight)
@@ -463,10 +464,6 @@ func (c *Sequencer) fetchNextDAEpoch(ctx context.Context, maxBytes uint64) (uint
463464
return 0, fmt.Errorf("failed to retrieve forced inclusion transactions: %w", err)
464465
}
465466

466-
// Store DA epoch end time for timestamp usage during catch-up
467-
if !forcedTxsEvent.Timestamp.IsZero() {
468-
c.currentDAEndTime = forcedTxsEvent.Timestamp.UTC()
469-
}
470467
// Record total tx count for the epoch so the timestamp jitter can be computed
471468
// after oversized txs are filtered out below.
472469

@@ -494,9 +491,15 @@ func (c *Sequencer) fetchNextDAEpoch(ctx context.Context, maxBytes uint64) (uint
494491
Bool("catching_up", c.catchUpState.Load() == catchUpInProgress).
495492
Msg("fetched forced inclusion transactions from DA")
496493

494+
// Cache the transactions for this DA epoch
497495
c.cachedForcedInclusionTxs = validTxs
498496
c.currentEpochTxCount = uint64(len(validTxs))
499497

498+
// Store DA epoch end time for timestamp usage during catch-up
499+
if daEndTime := forcedTxsEvent.Timestamp.UTC(); forcedTxsEvent.Timestamp.UTC().After(c.currentDAEndTime) {
500+
c.currentDAEndTime = daEndTime
501+
}
502+
500503
return forcedTxsEvent.EndDaHeight, nil
501504
}
502505

@@ -558,6 +561,10 @@ func (c *Sequencer) updateCatchUpState(ctx context.Context) {
558561
Msg("initialized catch-up timestamp floor from last block time")
559562
}
560563

564+
if c.lastCatchUpTimestamp.After(c.currentDAEndTime) {
565+
c.currentDAEndTime = c.lastCatchUpTimestamp
566+
}
567+
561568
c.catchUpState.Store(catchUpInProgress)
562569
c.logger.Warn().
563570
Uint64("checkpoint_da_height", currentDAHeight).

test/e2e/evm_force_inclusion_e2e_test.go

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"context"
88
"encoding/json"
99
"fmt"
10+
"math/big"
1011
"net/http"
1112
"os"
1213
"path/filepath"
@@ -849,7 +850,6 @@ func TestEvmSequencerCatchUpBasedSequencerE2E(t *testing.T) {
849850
"--evnode.clear_cache",
850851
"--evm.engine-url", env.Endpoints.GetFullNodeEngineURL(),
851852
"--evm.eth-url", env.Endpoints.GetFullNodeEthURL(),
852-
"--evnode.log.level", "debug",
853853
)
854854
sut.AwaitNodeLive(t, env.Endpoints.GetFullNodeRPCAddress(), NodeStartupTimeout)
855855
t.Log("Sync node restarted as normal full node")
@@ -915,6 +915,48 @@ func TestEvmSequencerCatchUpBasedSequencerE2E(t *testing.T) {
915915
require.NoError(t, err)
916916
t.Logf("Sequencer caught up to height: %d", seqHeader.Number.Uint64())
917917

918+
t.Log("Phase 9b: Compare Sequencer Caught-Up Blocks with Full Node Blocks")
919+
920+
// The sequencer caught up by replaying DA blocks, so its blocks from height 1
921+
// through basedSeqFinalHeight must be identical to what the full node has
922+
// (the full node synced the same DA chain). Compare block hashes, state roots,
923+
// and transaction counts at every height to prove deterministic replay.
924+
for h := uint64(1); h <= basedSeqFinalHeight; h++ {
925+
height := new(big.Int).SetUint64(h)
926+
927+
seqBlock, err := seqClient.BlockByNumber(ctx, height)
928+
require.NoError(t, err, "sequencer should have block %d", h)
929+
930+
fnBlock, err := fnClient.BlockByNumber(ctx, height)
931+
require.NoError(t, err, "full node should have block %d", h)
932+
933+
seqTime := seqBlock.Time()
934+
fnTime := fnBlock.Time()
935+
if seqBlock.Hash() != fnBlock.Hash() {
936+
t.Logf("❌ Block %d MISMATCH: seqHash=%s fnHash=%s seqTime=%d fnTime=%d timeDelta=%d seqTxs=%d fnTxs=%d seqRoot=%s fnRoot=%s",
937+
h, seqBlock.Hash().Hex(), fnBlock.Hash().Hex(),
938+
seqTime, fnTime, int64(seqTime)-int64(fnTime),
939+
len(seqBlock.Transactions()), len(fnBlock.Transactions()),
940+
seqBlock.Root().Hex(), fnBlock.Root().Hex())
941+
}
942+
943+
require.Equal(t, seqBlock.Hash(), fnBlock.Hash(),
944+
"block hash mismatch at height %d: sequencer=%s fullnode=%s seqTime=%d fnTime=%d timeDelta=%d (%v != %v)",
945+
h, seqBlock.Hash().Hex(), fnBlock.Hash().Hex(), seqTime, fnTime, int64(seqTime)-int64(fnTime), seqBlock, fnBlock)
946+
947+
require.Equal(t, seqBlock.Root(), fnBlock.Root(),
948+
"state root mismatch at height %d: sequencer=%s fullnode=%s",
949+
h, seqBlock.Root().Hex(), fnBlock.Root().Hex())
950+
951+
require.Equal(t, len(seqBlock.Transactions()), len(fnBlock.Transactions()),
952+
"tx count mismatch at height %d: sequencer=%d fullnode=%d",
953+
h, len(seqBlock.Transactions()), len(fnBlock.Transactions()))
954+
955+
t.Logf("✅ Block %d matches: hash=%s stateRoot=%s txs=%d",
956+
h, seqBlock.Hash().Hex(), seqBlock.Root().Hex(), len(seqBlock.Transactions()))
957+
}
958+
t.Logf("All %d blocks match between sequencer and full node", basedSeqFinalHeight)
959+
918960
// ===== PHASE 10: Verify Nodes Are in Sync =====
919961
t.Log("Phase 10: Verify Nodes Are in Sync")
920962

0 commit comments

Comments
 (0)