@@ -3,6 +3,7 @@ package based
33import (
44 "context"
55 "testing"
6+ "time"
67
78 ds "github.com/ipfs/go-datastore"
89 syncds "github.com/ipfs/go-datastore/sync"
@@ -539,3 +540,143 @@ func TestBasedSequencer_GetNextBatch_EmptyDABatch_IncreasesDAHeight(t *testing.T
539540
540541 mockRetriever .AssertExpectations (t )
541542}
543+
544+ func TestBasedSequencer_GetNextBatch_TimestampAdjustment (t * testing.T ) {
545+ // Test that timestamp is adjusted based on the number of transactions in the batch
546+ // The timestamp should be: daEndTime - (len(batch.Transactions) * 1ms)
547+
548+ testBlobs := [][]byte {[]byte ("tx1" ), []byte ("tx2" ), []byte ("tx3" )}
549+ daEndTime := time .Date (2024 , 1 , 1 , 12 , 0 , 0 , 0 , time .UTC )
550+
551+ mockRetriever := new (MockForcedInclusionRetriever )
552+ mockRetriever .On ("RetrieveForcedIncludedTxs" , mock .Anything , uint64 (100 )).Return (& block.ForcedInclusionEvent {
553+ Txs : testBlobs ,
554+ StartDaHeight : 100 ,
555+ EndDaHeight : 100 ,
556+ Timestamp : daEndTime ,
557+ }, nil )
558+
559+ gen := genesis.Genesis {
560+ ChainID : "test-chain" ,
561+ DAStartHeight : 100 ,
562+ DAEpochForcedInclusion : 1 ,
563+ }
564+
565+ seq := createTestSequencer (t , mockRetriever , gen )
566+
567+ req := coresequencer.GetNextBatchRequest {
568+ MaxBytes : 1000000 ,
569+ LastBatchData : nil ,
570+ }
571+
572+ resp , err := seq .GetNextBatch (context .Background (), req )
573+ require .NoError (t , err )
574+ require .NotNil (t , resp )
575+ require .NotNil (t , resp .Batch )
576+ assert .Equal (t , 3 , len (resp .Batch .Transactions ))
577+
578+ // Timestamp should be adjusted by subtracting 3ms (one per transaction)
579+ expectedTimestamp := daEndTime .Add (- 3 * time .Millisecond )
580+ assert .Equal (t , expectedTimestamp , resp .Timestamp )
581+
582+ mockRetriever .AssertExpectations (t )
583+ }
584+
585+ func TestBasedSequencer_GetNextBatch_TimestampAdjustment_PartialBatch (t * testing.T ) {
586+ // Test timestamp adjustment when MaxBytes limits the batch size
587+ tx1 := make ([]byte , 100 )
588+ tx2 := make ([]byte , 150 )
589+ tx3 := make ([]byte , 200 )
590+ testBlobs := [][]byte {tx1 , tx2 , tx3 }
591+ daEndTime := time .Date (2024 , 1 , 1 , 12 , 0 , 0 , 0 , time .UTC )
592+
593+ mockRetriever := new (MockForcedInclusionRetriever )
594+ mockRetriever .On ("RetrieveForcedIncludedTxs" , mock .Anything , uint64 (100 )).Return (& block.ForcedInclusionEvent {
595+ Txs : testBlobs ,
596+ StartDaHeight : 100 ,
597+ EndDaHeight : 100 ,
598+ Timestamp : daEndTime ,
599+ }, nil )
600+
601+ gen := genesis.Genesis {
602+ ChainID : "test-chain" ,
603+ DAStartHeight : 100 ,
604+ DAEpochForcedInclusion : 1 ,
605+ }
606+
607+ seq := createTestSequencer (t , mockRetriever , gen )
608+
609+ // First call with MaxBytes that fits only first 2 transactions
610+ req := coresequencer.GetNextBatchRequest {
611+ MaxBytes : 250 ,
612+ LastBatchData : nil ,
613+ }
614+
615+ resp , err := seq .GetNextBatch (context .Background (), req )
616+ require .NoError (t , err )
617+ require .NotNil (t , resp )
618+ require .NotNil (t , resp .Batch )
619+ assert .Equal (t , 2 , len (resp .Batch .Transactions ))
620+
621+ // Timestamp should be adjusted by subtracting 2ms (for 2 transactions)
622+ expectedTimestamp := daEndTime .Add (- 2 * time .Millisecond )
623+ assert .Equal (t , expectedTimestamp , resp .Timestamp )
624+
625+ // Second call should get the remaining transaction
626+ req = coresequencer.GetNextBatchRequest {
627+ MaxBytes : 1000 ,
628+ LastBatchData : nil ,
629+ }
630+
631+ // The timestamp for the second call should still have adjustment applieds
632+ resp , err = seq .GetNextBatch (context .Background (), req )
633+ require .NoError (t , err )
634+ require .NotNil (t , resp )
635+ require .NotNil (t , resp .Batch )
636+ assert .Equal (t , 1 , len (resp .Batch .Transactions ))
637+
638+ // Timestamp should be zero time with 1ms subtracted (which is still effectively zero but negative)
639+ // When t is zero time, t.Add(-1ms) results in a time before the zero time
640+ expectedTimestamp2 := daEndTime .Add (- 1 * time .Millisecond )
641+ assert .Equal (t , expectedTimestamp2 , resp .Timestamp )
642+
643+ mockRetriever .AssertExpectations (t )
644+ }
645+
646+ func TestBasedSequencer_GetNextBatch_TimestampAdjustment_EmptyBatch (t * testing.T ) {
647+ // Test that timestamp is zero when batch is empty
648+ daEndTime := time .Date (2024 , 1 , 1 , 12 , 0 , 0 , 0 , time .UTC )
649+
650+ mockRetriever := new (MockForcedInclusionRetriever )
651+ mockRetriever .On ("RetrieveForcedIncludedTxs" , mock .Anything , uint64 (100 )).Return (& block.ForcedInclusionEvent {
652+ Txs : [][]byte {},
653+ StartDaHeight : 100 ,
654+ EndDaHeight : 100 ,
655+ Timestamp : daEndTime ,
656+ }, nil )
657+
658+ gen := genesis.Genesis {
659+ ChainID : "test-chain" ,
660+ DAStartHeight : 100 ,
661+ DAEpochForcedInclusion : 1 ,
662+ }
663+
664+ seq := createTestSequencer (t , mockRetriever , gen )
665+
666+ req := coresequencer.GetNextBatchRequest {
667+ MaxBytes : 1000000 ,
668+ LastBatchData : nil ,
669+ }
670+
671+ resp , err := seq .GetNextBatch (context .Background (), req )
672+ require .NoError (t , err )
673+ require .NotNil (t , resp )
674+ require .NotNil (t , resp .Batch )
675+ assert .Equal (t , 0 , len (resp .Batch .Transactions ))
676+
677+ // When batch is empty, timestamp adjustment should still be applied (subtract 0ms)
678+ expectedTimestamp := daEndTime .Add (- 0 * time .Millisecond )
679+ assert .Equal (t , expectedTimestamp , resp .Timestamp )
680+
681+ mockRetriever .AssertExpectations (t )
682+ }
0 commit comments