Skip to content

feat: implement custom consensus for Rollkit to allow same timestamps#19

Merged
tac0turtle merged 7 commits intomainfrom
marko/timestamp
Jul 17, 2025
Merged

feat: implement custom consensus for Rollkit to allow same timestamps#19
tac0turtle merged 7 commits intomainfrom
marko/timestamp

Conversation

@tac0turtle
Copy link
Contributor

@tac0turtle tac0turtle commented Jul 17, 2025

This implements a custom consensus wrapper that allows multiple blocks to have the same timestamp, which is required for Rollkit's operation.

The key changes:

  • Add RollkitConsensus that wraps EthBeaconConsensus
  • Override validate_header_against_parent to allow header.timestamp >= parent.timestamp
  • Integrate with node builder using RollkitConsensusBuilder
  • Add comprehensive unit tests for timestamp validation

This addresses issue #15 where Rollkit needs to submit multiple blocks with the same timestamp.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Introduced a custom consensus mechanism (RollkitConsensus) that allows blocks with identical timestamps, diverging from standard Ethereum rules.
    • Added RollkitConsensusBuilder for easy integration and configuration of the custom consensus.
  • Documentation

    • Updated crate documentation to highlight the new custom consensus feature.
  • Tests

    • Added comprehensive unit tests to verify the new consensus logic, including timestamp, parent hash, and block number validation.
  • Chores

    • Updated dependency lists to include new consensus and Ethereum-related crates for enhanced functionality and integration.
    • Replaced EthereumConsensusBuilder with RollkitConsensusBuilder in the node setup for improved consensus handling.

This implements a custom consensus wrapper that allows multiple blocks
to have the same timestamp, which is required for Rollkit's operation.

The key changes:
- Add RollkitConsensus that wraps EthBeaconConsensus
- Override validate_header_against_parent to allow header.timestamp >= parent.timestamp
- Integrate with node builder using RollkitConsensusBuilder
- Add comprehensive unit tests for timestamp validation

This addresses issue #15 where Rollkit needs to submit multiple blocks
with the same timestamp.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Jul 17, 2025

Walkthrough

A custom consensus mechanism, RollkitConsensus, was introduced to allow blocks with identical timestamps, diverging from standard Ethereum consensus rules. The Lumen node and Rollkit crate were updated to use this new consensus logic, with supporting dependencies and tests added. Public exports and documentation were updated accordingly.

Changes

File(s) Change Summary
Cargo.toml, crates/rollkit/Cargo.toml Added consensus-related dependencies and reorganized dependency sections.
bin/lumen/Cargo.toml Added new workspace dependencies for consensus and Ethereum primitives.
bin/lumen/src/main.rs Replaced EthereumConsensusBuilder with RollkitConsensusBuilder in node initialization logic.
crates/rollkit/src/consensus.rs Introduced RollkitConsensus and RollkitConsensusBuilder with custom timestamp validation.
crates/rollkit/src/lib.rs Added and publicly re-exported the new consensus module and its types.
crates/rollkit/tests/consensus_tests.rs Added unit tests for RollkitConsensus header validation logic.

Sequence Diagram(s)

sequenceDiagram
    participant Node
    participant RollkitConsensusBuilder
    participant RollkitConsensus
    participant EthBeaconConsensus

    Node->>RollkitConsensusBuilder: build_consensus()
    RollkitConsensusBuilder->>RollkitConsensus: new(chain_spec)
    RollkitConsensus->>EthBeaconConsensus: delegate validation (except timestamp)
    RollkitConsensus->>RollkitConsensus: custom timestamp validation
    RollkitConsensus-->>Node: consensus instance with custom logic
Loading

Suggested reviewers

  • Manav-Aggarwal

Poem

In fields of code where consensus blooms,
A rabbit hops and Rollkit resumes.
Timestamps may match, but errors don't scare—
With custom logic, we handle with care.
Dependencies gathered, tests in the sun,
Consensus for Rollkit, a job well done!
🐇✨


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between bf44805 and d530ccc.

📒 Files selected for processing (1)
  • crates/rollkit/src/consensus.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/rollkit/src/consensus.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: test
  • GitHub Check: e2e
✨ 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 a specialized consensus mechanism tailored for Rollkit, enabling the creation of blocks with identical timestamps to their predecessors. This change is crucial for Rollkit's architecture, ensuring compatibility and proper block validation within its unique operational context. The implementation involves wrapping the existing Ethereum consensus and selectively modifying timestamp validation rules, along with integrating this custom logic into the node's build process.

Highlights

  • Custom Consensus Implementation: Introduced RollkitConsensus, a new consensus wrapper around EthBeaconConsensus, specifically designed to meet Rollkit's operational requirements.
  • Timestamp Validation Modification: Overrode the validate_header_against_parent method within RollkitConsensus to allow blocks to have a timestamp equal to or greater than their parent block's timestamp (header.timestamp >= parent.timestamp). This is a key deviation from standard Ethereum consensus, which requires header.timestamp > parent.timestamp.
  • Node Integration: Integrated the new custom consensus into the lumen node by introducing RollkitConsensusBuilder and configuring the node to use this builder instead of the default Ethereum consensus builder.
  • Comprehensive Unit Tests: Added a new test suite (consensus_tests.rs) to thoroughly validate the RollkitConsensus implementation, specifically confirming that same timestamps are allowed while other critical consensus rules (like parent hash and block number validation) are still enforced.
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

This pull request introduces a custom consensus engine for Rollkit to allow blocks with identical timestamps. I've identified a critical issue in the consensus validation logic that bypasses important checks when timestamps are equal, and provided a suggestion for a more robust implementation. Additionally, I've pointed out some redundant code and suggested improvements to the test suite.

Comment on lines +37 to +85
fn validate_header_against_parent(
&self,
header: &SealedHeader,
parent: &SealedHeader,
) -> Result<(), ConsensusError> {
// Custom validation that allows same timestamps
// This is the key difference from standard Ethereum consensus

// First validate parent hash and number
if header.parent_hash != parent.hash() {
return Err(ConsensusError::ParentHashMismatch(GotExpectedBoxed(
Box::new(GotExpected {
got: header.parent_hash,
expected: parent.hash(),
}),
)));
}

if header.number != parent.number + 1 {
return Err(ConsensusError::ParentBlockNumberMismatch {
parent_block_number: parent.number,
block_number: header.number,
});
}

// ROLLKIT MODIFICATION: Allow same timestamp
// Standard Ethereum requires: header.timestamp > parent.timestamp
// Rollkit allows: header.timestamp >= parent.timestamp
if header.timestamp < parent.timestamp {
return Err(ConsensusError::TimestampIsInPast {
parent_timestamp: parent.timestamp,
timestamp: header.timestamp,
});
}
// NOTE: We explicitly do NOT check for header.timestamp == parent.timestamp
// as an error, which is the main change for Rollkit

// For all other validations, delegate to the inner consensus
// but skip it when timestamps are equal since the inner consensus
// would reject this case
if header.timestamp == parent.timestamp {
// Timestamps are equal, which we explicitly allow for Rollkit
// Skip the inner consensus validation that would reject this
Ok(())
} else {
// Timestamps are different, so we can safely delegate to inner consensus
self.inner.validate_header_against_parent(header, parent)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

The current implementation of validate_header_against_parent returns Ok(()) without performing other essential header validations when header.timestamp == parent.timestamp. This would allow invalid blocks to be accepted by the consensus. The logic should be refactored to ensure all validations are performed, only altering the timestamp check.

    fn validate_header_against_parent(
        &self,
        header: &SealedHeader,
        parent: &SealedHeader,
    ) -> Result<(), ConsensusError> {
        match self.inner.validate_header_against_parent(header, parent) {
            Ok(()) => Ok(()),
            Err(ConsensusError::TimestampNotStrictlyIncreasing { .. }) => {
                if header.timestamp == parent.timestamp {
                    Ok(())
                } else {
                    Err(ConsensusError::TimestampIsInPast {
                        parent_timestamp: parent.timestamp,
                        timestamp: header.timestamp,
                    })
                }
            }
            Err(e) => Err(e),
        }
    }

@tac0turtle tac0turtle marked this pull request as ready for review July 17, 2025 13:28
@tac0turtle tac0turtle requested a review from a team as a code owner July 17, 2025 13:28
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.

Small comment

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

@tac0turtle tac0turtle enabled auto-merge (squash) July 17, 2025 14:10
@tac0turtle tac0turtle merged commit 50b7853 into main Jul 17, 2025
15 checks passed
@tac0turtle tac0turtle deleted the marko/timestamp branch July 17, 2025 14:14
github-merge-queue bot pushed a commit to evstack/ev-node that referenced this pull request Jul 17, 2025
<!--
Please read and fill out this form before submitting your PR.

Please make sure you have reviewed our contributors guide before
submitting your
first PR.

NOTE: PR titles should follow semantic commits:
https://www.conventionalcommits.org/en/v1.0.0/
-->

## Overview

This pr removes the +1 timestamp in order to avoid clock drift between
lumen and rollkit.

closes #2464 

based off of work from evstack/ev-reth#19

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Refactor**
* Simplified block timestamp handling to use the current block's
timestamp directly, removing previous logic that enforced strictly
increasing timestamps between blocks.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: tac0turtle <you@example.com>
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