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

Add verifier to e2e tests #325

Merged
merged 3 commits into from
Dec 20, 2024
Merged

Add verifier to e2e tests #325

merged 3 commits into from
Dec 20, 2024

Conversation

natebeauregard
Copy link
Collaborator

@natebeauregard natebeauregard commented Dec 19, 2024

Adds a verifier node to the e2e tests. A new e2e test was created to assert that the verifier node can correctly sync to the sequencer.

Summary by CodeRabbit

  • New Features

    • Introduced a new method to retrieve blocks by hash.
    • Added a new command for starting a verifier application.
    • Implemented a new test case for verifying synchronization between nodes.
  • Bug Fixes

    • Enhanced error handling for existing methods, providing clearer context in error messages.
    • Improved control flow for starting the L1 instance, preventing redundant startups.
  • Tests

    • Added a new function to check synchronization status between verifier and sequencer nodes.
    • Updated test configurations to include verifier-related functionality.

Only start the L1 instance if it isn't already up. This allows for
verifier nodes to boot up independently if no sequencer node is already
running.
Copy link
Contributor

coderabbitai bot commented Dec 19, 2024

Walkthrough

The pull request introduces enhancements to the end-to-end (e2e) testing framework for a blockchain system. The changes focus on improving the MonomerClient struct in e2e/clients.go by adding a new BlockByHash method and updating error handling in the BlockByNumber method. The e2e/e2e.go file is modified to support a new verifier application startup, including the addition of a VerifierClient to the StackConfig struct. A new test case for verifier synchronization is also implemented in e2e/e2e_test.go, enhancing the overall testing capabilities.

Changes

File Changes
e2e/clients.go - Added BlockByHash method to MonomerClient
- Updated BlockByNumber method with improved error wrapping
e2e/e2e.go - Added VerifierClient field to StackConfig
- Modified Run function to support verifier application startup
e2e/e2e_test.go - Added "Verifier Sync" test case
- Updated newStackConfig to create verifier client
e2e/stack_test.go - Added verifierSync function to test verifier node synchronization
integrations/integrations.go - Modified startOPDevnet function to improve L1 instance handling

Possibly Related PRs

Suggested Reviewers

  • NiloCK
  • joshklop

Poem

🐰 In the land of blocks and chains,
Verifiers dance, while sequencers reigns.
Errors wrapped in tales so bright,
Testing the code, a rabbit's delight!
Hop along, let the sync begin,
Together we thrive, let the blockchain spin! 🌟

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.


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 generate docstrings to generate docstrings for this PR. (Beta)
  • @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.

Copy link
Contributor

@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: 1

🧹 Nitpick comments (7)
e2e/e2e.go (3)

66-66: Setup script execution.
The helper script looks beneficial for environment setup. Consider logging the script's output for troubleshooting.


113-115: Prevent race conditions with "time.Sleep".
Sleeping for one second is a quick fix for waiting on L1 readiness. Consider using a more deterministic wait such as polling readiness or health checks.


129-131: Decouple environment.
Storing environment variables in Env might conflict with user OS environment. If you need custom environment variables, consider scoping them to the command only.

e2e/clients.go (1)

56-59: Wrap errors with consistent context.
Using “block by number: %v” is helpful. You might consider including the block number for quicker debugging.

-	return nil, fmt.Errorf("block by number: %v", err)
+	return nil, fmt.Errorf("block by number (%d): %w", number, err)
e2e/e2e_test.go (1)

61-63: Wait for node setup.
A 1-second sleep can be flaky in busy CI or slower machines. Consider a readiness check approach.

integrations/integrations.go (1)

296-298: Document intent more clearly.
This comment block clarifies that L1 can run or not. Expanding these docs helps future maintainers understand the design choice.

e2e/stack_test.go (1)

101-116: Enhance verifier sync test with better diagnostics and configurability

The verifier sync test implementation is functional but could be improved for better maintainability and debugging capabilities.

Consider these improvements:

+const (
+    defaultSyncTimeout = 10 * time.Second
+    defaultSyncInterval = time.Second
+)
+
 func verifierSync(t *testing.T, stack *e2e.StackConfig) {
     sequencerBlock, err := stack.MonomerClient.BlockByNumber(stack.Ctx, nil)
     require.NoError(t, err)
+    t.Logf("Sequencer at block height %d with hash %s", 
+           sequencerBlock.Header().Number.Uint64(),
+           sequencerBlock.Header().Hash().String())
 
-    // Wait 10 seconds for the verifier node to sync with the sequencer node
-    for i := 0; i < 10; i++ {
+    timeout := time.After(defaultSyncTimeout)
+    ticker := time.NewTicker(defaultSyncInterval)
+    defer ticker.Stop()
+
+    for {
+        select {
+        case <-timeout:
+            t.Fatalf("Verifier failed to sync with sequencer after %v", defaultSyncTimeout)
+        case <-ticker.C:
             verifierBlock, err := stack.VerifierClient.BlockByHash(stack.Ctx, sequencerBlock.Header().Hash())
-            if verifierBlock != nil && err == nil {
-                t.Log("Verifier node can sync with the sequencer node")
+            if err != nil {
+                t.Logf("Verifier sync attempt failed: %v", err)
+                continue
+            }
+            if verifierBlock != nil {
+                t.Logf("Verifier successfully synced to block height %d", 
+                       verifierBlock.Header().Number.Uint64())
                 return
             }
-
-            time.Sleep(time.Second)
+            t.Log("Verifier returned nil block, retrying...")
         }
-    require.Fail(t, "verifier node did not sync with the sequencer node")
+    }
 }

The improvements include:

  1. Configurable timeout and interval constants
  2. More detailed logging of sync progress and failures
  3. Use of proper Go timer patterns with select
  4. Better error handling and diagnostics
  5. Clearer failure messages
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d8ecc8c and c465f05.

⛔ Files ignored due to path filters (1)
  • go.work.sum is excluded by !**/*.sum
📒 Files selected for processing (5)
  • e2e/clients.go (1 hunks)
  • e2e/e2e.go (4 hunks)
  • e2e/e2e_test.go (4 hunks)
  • e2e/stack_test.go (1 hunks)
  • integrations/integrations.go (2 hunks)
🔇 Additional comments (16)
e2e/e2e.go (8)

12-12: Prefer narrowing import usage.
The addition of "time" as a named import is fine, but always ensure it’s used consistently and is necessary where added.


32-32: VerifierClient field helpful for multi-node setups!
Adding "VerifierClient" extends the testing stack's capabilities for spinning up verifier nodes. Good addition.


58-58: Double-check parallel processes.
Ensure that monogenCmd finishes execution before launching subsequent tasks, to avoid concurrency pitfalls.


71-71: Sequencer app command clarity.
Renaming it to "sequencerAppCmd" helps to disambiguate from other nodes. This is a good readability improvement.


100-103: Handle sequencer startup errors gracefully.
Starting the sequencer command is crucial. If it crashes repeatedly, consider implementing a retry mechanism or more detailed error logs.


105-111: Introduce context-based termination checks.
These lines ensure that we capture context cancellation. This robust approach prevents goroutine leaks if the test stops abruptly.


116-128: Verifier node command.
Copying logic from sequencer node is consistent, but ensure concurrency aspects are well managed since both nodes run simultaneously.


134-135: Proper cleanup of verifier process.
Similar to the sequencer, deferring error checks helps ensure we handle unexpected terminations. Keep an eye on concurrency side effects.

e2e/clients.go (1)

61-64: Newly added BlockByHash method.
This aligns well with the existing pattern. Great for verifying blocks by hash. Keep consistent error message format.

e2e/e2e_test.go (4)

41-44: New test “Verifier Sync”
This is a crucial test for ensuring the verifier node properly syncs with the sequencer. Great addition to the coverage.


86-92: Verifier client creation.
Instantiating a second client is straightforward. Always verify that both the L2 and verifier endpoints do not conflict in ports or addresses.


93-96: Verifier BFT client addition.
Starting and verifying the BFT client ensures consistent integration testing. Keep an eye out for potential resource leaks.


127-127: VerifierClient field
Linking the newly created verifier client to the StackConfig is a cohesive step in your expanded e2e tests.

integrations/integrations.go (2)

42-42: New RPC import.
The added “github.com/ethereum/go-ethereum/rpc” import is consistent with other usage patterns.


299-305: Close L1 client if already running.
Allows verifier node to boot independently. Good safeguard to avoid re-initializing an active L1 node.

e2e/stack_test.go (1)

101-116: 🛠️ Refactor suggestion

Consider adding block content verification

The current implementation only verifies that the verifier can retrieve the block by hash, but doesn't verify the block contents.

Consider adding block content verification:

 func verifierSync(t *testing.T, stack *e2e.StackConfig) {
     sequencerBlock, err := stack.MonomerClient.BlockByNumber(stack.Ctx, nil)
     require.NoError(t, err)
 
+    // Helper function to get block details for comparison
+    getBlockDetails := func(block types.Block) (hash common.Hash, number uint64, txCount int) {
+        header := block.Header()
+        return header.Hash(), header.Number.Uint64(), len(block.Transactions())
+    }
+
+    seqHash, seqNum, seqTxCount := getBlockDetails(sequencerBlock)
+
     // Wait 10 seconds for the verifier node to sync with the sequencer node
     for i := 0; i < 10; i++ {
         verifierBlock, err := stack.VerifierClient.BlockByHash(stack.Ctx, sequencerBlock.Header().Hash())
         if verifierBlock != nil && err == nil {
-            t.Log("Verifier node can sync with the sequencer node")
+            verHash, verNum, verTxCount := getBlockDetails(verifierBlock)
+            
+            // Verify block contents match
+            require.Equal(t, seqHash, verHash, "Block hash mismatch")
+            require.Equal(t, seqNum, verNum, "Block number mismatch")
+            require.Equal(t, seqTxCount, verTxCount, "Transaction count mismatch")
+            
+            t.Logf("Verifier synced and verified block %d with %d transactions", 
+                   verNum, verTxCount)
             return
         }
 
         time.Sleep(time.Second)
     }
     require.Fail(t, "verifier node did not sync with the sequencer node")
 }
✅ Verification successful

Block content verification is essential - similar pattern found in codebase

Based on the search results, there's evidence in the codebase (opdevnet_test.go) showing that block verification is indeed performed in other tests, specifically comparing state roots between verifier and sequencer nodes. This confirms that the original review comment's suggestion for adding block content verification is valid and follows existing patterns in the codebase.

The suggested changes in the review comment would improve test reliability by:

  • Comparing block hashes
  • Verifying block numbers match
  • Checking transaction counts
  • Providing more detailed logging

This aligns with the codebase's existing verification patterns while adding comprehensive block content checks.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if there are any block verification functions in the codebase that could be reused

# Search for functions that compare blocks
rg -A 5 'func.*Block.*Compare|func.*Compare.*Block'

# Search for block verification patterns
ast-grep --pattern 'func $name($block1, $block2) {
  $$$
  $block1.Header()
  $$$
  $block2.Header()
  $$$
}'

Length of output: 165


Script:

#!/bin/bash
# Let's search for existing block verification patterns in test files
rg -g '**/*test.go' -A 5 'verifier.*Block|block.*verif|compare.*block|block.*compare'

# Let's also check for any block verification in the main code
rg -g '**/*.go' -g '!**/*test.go' -A 5 'verifier.*Block|block.*verif|compare.*block|block.*compare'

# Let's look for any block header comparison patterns
rg -g '**/*.go' -A 5 'Header\(\).*Equal|Equal.*Header\(\)'

# Let's check how blocks are typically compared in the codebase
ast-grep --pattern 'require.Equal($t, $block1, $block2'

Length of output: 1719

e2e/e2e.go Show resolved Hide resolved
Copy link
Collaborator

@joshklop joshklop left a comment

Choose a reason for hiding this comment

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

Thanks!

e2e/e2e.go Outdated Show resolved Hide resolved
e2e/stack_test.go Outdated Show resolved Hide resolved
Copy link
Contributor

@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

🧹 Nitpick comments (1)
e2e/e2e.go (1)

Line range hint 71-111: Improve error context in sequencer command execution.

While the command setup is correct, the error message could be more descriptive.

-		return fmt.Errorf("run sequencer app: %v", err)
+		return fmt.Errorf("failed to start sequencer node (appName=%s): %w", appName, err)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c465f05 and 511914b.

⛔ Files ignored due to path filters (1)
  • go.work.sum is excluded by !**/*.sum
📒 Files selected for processing (3)
  • e2e/e2e.go (4 hunks)
  • e2e/e2e_test.go (4 hunks)
  • e2e/stack_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • e2e/e2e_test.go
🔇 Additional comments (5)
e2e/stack_test.go (1)

101-117: Verify test integration in the test suite

Ensure this verifier sync test is properly registered in the test suite.

✅ Verification successful

The search results show that verifierSync is registered in e2e/e2e_test.go as a test case. Let me verify the complete test registration context to ensure it's properly integrated.


Test is properly integrated in the test suite

The verifierSync test is correctly registered in the e2e test suite as part of the e2eTests slice, with a dedicated test case named "Verifier Sync". The test is executed through the main TestE2E function which runs all registered test cases. The test has proper access to all required dependencies through the StackConfig including the verifier client, making it a well-integrated part of the test suite.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the verifierSync test is registered in the test suite

# Search for test registration
rg -A 5 "verifierSync" --type go

# Look for test execution patterns
rg -A 10 'func Test.*\bVerifier\b.*\(t \*testing\.T\)' --type go

Length of output: 634


Script:

#!/bin/bash
# Check the complete test registration context
cat e2e/e2e_test.go

Length of output: 4151

e2e/e2e.go (4)

18-18: LGTM!

The URL package import is correctly added and is used for L1 reachability checks.


32-32: LGTM!

The VerifierClient field is appropriately added to support verifier node testing, maintaining consistency with the existing client field patterns.


58-58: LGTM!

The error assignment syntax is correctly updated while maintaining proper error handling.

Also applies to: 66-66


122-142: Improve error handling and verify port configurations.

  1. The error message improvement suggestion from the past review is still valid.

  2. The verifier uses specific ports that should be verified for availability:

    • RPC: 26667
    • Engine: 9010
    • Op-node: 9012
#!/bin/bash
# Description: Check if the ports required by the verifier are already in use

echo "Checking port availability..."
for port in 26667 9010 9012; do
    if nc -z localhost $port 2>/dev/null; then
        echo "Warning: Port $port is already in use"
    else
        echo "Port $port is available"
    fi
done

e2e/stack_test.go Show resolved Hide resolved
e2e/e2e.go Show resolved Hide resolved
@natebeauregard natebeauregard merged commit 4273774 into main Dec 20, 2024
16 checks passed
@natebeauregard natebeauregard deleted the nkb.verifier-e2e-2 branch December 20, 2024 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants