Skip to content

fix(consensus): mark future timestamps as transient#133

Open
panos-xyz wants to merge 2 commits into
mainfrom
codex/fix-transient-future-timestamp
Open

fix(consensus): mark future timestamps as transient#133
panos-xyz wants to merge 2 commits into
mainfrom
codex/fix-transient-future-timestamp

Conversation

@panos-xyz

@panos-xyz panos-xyz commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Mark ConsensusError::TimestampIsInFuture as transient in MorphConsensus so reth can retry briefly future-dated payloads instead of caching them as invalid.
  • Add a regression test covering the transient classification.

Root Cause

Morph header validation correctly rejects headers whose timestamp is ahead of the local clock, but MorphConsensus did not override is_transient_error. With reth v2.2.0, that caused short clock-skew rejections to enter the invalid header cache, so later payloads linked to the same block kept failing as descendants of a previously rejected block.

Impact

A block that is only ahead of the local clock can now be retried once local time catches up. Other consensus errors keep the default non-transient behavior.

Test Plan

  • cargo fmt --all -- --check
  • cargo test -p morph-consensus
  • cargo clippy -p morph-consensus --all-targets -- -D warnings
  • cargo clippy --all --all-targets -- -D warnings
  • cargo test --doc --all --verbose

Summary by CodeRabbit

  • Refactor

    • Improved error classification in consensus validation to distinguish transient errors from permanent failures
    • Simplified error handling in Engine RPC methods for more consistent error propagation
  • Tests

    • Added validation for transient error classification

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds is_transient_error to MorphConsensus, classifying ConsensusError::TimestampIsInFuture as transient, with a unit test. Separately, seven Engine RPC methods in crates/engine-api/src/rpc.rs replace tracing::error!-logged error closures with direct map_err(|e| e.into()).

Changes

MorphConsensus transient error classification

Layer / File(s) Summary
is_transient_error impl and test
crates/consensus/src/validation.rs
Implements fn is_transient_error returning true only for ConsensusError::TimestampIsInFuture { .. }, and adds test_timestamp_in_future_is_transient_error asserting that result.

Engine RPC error mapping cleanup

Layer / File(s) Summary
Remove tracing::error! from RPC methods
crates/engine-api/src/rpc.rs
assemble_l2_block, assemble_l2_block_v2, validate_l2_block, new_l2_block, new_l2_block_v2, new_safe_l2_block, and set_block_tags replace logged error closures with map_err(|e| e.into()).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop, hop — a timestamp too far ahead,
Now marked as transient, no panic, no dread.
Seven methods shed their noisy log calls,
Just .into() echoes through the halls.
Less clutter, more signal — the rabbit approves,
Clean errors glide on with effortless moves!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly describes the main change: marking future timestamp errors as transient in the consensus module, which aligns with the primary objective of the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-transient-future-timestamp

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@panos-xyz panos-xyz force-pushed the codex/fix-transient-future-timestamp branch from 68c1e4c to cc0c65d Compare June 16, 2026 01:31
@panos-xyz panos-xyz marked this pull request as ready for review June 16, 2026 01:51

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (2)
crates/consensus/src/validation.rs (1)

1138-1148: ⚡ Quick win

Consider adding test coverage for non-transient errors.

The test correctly verifies that TimestampIsInFuture is transient. To ensure the implementation doesn't accidentally mark other errors as transient, consider adding a test case that verifies at least one other ConsensusError variant returns false.

✅ Example test for non-transient error
     assert!(Consensus::<Block>::is_transient_error(&consensus, &error));
 }
 
+#[test]
+fn test_other_consensus_errors_are_not_transient() {
+    let chain_spec = create_test_chainspec();
+    let consensus = MorphConsensus::new(chain_spec);
+    
+    // Test that a non-timestamp error is not transient
+    let error = ConsensusError::BaseFeeMissing;
+    assert!(!Consensus::<Block>::is_transient_error(&consensus, &error));
+}
+
 #[test]
 fn test_validate_header_gas_limit_exceeds_max() {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/consensus/src/validation.rs` around lines 1138 - 1148, Add a new test
function to complement the existing test_timestamp_in_future_is_transient_error
test. This new test should instantiate the MorphConsensus and the
is_transient_error method with a different ConsensusError variant (one that
should not be transient, such as an error related to invalid block or signature
validation) and assert that is_transient_error returns false. This will provide
coverage that the implementation correctly distinguishes between transient and
non-transient errors rather than potentially marking all errors as transient.
crates/engine-api/src/rpc.rs (1)

121-124: Consider structured error logging for RPC failures.

The removal of tracing::error! logging from these seven methods reduces error visibility in production environments where debug logs are typically disabled. While errors are still returned to RPC clients, operators lose server-side error signals for monitoring and alerting.

Consider one of these approaches:

  • Re-add error-level logging in the error path (e.g., tracing::error!(target: "morph::engine", error = %e, "RPC method failed") before .into())
  • Ensure your observability stack captures RPC error responses through other means (metrics, middleware, etc.)
  • Document the rationale if error logging was intentionally removed to reduce log volume

Also applies to: 141-141, 152-155, 166-166, 177-177, 187-190, 208-208

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/engine-api/src/rpc.rs` around lines 121 - 124, Re-add structured
error-level logging to all seven RPC methods in crates/engine-api/src/rpc.rs to
restore error visibility in production environments. For each affected method
(at lines 121-124, 141, 152-155, 166, 177, 187-190, and 208), add a
tracing::error! call in the error path before the .into() conversion. Use a
consistent log format such as tracing::error!(target: "morph::engine", error =
%e, "RPC method failed") to capture the actual error details along with method
context, enabling operators to monitor and alert on RPC failures through
server-side signals.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/consensus/src/validation.rs`:
- Around line 332-334: The is_transient_error method implementation is correct,
but the existing test only covers the positive case where TimestampIsInFuture is
transient. Add additional test cases to the test for is_transient_error that
verify negative scenarios, asserting that other ConsensusError variants such as
ExtraDataExceedsMax return false from is_transient_error. This ensures the
method correctly identifies which errors are transient and which are not.

---

Nitpick comments:
In `@crates/consensus/src/validation.rs`:
- Around line 1138-1148: Add a new test function to complement the existing
test_timestamp_in_future_is_transient_error test. This new test should
instantiate the MorphConsensus and the is_transient_error method with a
different ConsensusError variant (one that should not be transient, such as an
error related to invalid block or signature validation) and assert that
is_transient_error returns false. This will provide coverage that the
implementation correctly distinguishes between transient and non-transient
errors rather than potentially marking all errors as transient.

In `@crates/engine-api/src/rpc.rs`:
- Around line 121-124: Re-add structured error-level logging to all seven RPC
methods in crates/engine-api/src/rpc.rs to restore error visibility in
production environments. For each affected method (at lines 121-124, 141,
152-155, 166, 177, 187-190, and 208), add a tracing::error! call in the error
path before the .into() conversion. Use a consistent log format such as
tracing::error!(target: "morph::engine", error = %e, "RPC method failed") to
capture the actual error details along with method context, enabling operators
to monitor and alert on RPC failures through server-side signals.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a4687c14-f11e-41a2-9eae-27d90d47f4b8

📥 Commits

Reviewing files that changed from the base of the PR and between db1f388 and cc0c65d.

📒 Files selected for processing (2)
  • crates/consensus/src/validation.rs
  • crates/engine-api/src/rpc.rs

Comment on lines +332 to +334
fn is_transient_error(&self, error: &ConsensusError) -> bool {
matches!(error, ConsensusError::TimestampIsInFuture { .. })
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify matches! macro usage and check for syntax issues

# Check Rust version and toolchain
rustc --version || echo "rustc not available"

# Search for other uses of matches! in the codebase to see if it's used elsewhere
rg -n 'matches!\(' --type=rust -C2

# Check if there are any known issues with matches! in similar contexts
ast-grep --pattern $'impl Consensus<$_> for $_ {
  $$$
  fn is_transient_error(&$_, error: &ConsensusError) -> bool {
    $$$
  }
  $$$
}'

Repository: morph-l2/morph-reth

Length of output: 25311


🏁 Script executed:

# Check the test implementation at lines 1138-1148
sed -n '1138,1148p' crates/consensus/src/validation.rs

# Search for other tests or usages of is_transient_error
rg -n 'is_transient_error' crates/consensus/src/validation.rs

Repository: morph-l2/morph-reth

Length of output: 663


The matches! macro warning is a false positive; add a test for negative cases.

The implementation is correct—matches! is used successfully throughout the codebase including in this same file. However, the test only verifies that TimestampIsInFuture is transient. Add a test case asserting that other error variants (e.g., ConsensusError::ExtraDataExceedsMax) return false from is_transient_error.

🧰 Tools
🪛 GitHub Actions: PR `#133` / 0_Analyze (rust).txt

[warning] 333-333: Rustc warning: macro expansion failed for 'matches' (macro expansion failed)

🪛 GitHub Actions: PR `#133` / Analyze (rust)

[warning] 333-333: Rust warning: macro expansion failed for 'matches'.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/consensus/src/validation.rs` around lines 332 - 334, The
is_transient_error method implementation is correct, but the existing test only
covers the positive case where TimestampIsInFuture is transient. Add additional
test cases to the test for is_transient_error that verify negative scenarios,
asserting that other ConsensusError variants such as ExtraDataExceedsMax return
false from is_transient_error. This ensures the method correctly identifies
which errors are transient and which are not.

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.

1 participant