Skip to content

Commit

Permalink
fix GetNextBatch for max bytes and add additional tests
Browse files Browse the repository at this point in the history
  • Loading branch information
gupadhyaya committed Oct 1, 2024
1 parent fef5601 commit a98e57c
Show file tree
Hide file tree
Showing 2 changed files with 241 additions and 10 deletions.
35 changes: 29 additions & 6 deletions test/dummy.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"context"
"errors"
"math"
"sync"
"time"

Expand All @@ -30,17 +31,39 @@ func (tq *TransactionQueue) AddTransaction(tx sequencing.Tx) {
tq.queue = append(tq.queue, tx)
}

func totalBytes(data [][]byte) int {
total := 0
for _, sub := range data {
total += len(sub)
}
return total
}

// GetNextBatch extracts a batch of transactions from the queue
func (tq *TransactionQueue) GetNextBatch() *sequencing.Batch {
func (tq *TransactionQueue) GetNextBatch(maxBytes uint64) *sequencing.Batch {
tq.mu.Lock()
defer tq.mu.Unlock()

size := len(tq.queue)
if size == 0 {
var batch [][]byte
batchSize := uint64(len(tq.queue))
if batchSize == 0 {
return &sequencing.Batch{Transactions: nil}
}
batch := tq.queue[:size]
tq.queue = tq.queue[size:]

if maxBytes == 0 {
maxBytes = math.MaxUint64
}

for {
batch = tq.queue[:batchSize]
blobSize := totalBytes(batch)
if uint64(blobSize) <= maxBytes {
break
}
batchSize = batchSize - 1
}

tq.queue = tq.queue[batchSize:]
return &sequencing.Batch{Transactions: batch}
}

Expand Down Expand Up @@ -78,7 +101,7 @@ func (d *DummySequencer) GetNextBatch(ctx context.Context, req sequencing.GetNex
}
}

batch := d.tq.GetNextBatch()
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 {
Expand Down
216 changes: 212 additions & 4 deletions test/dummy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package test

import (
"context"
"math"
"testing"
"time"

Expand All @@ -17,7 +18,7 @@ func TestTransactionQueue_AddTransaction(t *testing.T) {
queue.AddTransaction(tx1)

// Check that the transaction was added
batch := queue.GetNextBatch()
batch := queue.GetNextBatch(math.MaxUint64)
assert.Equal(t, 1, len(batch.Transactions))
assert.Equal(t, tx1, batch.Transactions[0])
}
Expand All @@ -32,13 +33,13 @@ func TestTransactionQueue_GetNextBatch(t *testing.T) {
queue.AddTransaction(tx2)

// Get next batch and check if all transactions are retrieved
batch := queue.GetNextBatch()
batch := queue.GetNextBatch(math.MaxUint64)
assert.Equal(t, 2, len(batch.Transactions))
assert.Equal(t, tx1, batch.Transactions[0])
assert.Equal(t, tx2, batch.Transactions[1])

// Ensure the queue is empty after retrieving the batch
emptyBatch := queue.GetNextBatch()
emptyBatch := queue.GetNextBatch(math.MaxUint64)
assert.Equal(t, 0, len(emptyBatch.Transactions))
}

Expand All @@ -61,11 +62,73 @@ func TestDummySequencer_SubmitRollupTransaction(t *testing.T) {
assert.NotNil(t, resp)

// Check that the transaction is in the queue
batch := sequencer.tq.GetNextBatch()
batch := sequencer.tq.GetNextBatch(math.MaxUint64)
assert.Equal(t, 1, len(batch.Transactions))
assert.Equal(t, tx, batch.Transactions[0])
}

func TestDummySequencer_SubmitEmptyTransaction(t *testing.T) {
sequencer := NewDummySequencer()

// Define a test rollup ID and an empty transaction
rollupId := []byte("test_rollup_id")
tx := []byte("")

// Submit an empty transaction
req := sequencing.SubmitRollupTransactionRequest{
RollupId: rollupId,
Tx: tx,
}
resp, err := sequencer.SubmitRollupTransaction(context.Background(), req)

// Assert no error (since the sequencer may accept empty transactions) and ensure the transaction was added
assert.NoError(t, err)
assert.NotNil(t, resp)

// Check that the transaction is in the queue (even if empty)
batch := sequencer.tq.GetNextBatch(math.MaxUint64)
assert.Equal(t, 1, len(batch.Transactions))
assert.Equal(t, tx, batch.Transactions[0])
}

func TestDummySequencer_SubmitMultipleTransactions(t *testing.T) {
sequencer := NewDummySequencer()

// 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")

// Submit multiple transactions
req1 := sequencing.SubmitRollupTransactionRequest{
RollupId: rollupId,
Tx: tx1,
}
req2 := sequencing.SubmitRollupTransactionRequest{
RollupId: rollupId,
Tx: tx2,
}
req3 := sequencing.SubmitRollupTransactionRequest{
RollupId: rollupId,
Tx: tx3,
}

_, err := sequencer.SubmitRollupTransaction(context.Background(), req1)
assert.NoError(t, err)
_, err = sequencer.SubmitRollupTransaction(context.Background(), req2)
assert.NoError(t, err)
_, err = sequencer.SubmitRollupTransaction(context.Background(), req3)
assert.NoError(t, err)

// Check that all transactions are added to the queue
batch := sequencer.tq.GetNextBatch(math.MaxUint64)
assert.Equal(t, 3, len(batch.Transactions))
assert.Equal(t, tx1, batch.Transactions[0])
assert.Equal(t, tx2, batch.Transactions[1])
assert.Equal(t, tx3, batch.Transactions[2])
}

func TestDummySequencer_GetNextBatch(t *testing.T) {
sequencer := NewDummySequencer()

Expand Down Expand Up @@ -97,6 +160,24 @@ func TestDummySequencer_GetNextBatch(t *testing.T) {
assert.WithinDuration(t, time.Now(), batchResp.Timestamp, time.Second)
}

// Test retrieving a batch with no transactions
func TestDummySequencer_GetNextBatch_NoTransactions(t *testing.T) {
sequencer := NewDummySequencer()

// Attempt to retrieve a batch with no transactions in the queue
getBatchReq := sequencing.GetNextBatchRequest{
RollupId: []byte("test_rollup_id"),
LastBatchHash: nil,
}
batchResp, err := sequencer.GetNextBatch(context.Background(), getBatchReq)

// Assert no error
assert.NoError(t, err)
// Assert that the batch is empty
assert.NotNil(t, batchResp)
assert.Equal(t, 0, len(batchResp.Batch.Transactions))
}

func TestDummySequencer_GetNextBatch_LastBatchHashMismatch(t *testing.T) {
sequencer := NewDummySequencer()

Expand All @@ -122,6 +203,72 @@ func TestDummySequencer_GetNextBatch_LastBatchHashMismatch(t *testing.T) {
assert.Equal(t, "lastBatch is supposed to be nil", err.Error())
}

// Test retrieving a batch with maxBytes limit
func TestDummySequencer_GetNextBatch_MaxBytesLimit(t *testing.T) {
sequencer := NewDummySequencer()

// 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")

// Submit multiple transactions
req1 := sequencing.SubmitRollupTransactionRequest{
RollupId: rollupId,
Tx: tx1,
}
req2 := sequencing.SubmitRollupTransactionRequest{
RollupId: rollupId,
Tx: tx2,
}
req3 := sequencing.SubmitRollupTransactionRequest{
RollupId: rollupId,
Tx: tx3,
}

_, err := sequencer.SubmitRollupTransaction(context.Background(), req1)
assert.NoError(t, err)
_, err = sequencer.SubmitRollupTransaction(context.Background(), req2)
assert.NoError(t, err)
_, err = sequencer.SubmitRollupTransaction(context.Background(), req3)
assert.NoError(t, err)

// Retrieve the next batch with maxBytes limit (assuming maxBytes limits the size of transactions returned)
maxBytes := uint64(len(tx1) + len(tx2)) // Set maxBytes to the size of tx1 + tx2

getBatchReq := sequencing.GetNextBatchRequest{
RollupId: rollupId,
LastBatchHash: nil,
MaxBytes: maxBytes,
}
batchResp, err := sequencer.GetNextBatch(context.Background(), getBatchReq)

// Assert no error
assert.NoError(t, err)
// Assert that only two transactions (tx1 and tx2) are retrieved due to the maxBytes limit
assert.NotNil(t, batchResp)
assert.Equal(t, 2, len(batchResp.Batch.Transactions))
assert.Equal(t, tx1, batchResp.Batch.Transactions[0])
assert.Equal(t, tx2, batchResp.Batch.Transactions[1])

lastBatchHash, err := batchResp.Batch.Hash()
assert.NoError(t, err)
// Retrieve the remaining transaction (tx3) with another call
getBatchReq2 := sequencing.GetNextBatchRequest{
RollupId: rollupId,
LastBatchHash: lastBatchHash,
MaxBytes: maxBytes, // This can be set higher to retrieve all remaining transactions
}
batchResp2, err2 := sequencer.GetNextBatch(context.Background(), getBatchReq2)

// Assert no error and tx3 is retrieved
assert.NoError(t, err2)
assert.NotNil(t, batchResp2)
assert.Equal(t, 1, len(batchResp2.Batch.Transactions))
assert.Equal(t, tx3, batchResp2.Batch.Transactions[0])
}

func TestDummySequencer_VerifyBatch(t *testing.T) {
sequencer := NewDummySequencer()

Expand Down Expand Up @@ -156,6 +303,67 @@ func TestDummySequencer_VerifyBatch(t *testing.T) {
assert.True(t, verifyResp.Status)
}

func TestDummySequencer_VerifyEmptyBatch(t *testing.T) {
sequencer := NewDummySequencer()

// Create a request with an empty batch hash
emptyBatchHash := []byte{}
verifyReq := sequencing.VerifyBatchRequest{
BatchHash: emptyBatchHash,
}

// Attempt to verify the empty batch
verifyResp, err := sequencer.VerifyBatch(context.Background(), verifyReq)

// Assert that the batch is not verified (as it's empty)
assert.NoError(t, err)
assert.False(t, verifyResp.Status)
}

func TestDummySequencer_VerifyBatchWithMultipleTransactions(t *testing.T) {
sequencer := NewDummySequencer()

// Define a test rollup ID and multiple transactions
rollupId := []byte("test_rollup_id")
tx1 := []byte("transaction_1")
tx2 := []byte("transaction_2")

// Submit multiple transactions
req1 := sequencing.SubmitRollupTransactionRequest{
RollupId: rollupId,
Tx: tx1,
}
req2 := sequencing.SubmitRollupTransactionRequest{
RollupId: rollupId,
Tx: tx2,
}

_, err := sequencer.SubmitRollupTransaction(context.Background(), req1)
assert.NoError(t, err)
_, err = sequencer.SubmitRollupTransaction(context.Background(), req2)
assert.NoError(t, err)

// Get the next batch to generate the batch hash
getBatchReq := sequencing.GetNextBatchRequest{
RollupId: rollupId,
LastBatchHash: nil,
}
batchResp, err := sequencer.GetNextBatch(context.Background(), getBatchReq)
assert.NoError(t, err)

batchHash, err := batchResp.Batch.Hash()
assert.NoError(t, err)
// Verify the batch using the batch hash
verifyReq := sequencing.VerifyBatchRequest{
BatchHash: batchHash,
}
verifyResp, err := sequencer.VerifyBatch(context.Background(), verifyReq)

// Assert that the batch with multiple transactions is verified successfully
assert.NoError(t, err)
assert.True(t, verifyResp.Status)
}

func TestDummySequencer_VerifyBatch_NotFound(t *testing.T) {
sequencer := NewDummySequencer()

Expand Down

0 comments on commit a98e57c

Please sign in to comment.