Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: extend api to include rollup id, add Hash function to Batch, add maxBytes #13

Merged
merged 14 commits into from
Oct 2, 2024

Conversation

gupadhyaya
Copy link
Member

@gupadhyaya gupadhyaya commented Oct 1, 2024

Fixes #6 #10 #11

Summary by CodeRabbit

  • New Features

    • Introduced structured request and response types for rollup transactions, batch retrieval, and verification, enhancing clarity and usability.
    • Added a method to compute a SHA-256 hash for the Batch struct.
  • Bug Fixes

    • Improved error handling for rollup ID mismatches during transaction submissions.
  • Tests

    • Implemented unit tests for transaction submission, batch retrieval, and verification processes, ensuring robust functionality.
    • Added comprehensive tests for transaction queue behavior and batch verification scenarios.

@gupadhyaya gupadhyaya added the enhancement New feature or request label Oct 1, 2024
Copy link

coderabbitai bot commented Oct 1, 2024

Walkthrough

The changes involve updates to the go.mod file for new dependencies, modifications to the sequencing.proto file to enhance service definitions, and significant alterations to the method signatures and internal logic in various Go files, including client.go, server.go, and sequencing.go. The updates introduce structured request and response types across the sequencer interface, improving encapsulation and clarity. Additionally, a new method for hashing batches has been added, and unit tests have been introduced to validate the functionality of the updated sequencer.

Changes

Files Change Summary
go.mod Added new dependencies: github.com/stretchr/testify, github.com/davecgh/go-spew, github.com/pmezard/go-difflib, and gopkg.in/yaml.v3.
proto/sequencing/sequencing.proto Updated service definitions: added max_bytes to GetNextBatchRequest and rollup_id to both request messages.
proxy/grpc/client.go, proxy/grpc/server.go, sequencing.go, test/dummy.go Updated method signatures to use structured request and response types, enhancing encapsulation.
serialization.go Introduced a Hash method in the Batch struct for generating a SHA-256 hash of serialized data.
test/dummy_test.go Added unit tests for transaction queue and dummy sequencer operations, covering various scenarios.

Assessment against linked issues

Objective Addressed Explanation
maxBytes parameter in GetNextBatch (Issue #6)

🐰 In the meadow, where changes bloom,
New fields added, dispelling gloom.
With structured requests, our code takes flight,
A hash for batches, all feels just right!
In tests we trust, our logic is clear,
Hopping along, we have nothing to fear!
🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@RollkitBot RollkitBot requested review from a team, tuxcanfly, tzdybal and Manav-Aggarwal and removed request for a team October 1, 2024 13:19
@gupadhyaya gupadhyaya requested review from MSevey, Manav-Aggarwal and tuxcanfly and removed request for tuxcanfly and Manav-Aggarwal October 1, 2024 13:19
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

🧹 Outside diff range and nitpick comments (12)
serialization.go (1)

52-59: Approve implementation with minor improvements

The Hash method is well-implemented and provides a valuable addition to the Batch struct. It correctly uses the existing Marshal method for consistency and implements proper error handling. The use of SHA-256 is appropriate for generating a unique hash.

To improve the code:

  1. Add a comment explaining the method's purpose and return values.
  2. Address the static analysis hint by making the comment for this exported method.

Here's a suggested improvement:

+// Hash computes and returns the SHA-256 hash of the serialized Batch.
+// It returns the 32-byte hash as a byte slice, or an error if serialization fails.
 func (batch *Batch) Hash() ([]byte, error) {
     batchBytes, err := batch.Marshal()
     if err != nil {
         return nil, err
     }
     hash := sha256.Sum256(batchBytes)
     return hash[:], nil
 }

This comment addresses both the need for documentation and satisfies the static analysis requirement for exported methods.

🧰 Tools
🪛 GitHub Check: lint / golangci-lint

[failure] 52-52:
exported: exported method Batch.Hash should have comment or be unexported (revive)

test/dummy_test.go (5)

12-31: LGTM with a minor suggestion: Check the error returned by SubmitRollupTransaction.

The test function effectively covers the basic functionality of submitting a rollup transaction. It checks for both the absence of errors and the correct state of the sequencer after submission. However, it's advisable to check the error returned by sequencer.SubmitRollupTransaction.

Consider modifying line 24 to check the error:

-	resp, err := sequencer.SubmitRollupTransaction(context.Background(), req)
+	resp, err := sequencer.SubmitRollupTransaction(context.Background(), req)
+	assert.NoError(t, err)

This ensures that any unexpected errors during transaction submission are caught and reported.


33-57: LGTM with suggestions: Improve error handling and consider additional assertions.

The test function effectively covers the important edge case of submitting transactions with mismatched rollup IDs. However, there are a few areas for improvement:

  1. Check the error returned by the first SubmitRollupTransaction call.
  2. Consider adding an assertion to verify that the first transaction was successfully added to the queue.
  3. Use assert.ErrorIs instead of assert.Equal for error comparison.

Here's a suggested improvement:

 	req1 := sequencing.SubmitRollupTransactionRequest{
 		RollupId: rollupId1,
 		Tx:       tx1,
 	}
-	sequencer.SubmitRollupTransaction(context.Background(), req1)
+	_, err := sequencer.SubmitRollupTransaction(context.Background(), req1)
+	assert.NoError(t, err)
+	assert.Equal(t, rollupId1, sequencer.RollupId)

 	// Submit a transaction with a different rollup ID (should cause an error)
 	rollupId2 := []byte("test_rollup_id2")
 	tx2 := []byte("test_transaction_2")
 	req2 := sequencing.SubmitRollupTransactionRequest{
 		RollupId: rollupId2,
 		Tx:       tx2,
 	}
-	_, err := sequencer.SubmitRollupTransaction(context.Background(), req2)
+	_, err = sequencer.SubmitRollupTransaction(context.Background(), req2)

 	// Assert that the error is ErrorRollupIdMismatch
 	assert.Error(t, err)
-	assert.Equal(t, err, ErrorRollupIdMismatch)
+	assert.ErrorIs(t, err, ErrorRollupIdMismatch)

These changes will improve error handling and make the test more robust.

🧰 Tools
🪛 GitHub Check: lint / golangci-lint

[failure] 43-43:
Error return value of sequencer.SubmitRollupTransaction is not checked (errcheck)


59-91: LGTM with suggestions: Improve error handling and consider additional assertions.

The test function effectively covers the basic functionality of retrieving the next batch after submitting a transaction. However, there are a few areas for improvement:

  1. Check the error returned by the SubmitRollupTransaction call.
  2. Consider adding an assertion to verify the LastBatchHash in the response.
  3. Verify that the MaxBytes parameter is respected in the returned batch.

Here's a suggested improvement:

 	}
-	sequencer.SubmitRollupTransaction(context.Background(), req)
+	_, err := sequencer.SubmitRollupTransaction(context.Background(), req)
+	assert.NoError(t, err)

 	// Get the next batch
 	getBatchReq := sequencing.GetNextBatchRequest{
 		RollupId:      rollupId,
 		LastBatchHash: nil,
 		MaxBytes:      1024,
 	}
-	batchRes, err := sequencer.GetNextBatch(context.Background(), getBatchReq)
+	batchRes, err := sequencer.GetNextBatch(context.Background(), getBatchReq)
 	assert.NoError(t, err)

 	// Assert that the returned batch contains the correct transaction
 	assert.NotNil(t, batchRes.Batch)
 	assert.Equal(t, 1, len(batchRes.Batch.Transactions))
 	assert.Equal(t, tx, batchRes.Batch.Transactions[0])

+	// Assert that LastBatchHash is set correctly
+	assert.NotNil(t, batchRes.LastBatchHash)

+	// Assert that the batch respects the MaxBytes parameter
+	assert.LessOrEqual(t, len(batchRes.Batch.Transactions[0]), 1024)

 	// Assert timestamp is recent
 	assert.WithinDuration(t, time.Now(), batchRes.Timestamp, time.Second)

These changes will improve error handling and make the test more comprehensive.

🧰 Tools
🪛 GitHub Check: lint / golangci-lint

[failure] 71-71:
Error return value of sequencer.SubmitRollupTransaction is not checked (errcheck)


93-130: LGTM with suggestions: Improve error handling and consider additional test cases.

The test function effectively covers the full flow from submitting a transaction to verifying a batch. However, there are a few areas for improvement:

  1. Check the error returned by the SubmitRollupTransaction call.
  2. Consider adding a negative test case where verification fails.
  3. Verify that the BatchHash in the verification request matches the one returned by GetNextBatch.

Here's a suggested improvement:

 	}
-	sequencer.SubmitRollupTransaction(context.Background(), req)
+	_, err := sequencer.SubmitRollupTransaction(context.Background(), req)
+	assert.NoError(t, err)

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

 	batchHash, err := batchRes.Batch.Hash()
 	assert.NoError(t, err)
+	
+	// Verify that the BatchHash matches the one from GetNextBatch
+	assert.Equal(t, batchRes.LastBatchHash, batchHash)
+	
 	// Verify the batch
 	verifyReq := sequencing.VerifyBatchRequest{
 		RollupId:  rollupId,
 		BatchHash: batchHash, // hash of the submitted transaction
 	}
 	verifyRes, err := sequencer.VerifyBatch(context.Background(), verifyReq)

 	// Assert no error
 	assert.NoError(t, err)

 	// Assert that the batch was verified successfully
 	assert.True(t, verifyRes.Status)
+	
+	// Add a negative test case
+	invalidBatchHash := []byte("invalid_hash")
+	invalidVerifyReq := sequencing.VerifyBatchRequest{
+		RollupId:  rollupId,
+		BatchHash: invalidBatchHash,
+	}
+	invalidVerifyRes, err := sequencer.VerifyBatch(context.Background(), invalidVerifyReq)
+	assert.NoError(t, err)
+	assert.False(t, invalidVerifyRes.Status)

These changes will improve error handling and make the test more comprehensive by including both positive and negative test cases.

🧰 Tools
🪛 GitHub Check: lint / golangci-lint

[failure] 105-105:
Error return value of sequencer.SubmitRollupTransaction is not checked (errcheck)


1-130: Overall, well-structured and comprehensive test suite with room for enhancement.

The test file provides good coverage of the main functionalities of the dummy sequencer implementation. The test functions are well-organized, follow consistent patterns, and cover important scenarios such as transaction submission, batch retrieval, and batch verification.

To further improve the test suite, consider the following suggestions:

  1. Add more edge cases and error scenarios, such as:
    • Submitting an empty transaction
    • Retrieving a batch with no transactions
    • Verifying a batch with an invalid rollup ID
  2. Implement table-driven tests for scenarios with multiple similar test cases.
  3. Add benchmarks for performance-critical operations.
  4. Consider using a setup function to reduce code duplication across test functions.

Here's an example of how you could implement a table-driven test for transaction submission:

func TestSubmitRollupTransactionScenarios(t *testing.T) {
	scenarios := []struct {
		name     string
		rollupId []byte
		tx       []byte
		wantErr  bool
	}{
		{"Valid transaction", []byte("valid_id"), []byte("valid_tx"), false},
		{"Empty transaction", []byte("valid_id"), []byte{}, false},
		{"Empty rollup ID", []byte{}, []byte("valid_tx"), true},
		// Add more scenarios as needed
	}

	for _, sc := range scenarios {
		t.Run(sc.name, func(t *testing.T) {
			sequencer := NewDummySequencer()
			req := sequencing.SubmitRollupTransactionRequest{
				RollupId: sc.rollupId,
				Tx:       sc.tx,
			}
			_, err := sequencer.SubmitRollupTransaction(context.Background(), req)
			if sc.wantErr {
				assert.Error(t, err)
			} else {
				assert.NoError(t, err)
				assert.Equal(t, sc.rollupId, sequencer.RollupId)
			}
		})
	}
}

This approach would allow you to easily add and test multiple scenarios for transaction submission.

🧰 Tools
🪛 GitHub Check: lint / golangci-lint

[failure] 43-43:
Error return value of sequencer.SubmitRollupTransaction is not checked (errcheck)


[failure] 71-71:
Error return value of sequencer.SubmitRollupTransaction is not checked (errcheck)


[failure] 105-105:
Error return value of sequencer.SubmitRollupTransaction is not checked (errcheck)

sequencing.go (5)

Line range hint 42-44: Missing Hash function in Batch struct

According to the PR objectives, a Hash function should be added to the Batch struct. However, there is no Hash method implemented for Batch. Please implement the Hash function to compute the hash of the batch as intended.


49-53: Add field comments to SubmitRollupTransactionRequest struct

To enhance code readability, consider adding comments for each field in the SubmitRollupTransactionRequest struct. This will help other developers understand the purpose of each field.


59-64: Add field comments to GetNextBatchRequest struct

Please add comments for each field in the GetNextBatchRequest struct, especially for the new MaxBytes parameter, to clarify their purposes.


67-70: Add field comments to GetNextBatchResponse struct

To improve maintainability, consider adding comments for each field in the GetNextBatchResponse struct, explaining what Batch and Timestamp represent.


73-76: Add field comments to VerifyBatchRequest struct

Including comments for each field in the VerifyBatchRequest struct will enhance code clarity and assist future developers.

test/dummy.go (1)

92-92: Ensure Batch.Transactions is an empty slice, not nil

When there are no transactions, the Transactions field in the batch is set to nil. This could lead to nil pointer dereferences when iterating over Transactions. It's safer to initialize it as an empty slice.

Update the GetNextBatch method in TransactionQueue:

 func (tq *TransactionQueue) GetNextBatch() *sequencing.Batch {
 	tq.mu.Lock()
 	defer tq.mu.Unlock()

 	size := len(tq.queue)
 	if size == 0 {
-		return &sequencing.Batch{Transactions: nil}
+		return &sequencing.Batch{Transactions: []sequencing.Tx{}}
 	}
 	batch := tq.queue[:size]
 	tq.queue = tq.queue[size:]
 	return &sequencing.Batch{Transactions: batch}
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 0098194 and 50fe9a6.

⛔ Files ignored due to path filters (2)
  • go.sum is excluded by !**/*.sum
  • types/pb/sequencing/sequencing.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (8)
  • go.mod (1 hunks)
  • proto/sequencing/sequencing.proto (2 hunks)
  • proxy/grpc/client.go (1 hunks)
  • proxy/grpc/server.go (2 hunks)
  • sequencing.go (2 hunks)
  • serialization.go (2 hunks)
  • test/dummy.go (1 hunks)
  • test/dummy_test.go (1 hunks)
🧰 Additional context used
🪛 GitHub Check: lint / golangci-lint
serialization.go

[failure] 52-52:
exported: exported method Batch.Hash should have comment or be unexported (revive)

test/dummy_test.go

[failure] 43-43:
Error return value of sequencer.SubmitRollupTransaction is not checked (errcheck)


[failure] 71-71:
Error return value of sequencer.SubmitRollupTransaction is not checked (errcheck)


[failure] 105-105:
Error return value of sequencer.SubmitRollupTransaction is not checked (errcheck)

🔇 Additional comments (17)
go.mod (5)

7-7: LGTM: Addition of testify framework

The addition of github.com/stretchr/testify v1.8.4 as a direct dependency is a good choice. This popular testing toolkit will enhance the project's testing capabilities, making it easier to write and maintain tests.


12-12: Indirect dependency added: go-spew

The addition of github.com/davecgh/go-spew v1.1.1 as an indirect dependency is likely due to its use by the testify framework. This library provides improved formatting for Go data structures, which can be helpful during testing and debugging.


14-14: Indirect dependency added: go-difflib

The addition of github.com/pmezard/go-difflib v1.0.0 as an indirect dependency is expected. This library is often used by testing frameworks like testify to generate unified diffs, which are helpful for comparing expected and actual test results.


Line range hint 1-22: Summary of dependency changes

The updates to the go.mod file primarily focus on enhancing the project's testing capabilities and potentially introducing new functionality:

  1. Addition of github.com/stretchr/testify as a direct dependency for improved testing.
  2. Indirect dependencies (go-spew, go-difflib, and yaml.v3) added, likely as requirements for testify or other project needs.

These changes should positively impact the project's test coverage and potentially introduce new features or configuration options. Ensure that the new testing framework is utilized effectively across the project to maximize its benefits.


20-20: Verify usage of newly added YAML dependency

The addition of gopkg.in/yaml.v3 v3.0.1 as an indirect dependency introduces YAML parsing capabilities to the project. While this is likely a requirement of another dependency, it's worth verifying if this addition aligns with any new YAML-related functionality or configuration options in the project.

To ensure this dependency is being used appropriately, you can run the following command to check for YAML file usage in the project:

proto/sequencing/sequencing.proto (2)

Line range hint 1-70: Overall changes align well with PR objectives.

The modifications to this protobuf file successfully implement the required changes:

  1. Extended the API to include rollup_id in both GetNextBatchRequest and VerifyBatchRequest.
  2. Added max_bytes to GetNextBatchRequest, addressing issue maxBytes parameter in GetNextBatch #6 and allowing the execution layer to specify a maximum size for batches.

These changes will enable better control over batch sizes and improve the handling of rollup-specific data. The naming conventions used (e.g., max_bytes) follow protobuf best practices.


59-62: LGTM! New field added as per requirements.

The changes to VerifyBatchRequest look good and align with the PR objectives:

  1. Added rollup_id field to extend the API.

However, please note that reordering the batch_hash field is a breaking change that might affect existing clients. Ensure this change is communicated clearly in the changelog and to any affected parties.

To verify the impact of this change, let's check for any other occurrences of VerifyBatchRequest:

#!/bin/bash
# Description: Check for other occurrences of VerifyBatchRequest
# Expected: No other occurrences that might be affected by the field reordering

rg --type go "VerifyBatchRequest" -C 5
proxy/grpc/server.go (5)

49-49: LGTM: Improved API structure for SubmitRollupTransaction

The change to use a structured sequencing.SubmitRollupTransactionRequest object aligns with the PR objectives and improves code clarity. This approach enhances maintainability and readability.


58-58: LGTM: Improved API structure for GetNextBatch

The changes to use structured sequencing.GetNextBatchRequest and handle the response accordingly improve code clarity and maintainability. The timestamp handling is correct.

Also applies to: 62-62, 66-66


71-71: LGTM: Improved API structure for VerifyBatch

The changes to use a structured sequencing.VerifyBatchRequest and handle the response accordingly are consistent with the improvements made to other methods. This enhances code clarity and maintainability.

Also applies to: 75-75


Line range hint 1-75: Overall assessment: Good improvements with one open question

The changes in this file consistently improve the API structure by using structured request and response objects across all modified methods. This enhances code readability and maintainability, aligning well with the PR objectives.

However, there's an open question regarding the implementation of the maxBytes parameter mentioned in the PR objectives. This parameter is not visible in the current implementation of GetNextBatch or other methods in this file. Clarification on where and how this parameter is being implemented would be helpful.

#!/bin/bash
# Search for maxBytes implementation in the entire codebase
rg --type go "maxBytes"

58-58: Query: Implementation of maxBytes parameter

The PR objectives mention adding a maxBytes parameter to allow the execution layer to specify a maximum size for batches. However, this parameter is not visible in the current implementation of GetNextBatch. Could you clarify where and how the maxBytes parameter is being implemented?

test/dummy_test.go (1)

3-10: LGTM: Import statements are appropriate and well-organized.

The import statements include all necessary packages for the test file and follow Go conventions for import ordering.

proxy/grpc/client.go (3)

68-68: Handle potential errors when constructing GetNextBatchResponse.

When returning the GetNextBatchResponse, ensure that all fields are correctly populated, and consider handling any potential errors in the mapping process.


72-77: VerifyBatch correctly maps the request and response fields.

The VerifyBatch function constructs the request with RollupId and BatchHash and returns the response status correctly.


80-80: Confirm interface implementation with compile-time assertion.

The line var _ sequencing.Sequencer = &Client{} ensures that Client implements the sequencing.Sequencer interface, providing a compile-time check.

test/dummy.go (1)

74-102: ⚠️ Potential issue

Implement the maxBytes parameter as per PR objectives

According to the PR objectives, the GetNextBatch method should handle a maxBytes parameter to limit the size of the batch. Currently, the maxBytes functionality is not implemented.

Please ensure that the maxBytes parameter is utilized to limit the batch size. You might need to adjust the GetNextBatch method to consider req.MaxBytes when assembling the batch.

For example:

func (tq *TransactionQueue) GetNextBatch(maxBytes int) *sequencing.Batch {
	// Existing locking code...

	var batch []sequencing.Tx
	currentSize := 0
	for _, tx := range tq.queue {
		txSize := len(tx.Data)
		if currentSize+txSize > maxBytes {
			break
		}
		batch = append(batch, tx)
		currentSize += txSize
	}
	tq.queue = tq.queue[len(batch):]
	return &sequencing.Batch{Transactions: batch}
}

Update the call in GetNextBatch method:

batch := d.tq.GetNextBatch(int(req.MaxBytes))

Ensure that you handle cases where MaxBytes is zero or negative.

proto/sequencing/sequencing.proto Show resolved Hide resolved
proxy/grpc/client.go Outdated Show resolved Hide resolved
proxy/grpc/client.go Outdated Show resolved Hide resolved
sequencing.go Show resolved Hide resolved
sequencing.go Show resolved Hide resolved
sequencing.go Show resolved Hide resolved
test/dummy.go Outdated Show resolved Hide resolved
test/dummy.go Outdated Show resolved Hide resolved
test/dummy.go Outdated Show resolved Hide resolved
test/dummy.go Outdated Show resolved Hide resolved
sequencing.go Show resolved Hide resolved
test/dummy_test.go Outdated Show resolved Hide resolved
test/dummy_test.go Outdated Show resolved Hide resolved
Copy link
Collaborator

@MSevey MSevey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall lgtm, few questions I'd like to understand more that I left comments about.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Outside diff range and nitpick comments (6)
proxy/grpc/server.go (2)

58-66: LGTM: Improved request and response handling for GetNextBatch

The changes enhance the API by using structured types for both request and response, improving encapsulation and type safety. This aligns well with the PR objectives.

A minor suggestion for improvement:

Consider combining the error checks to reduce nesting and improve readability:

resp, err := s.SequencerOutput.GetNextBatch(ctx, sequencing.GetNextBatchRequest{RollupId: req.RollupId, LastBatchHash: req.LastBatchHash})
if err != nil {
    return nil, err
}

ts, err := types.TimestampProto(resp.Timestamp)
if err != nil {
    return nil, err
}

return &pbseq.GetNextBatchResponse{Batch: resp.Batch.ToProto(), Timestamp: ts}, nil

Implement maxBytes Parameter in Server Methods

The maxBytes parameter defined in types/pb/sequencing/sequencing.pb.go is not implemented in proxy/grpc/server.go. To fully meet the PR objectives, please ensure that maxBytes is properly handled in the relevant methods, such as GetNextBatch.

🔗 Analysis chain

Line range hint 1-75: Overall improvements to API structure, but missing maxBytes implementation

The changes in this file consistently improve the API structure by using more structured request and response types across all methods. This enhances type safety and encapsulation, which is a positive direction for the codebase.

However, I noticed that the maxBytes parameter mentioned in the PR objectives (specifically issue #6) is not implemented in this file.

To confirm this, let's check if maxBytes is implemented elsewhere:

If the maxBytes parameter is not found, consider adding it to the relevant methods, particularly GetNextBatch, to fulfill the PR objectives completely.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for maxBytes implementation
rg --type go 'maxBytes'

Length of output: 166

test/dummy_test.go (4)

12-22: Consider expanding test coverage for TestTransactionQueue_AddTransaction.

While the current test covers the basic functionality, consider adding the following scenarios to improve test coverage:

  1. Test adding multiple transactions to ensure they are stored correctly.
  2. Test adding an empty transaction to verify error handling.
  3. Test adding transactions up to and beyond the queue's capacity (if applicable).

These additional test cases will help ensure the robustness of the AddTransaction method.


24-42: LGTM! Consider adding edge case tests.

The test covers the main functionality well, including multiple transactions and queue emptiness. To further improve it, consider adding:

  1. A test case for GetNextBatch on an empty queue.
  2. A test with a large number of transactions to ensure scalability.

These additions will help cover edge cases and ensure the robustness of the GetNextBatch method.


155-167: LGTM! Consider adding a test with a valid hash format.

The test correctly verifies the behavior for a non-existent batch. To further improve it, consider adding a test case with a valid hash format that doesn't correspond to any existing batch. This could be done by:

  1. Submitting and retrieving a valid batch to get a real hash format.
  2. Modifying one byte of the valid hash.
  3. Attempting to verify the batch with this modified hash.

This addition will ensure that the verification process correctly handles cases where the hash format is valid but doesn't correspond to any existing batch.


1-167: Overall good test coverage, but consider adding tests for maxBytes.

The test suite provides comprehensive coverage for the new functionality, including rollup ID handling and batch processing. However, to fully align with the PR objectives, consider adding tests for the maxBytes parameter mentioned in the PR summary. Specifically:

  1. Add a test case in TestDummySequencer_GetNextBatch that specifies a maxBytes value and verifies that the returned batch does not exceed this size.
  2. Include a test where the maxBytes limit is smaller than a single transaction to ensure proper handling of edge cases.

These additions will ensure that all aspects of the PR objectives are thoroughly tested.

🧰 Tools
🪛 GitHub Check: lint / golangci-lint

[failure] 78-78:
Error return value of sequencer.SubmitRollupTransaction is not checked (errcheck)


[failure] 108-108:
Error return value of sequencer.SubmitRollupTransaction is not checked (errcheck)


[failure] 132-132:
Error return value of sequencer.SubmitRollupTransaction is not checked (errcheck)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between ec3f843 and 86e7a61.

⛔ Files ignored due to path filters (2)
  • go.sum is excluded by !**/*.sum
  • types/pb/sequencing/sequencing.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (8)
  • go.mod (1 hunks)
  • proto/sequencing/sequencing.proto (2 hunks)
  • proxy/grpc/client.go (1 hunks)
  • proxy/grpc/server.go (2 hunks)
  • sequencing.go (2 hunks)
  • serialization.go (2 hunks)
  • test/dummy.go (1 hunks)
  • test/dummy_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • go.mod
  • proto/sequencing/sequencing.proto
  • sequencing.go
  • serialization.go
  • test/dummy.go
🧰 Additional context used
🪛 GitHub Check: lint / golangci-lint
test/dummy_test.go

[failure] 78-78:
Error return value of sequencer.SubmitRollupTransaction is not checked (errcheck)


[failure] 108-108:
Error return value of sequencer.SubmitRollupTransaction is not checked (errcheck)


[failure] 132-132:
Error return value of sequencer.SubmitRollupTransaction is not checked (errcheck)

🔇 Additional comments (5)
proxy/grpc/server.go (2)

49-49: LGTM: Improved request structure for SubmitRollupTransaction

The change to use sequencing.SubmitRollupTransactionRequest struct enhances the API by improving encapsulation and type safety. This aligns well with the PR objectives and the overall direction of the changes.


71-75: LGTM: Improved request and response handling for VerifyBatch

The changes enhance the API by using structured types for both request and response, improving encapsulation and type safety. This aligns well with the PR objectives and maintains consistency with the other method changes in this file.

proxy/grpc/client.go (3)

57-68: GetNextBatch method updated appropriately

The GetNextBatch method has been correctly refactored to use the new GetNextBatchRequest and GetNextBatchResponse types. The request is properly constructed with RollupId and LastBatchHash, and the response is appropriately mapped to the sequencing types. Error handling is correctly implemented.


72-77: VerifyBatch method implemented correctly

The VerifyBatch method now utilizes the new request and response structs, aligning with the updated API design. The request is accurately populated with RollupId and BatchHash, and the response status is correctly returned. Error handling is properly addressed.


80-80: Assertion of interface compliance

The addition of var _ sequencing.Sequencer = &Client{} is a good practice. This compile-time assertion ensures that Client satisfies the sequencing.Sequencer interface, helping to catch any deviations early in the development process.

test/dummy_test.go Outdated Show resolved Hide resolved
test/dummy_test.go Outdated Show resolved Hide resolved
test/dummy_test.go Outdated Show resolved Hide resolved
test/dummy_test.go Outdated Show resolved Hide resolved
@gupadhyaya gupadhyaya requested a review from MSevey October 1, 2024 16:48
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 86e7a61 and a98e57c.

📒 Files selected for processing (2)
  • test/dummy.go (2 hunks)
  • test/dummy_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/dummy_test.go
🔇 Additional comments (3)
test/dummy.go (3)

34-40: Function totalBytes is correctly implemented.

The totalBytes function accurately calculates the total number of bytes in the provided data slices.


72-77: Proper synchronization for shared resources is implemented.

The addition of mutexes lastBatchHashMutex and seenBatchesMutex ensures thread-safe access to shared resources in DummySequencer.


120-122: Potential issue with using raw bytes as map keys in seenBatches.

Storing []byte keys as strings may lead to incorrect behavior if the byte slices contain arbitrary data that doesn't represent valid UTF-8 strings.

Refer to the previous review comment regarding consistent key formatting in seenBatches.

test/dummy.go Outdated Show resolved Hide resolved
test/dummy.go Outdated Show resolved Hide resolved
test/dummy.go Outdated Show resolved Hide resolved
test/dummy.go Outdated Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (2)
test/dummy.go (2)

15-15: Add a comment for the exported error variable

The exported variable ErrInvalidRollupId should have a comment explaining its purpose. This will improve code documentation and satisfy the linter requirement.

Consider adding a comment like this:

// ErrInvalidRollupId is returned when an invalid rollup ID is provided
var ErrInvalidRollupId = errors.New("invalid rollup id")
🧰 Tools
🪛 GitHub Check: lint / golangci-lint

[failure] 15-15:
exported: exported var ErrInvalidRollupId should have comment or be unexported (revive)


98-134: Improved GetNextBatch method with suggestion

The GetNextBatch method has been significantly improved:

  1. It now accepts a GetNextBatchRequest struct, enhancing API consistency.
  2. Rollup ID validation has been added, improving security.
  3. The method now uses batch.Hash(), which is more maintainable.

These changes are approved. However, the lastBatchHash comparison logic could be simplified:

Consider simplifying the lastBatchHash comparison logic:

if !bytes.Equal(lastBatchHash, req.LastBatchHash) {
    return nil, errors.New("provided LastBatchHash does not match the sequencer's last batch hash")
}

This change would make the code more concise while maintaining the same functionality.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between a98e57c and b30eec5.

📒 Files selected for processing (2)
  • test/dummy.go (2 hunks)
  • test/dummy_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/dummy_test.go
🧰 Additional context used
🪛 GitHub Check: lint / golangci-lint
test/dummy.go

[failure] 15-15:
exported: exported var ErrInvalidRollupId should have comment or be unexported (revive)

🔇 Additional comments (6)
test/dummy.go (6)

46-74: Improved batch size handling

The updated GetNextBatch method now correctly handles the maxBytes parameter, ensuring that the returned batch does not exceed the specified maximum size. The implementation also properly handles edge cases, such as when no transactions can fit within the maxBytes limit.

Great job on implementing this feature! It addresses the objective of introducing a maxBytes parameter as mentioned in the linked issue #6.


79-85: Improved thread safety and rollup ID handling

The DummySequencer struct has been updated with better thread safety measures and explicit rollup ID handling:

  1. The rollupId field allows for proper validation of incoming requests.
  2. The lastBatchHashMutex is now more clearly named.
  3. The new seenBatchesMutex prevents potential race conditions when accessing the seenBatches map.

These changes enhance the overall robustness and correctness of the DummySequencer implementation.


89-94: Improved SubmitRollupTransaction method

The SubmitRollupTransaction method has been updated to:

  1. Accept a SubmitRollupTransactionRequest struct, improving API consistency.
  2. Use the isValid method for rollup ID validation, enhancing code reusability.
  3. Return a SubmitRollupTransactionResponse struct, providing a more flexible response structure.

These changes improve the method's consistency with the rest of the API and make it more robust with explicit rollup ID validation.


138-149: Improved VerifyBatch method

The VerifyBatch method has been updated with several improvements:

  1. It now accepts a VerifyBatchRequest struct, enhancing API consistency.
  2. Rollup ID validation has been added, improving security.
  3. The batch verification now uses hex encoding for the map key, addressing potential issues with arbitrary bytes in the hash.

These changes significantly improve the method's robustness and consistency with the rest of the API. The use of hex encoding for the map key is particularly noteworthy as it resolves a potential issue raised in a previous review comment.


151-153: Approve addition of isValid method

The new isValid method is a good addition to the DummySequencer:

  1. It enhances code reusability by centralizing the rollup ID validation logic.
  2. The implementation is correct and straightforward, using bytes.Equal for comparison.

This method improves the overall code structure and makes rollup ID validation more consistent across different methods.


156-161: Improved NewDummySequencer initialization

The NewDummySequencer function has been updated to accept and store a rollupId:

  1. This change allows for proper initialization of the DummySequencer with a specific rollup ID.
  2. It aligns with the new rollup ID validation implemented in other methods.

This improvement ensures that each DummySequencer instance is associated with a specific rollup ID from its creation, enhancing the overall consistency and correctness of the implementation.

MSevey
MSevey previously approved these changes Oct 1, 2024
proxy/grpc/client.go Outdated Show resolved Hide resolved
@tuxcanfly
Copy link
Collaborator

@gupadhyaya what do you think about keeping primitive or close aliases in the go interface, e.g.:

// SequencerInput provides a method for submitting a transaction from rollup to sequencer
type SequencerInput interface {
	// SubmitRollupTransaction submits a transaction from rollup to sequencer
	// RollupId is the unique identifier for the rollup chain
	// Tx is the transaction to submit
	// returns an error if any from the sequencer
	SubmitRollupTransaction(ctx context.Context, rollupId RollupId, tx Tx) error
}

// SequencerOutput provides a method for getting the next batch of transactions from sequencer to rollup
type SequencerOutput interface {
	// GetNextBatch returns the next batch of transactions from sequencer to rollup
	// RollupId is the unique identifier for the rollup chain
	// LastBatchHash is the cryptographic hash of the last batch received by the rollup
	// MaxBytes is the maximum number of bytes to return in the batch
	// returns the next batch of transactions and an error if any from the sequencer
	GetNextBatch(ctx context.Context, rollupId RollupId, lastBatchHash Hash, maxBytes uint64) (*Batch, time.Time, error)
}

// BatchVerifier provides a method for verifying a batch of transactions received from the sequencer
type BatchVerifier interface {
	// VerifyBatch verifies a batch of transactions received from the sequencer
	// RollupId is the unique identifier for the rollup chain
	// BatchHash is the cryptographic hash of the batch to verify
	// returns a boolean indicating if the batch is valid and an error if any from the sequencer
	VerifyBatch(ctx context.Context, rollupId RollupId, batchHash Hash) (bool, error)
}

then the grpc implementations can cast to their appropriate Request, Response types. This allows the go interface to remain cleaner and not be dependent on protobuf types.

@gupadhyaya
Copy link
Member Author

@gupadhyaya what do you think about keeping primitive or close aliases in the go interface, e.g.:

// SequencerInput provides a method for submitting a transaction from rollup to sequencer
type SequencerInput interface {
	// SubmitRollupTransaction submits a transaction from rollup to sequencer
	// RollupId is the unique identifier for the rollup chain
	// Tx is the transaction to submit
	// returns an error if any from the sequencer
	SubmitRollupTransaction(ctx context.Context, rollupId RollupId, tx Tx) error
}

// SequencerOutput provides a method for getting the next batch of transactions from sequencer to rollup
type SequencerOutput interface {
	// GetNextBatch returns the next batch of transactions from sequencer to rollup
	// RollupId is the unique identifier for the rollup chain
	// LastBatchHash is the cryptographic hash of the last batch received by the rollup
	// MaxBytes is the maximum number of bytes to return in the batch
	// returns the next batch of transactions and an error if any from the sequencer
	GetNextBatch(ctx context.Context, rollupId RollupId, lastBatchHash Hash, maxBytes uint64) (*Batch, time.Time, error)
}

// BatchVerifier provides a method for verifying a batch of transactions received from the sequencer
type BatchVerifier interface {
	// VerifyBatch verifies a batch of transactions received from the sequencer
	// RollupId is the unique identifier for the rollup chain
	// BatchHash is the cryptographic hash of the batch to verify
	// returns a boolean indicating if the batch is valid and an error if any from the sequencer
	VerifyBatch(ctx context.Context, rollupId RollupId, batchHash Hash) (bool, error)
}

then the grpc implementations can cast to their appropriate Request, Response types. This allows the go interface to remain cleaner and not be dependent on protobuf types.

totally agree. its currently not dependent on the protobuf types. instead just wrapped types within the sequencer interface instead of primitive types. see: https://github.com/rollkit/go-sequencing/blob/max_bytes/sequencing.go#L58, these wrapper types are not protobuf types. these wrapper types will help manage future updates to params and returns better. what do you think?

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between ad1c339 and 2923ec8.

📒 Files selected for processing (1)
  • proxy/grpc/client.go (1 hunks)
🔇 Additional comments (2)
proxy/grpc/client.go (2)

80-80: LGTM: Good practice for interface compliance.

The addition of this line is a good practice. It provides a compile-time check to ensure that the Client struct correctly implements all methods of the sequencing.Sequencer interface.


57-68: Verify handling of LastBatchHash.

The method now uses req.LastBatchHash directly without any explicit nil or empty checks. While this might be safe depending on how pbseq.GetNextBatchRequest handles nil slices, it's worth verifying to ensure robustness.

To confirm the safety of this approach, let's check the definition of pbseq.GetNextBatchRequest:

✅ Verification successful

LastBatchHash Handling Verified.

The LastBatchHash field in pbseq.GetNextBatchRequest is defined as a byte slice with omitempty, allowing it to be nil or empty. Protobuf serialization appropriately handles empty values by omitting the field. Given that SequencerOutputClient.GetNextBatch accepts this field without additional constraints, the current handling is robust and requires no further checks.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the definition of pbseq.GetNextBatchRequest
# Expected result: The definition should show how LastBatchHash is defined and any default values or constraints

rg --type go -A 10 "type GetNextBatchRequest struct" types/pb/sequencing/

Length of output: 1146

proxy/grpc/client.go Outdated Show resolved Hide resolved
proxy/grpc/client.go Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (3)
proxy/grpc/client.go (3)

48-56: LGTM! Consider explicit error handling.

The changes to SubmitRollupTransaction look good. The method now uses a structured request and response, improving encapsulation and API clarity.

Consider handling potential errors from the gRPC call more explicitly:

 func (c *Client) SubmitRollupTransaction(ctx context.Context, req sequencing.SubmitRollupTransactionRequest) (*sequencing.SubmitRollupTransactionResponse, error) {
-	_, err := c.SequencerInputClient.SubmitRollupTransaction(ctx, &pbseq.SubmitRollupTransactionRequest{
+	resp, err := c.SequencerInputClient.SubmitRollupTransaction(ctx, &pbseq.SubmitRollupTransactionRequest{
 		RollupId: req.RollupId,
 		Data:     req.Tx,
 	})
 	if err != nil {
 		return nil, err
 	}
-	return &sequencing.SubmitRollupTransactionResponse{}, nil
+	return &sequencing.SubmitRollupTransactionResponse{
+		// Map any relevant fields from resp
+	}, nil
 }

This change allows for future expansion of the response structure if needed.


60-71: LGTM! Consider adding a nil check for LastBatchHash.

The changes to GetNextBatch look good. The method now uses structured request and response types, improving encapsulation and API clarity.

Consider adding a nil check for LastBatchHash to improve robustness:

 func (c *Client) GetNextBatch(ctx context.Context, req sequencing.GetNextBatchRequest) (*sequencing.GetNextBatchResponse, error) {
+	if req.LastBatchHash == nil {
+		req.LastBatchHash = []byte{}
+	}
 	resp, err := c.SequencerOutputClient.GetNextBatch(ctx, &pbseq.GetNextBatchRequest{RollupId: req.RollupId, LastBatchHash: req.LastBatchHash})
 	if err != nil {
 		return nil, err
 	}
 	// ... rest of the function
 }

This change ensures that the LastBatchHash field is always a valid slice, even if it's empty.


75-80: LGTM! Consider adding input validation.

The changes to VerifyBatch look good. The method now uses structured request and response types, improving encapsulation and API clarity.

Consider adding input validation as suggested in a previous review:

 func (c *Client) VerifyBatch(ctx context.Context, req sequencing.VerifyBatchRequest) (*sequencing.VerifyBatchResponse, error) {
+	if len(req.RollupId) == 0 {
+		return nil, errors.New("RollupId cannot be empty")
+	}
+	if len(req.BatchHash) == 0 {
+		return nil, errors.New("BatchHash cannot be empty")
+	}
 	resp, err := c.BatchVerifierClient.VerifyBatch(ctx, &pbseq.VerifyBatchRequest{RollupId: req.RollupId, BatchHash: req.BatchHash})
 	if err != nil {
 		return nil, err
 	}
 	return &sequencing.VerifyBatchResponse{Status: resp.Status}, nil
 }

This change adds basic input validation to ensure the integrity of the data being passed to the gRPC call.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 2923ec8 and a13a943.

📒 Files selected for processing (1)
  • proxy/grpc/client.go (1 hunks)
🔇 Additional comments (1)
proxy/grpc/client.go (1)

83-83: LGTM! Good practice to include interface assertion.

The addition of the interface assertion is a good practice. It ensures at compile-time that the Client struct correctly implements all methods required by the sequencing.Sequencer interface.

Copy link
Collaborator

@tuxcanfly tuxcanfly left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK.

@Manav-Aggarwal Manav-Aggarwal merged commit 2abeb01 into main Oct 2, 2024
11 checks passed
@Manav-Aggarwal Manav-Aggarwal deleted the max_bytes branch October 2, 2024 15:42
Copy link

github-actions bot commented Oct 2, 2024

🎉 This PR is included in version 0.2.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request released
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

maxBytes parameter in GetNextBatch
5 participants