Skip to content

Conversation

@tac0turtle
Copy link
Contributor

@tac0turtle tac0turtle commented Jun 23, 2025

Summary

This PR introduces Lumen, a specialized integration layer that enables
Reth to work seamlessly with Rollkit by implementing custom Engine API
transaction submission capabilities. This allows Reth to function as an
execution client for Rollkit-based rollups.

Key Changes

🏗️ Core Implementation

  • Custom Payload Builder (crates/node/): Implements RollkitPayloadBuilder
    that supports transaction submission via Engine API attributes
  • Rollkit Types (crates/rollkit/): Defines custom Engine API types
    including RollkitEngineTypes and RollkitPayloadAttributes for transaction
    encoding/decoding
  • Main Binary (bin/lumen/): Complete node implementation with CLI,
    configuration, and custom Engine API validator

🧪 Testing Infrastructure

  • E2E Tests (crates/e2e-tests/): Comprehensive test suite covering:
    • Engine API transaction submission
    • Payload building and validation
    • Integration with standard Reth components
    • Transaction pool bypass functionality

🔧 Development & CI/CD

  • GitHub Workflows: Added complete CI pipeline including:
    • Unit tests, integration tests, and E2E tests
    • Linting (Rust, TOML, Markdown, GitHub Actions)
    • Dependency management and security scanning
    • Docker image building and release automation
  • Docker Support: Multi-stage Dockerfiles for optimized production builds
  • Documentation: Comprehensive README with architecture overview, usage
    instructions, and development guidelines

📋 Project Setup

  • Cargo Workspace: Organized monorepo structure with shared dependencies
  • Configuration: Added development tools configuration (rustfmt, clippy,
    deny)
  • Licensing: Dual-licensed under MIT and Apache 2.0
  • Issue Templates: Bug report and feature request templates for better
    collaboration

Technical Highlights

  1. Engine API Extensions: Modified Engine API to accept transactions
    directly in payload attributes, bypassing the traditional mempool
  2. Custom Validation: Implemented RollkitEngineValidator that relaxes
    certain validation rules for rollup compatibility
  3. Gas Limit Flexibility: Support for custom gas limits per payload
    request
  4. State Execution: Full transaction execution with proper state
    transitions and receipt generation

Testing

  • ✅ Unit tests for core components
  • ✅ Integration tests for node functionality
  • ✅ E2E tests for complete transaction flow
  • ✅ Linting and formatting checks

Summary by CodeRabbit

  • New Features

    • Introduced the Lumen project, an integration layer combining Reth with Rollkit, providing a custom payload builder, Engine API transaction support, and flexible block validation.
    • Added a node binary with command-line interface for running a Rollkit node with custom payload building and validation.
    • Implemented Rollkit-specific payload attributes, configuration, and builder logic for transaction inclusion and block creation.
  • Documentation

    • Rewrote and expanded the README with installation, usage, architecture, configuration, development, and contribution guidelines.
    • Added issue and pull request templates for standardized GitHub contributions.
    • Provided branch protection rules and licensing information (MIT and Apache 2.0).
  • Chores

    • Added configuration files for code quality (clippy, rustfmt), dependency management (cargo-deny, dependabot), and .gitignore.
    • Established comprehensive CI/CD workflows for linting, testing, integration, end-to-end tests, dependency updates, and release automation.
    • Introduced Dockerfiles and a Makefile for building, testing, and deploying the project across multiple platforms.
    • Included a genesis configuration for blockchain initialization.
  • Tests

    • Added extensive unit and integration tests covering payload building, Engine API execution flows, error handling, and CLI behavior.
    • Developed test fixtures and utilities for Rollkit payload builder and Ethereum mock providers.
    • Implemented Engine API integration tests with real and mock node interactions.
    • Added performance and edge case tests for payload building and transaction processing.

@coderabbitai
Copy link

coderabbitai bot commented Jun 23, 2025

Warning

Rate limit exceeded

@tac0turtle has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 15 minutes and 5 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between cd627c1 and ab37fbd.

📒 Files selected for processing (5)
  • crates/rollkit/src/tests.rs (1 hunks)
  • crates/tests/src/engine_api_tests.rs (1 hunks)
  • crates/tests/src/integration_tests.rs (1 hunks)
  • crates/tests/src/payload_builder_tests.rs (1 hunks)
  • crates/tests/src/test_rollkit_engine_api.rs (1 hunks)

Walkthrough

This change introduces the initial project scaffolding for a Rust-based system called "Lumen," which integrates Reth with Rollkit. It adds workspace configuration, multiple crates, a node binary, core logic for Rollkit payload building and validation, CI/CD workflows, Dockerfiles, configuration files, documentation, and licensing. The setup includes code quality tools, dependency management, and templates for issues and pull requests.

Changes

Files / Grouped Paths Change Summary
.github/CODEOWNERS Added code owners file assigning @rollkit/binary-builders as repository owners
.github/ISSUE_TEMPLATE/bug_report.md,
.github/ISSUE_TEMPLATE/feature_request.md
Added GitHub issue templates for bug reports and feature requests
.github/assets/Dockerfile,
.github/workflows/docker.yml,
.github/workflows/dependencies.yml,
.github/workflows/e2e.yml,
.github/workflows/integration.yml,
.github/workflows/lint-actions.yml,
.github/workflows/lint.yml,
.github/workflows/release.yml,
.github/workflows/unit.yml
Added GitHub Actions workflows for dependencies, Docker image build and publish, end-to-end, integration, linting, release, and unit tests
.github/branch-protection.md Added branch protection guideline document
.github/dependabot.yml Added Dependabot configuration for automated dependency updates
.github/pull_request_template.md Added pull request template
.gitignore Added comprehensive .gitignore for Rust, editor, test, and system files
Cargo.toml Introduced workspace configuration, dependencies, linting, and release profile
LICENSE-APACHE,
LICENSE-MIT
Added Apache 2.0 and MIT license texts
Makefile Added Makefile with build, test, lint, doc, and Docker targets
README.md Rewrote and expanded README with project overview, architecture, usage, and contribution guidelines
bin/lumen/Cargo.toml,
bin/lumen/src/main.rs
Added manifest and main binary implementing Rollkit node, payload builder, and validator integration
clippy.toml,
rustfmt.toml
Added Clippy and Rustfmt configuration files for linting and formatting
crates/common/Cargo.toml,
crates/common/src/constants.rs,
crates/common/src/lib.rs
Added lumen-common crate with shared constants and utilities
crates/node/Cargo.toml,
crates/node/src/builder.rs,
crates/node/src/config.rs,
crates/node/src/lib.rs
Added lumen-node crate with Rollkit payload builder, configuration, and re-exports
crates/rollkit/Cargo.toml,
crates/rollkit/src/lib.rs,
crates/rollkit/src/tests.rs,
crates/rollkit/src/types.rs
Added lumen-rollkit crate with Rollkit-specific types, payload attributes, error types, and tests
deny.toml Added cargo-deny configuration for dependency license and advisory checks
etc/lumen-genesis.json Added blockchain genesis configuration file
crates/tests/Cargo.toml,
crates/tests/src/common.rs,
crates/tests/src/engine_api_tests.rs,
crates/tests/src/integration_tests.rs,
crates/tests/src/lib.rs,
crates/tests/src/payload_builder_tests.rs,
crates/tests/src/test_rollkit_engine_api.rs
Added integration and unit test crates and modules with test fixtures, engine API tests, payload builder tests, and CLI integration tests
Dockerfile,
Dockerfile.cross
Added multi-stage and cross-platform Dockerfiles for building and running the lumen binary

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant LumenNode (main.rs)
    participant RollkitPayloadBuilder
    participant RethEngine
    participant RollkitValidator

    User->>LumenNode (main.rs): Start node with CLI args
    LumenNode (main.rs)->>RethEngine: Initialize Reth components
    LumenNode (main.rs)->>RollkitPayloadBuilder: Configure payload builder
    RethEngine->>RollkitPayloadBuilder: Request payload build (with attributes)
    RollkitPayloadBuilder->>RollkitPayloadBuilder: Validate attributes
    RollkitPayloadBuilder->>RethEngine: Fetch state, parent header
    RollkitPayloadBuilder->>RollkitPayloadBuilder: Build block with transactions
    RollkitPayloadBuilder->>RethEngine: Return sealed block
    RethEngine->>RollkitValidator: Validate payload
    RollkitValidator->>RethEngine: Return validation result
    RethEngine->>LumenNode (main.rs): Complete block proposal
Loading

Poem

🐇
A warren of code, now freshly begun,
With Docker and Makefile, the groundwork is spun.
Rollkit and Reth, together they play,
CI flows and templates keep bugs at bay.
Licenses in tow, and a README to show—
Lumen’s first hop is ready to go!

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this 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.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @tac0turtle, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces "Lumen," a specialized integration layer that transforms Reth into a Rollkit-compatible execution client. It achieves this by implementing a custom payload builder that allows transactions to be submitted directly via the Engine API, enabling Rollkit to produce blocks with custom transaction sets and flexible validation rules.

Highlights

  • Rollkit-Reth Node: A new rollkit-reth binary is introduced, built on Reth, but customized to serve as a Rollkit-compatible execution client.
  • Custom Payload Builder: Implemented RollkitPayloadBuilder and RollkitEnginePayloadBuilder to accept and process transactions provided through the Engine API's payload attributes, allowing Rollkit to dictate block content.
  • Flexible Engine API Validation: The RollkitEngineValidator is introduced to adapt Reth's Engine API validation, specifically bypassing block hash validation for Rollkit blocks and allowing custom gas limits, while maintaining other critical checks.
  • Comprehensive Project Setup: The PR includes a complete project structure with a Rust workspace, Cargo.toml configurations, Makefile for build automation, clippy.toml for linting, and detailed README.md documentation.
  • Extensive Testing: New unit tests for payload attributes, and integration tests for the payload builder and Engine API interactions (including mock and real node scenarios), are added to ensure robustness and correctness.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

The pull request introduces a custom payload builder for Reth to integrate with Rollkit, enabling transaction submission via the Engine API. The changes include new configuration files, updated build scripts, and core logic for handling Rollkit-specific block building and validation. The README.md is comprehensive and provides good context. Overall, the changes are well-structured and address the stated objective. However, there are a few areas related to maintainability, error handling, and asynchronous programming patterns that could be improved.

# quite mature enough for use in our codebase and some we don't really want.
# Explicitly listing should make it easier to fix in the future.
as_ptr_cast_mut = "allow"
cognitive_complexity = "allow"
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The cognitive_complexity lint is explicitly allowed here, but clippy.toml sets a max-cognitive-complexity-threshold. Allowing the lint here effectively overrides the threshold, making it ineffective. It's generally better to either enforce the lint with a warning/deny and a threshold, or remove the threshold if the lint is intentionally allowed.

cognitive_complexity = "warn"

Comment on lines 59 to 61
PayloadBuilderError::Internal(RethError::Other("Gas limit is required for rollkit payloads".into()))
})?;

Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The gas_limit field in RollkitPayloadAttributes is defined as Option<u64>, implying it's optional. However, here it's unwrapped with ok_or_else, making it a required field for build_payload. This creates an inconsistency. If gas_limit is truly optional, a default value should be provided or a different error should be returned if it's None and required for a specific operation. If it's always required, it should not be an Option type in RollkitPayloadAttributes.

Suggested change
PayloadBuilderError::Internal(RethError::Other("Gas limit is required for rollkit payloads".into()))
})?;
let gas_limit = attributes.gas_limit.unwrap_or(reth_primitives::constants::GAS_LIMIT_MAX); // Or some other appropriate default

Comment on lines 92 to 94
let recovered_tx = tx.try_clone_into_recovered().map_err(|_| {
PayloadBuilderError::Internal(RethError::Other("Failed to recover transaction".into()))
})?;
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The error message "Failed to recover transaction" is quite generic. It would be more helpful for debugging if the error message included details from the underlying recovery failure, or at least indicated which transaction failed.

Suggested change
let recovered_tx = tx.try_clone_into_recovered().map_err(|_| {
PayloadBuilderError::Internal(RethError::Other("Failed to recover transaction".into()))
})?;
let recovered_tx = tx.try_clone_into_recovered().map_err(|e| {
PayloadBuilderError::Internal(RethError::Other(format!("Failed to recover transaction: {}", e).into()))
})?;

println!("Mock mode tests should still pass to verify the basic functionality");
}

// At least one test should pass to consider this successful
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The assertion assert!(passed > 0, "At least one Engine API test should pass"); is quite weak for an integration test. Ideally, all expected tests should pass for the integration to be considered successful. A stronger assertion like assert_eq!(failed, 0, "All Engine API tests should pass"); would provide more robust validation of the integration.

Suggested change
// At least one test should pass to consider this successful
assert_eq!(failed, 0, "All Engine API tests should pass");

/// This error occurs when the transaction list is empty, which is invalid
/// since a payload must contain at least one transaction to be meaningful.
#[error("No transactions provided")]
EmptyTransactions,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Manav-Aggarwal what is the thought here? this seems like it would break the current flow

@tac0turtle tac0turtle marked this pull request as ready for review June 23, 2025 16:17
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: 9

♻️ Duplicate comments (2)
crates/rollkit/src/types.rs (1)

67-72: Remove unused error variant or implement its validation.

The EmptyTransactions error variant is defined but never used in the validation logic. The validation method explicitly allows empty transactions (line 48-49), making this error variant unreachable.

Either remove the unused variant:

-    /// Error when no transactions are provided in the payload attributes
-    ///
-    /// This error occurs when the transaction list is empty, which is invalid
-    /// since a payload must contain at least one transaction to be meaningful.
-    #[error("No transactions provided")]
-    EmptyTransactions,

Or implement the validation if empty transactions should actually be rejected:

 pub const fn validate(&self) -> Result<(), PayloadAttributesError> {
-        // For rollkit, empty transactions are allowed (empty blocks are valid)
+        if self.transactions.is_empty() {
+            return Err(PayloadAttributesError::EmptyTransactions);
+        }
Cargo.toml (1)

193-193: Resolve cognitive_complexity lint configuration conflict

The cognitive_complexity lint is allowed here, but clippy.toml likely sets a threshold. This creates a configuration conflict where the threshold is ineffective.

Either enforce the lint with a warning and keep the threshold:

-cognitive_complexity = "allow"
+cognitive_complexity = "warn"

Or remove the threshold from clippy.toml if the lint is intentionally disabled.

🧹 Nitpick comments (26)
LICENSE-MIT (1)

3-3: Consider updating the copyright year
Current line reads “© 2024 Rollkit Contributors”; you may want to sync it with the year in your Cargo.toml metadata or the project’s creation year.

.github/dependabot.yml (1)

33-33: Add newline at end of file.
YAML files should terminate with a newline to satisfy parsers and linters.

.github/ISSUE_TEMPLATE/feature_request.md (1)

9-9: Remove trailing punctuation from heading

The trailing period in this heading conflicts with markdownlint rule MD026. Use the heading without a trailing period.

-## Is your feature request related to a problem? Please describe.
+## Is your feature request related to a problem? Please describe
.github/ISSUE_TEMPLATE/bug_report.md (1)

37-39: Specify language for fenced code blocks

Add a language identifier (e.g., text) to the logs code block to satisfy MD040.

-```
+```text
 Please paste any relevant log output here
-```
+```
etc/lumen-genesis.json (1)

20-23: Consider specifying baseFeePerGas and verify empty alloc
Since EIP-1559 is enabled at genesis (londonBlock: 0), you may need a top-level "baseFeePerGas" entry. Also confirm that an empty "alloc": {} is intentional (no pre-funded accounts).

Example diff:

   "gasLimit": "0x1c9c380",
+  "baseFeePerGas": "0x1",
   "alloc": {}
.github/workflows/lint-actions.yml (2)

2-6: Narrow trigger scope to workflow files
Currently this runs actionlint on every push/PR. You can limit it to YAML under .github/workflows/ for faster CI:

on:
  pull_request:
    paths:
      - '.github/workflows/**.yml'
  push:
    branches: [main]
    paths:
      - '.github/workflows/**.yml'

19-19: Add newline at end of file
YAML files should end with a trailing newline.

.github/pull_request_template.md (2)

5-13: Add “Chore” to Type of Change
Your CI/config changes are neither a bug fix nor a feature. Consider adding:

- [ ] Chore (repository maintenance tasks)

7-7: Refine wording for formality
Use a more formal verb than “fixes” in the bug-fix option, e.g.:

- [ ] Bug fix (non-breaking change which resolves an issue)
crates/rollkit/Cargo.toml (1)

1-10: Consider marking this crate publish = false
If lumen-rollkit isn’t intended for independent publishing, add:

[package]
name = "lumen-rollkit"
publish = false
version.workspace = true
#

This prevents accidental crates.io publishes.

.github/workflows/docker.yml (1)

40-40: Add a newline at end of file
YAML files should end with a single newline to satisfy linters and POSIX standards.

.github/branch-protection.md (1)

27-27: Hyphenate “up to date” for consistency
Change “Require branches to be up to date before merging” to “Require branches to be up-to-date before merging.”

.github/workflows/e2e.yml (1)

45-45: Add a newline at end of file
Ensure the file ends with a single newline to comply with YAML linting rules.

.github/workflows/dependencies.yml (1)

61-61: Add a newline at end of file
A trailing newline is required to satisfy YAML linters.

crates/node/Cargo.toml (1)

24-24: Consider moving test-utils feature to dev-dependencies.

The test-utils feature for reth-provider is typically used only during testing. Consider moving this to dev-dependencies unless it's specifically needed for the main crate functionality.

-reth-provider = { workspace = true, features = ["test-utils"] }
+reth-provider.workspace = true

And in dev-dependencies:

+reth-provider = { workspace = true, features = ["test-utils"] }
.github/workflows/release.yml (2)

76-76: Fix trailing spaces.

Static analysis detected trailing spaces on this line.

-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v4

92-92: Add newline at end of file.

Static analysis detected missing newline character at the end of the file.

             artifacts/lumen-*.zip
+
README.md (2)

137-137: Fix word repetition in transaction flow description.

There's a word repetition issue in the description.

-3. `RollkitPayloadBuilder` executes transactions and builds block
+3. `RollkitPayloadBuilder` executes transactions and builds the block

161-195: Add language specification to code block.

The project structure code block should specify the language for better syntax highlighting.

-```
+```text
 lumen/
 ├── bin/
crates/rollkit/src/types.rs (1)

46-57: Consider validating individual transactions.

The validation method only checks the gas limit but doesn't validate individual transactions. Consider adding transaction validation to catch malformed transactions early.

 pub const fn validate(&self) -> Result<(), PayloadAttributesError> {
     // For rollkit, empty transactions are allowed (empty blocks are valid)

+    // Validate individual transactions if needed
+    // Note: This would require making the function non-const
+    // for tx in &self.transactions {
+    //     tx.validate().map_err(|e| PayloadAttributesError::TransactionValidation(e.to_string()))?;
+    // }

     if let Some(gas_limit) = self.gas_limit {
         if gas_limit == 0 {
             return Err(PayloadAttributesError::InvalidGasLimit);
         }
     }

     Ok(())
 }
.github/workflows/integration.yml (1)

52-52: Add missing newline at end of file.

The file is missing a newline character at the end, which violates POSIX standards and can cause issues with some tools.

           jobs: ${{ toJSON(needs) }}
+
.github/workflows/unit.yml (1)

67-67: Add missing newline at end of file.

The file is missing a newline character at the end.

           jobs: ${{ toJSON(needs) }}
+
.github/workflows/lint.yml (1)

110-110: Add missing newline at end of file.

The file is missing a newline character at the end.

           jobs: ${{ toJSON(needs) }}
+
bin/lumen/Cargo.toml (1)

42-42: Remove unnecessary blank line.

There's an extra blank line that doesn't serve any organizational purpose.

-
 # Core dependencies
crates/node/src/builder.rs (1)

75-75: Verify the hardcoded parent_beacon_block_root value

The parent_beacon_block_root is hardcoded to B256::ZERO for rollkit blocks. Please confirm this is the intended behavior and consider documenting why rollkit doesn't use beacon block roots.

Would you like me to add a more detailed comment explaining why rollkit blocks don't require beacon block roots?

bin/lumen/src/main.rs (1)

252-265: Document the security implications of bypassing block hash validation

The code bypasses block hash mismatch errors for rollkit. While this may be intentional for rollkit's consensus model, it's a significant security consideration that should be well-documented.

Consider:

  1. Adding detailed documentation explaining why this bypass is safe for rollkit
  2. Adding a configuration flag to control this behavior
  3. Logging these bypasses at a higher level (warn/error) for auditability

Would you like me to help draft comprehensive documentation for this security consideration?

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f446dfd and 0c817f3.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (39)
  • .github/CODEOWNERS (1 hunks)
  • .github/ISSUE_TEMPLATE/bug_report.md (1 hunks)
  • .github/ISSUE_TEMPLATE/feature_request.md (1 hunks)
  • .github/assets/Dockerfile (1 hunks)
  • .github/branch-protection.md (1 hunks)
  • .github/dependabot.yml (1 hunks)
  • .github/pull_request_template.md (1 hunks)
  • .github/workflows/dependencies.yml (1 hunks)
  • .github/workflows/docker.yml (1 hunks)
  • .github/workflows/e2e.yml (1 hunks)
  • .github/workflows/integration.yml (1 hunks)
  • .github/workflows/lint-actions.yml (1 hunks)
  • .github/workflows/lint.yml (1 hunks)
  • .github/workflows/release.yml (1 hunks)
  • .github/workflows/unit.yml (1 hunks)
  • .gitignore (1 hunks)
  • Cargo.toml (1 hunks)
  • Dockerfile (1 hunks)
  • Dockerfile.cross (1 hunks)
  • LICENSE-APACHE (1 hunks)
  • LICENSE-MIT (1 hunks)
  • Makefile (1 hunks)
  • README.md (1 hunks)
  • bin/lumen/Cargo.toml (1 hunks)
  • bin/lumen/src/main.rs (1 hunks)
  • clippy.toml (1 hunks)
  • crates/common/Cargo.toml (1 hunks)
  • crates/common/src/constants.rs (1 hunks)
  • crates/common/src/lib.rs (1 hunks)
  • crates/node/Cargo.toml (1 hunks)
  • crates/node/src/builder.rs (1 hunks)
  • crates/node/src/config.rs (1 hunks)
  • crates/node/src/lib.rs (1 hunks)
  • crates/rollkit/Cargo.toml (1 hunks)
  • crates/rollkit/src/lib.rs (1 hunks)
  • crates/rollkit/src/types.rs (1 hunks)
  • deny.toml (1 hunks)
  • etc/lumen-genesis.json (1 hunks)
  • rustfmt.toml (1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
.github/ISSUE_TEMPLATE/bug_report.md

37-37: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

.github/ISSUE_TEMPLATE/feature_request.md

9-9: Trailing punctuation in heading
Punctuation: '.'

(MD026, no-trailing-punctuation)

README.md

161-161: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

🪛 LanguageTool
.github/branch-protection.md

[uncategorized] ~27-~27: It appears that hyphens are missing in the adjective “up-to-date”.
Context: ...e merging** - Require branches to be up to date before merging - Status checks liste...

(UP_TO_DATE_HYPHEN)

.github/pull_request_template.md

[style] ~7-~7: Consider using a different verb for a more formal wording.
Context: ... [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaki...

(FIX_RESOLVE)

README.md

[uncategorized] ~103-~103: Loose punctuation mark.
Context: ...paration of concerns: - bin/lumen: The main executable binary - **`crates/...

(UNLIKELY_OPENING_PUNCTUATION)


[duplication] ~137-~137: Possible typo: you repeated a word.
Context: ...ilder` executes transactions and builds block 4. Block is returned via standard Engine API res...

(ENGLISH_WORD_REPEAT_RULE)


[uncategorized] ~152-~152: Loose punctuation mark.
Context: ...ons for Rollkit integration: - --http: Enable HTTP-RPC server - --ws: Enable...

(UNLIKELY_OPENING_PUNCTUATION)

🪛 YAMLlint (1.37.1)
.github/dependabot.yml

[error] 33-33: no new line character at the end of file

(new-line-at-end-of-file)

.github/workflows/dependencies.yml

[error] 61-61: no new line character at the end of file

(new-line-at-end-of-file)

.github/workflows/lint-actions.yml

[error] 19-19: no new line character at the end of file

(new-line-at-end-of-file)

.github/workflows/docker.yml

[error] 40-40: no new line character at the end of file

(new-line-at-end-of-file)

.github/workflows/integration.yml

[error] 52-52: no new line character at the end of file

(new-line-at-end-of-file)

.github/workflows/release.yml

[error] 76-76: trailing spaces

(trailing-spaces)


[error] 92-92: no new line character at the end of file

(new-line-at-end-of-file)

🔇 Additional comments (22)
clippy.toml (1)

1-1: Strict wildcard import linting enabled
Enabling warn-on-all-wildcard-imports enforces explicit imports across the workspace, which is aligned with the new lint workflow.

.github/CODEOWNERS (1)

4-4: Assigns @rollkit/binary-builders as repo owners
The pattern * @rollkit/binary-builders covers all files, ensuring PRs are routed to the right review team.

rustfmt.toml (1)

2-5: Consistent formatting rules applied
The Rust 2021 edition, import reordering, crate-level granularity, and doc comment formatting ensure a uniform code style.

LICENSE-MIT (1)

1-21: MIT license file added
The full MIT license text is correctly included, establishing one half of the dual-license scheme.

deny.toml (1)

1-29: Cargo-deny policy configuration is sound
The license allowlist, advisory rules, and source checks are well scoped to enforce supply-chain security.

.github/dependabot.yml (1)

10-11: Ensure reviewer team slugs are fully qualified.
Dependabot requires team slugs in the form org/team-slug. Confirm that "lumen-maintainers" and "lumen-devops-team" include the proper organization prefix or are valid GitHub usernames.

Also applies to: 26-27

LICENSE-APACHE (1)

1-176: Apache License text is correctly included.
The full Apache 2.0 license has been added to govern contributions and distribution.

crates/common/src/lib.rs (1)

1-5: Module structure looks good.
The common crate cleanly exposes its constants module via a public re-export.

crates/rollkit/src/lib.rs (1)

1-11: Rollkit crate entrypoint is well-defined.
Public API types are clearly re-exported and the crate documentation accurately describes its purpose.

Dockerfile.cross (1)

1-16: Approved: Cross-platform Dockerfile setup is sound

The Dockerfile correctly handles multi‐arch copying of the prebuilt binary, exposes all necessary ports, and sets the entrypoint appropriately.

.github/assets/Dockerfile (1)

1-23: Approved: CI-specific Dockerfile for E2E tests

The Dockerfile correctly creates a non-root user, sets permissions, and exposes the necessary ports for end-to-end testing.

Dockerfile (1)

3-32: Approved: Multi-stage build Dockerfile

The build and runtime stages follow best practices, dependencies are installed cleanly, and exposed ports align with the application requirements.

etc/lumen-genesis.json (1)

2-19: Genesis config looks correct
Enabling all hard forks from block 0 aligns with the intended Lumen network setup.

.github/workflows/lint-actions.yml (1)

13-16: Verify download-actionlint.bash sets an output
Ensure the script publishes an executable output (via ::set-output) so ${{ steps.get_actionlint.outputs.executable }} is defined.

crates/node/src/lib.rs (1)

1-7: Confirm presence of RPC module
The crate-level docs mention “RPC interfaces,” but no rpc module is exported here. Please verify if RPC definitions exist or update the documentation.

crates/rollkit/Cargo.toml (1)

29-30: Verify [lints] section validity
Cargo doesn’t natively recognize [lints]; ensure your tooling (e.g., cargo-deny) picks this up.

crates/common/src/constants.rs (1)

1-14: Constants look good and are clearly documented
These default values are appropriate for shared use across the workspace.

.github/workflows/e2e.yml (1)

36-44: Enable or remove the commented E2E test step
The workflow scaffolds the E2E test command but leaves it commented out. Confirm whether this is intentional; if not, uncomment and validate the test invocation.

.gitignore (1)

1-60: Comprehensive .gitignore setup looks excellent.

The .gitignore file provides thorough coverage of build artifacts, sensitive files, and development artifacts. The organization with clear section comments makes it easy to maintain.

crates/node/src/config.rs (1)

1-53: LGTM! Well-structured configuration implementation.

The configuration struct follows Rust best practices with const constructors, comprehensive validation, and proper error handling using thiserror. The default values are sensible for a payload builder (1000 max transactions, 1 Gwei min gas price).

.github/workflows/lint.yml (1)

62-62: Verify the MSRV version is correct.

Rust 1.86 appears to be a very recent version for an MSRV (Minimum Supported Rust Version). Most projects use older versions like 1.70-1.75 for broader compatibility. Please verify this is intentional and not a typo.

What is the release date of Rust 1.86 and is it appropriate for an MSRV?
bin/lumen/Cargo.toml (1)

1-70: LGTM! Well-organized binary crate manifest.

The dependencies are logically grouped, workspace inheritance is used appropriately, and the feature flags provide good flexibility for different build configurations and performance optimizations.

# Docker configuration
GIT_TAG ?= $(shell git describe --tags --abbrev=0 || echo "latest")
BIN_DIR = dist/bin
DOCKER_IMAGE_NAME ?= ghcr.io/$(shell git config --get remote.origin.url | sed 's/.*github.com[:/]\(.*\)\.git/\1/' | cut -d'/' -f1)/lumen
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Make Docker image name extraction more robust

The current sed command for extracting the repository name from the git URL is fragile and may fail with non-standard URLs (e.g., SSH with custom ports, URLs without .git suffix).

Consider a more robust approach:

-DOCKER_IMAGE_NAME ?= ghcr.io/$(shell git config --get remote.origin.url | sed 's/.*github.com[:/]\(.*\)\.git/\1/' | cut -d'/' -f1)/lumen
+DOCKER_IMAGE_NAME ?= ghcr.io/$(shell git config --get remote.origin.url | sed -E 's|.*github\.com[:/]([^/]+)/.*|\1|' | grep -E '^[a-zA-Z0-9_-]+$$' || echo "rollkit")/lumen

Or provide a simpler default:

-DOCKER_IMAGE_NAME ?= ghcr.io/$(shell git config --get remote.origin.url | sed 's/.*github.com[:/]\(.*\)\.git/\1/' | cut -d'/' -f1)/lumen
+DOCKER_IMAGE_NAME ?= ghcr.io/rollkit/lumen
🤖 Prompt for AI Agents
In the Makefile at line 117, the current sed command used to extract the Docker
image name from the git remote URL is fragile and can fail with non-standard
URLs. To fix this, simplify the extraction by using a more robust shell command
or fallback to a simpler default image name if extraction fails. For example,
parse the URL more reliably by handling different URL formats or set a static
default value to ensure the variable is always valid.

GasLimitExceeded,
#[error("Rollkit payload attributes error: {0}")]
PayloadAttributes(#[from] PayloadAttributesError),
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use consistent logging throughout the codebase

The code mixes eprintln! with the tracing framework's info! macro. Use the tracing framework consistently.

Replace eprintln! with appropriate tracing macros:

-        eprintln!(
-            "Rollkit payload builder: executing {} transactions",
-            attributes.transactions.len()
-        );
+        info!(
+            transaction_count = attributes.transactions.len(),
+            "Rollkit payload builder: executing transactions"
+        );
-                    eprintln!("Transaction {i} executed successfully, gas used: {gas_used}");
+                    info!(index = i, gas_used, "Transaction executed successfully");
-                    eprintln!("Transaction {i} execution failed: {err:?}");
+                    warn!(index = i, error = ?err, "Transaction execution failed");
-        eprintln!("Error: {err:?}");
+        error!("Failed to run node: {err:?}");

Also applies to: 115-115, 119-119, 636-636

🤖 Prompt for AI Agents
In bin/lumen/src/main.rs at lines 91, 115, 119, and 636, replace all instances
of eprintln! with the appropriate tracing macros such as info!, warn!, or error!
to maintain consistent logging using the tracing framework throughout the
codebase. Identify the log level based on the message context and update the
code accordingly.

Copy link
Member

@Manav-Aggarwal Manav-Aggarwal left a comment

Choose a reason for hiding this comment

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

LGTM. Maybe we can add the unit/integration tests from Manav-Aggarwal/reth#1 in a follow up?

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: 3

🧹 Nitpick comments (4)
crates/tests/src/payload_builder_tests.rs (2)

54-56: Consider making timeout duration configurable

The hard-coded 30-second timeout could cause flaky tests in slower environments (CI, resource-constrained systems).

Consider making the timeout configurable via an environment variable:

-let result = timeout(
-    Duration::from_secs(30),
-    fixture.builder.build_payload(payload_attrs)
-).await;
+let timeout_secs = std::env::var("PAYLOAD_BUILD_TIMEOUT_SECS")
+    .unwrap_or_else(|_| "30".to_string())
+    .parse()
+    .unwrap_or(30);
+let result = timeout(
+    Duration::from_secs(timeout_secs),
+    fixture.builder.build_payload(payload_attrs)
+).await;

200-201: Make performance assertion timeout configurable

Similar to the operation timeout, the performance assertion threshold should be configurable.

-assert!(duration < Duration::from_secs(30), 
-    "Payload building should complete within 30 seconds");
+let perf_threshold_secs = std::env::var("PAYLOAD_PERF_THRESHOLD_SECS")
+    .unwrap_or_else(|_| "30".to_string())
+    .parse()
+    .unwrap_or(30);
+assert!(duration < Duration::from_secs(perf_threshold_secs), 
+    "Payload building should complete within {} seconds", perf_threshold_secs);
crates/tests/src/engine_api_tests.rs (1)

9-9: Remove unused import

The Arc import is not used in this file.

-use std::sync::Arc;
crates/tests/src/test_rollkit_engine_api.rs (1)

246-246: Consider increasing the gas limit for better safety margin.

The gas limit of 50,000 for 2 transactions provides minimal buffer (only ~4,000 gas per transaction above the standard 21,000).

-        gas_limit: Some(50_000), // Enough for both transactions
+        gas_limit: Some(100_000), // Sufficient buffer for both transactions
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0c817f3 and 078325d.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • Cargo.toml (1 hunks)
  • crates/rollkit/Cargo.toml (1 hunks)
  • crates/rollkit/src/lib.rs (1 hunks)
  • crates/rollkit/src/tests.rs (1 hunks)
  • crates/tests/Cargo.toml (1 hunks)
  • crates/tests/src/common.rs (1 hunks)
  • crates/tests/src/engine_api_tests.rs (1 hunks)
  • crates/tests/src/integration_tests.rs (1 hunks)
  • crates/tests/src/lib.rs (1 hunks)
  • crates/tests/src/payload_builder_tests.rs (1 hunks)
  • crates/tests/src/test_rollkit_engine_api.rs (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • crates/tests/src/lib.rs
  • crates/tests/Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (3)
  • crates/rollkit/src/lib.rs
  • crates/rollkit/Cargo.toml
  • Cargo.toml
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: e2e
  • GitHub Check: clippy
  • GitHub Check: docs
  • GitHub Check: clippy
🔇 Additional comments (7)
crates/rollkit/src/tests.rs (1)

1-257: Comprehensive test coverage for RollkitPayloadAttributes

The test suite provides excellent coverage including:

  • Basic functionality and field assignment
  • Validation logic with various gas limit scenarios
  • Serialization/deserialization integrity
  • Error type coverage
  • Edge cases with boundary values

Well-structured and thorough testing approach.

crates/tests/src/integration_tests.rs (1)

1-172: Well-designed integration test suite

The integration tests are well-structured with:

  • Proper error handling for missing dependencies
  • Flexible assertions that won't break with minor CLI changes
  • Non-critical treatment of documentation generation failures
  • Good coverage of binary, library, and workspace integration
crates/tests/src/engine_api_tests.rs (1)

16-303: Comprehensive Engine API test coverage

The test suite excellently mirrors the Go test implementation with:

  • Build chain phase testing blocks 1-10 with edge cases
  • Sync chain phase simulating fresh node synchronization
  • Error handling for invalid inputs and edge cases
  • Clear documentation of test flow and expectations
crates/tests/src/common.rs (2)

48-49: Clarify usage of temp_dir field

The temp_dir field is marked with #[allow(dead_code)] but is created in the constructor.

If the field is kept for automatic cleanup when the fixture is dropped, consider adding a comment explaining this. Otherwise, remove the field if it's truly unused.

-    /// Temporary directory for test data
-    #[allow(dead_code)]
-    pub temp_dir: TempDir,
+    /// Temporary directory for test data (kept for automatic cleanup on drop)
+    pub temp_dir: TempDir,

52-190: Well-designed test fixture with modern Ethereum support

The test utilities provide:

  • Proper Cancun hardfork configuration with EIP-4844/4788 fields
  • Mock provider setup with genesis state
  • Convenient helper functions for creating transactions and payload attributes
  • Proper test account setup with signature recovery

Excellent foundation for the test suite.

crates/tests/src/test_rollkit_engine_api.rs (2)

360-360: Well-designed assertion for dual-mode testing.

The assertion that at least one test should pass is appropriate for the dual-mode testing approach, ensuring the test suite doesn't fail entirely when no real node is available.


209-217: Excellent error handling with clear visual feedback.

The distinction between expected failures (unknown hash) and actual errors provides good debugging information, and the use of visual indicators (✓, ⚠) improves test output readability.

.post(&self.rpc_url)
.header("Content-Type", "application/json")
.json(&request)
.timeout(std::time::Duration::from_millis(500))
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Increase the timeout for node availability check.

The 500ms timeout might be too short and could cause false negatives in CI environments or under network latency.

-            .timeout(std::time::Duration::from_millis(500))
+            .timeout(std::time::Duration::from_secs(2))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.timeout(std::time::Duration::from_millis(500))
.timeout(std::time::Duration::from_secs(2))
🤖 Prompt for AI Agents
In crates/tests/src/test_rollkit_engine_api.rs at line 81, the timeout for the
node availability check is set to 500 milliseconds, which may be too short and
cause false negatives in CI or slow network conditions. Increase the timeout
duration to a higher value, such as 2000 milliseconds or more, to provide
sufficient time for the node to become available before timing out.

Comment on lines 122 to 166
/// Returns mock responses for testing without a real node
fn get_mock_response(&self, method: &str) -> Result<serde_json::Value> {
match method {
"engine_forkchoiceUpdatedV3" => {
Ok(json!({
"payloadStatus": {
"status": "VALID",
"latestValidHash": format!("0x{:064x}", rand::random::<u64>()),
"validationError": null
},
"payloadId": format!("0x{:016x}", rand::random::<u64>())
}))
}
"engine_getPayloadV3" => {
Ok(json!({
"executionPayload": {
"parentHash": format!("0x{:064x}", rand::random::<u64>()),
"feeRecipient": TEST_TO_ADDRESS,
"stateRoot": format!("0x{:064x}", rand::random::<u64>()),
"receiptsRoot": format!("0x{:064x}", rand::random::<u64>()),
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"prevRandao": format!("0x{:064x}", rand::random::<u64>()),
"blockNumber": "0x1",
"gasLimit": "0x1c9c380",
"gasUsed": "0xa410",
"timestamp": format!("0x{:x}", chrono::Utc::now().timestamp()),
"extraData": "0x",
"baseFeePerGas": "0x7",
"blockHash": format!("0x{:064x}", rand::random::<u64>()),
"transactions": [
"0xf86c808504a817c800825208941234567890123456789012345678901234567890880de0b6b3a764000080820a95a01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6ba01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b",
"0xf86c018504a817c800825208941234567890123456789012345678901234567890880de0b6b3a764000080820a96a01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6ba01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"
]
},
"blockValue": "0x0",
"blobsBundle": {
"commitments": [],
"proofs": [],
"blobs": []
}
}))
}
_ => Ok(json!({"result": "mock_response"}))
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add missing crate imports for rand and chrono.

The code uses rand::random() and chrono::Utc::now() without importing these crates, which will cause compilation errors.

Add these imports at the top of the file:

+use chrono::Utc;
+use rand::random;

Alternatively, if these crates are not already dependencies, you could use:

  • std::time::SystemTime::now() for timestamps
  • Generate deterministic values for mock data instead of random ones
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// Returns mock responses for testing without a real node
fn get_mock_response(&self, method: &str) -> Result<serde_json::Value> {
match method {
"engine_forkchoiceUpdatedV3" => {
Ok(json!({
"payloadStatus": {
"status": "VALID",
"latestValidHash": format!("0x{:064x}", rand::random::<u64>()),
"validationError": null
},
"payloadId": format!("0x{:016x}", rand::random::<u64>())
}))
}
"engine_getPayloadV3" => {
Ok(json!({
"executionPayload": {
"parentHash": format!("0x{:064x}", rand::random::<u64>()),
"feeRecipient": TEST_TO_ADDRESS,
"stateRoot": format!("0x{:064x}", rand::random::<u64>()),
"receiptsRoot": format!("0x{:064x}", rand::random::<u64>()),
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"prevRandao": format!("0x{:064x}", rand::random::<u64>()),
"blockNumber": "0x1",
"gasLimit": "0x1c9c380",
"gasUsed": "0xa410",
"timestamp": format!("0x{:x}", chrono::Utc::now().timestamp()),
"extraData": "0x",
"baseFeePerGas": "0x7",
"blockHash": format!("0x{:064x}", rand::random::<u64>()),
"transactions": [
"0xf86c808504a817c800825208941234567890123456789012345678901234567890880de0b6b3a764000080820a95a01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6ba01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b",
"0xf86c018504a817c800825208941234567890123456789012345678901234567890880de0b6b3a764000080820a96a01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6ba01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"
]
},
"blockValue": "0x0",
"blobsBundle": {
"commitments": [],
"proofs": [],
"blobs": []
}
}))
}
_ => Ok(json!({"result": "mock_response"}))
}
}
// At the top of `crates/tests/src/test_rollkit_engine_api.rs`, add the missing imports:
use chrono::Utc;
use rand::random;
🤖 Prompt for AI Agents
In crates/tests/src/test_rollkit_engine_api.rs around lines 122 to 166, the code
uses rand::random() and chrono::Utc::now() without importing the rand and chrono
crates, causing compilation errors. Fix this by adding the necessary use
statements for rand and chrono at the top of the file. If these crates are not
dependencies, replace chrono::Utc::now() with std::time::SystemTime::now() for
timestamps and substitute rand::random() calls with deterministic mock values.

Comment on lines 152 to 153
"0xf86c808504a817c800825208941234567890123456789012345678901234567890880de0b6b3a764000080820a95a01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6ba01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b",
"0xf86c018504a817c800825208941234567890123456789012345678901234567890880de0b6b3a764000080820a96a01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6ba01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace hardcoded transaction hex with properly encoded test transactions.

The hardcoded transaction hex strings may not be valid encoded transactions, which could cause decoding issues in tests.

Use the existing test transaction creation utilities:

-                        "transactions": [
-                            "0xf86c808504a817c800825208941234567890123456789012345678901234567890880de0b6b3a764000080820a95a01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6ba01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b",
-                            "0xf86c018504a817c800825208941234567890123456789012345678901234567890880de0b6b3a764000080820a96a01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6ba01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"
-                        ]
+                        "transactions": {
+                            let txs = create_test_transactions(2, 0);
+                            txs.iter().map(|tx| {
+                                format!("0x{}", encode_transaction(tx).unwrap().to_string())
+                            }).collect::<Vec<_>>()
+                        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"0xf86c808504a817c800825208941234567890123456789012345678901234567890880de0b6b3a764000080820a95a01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6ba01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b",
"0xf86c018504a817c800825208941234567890123456789012345678901234567890880de0b6b3a764000080820a96a01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6ba01b6b6d1c7b6f6b5a7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"
"transactions": {
let txs = create_test_transactions(2, 0);
txs.iter().map(|tx| {
format!("0x{}", encode_transaction(tx).unwrap().to_string())
}).collect::<Vec<_>>()
}
🤖 Prompt for AI Agents
In crates/tests/src/test_rollkit_engine_api.rs around lines 152 to 153, the
hardcoded transaction hex strings are likely invalid and may cause decoding
errors in tests. Replace these hardcoded hex strings with properly encoded test
transactions by using the existing test transaction creation utilities available
in the codebase to generate valid transaction data for the tests.

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

♻️ Duplicate comments (3)
Makefile (2)

40-42: Remove or implement the commented integration test target


117-117: Make Docker image name extraction more robust

bin/lumen/src/main.rs (1)

91-91: Use consistent logging throughout the codebase

The code uses eprintln! instead of the tracing framework.

🧹 Nitpick comments (4)
.github/workflows/e2e.yml (1)

44-45: Consider using a less verbose log level for E2E tests

Using RUST_LOG=debug might produce excessive output in CI logs. Consider using info level or selectively enabling debug logs for specific modules.

         env:
-          RUST_LOG: debug
+          RUST_LOG: info,lumen=debug
crates/tests/src/payload_builder_tests.rs (1)

59-62: Make timeout duration configurable for better test flexibility

The 30-second timeout is hardcoded. Consider making it configurable via environment variable for different CI environments.

+        const DEFAULT_TIMEOUT_SECS: u64 = 30;
+        let timeout_secs = std::env::var("E2E_TIMEOUT_SECS")
+            .ok()
+            .and_then(|s| s.parse().ok())
+            .unwrap_or(DEFAULT_TIMEOUT_SECS);
+
         let result = timeout(
-            Duration::from_secs(30),
+            Duration::from_secs(timeout_secs),
             fixture.builder.build_payload(payload_attrs),
         )
         .await;
Makefile (1)

81-82: Ensure cargo-audit is installed before running audit target

The audit target uses cargo audit which is not installed by default. Consider checking if it's installed or document the prerequisite.

 ## audit: Audit dependencies for security vulnerabilities
 audit:
+	@command -v cargo-audit >/dev/null 2>&1 || { echo "Installing cargo-audit..."; cargo install cargo-audit; }
 	$(CARGO) audit
bin/lumen/src/main.rs (1)

568-568: ```shell
#!/bin/bash

List all payload_id() invocations with proper escaping

echo "Listing all payload_id() calls..."
rg --color=never -n "payload_id\(\)" --glob "*.rs"

Locate EthBuiltPayload struct definition

echo -e "\nFinding EthBuiltPayload struct definition..."
rg --color=never -n "struct EthBuiltPayload" --glob "*.rs"

Locate EthBuiltPayload::new signature

echo -e "\nFinding EthBuiltPayload::new signature..."
rg --color=never -n "fn new" --glob "*.rs" | grep "EthBuiltPayload"


</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

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


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 078325dfcba78b0746fbe91a740f16a2cb217fed and 845f565798b7c13a5e8b013b5868447ab28198bc.

</details>

<details>
<summary>📒 Files selected for processing (10)</summary>

* `.github/workflows/e2e.yml` (1 hunks)
* `Makefile` (1 hunks)
* `bin/lumen/src/main.rs` (1 hunks)
* `crates/node/src/builder.rs` (1 hunks)
* `crates/node/src/lib.rs` (1 hunks)
* `crates/tests/src/engine_api_tests.rs` (1 hunks)
* `crates/tests/src/integration_tests.rs` (1 hunks)
* `crates/tests/src/lib.rs` (1 hunks)
* `crates/tests/src/payload_builder_tests.rs` (1 hunks)
* `crates/tests/src/test_rollkit_engine_api.rs` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (6)</summary>

* crates/tests/src/lib.rs
* crates/node/src/lib.rs
* crates/tests/src/integration_tests.rs
* crates/node/src/builder.rs
* crates/tests/src/engine_api_tests.rs
* crates/tests/src/test_rollkit_engine_api.rs

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (3)</summary>

* GitHub Check: e2e
* GitHub Check: test
* GitHub Check: test

</details>

<details>
<summary>🔇 Additional comments (4)</summary><blockquote>

<details>
<summary>.github/workflows/e2e.yml (1)</summary>

`30-31`: ```shell
#!/bin/bash
# Search entire repo for any Foundry tool usage
echo "Searching for Foundry tool commands anywhere in the repository..."
rg -i "(forge|cast|anvil|chisel)"

# Specifically check GitHub workflows for Foundry-related steps
echo -e "\nSearching .github/workflows for Foundry, forge or anvil references..."
rg -i "(foundry|forge|anvil)" .github/workflows
bin/lumen/src/main.rs (3)

502-504: Good use of tokio::task::block_in_place for async execution

The implementation correctly uses block_in_place with the current runtime handle instead of creating a new runtime. This is much more efficient than spawning a new runtime for each payload build.


561-563: Good use of tokio::task::block_in_place for async execution

Consistent with the previous usage, this correctly handles async execution in a blocking context.


319-325: Consider implementing proper payload attributes validation

The validate_payload_attributes_against_header method is empty and returns Ok(()) unconditionally. While the comment mentions skipping timestamp validation for Rollkit, other validations might still be necessary.

#!/bin/bash
# Description: Check what validations are performed in the standard implementation

# Search for the standard implementation of validate_payload_attributes_against_header
echo "Searching for standard payload validation implementation..."
ast-grep --pattern 'fn validate_payload_attributes_against_header' -A 10

# Check what validations might be important
echo -e "\nSearching for validation patterns in similar validators..."
rg "validate.*attributes.*header" -A 5

Comment on lines 157 to 179
let large_tx_count = 1000;
let transactions = create_test_transactions(large_tx_count, 0);
let payload_attrs = fixture.create_payload_attributes(
transactions,
1,
TEST_TIMESTAMP,
fixture.genesis_hash,
Some(TEST_GAS_LIMIT),
);

let result = fixture.builder.build_payload(payload_attrs).await;
match result {
Ok(sealed_block) => {
println!(
"✓ Large transaction batch handled: {} transactions, gas_used={}",
large_tx_count, sealed_block.gas_used
);
}
Err(e) => {
println!("✓ Large transaction batch rejected appropriately: {}", e);
}
}

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add specific assertions for large transaction batch handling

The test for large transaction batches (1000 transactions) only prints the result without asserting specific behavior. Consider adding assertions to verify expected outcomes.

     let result = fixture.builder.build_payload(payload_attrs).await;
     match result {
         Ok(sealed_block) => {
             println!(
                 "✓ Large transaction batch handled: {} transactions, gas_used={}",
                 large_tx_count, sealed_block.gas_used
             );
+            // Assert that not all transactions were included if gas limit was exceeded
+            assert!(
+                sealed_block.transaction_count() <= large_tx_count,
+                "Transaction count should not exceed requested amount"
+            );
+            assert!(
+                sealed_block.gas_used <= TEST_GAS_LIMIT,
+                "Gas used should not exceed gas limit"
+            );
         }
         Err(e) => {
             println!("✓ Large transaction batch rejected appropriately: {}", e);
+            // If rejected, ensure it's due to a valid reason
+            assert!(
+                e.to_string().contains("gas") || e.to_string().contains("limit"),
+                "Error should be related to gas or transaction limits"
+            );
         }
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let large_tx_count = 1000;
let transactions = create_test_transactions(large_tx_count, 0);
let payload_attrs = fixture.create_payload_attributes(
transactions,
1,
TEST_TIMESTAMP,
fixture.genesis_hash,
Some(TEST_GAS_LIMIT),
);
let result = fixture.builder.build_payload(payload_attrs).await;
match result {
Ok(sealed_block) => {
println!(
"✓ Large transaction batch handled: {} transactions, gas_used={}",
large_tx_count, sealed_block.gas_used
);
}
Err(e) => {
println!("✓ Large transaction batch rejected appropriately: {}", e);
}
}
let result = fixture.builder.build_payload(payload_attrs).await;
match result {
Ok(sealed_block) => {
println!(
"✓ Large transaction batch handled: {} transactions, gas_used={}",
large_tx_count, sealed_block.gas_used
);
// Assert that the number of included transactions does not exceed the requested amount
assert!(
sealed_block.transaction_count() <= large_tx_count,
"Transaction count should not exceed requested amount"
);
// Assert that gas used stays within the configured limit
assert!(
sealed_block.gas_used <= TEST_GAS_LIMIT,
"Gas used should not exceed gas limit"
);
}
Err(e) => {
println!("✓ Large transaction batch rejected appropriately: {}", e);
// If rejected, ensure it's due to gas or transaction limits
assert!(
e.to_string().contains("gas") || e.to_string().contains("limit"),
"Error should be related to gas or transaction limits"
);
}
}
🤖 Prompt for AI Agents
In crates/tests/src/payload_builder_tests.rs around lines 157 to 179, the test
for handling a large batch of 1000 transactions currently only prints success or
error messages without verifying expected behavior. Add assertions after
building the payload to explicitly check conditions such as whether the payload
was successfully created or rejected as expected, and validate key properties
like gas_used or error types to ensure the test verifies correct handling of
large transaction batches.

@tac0turtle tac0turtle enabled auto-merge (squash) June 24, 2025 08:55
@tac0turtle tac0turtle merged commit 019fb82 into main Jun 24, 2025
15 checks passed
@tac0turtle tac0turtle deleted the marko/layout branch June 24, 2025 09:01
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.

3 participants