From 3134457dc4e58b12abb9e65a28e25bbd7946c2fb Mon Sep 17 00:00:00 2001 From: gupadhyaya Date: Thu, 10 Oct 2024 09:31:31 +0400 Subject: [PATCH 1/8] adding multi-rollup sequencer for the purpose of testing --- test/multi_rollup_sequencer.go | 134 +++++++++++++++++++++++++ test/multi_rollup_sequencer_test.go | 150 ++++++++++++++++++++++++++++ 2 files changed, 284 insertions(+) create mode 100644 test/multi_rollup_sequencer.go create mode 100644 test/multi_rollup_sequencer_test.go diff --git a/test/multi_rollup_sequencer.go b/test/multi_rollup_sequencer.go new file mode 100644 index 0000000..bcb19fc --- /dev/null +++ b/test/multi_rollup_sequencer.go @@ -0,0 +1,134 @@ +package test + +import ( + "bytes" + "context" + "encoding/hex" + "errors" + "sync" + "time" + + "github.com/rollkit/go-sequencing" +) + +// MultiRollupSequencer is a sequencer for testing that serves multiple rollups +type MultiRollupSequencer struct { + rollups map[string]*RollupData + rollupsMutex sync.RWMutex +} + +// RollupData holds the data for a specific rollup, including its transaction queue, last batch hash, and seen batches. +type RollupData struct { + tq *TransactionQueue + lastBatchHash []byte + lastBatchHashMutex sync.RWMutex + + seenBatches map[string]struct{} + seenBatchesMutex sync.Mutex +} + +// SubmitRollupTransaction implements sequencing.Sequencer. +func (d *MultiRollupSequencer) SubmitRollupTransaction(ctx context.Context, req sequencing.SubmitRollupTransactionRequest) (*sequencing.SubmitRollupTransactionResponse, error) { + rollup, err := d.getOrCreateRollup(req.RollupId) + if err != nil { + return nil, err + } + rollup.tq.AddTransaction(req.Tx) + return &sequencing.SubmitRollupTransactionResponse{}, nil +} + +// GetNextBatch implements sequencing.Sequencer. +func (d *MultiRollupSequencer) GetNextBatch(ctx context.Context, req sequencing.GetNextBatchRequest) (*sequencing.GetNextBatchResponse, error) { + rollup, err := d.getOrCreateRollup(req.RollupId) + if err != nil { + return nil, err + } + + now := time.Now() + rollup.lastBatchHashMutex.RLock() + lastBatchHash := rollup.lastBatchHash + rollup.lastBatchHashMutex.RUnlock() + + if lastBatchHash == nil && req.LastBatchHash != nil { + return nil, errors.New("lastBatch is supposed to be nil") + } else if lastBatchHash != nil && req.LastBatchHash == nil { + return nil, errors.New("lastBatch is not supposed to be nil") + } else if !bytes.Equal(lastBatchHash, req.LastBatchHash) { + return nil, errors.New("supplied lastBatch does not match with sequencer last batch") + } + + batch := rollup.tq.GetNextBatch(req.MaxBytes) + batchRes := &sequencing.GetNextBatchResponse{Batch: batch, Timestamp: now} + // If there are no transactions, return empty batch without updating the last batch hash + if batch.Transactions == nil { + return batchRes, nil + } + + h, err := batch.Hash() + if err != nil { + return nil, err + } + + rollup.lastBatchHashMutex.Lock() + rollup.lastBatchHash = h + rollup.lastBatchHashMutex.Unlock() + + rollup.seenBatchesMutex.Lock() + rollup.seenBatches[hex.EncodeToString(h)] = struct{}{} + rollup.seenBatchesMutex.Unlock() + return batchRes, nil +} + +// VerifyBatch implements sequencing.Sequencer. +func (d *MultiRollupSequencer) VerifyBatch(ctx context.Context, req sequencing.VerifyBatchRequest) (*sequencing.VerifyBatchResponse, error) { + rollup, err := d.getOrCreateRollup(req.RollupId) + if err != nil { + return nil, err + } + + rollup.seenBatchesMutex.Lock() + defer rollup.seenBatchesMutex.Unlock() + key := hex.EncodeToString(req.BatchHash) + if _, exists := rollup.seenBatches[key]; exists { + return &sequencing.VerifyBatchResponse{Status: true}, nil + } + return &sequencing.VerifyBatchResponse{Status: false}, nil +} + +// getOrCreateRollup returns the RollupData for a given rollupId, creating it if necessary. +func (d *MultiRollupSequencer) getOrCreateRollup(rollupId []byte) (*RollupData, error) { + rollupKey := hex.EncodeToString(rollupId) + + d.rollupsMutex.RLock() + rollup, exists := d.rollups[rollupKey] + d.rollupsMutex.RUnlock() + + if exists { + return rollup, nil + } + + d.rollupsMutex.Lock() + defer d.rollupsMutex.Unlock() + + // Double-check existence after acquiring write lock + if rollup, exists := d.rollups[rollupKey]; exists { + return rollup, nil + } + + // Create a new RollupData if it doesn't exist + rollup = &RollupData{ + tq: NewTransactionQueue(), + seenBatches: make(map[string]struct{}, 0), + } + d.rollups[rollupKey] = rollup + return rollup, nil +} + +// NewMultiRollupSequencer creates a new MultiRollupSequencer +func NewMultiRollupSequencer() *MultiRollupSequencer { + return &MultiRollupSequencer{ + rollups: make(map[string]*RollupData), + } +} + +var _ sequencing.Sequencer = &MultiRollupSequencer{} diff --git a/test/multi_rollup_sequencer_test.go b/test/multi_rollup_sequencer_test.go new file mode 100644 index 0000000..ce692b8 --- /dev/null +++ b/test/multi_rollup_sequencer_test.go @@ -0,0 +1,150 @@ +package test + +import ( + "context" + "math" + "testing" + + "github.com/rollkit/go-sequencing" + "github.com/stretchr/testify/assert" +) + +func TestMultiRollupSequencer_SubmitRollupTransaction(t *testing.T) { + sequencer := NewMultiRollupSequencer() + + rollupId := []byte("test-rollup") + tx := []byte("transaction data") + + // Submit the transaction + req := sequencing.SubmitRollupTransactionRequest{ + RollupId: rollupId, + Tx: tx, + } + + res, err := sequencer.SubmitRollupTransaction(context.Background(), req) + + assert.NoError(t, err) + assert.NotNil(t, res) + + // Ensure that the transaction was added to the transaction queue for the rollup + rollup, _ := sequencer.getOrCreateRollup(rollupId) + nextBatch := rollup.tq.GetNextBatch(math.MaxInt32) + + assert.Equal(t, 1, len(nextBatch.Transactions)) + assert.Equal(t, tx, nextBatch.Transactions[0]) +} + +func TestMultiRollupSequencer_GetNextBatch(t *testing.T) { + sequencer := NewMultiRollupSequencer() + + rollupId := []byte("test-rollup") + tx := []byte("transaction data") + + // Submit the transaction + req := sequencing.SubmitRollupTransactionRequest{ + RollupId: rollupId, + Tx: tx, + } + _, err := sequencer.SubmitRollupTransaction(context.Background(), req) + assert.NoError(t, err) + + // Get next batch + getBatchReq := sequencing.GetNextBatchRequest{ + RollupId: rollupId, + LastBatchHash: nil, + MaxBytes: math.MaxInt32, + } + batchRes, err := sequencer.GetNextBatch(context.Background(), getBatchReq) + assert.NoError(t, err) + + // Verify that the batch contains the transaction + assert.NotNil(t, batchRes.Batch) + assert.Equal(t, 1, len(batchRes.Batch.Transactions)) + assert.Equal(t, tx, batchRes.Batch.Transactions[0]) +} + +func TestMultiRollupSequencer_VerifyBatch(t *testing.T) { + sequencer := NewMultiRollupSequencer() + + rollupId := []byte("test-rollup") + tx := []byte("transaction data") + + // Submit the transaction + req := sequencing.SubmitRollupTransactionRequest{ + RollupId: rollupId, + Tx: tx, + } + _, err := sequencer.SubmitRollupTransaction(context.Background(), req) + assert.NoError(t, err) + + // Get the next batch to update the last batch hash + getBatchReq := sequencing.GetNextBatchRequest{ + RollupId: rollupId, + LastBatchHash: nil, + MaxBytes: math.MaxInt32, + } + batchRes, err := sequencer.GetNextBatch(context.Background(), getBatchReq) + assert.NoError(t, err) + + bHash, err := batchRes.Batch.Hash() + assert.NoError(t, err) + + // Verify the batch + verifyReq := sequencing.VerifyBatchRequest{ + RollupId: rollupId, + BatchHash: bHash, + } + + verifyRes, err := sequencer.VerifyBatch(context.Background(), verifyReq) + assert.NoError(t, err) + assert.True(t, verifyRes.Status) +} + +func TestMultiRollupSequencer_MultipleRollups(t *testing.T) { + sequencer := NewMultiRollupSequencer() + + rollupId1 := []byte("rollup-1") + rollupId2 := []byte("rollup-2") + tx1 := []byte("tx data 1") + tx2 := []byte("tx data 2") + + // Submit transactions for two different rollups + req1 := sequencing.SubmitRollupTransactionRequest{ + RollupId: rollupId1, + Tx: tx1, + } + req2 := sequencing.SubmitRollupTransactionRequest{ + RollupId: rollupId2, + Tx: tx2, + } + + _, err := sequencer.SubmitRollupTransaction(context.Background(), req1) + assert.NoError(t, err) + + _, err = sequencer.SubmitRollupTransaction(context.Background(), req2) + assert.NoError(t, err) + + // Get next batch for rollup 1 + getBatchReq1 := sequencing.GetNextBatchRequest{ + RollupId: rollupId1, + LastBatchHash: nil, + MaxBytes: math.MaxInt32, + } + batchRes1, err := sequencer.GetNextBatch(context.Background(), getBatchReq1) + assert.NoError(t, err) + + assert.Equal(t, 1, len(batchRes1.Batch.Transactions)) + assert.Equal(t, tx1, batchRes1.Batch.Transactions[0]) + + // Get next batch for rollup 2 + getBatchReq2 := sequencing.GetNextBatchRequest{ + RollupId: rollupId2, + LastBatchHash: nil, + MaxBytes: math.MaxInt32, + } + batchRes2, err := sequencer.GetNextBatch(context.Background(), getBatchReq2) + assert.NoError(t, err) + + assert.Equal(t, 1, len(batchRes2.Batch.Transactions)) + assert.Equal(t, tx2, batchRes2.Batch.Transactions[0]) +} From 6eb03f557fffced8d8668e37b781cf9232fcbac9 Mon Sep 17 00:00:00 2001 From: gupadhyaya Date: Thu, 10 Oct 2024 09:42:21 +0400 Subject: [PATCH 2/8] lint --- test/multi_rollup_sequencer_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/multi_rollup_sequencer_test.go b/test/multi_rollup_sequencer_test.go index ce692b8..8d23c55 100644 --- a/test/multi_rollup_sequencer_test.go +++ b/test/multi_rollup_sequencer_test.go @@ -5,8 +5,9 @@ import ( "math" "testing" - "github.com/rollkit/go-sequencing" "github.com/stretchr/testify/assert" + + "github.com/rollkit/go-sequencing" ) func TestMultiRollupSequencer_SubmitRollupTransaction(t *testing.T) { From c3283832f06596d4c5974ca40384646ebc5fa61a Mon Sep 17 00:00:00 2001 From: gupadhyaya Date: Fri, 11 Oct 2024 14:31:05 +0400 Subject: [PATCH 3/8] minor fix --- test/dummy.go | 2 +- test/multi_rollup_sequencer.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/dummy.go b/test/dummy.go index 83adbbf..d3d5ee6 100644 --- a/test/dummy.go +++ b/test/dummy.go @@ -116,7 +116,7 @@ func (d *DummySequencer) GetNextBatch(ctx context.Context, req sequencing.GetNex batch := d.tq.GetNextBatch(req.MaxBytes) batchRes := &sequencing.GetNextBatchResponse{Batch: batch, Timestamp: now} // If there are no transactions, return empty batch without updating the last batch hash - if batch.Transactions == nil { + if len(batch.Transactions) == 0 { return batchRes, nil } diff --git a/test/multi_rollup_sequencer.go b/test/multi_rollup_sequencer.go index bcb19fc..cafc5ee 100644 --- a/test/multi_rollup_sequencer.go +++ b/test/multi_rollup_sequencer.go @@ -60,7 +60,7 @@ func (d *MultiRollupSequencer) GetNextBatch(ctx context.Context, req sequencing. batch := rollup.tq.GetNextBatch(req.MaxBytes) batchRes := &sequencing.GetNextBatchResponse{Batch: batch, Timestamp: now} // If there are no transactions, return empty batch without updating the last batch hash - if batch.Transactions == nil { + if len(batch.Transactions) == 0 { return batchRes, nil } From 27d57eac3dbd2f274f291e7d5353de1b855db37f Mon Sep 17 00:00:00 2001 From: gupadhyaya Date: Thu, 17 Oct 2024 09:58:31 +0400 Subject: [PATCH 4/8] fix tests and checks --- test/dummy.go | 11 ++--- test/dummy_test.go | 75 ++++++++++++++++++++--------- test/multi_rollup_sequencer.go | 20 +++----- test/multi_rollup_sequencer_test.go | 21 +++++--- 4 files changed, 78 insertions(+), 49 deletions(-) diff --git a/test/dummy.go b/test/dummy.go index d3d5ee6..d07cab2 100644 --- a/test/dummy.go +++ b/test/dummy.go @@ -5,6 +5,7 @@ import ( "context" "encoding/hex" "errors" + "fmt" "math" "sync" "time" @@ -105,12 +106,10 @@ func (d *DummySequencer) GetNextBatch(ctx context.Context, req sequencing.GetNex lastBatchHash := d.lastBatchHash d.lastBatchHashMutex.RUnlock() - if lastBatchHash == nil && req.LastBatchHash != nil { - return nil, errors.New("lastBatch is supposed to be nil") - } else if lastBatchHash != nil && req.LastBatchHash == nil { - return nil, errors.New("lastBatch is not supposed to be nil") - } else if !bytes.Equal(lastBatchHash, req.LastBatchHash) { - return nil, errors.New("supplied lastBatch does not match with sequencer last batch") + if (lastBatchHash == nil && req.LastBatchHash != nil) || (lastBatchHash != nil && req.LastBatchHash == nil) { + return nil, fmt.Errorf("nil mismatch: lastBatchHash = %v, req.LastBatchHash = %v", lastBatchHash, req.LastBatchHash) + } else if lastBatchHash != nil && !bytes.Equal(lastBatchHash, req.LastBatchHash) { + return nil, fmt.Errorf("batch hash mismatch: lastBatchHash = %x, req.LastBatchHash = %x", lastBatchHash, req.LastBatchHash) } batch := d.tq.GetNextBatch(req.MaxBytes) diff --git a/test/dummy_test.go b/test/dummy_test.go index 7ef7175..0feca62 100644 --- a/test/dummy_test.go +++ b/test/dummy_test.go @@ -2,6 +2,9 @@ package test import ( "context" + "crypto/rand" + "fmt" + "io" "math" "testing" "time" @@ -14,7 +17,8 @@ import ( func TestTransactionQueue_AddTransaction(t *testing.T) { queue := NewTransactionQueue() - tx1 := []byte("transaction_1") + tx1, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) queue.AddTransaction(tx1) // Check that the transaction was added @@ -27,8 +31,10 @@ func TestTransactionQueue_GetNextBatch(t *testing.T) { queue := NewTransactionQueue() // Add multiple transactions - tx1 := []byte("transaction_1") - tx2 := []byte("transaction_2") + tx1, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) + tx2, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) queue.AddTransaction(tx1) queue.AddTransaction(tx2) @@ -46,7 +52,8 @@ func TestTransactionQueue_GetNextBatch(t *testing.T) { func TestDummySequencer_SubmitRollupTransaction(t *testing.T) { // Define a test rollup ID and transaction rollupId := []byte("test_rollup_id") - tx := []byte("test_transaction") + tx, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) sequencer := NewDummySequencer(rollupId) // Submit a transaction @@ -92,9 +99,12 @@ func TestDummySequencer_SubmitEmptyTransaction(t *testing.T) { func TestDummySequencer_SubmitMultipleTransactions(t *testing.T) { // Define a test rollup ID and multiple transactions rollupId := []byte("test_rollup_id") - tx1 := []byte("transaction_1") - tx2 := []byte("transaction_2") - tx3 := []byte("transaction_3") + tx1, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) + tx2, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) + tx3, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) sequencer := NewDummySequencer(rollupId) // Submit multiple transactions @@ -111,7 +121,7 @@ func TestDummySequencer_SubmitMultipleTransactions(t *testing.T) { Tx: tx3, } - _, err := sequencer.SubmitRollupTransaction(context.Background(), req1) + _, err = sequencer.SubmitRollupTransaction(context.Background(), req1) assert.NoError(t, err) _, err = sequencer.SubmitRollupTransaction(context.Background(), req2) assert.NoError(t, err) @@ -129,13 +139,14 @@ func TestDummySequencer_SubmitMultipleTransactions(t *testing.T) { func TestDummySequencer_GetNextBatch(t *testing.T) { // Add a transaction to the queue rollupId := []byte("test_rollup_id") - tx := []byte("test_transaction") + tx, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) sequencer := NewDummySequencer(rollupId) req := sequencing.SubmitRollupTransactionRequest{ RollupId: rollupId, Tx: tx, } - _, err := sequencer.SubmitRollupTransaction(context.Background(), req) + _, err = sequencer.SubmitRollupTransaction(context.Background(), req) assert.NoError(t, err) // Retrieve the next batch @@ -178,12 +189,13 @@ func TestDummySequencer_GetNextBatch_LastBatchHashMismatch(t *testing.T) { // Submit a transaction rollupId := []byte("test_rollup_id") sequencer := NewDummySequencer(rollupId) - tx := []byte("test_transaction") + tx, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) req := sequencing.SubmitRollupTransactionRequest{ RollupId: rollupId, Tx: tx, } - _, err := sequencer.SubmitRollupTransaction(context.Background(), req) + _, err = sequencer.SubmitRollupTransaction(context.Background(), req) assert.NoError(t, err) // Retrieve the next batch @@ -195,7 +207,7 @@ func TestDummySequencer_GetNextBatch_LastBatchHashMismatch(t *testing.T) { // Assert that the batch hash mismatch error is returned assert.Error(t, err) - assert.Equal(t, "lastBatch is supposed to be nil", err.Error()) + assert.ErrorContains(t, err, "nil mismatch", "unexpected error message") } // Test retrieving a batch with maxBytes limit @@ -203,9 +215,12 @@ func TestDummySequencer_GetNextBatch_MaxBytesLimit(t *testing.T) { // Define a test rollup ID and multiple transactions rollupId := []byte("test_rollup_id") sequencer := NewDummySequencer(rollupId) - tx1 := []byte("transaction_1") - tx2 := []byte("transaction_2") - tx3 := []byte("transaction_3") + tx1, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) + tx2, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) + tx3, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) // Submit multiple transactions req1 := sequencing.SubmitRollupTransactionRequest{ @@ -221,7 +236,7 @@ func TestDummySequencer_GetNextBatch_MaxBytesLimit(t *testing.T) { Tx: tx3, } - _, err := sequencer.SubmitRollupTransaction(context.Background(), req1) + _, err = sequencer.SubmitRollupTransaction(context.Background(), req1) assert.NoError(t, err) _, err = sequencer.SubmitRollupTransaction(context.Background(), req2) assert.NoError(t, err) @@ -267,12 +282,13 @@ func TestDummySequencer_VerifyBatch(t *testing.T) { // Add and retrieve a batch rollupId := []byte("test_rollup_id") sequencer := NewDummySequencer(rollupId) - tx := []byte("test_transaction") + tx, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) req := sequencing.SubmitRollupTransactionRequest{ RollupId: rollupId, Tx: tx, } - _, err := sequencer.SubmitRollupTransaction(context.Background(), req) + _, err = sequencer.SubmitRollupTransaction(context.Background(), req) assert.NoError(t, err) // Get the next batch to generate batch hash @@ -320,8 +336,10 @@ func TestDummySequencer_VerifyBatchWithMultipleTransactions(t *testing.T) { // Define a test rollup ID and multiple transactions rollupId := []byte("test_rollup_id") sequencer := NewDummySequencer(rollupId) - tx1 := []byte("transaction_1") - tx2 := []byte("transaction_2") + tx1, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) + tx2, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) // Submit multiple transactions req1 := sequencing.SubmitRollupTransactionRequest{ @@ -333,7 +351,7 @@ func TestDummySequencer_VerifyBatchWithMultipleTransactions(t *testing.T) { Tx: tx2, } - _, err := sequencer.SubmitRollupTransaction(context.Background(), req1) + _, err = sequencer.SubmitRollupTransaction(context.Background(), req1) assert.NoError(t, err) _, err = sequencer.SubmitRollupTransaction(context.Background(), req2) assert.NoError(t, err) @@ -375,3 +393,16 @@ func TestDummySequencer_VerifyBatch_NotFound(t *testing.T) { assert.NoError(t, err) assert.False(t, verifyResp.Status) } + +// GenerateSecureRandomBytes generates cryptographically secure random bytes of the given length. +func GenerateSecureRandomBytes(length int) ([]byte, error) { + if length <= 0 { + return nil, fmt.Errorf("invalid length: %d, must be greater than 0", length) + } + + buf := make([]byte, length) + if _, err := io.ReadFull(rand.Reader, buf); err != nil { + return nil, fmt.Errorf("failed to generate random bytes: %w", err) + } + return buf, nil +} diff --git a/test/multi_rollup_sequencer.go b/test/multi_rollup_sequencer.go index cafc5ee..816048b 100644 --- a/test/multi_rollup_sequencer.go +++ b/test/multi_rollup_sequencer.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/hex" - "errors" + "fmt" "sync" "time" @@ -49,12 +49,10 @@ func (d *MultiRollupSequencer) GetNextBatch(ctx context.Context, req sequencing. lastBatchHash := rollup.lastBatchHash rollup.lastBatchHashMutex.RUnlock() - if lastBatchHash == nil && req.LastBatchHash != nil { - return nil, errors.New("lastBatch is supposed to be nil") - } else if lastBatchHash != nil && req.LastBatchHash == nil { - return nil, errors.New("lastBatch is not supposed to be nil") - } else if !bytes.Equal(lastBatchHash, req.LastBatchHash) { - return nil, errors.New("supplied lastBatch does not match with sequencer last batch") + if (lastBatchHash == nil && req.LastBatchHash != nil) || (lastBatchHash != nil && req.LastBatchHash == nil) { + return nil, fmt.Errorf("nil mismatch: lastBatchHash = %v, req.LastBatchHash = %v", lastBatchHash, req.LastBatchHash) + } else if lastBatchHash != nil && !bytes.Equal(lastBatchHash, req.LastBatchHash) { + return nil, fmt.Errorf("batch hash mismatch: lastBatchHash = %x, req.LastBatchHash = %x", lastBatchHash, req.LastBatchHash) } batch := rollup.tq.GetNextBatch(req.MaxBytes) @@ -99,17 +97,13 @@ func (d *MultiRollupSequencer) VerifyBatch(ctx context.Context, req sequencing.V func (d *MultiRollupSequencer) getOrCreateRollup(rollupId []byte) (*RollupData, error) { rollupKey := hex.EncodeToString(rollupId) - d.rollupsMutex.RLock() + d.rollupsMutex.Lock() + defer d.rollupsMutex.Unlock() rollup, exists := d.rollups[rollupKey] - d.rollupsMutex.RUnlock() - if exists { return rollup, nil } - d.rollupsMutex.Lock() - defer d.rollupsMutex.Unlock() - // Double-check existence after acquiring write lock if rollup, exists := d.rollups[rollupKey]; exists { return rollup, nil diff --git a/test/multi_rollup_sequencer_test.go b/test/multi_rollup_sequencer_test.go index 8d23c55..180ad5d 100644 --- a/test/multi_rollup_sequencer_test.go +++ b/test/multi_rollup_sequencer_test.go @@ -14,7 +14,8 @@ func TestMultiRollupSequencer_SubmitRollupTransaction(t *testing.T) { sequencer := NewMultiRollupSequencer() rollupId := []byte("test-rollup") - tx := []byte("transaction data") + tx, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) // Submit the transaction req := sequencing.SubmitRollupTransactionRequest{ @@ -39,14 +40,15 @@ func TestMultiRollupSequencer_GetNextBatch(t *testing.T) { sequencer := NewMultiRollupSequencer() rollupId := []byte("test-rollup") - tx := []byte("transaction data") + tx, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) // Submit the transaction req := sequencing.SubmitRollupTransactionRequest{ RollupId: rollupId, Tx: tx, } - _, err := sequencer.SubmitRollupTransaction(context.Background(), req) + _, err = sequencer.SubmitRollupTransaction(context.Background(), req) assert.NoError(t, err) // Get next batch @@ -68,14 +70,15 @@ func TestMultiRollupSequencer_VerifyBatch(t *testing.T) { sequencer := NewMultiRollupSequencer() rollupId := []byte("test-rollup") - tx := []byte("transaction data") + tx, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) // Submit the transaction req := sequencing.SubmitRollupTransactionRequest{ RollupId: rollupId, Tx: tx, } - _, err := sequencer.SubmitRollupTransaction(context.Background(), req) + _, err = sequencer.SubmitRollupTransaction(context.Background(), req) assert.NoError(t, err) // Get the next batch to update the last batch hash @@ -106,8 +109,10 @@ func TestMultiRollupSequencer_MultipleRollups(t *testing.T) { rollupId1 := []byte("rollup-1") rollupId2 := []byte("rollup-2") - tx1 := []byte("tx data 1") - tx2 := []byte("tx data 2") + tx1, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) + tx2, err := GenerateSecureRandomBytes(32) + assert.NoError(t, err) // Submit transactions for two different rollups req1 := sequencing.SubmitRollupTransactionRequest{ @@ -119,7 +124,7 @@ func TestMultiRollupSequencer_MultipleRollups(t *testing.T) { Tx: tx2, } - _, err := sequencer.SubmitRollupTransaction(context.Background(), req1) + _, err = sequencer.SubmitRollupTransaction(context.Background(), req1) assert.NoError(t, err) _, err = sequencer.SubmitRollupTransaction(context.Background(), req2) From 67c8e6930719fab9f440e59bae10c852a54c59ef Mon Sep 17 00:00:00 2001 From: gupadhyaya Date: Thu, 17 Oct 2024 18:04:24 +0400 Subject: [PATCH 5/8] DeepEqual --- test/dummy.go | 5 ++--- test/dummy_test.go | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/test/dummy.go b/test/dummy.go index d07cab2..f064cb2 100644 --- a/test/dummy.go +++ b/test/dummy.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "math" + "reflect" "sync" "time" @@ -106,9 +107,7 @@ func (d *DummySequencer) GetNextBatch(ctx context.Context, req sequencing.GetNex lastBatchHash := d.lastBatchHash d.lastBatchHashMutex.RUnlock() - if (lastBatchHash == nil && req.LastBatchHash != nil) || (lastBatchHash != nil && req.LastBatchHash == nil) { - return nil, fmt.Errorf("nil mismatch: lastBatchHash = %v, req.LastBatchHash = %v", lastBatchHash, req.LastBatchHash) - } else if lastBatchHash != nil && !bytes.Equal(lastBatchHash, req.LastBatchHash) { + if !reflect.DeepEqual(lastBatchHash, req.LastBatchHash) { return nil, fmt.Errorf("batch hash mismatch: lastBatchHash = %x, req.LastBatchHash = %x", lastBatchHash, req.LastBatchHash) } diff --git a/test/dummy_test.go b/test/dummy_test.go index 0feca62..4d072cb 100644 --- a/test/dummy_test.go +++ b/test/dummy_test.go @@ -207,7 +207,7 @@ func TestDummySequencer_GetNextBatch_LastBatchHashMismatch(t *testing.T) { // Assert that the batch hash mismatch error is returned assert.Error(t, err) - assert.ErrorContains(t, err, "nil mismatch", "unexpected error message") + assert.ErrorContains(t, err, "batch hash mismatch", "unexpected error message") } // Test retrieving a batch with maxBytes limit From cb5ec7e18ffafbaaa9920f642bd9083dfc70d165 Mon Sep 17 00:00:00 2001 From: gupadhyaya Date: Thu, 17 Oct 2024 18:05:21 +0400 Subject: [PATCH 6/8] more deepequal --- test/multi_rollup_sequencer.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/multi_rollup_sequencer.go b/test/multi_rollup_sequencer.go index 816048b..c3897c3 100644 --- a/test/multi_rollup_sequencer.go +++ b/test/multi_rollup_sequencer.go @@ -1,10 +1,10 @@ package test import ( - "bytes" "context" "encoding/hex" "fmt" + "reflect" "sync" "time" @@ -49,9 +49,7 @@ func (d *MultiRollupSequencer) GetNextBatch(ctx context.Context, req sequencing. lastBatchHash := rollup.lastBatchHash rollup.lastBatchHashMutex.RUnlock() - if (lastBatchHash == nil && req.LastBatchHash != nil) || (lastBatchHash != nil && req.LastBatchHash == nil) { - return nil, fmt.Errorf("nil mismatch: lastBatchHash = %v, req.LastBatchHash = %v", lastBatchHash, req.LastBatchHash) - } else if lastBatchHash != nil && !bytes.Equal(lastBatchHash, req.LastBatchHash) { + if !reflect.DeepEqual(lastBatchHash, req.LastBatchHash) { return nil, fmt.Errorf("batch hash mismatch: lastBatchHash = %x, req.LastBatchHash = %x", lastBatchHash, req.LastBatchHash) } From 5ce114a24f9795b58bfb62552a8dc10e28a9940a Mon Sep 17 00:00:00 2001 From: gupadhyaya Date: Thu, 17 Oct 2024 18:12:30 +0400 Subject: [PATCH 7/8] adding multi-rollup test --- test/multi_rollup_sequencer_test.go | 51 +++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/test/multi_rollup_sequencer_test.go b/test/multi_rollup_sequencer_test.go index 180ad5d..8349c9c 100644 --- a/test/multi_rollup_sequencer_test.go +++ b/test/multi_rollup_sequencer_test.go @@ -3,6 +3,7 @@ package test import ( "context" "math" + "math/rand" "testing" "github.com/stretchr/testify/assert" @@ -154,3 +155,53 @@ func TestMultiRollupSequencer_MultipleRollups(t *testing.T) { assert.Equal(t, 1, len(batchRes2.Batch.Transactions)) assert.Equal(t, tx2, batchRes2.Batch.Transactions[0]) } + +// TestMultiRollupSequencer tests the MultiRollupSequencer core functionality of +// submitting transactions, getting the next batch, and verifying a batch +func TestMultiRollupSequencer(t *testing.T) { + // Test with 1 rollup + testMultiRollupSequencer(t, 1) + // Test with 2 to 5 rollups + numRollups := rand.Intn(4) + 2 + testMultiRollupSequencer(t, numRollups) +} + +func testMultiRollupSequencer(t *testing.T, numRollups int) { + sequencer := NewMultiRollupSequencer() + + for i := 0; i < numRollups; i++ { + // Submit a transaction + rollupId, err := GenerateSecureRandomBytes(10) + assert.NoError(t, err) + tx, err := GenerateSecureRandomBytes(30) + assert.NoError(t, err) + req := sequencing.SubmitRollupTransactionRequest{ + RollupId: rollupId, + Tx: tx, + } + _, err = sequencer.SubmitRollupTransaction(context.Background(), req) + assert.NoError(t, err) + + // Get Next Batch + getBatchReq := sequencing.GetNextBatchRequest{ + RollupId: rollupId, + LastBatchHash: nil, + MaxBytes: math.MaxInt32, + } + batchRes, err := sequencer.GetNextBatch(context.Background(), getBatchReq) + assert.NoError(t, err) + assert.Equal(t, 1, len(batchRes.Batch.Transactions)) + assert.Equal(t, tx, batchRes.Batch.Transactions[0]) + + // Verify the batch + bHash, err := batchRes.Batch.Hash() + assert.NoError(t, err) + verifyReq := sequencing.VerifyBatchRequest{ + RollupId: rollupId, + BatchHash: bHash, + } + verifyRes, err := sequencer.VerifyBatch(context.Background(), verifyReq) + assert.NoError(t, err) + assert.True(t, verifyRes.Status) + } +} From dae98a57673c9c647f52997db68878382d340ca9 Mon Sep 17 00:00:00 2001 From: gupadhyaya Date: Thu, 17 Oct 2024 19:56:19 +0400 Subject: [PATCH 8/8] add test --- test/multi_rollup_sequencer_test.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/multi_rollup_sequencer_test.go b/test/multi_rollup_sequencer_test.go index 8349c9c..a5f4345 100644 --- a/test/multi_rollup_sequencer_test.go +++ b/test/multi_rollup_sequencer_test.go @@ -2,8 +2,9 @@ package test import ( "context" + "crypto/rand" "math" - "math/rand" + "math/big" "testing" "github.com/stretchr/testify/assert" @@ -161,8 +162,12 @@ func TestMultiRollupSequencer_MultipleRollups(t *testing.T) { func TestMultiRollupSequencer(t *testing.T) { // Test with 1 rollup testMultiRollupSequencer(t, 1) + // Test with 2 to 5 rollups - numRollups := rand.Intn(4) + 2 + r, err := rand.Int(rand.Reader, big.NewInt(4)) // Generates a number between 0 and 3 + assert.NoError(t, err) + + numRollups := int(r.Int64() + 2) // Adjust range to be between 2 and 5, cast to int testMultiRollupSequencer(t, numRollups) }