Skip to content

feat(l1): ethrex_replay add tooling for periodic replay runs #4108

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 117 commits into
base: main
Choose a base branch
from

Conversation

tomip01
Copy link
Contributor

@tomip01 tomip01 commented Aug 20, 2025

Motivation

We urge the need for a tool for internal usage that replays L1 blocks from public networks like Hoodi, Sepolia, and Mainnet periodically (either execution with or without SP1, or proving with SP1) to ensure ethrex-replay works correctly and also to find potential bugs in ethrex.

Description

Replayer script that executes or proves the latest public network blocks in a loop and notifies to a Slack channel through a slack web hook if the flag --slack-web-hook is passed.

Usage

Usage: ethrex-replayer [OPTIONS] <--hoodi-rpc-url <URL>|--sepolia-rpc-url <URL>|--mainnet-rpc-url <URL>>

Options:
  -h, --help  Print help

Replayer options:
      --slack-webhook-url <URL>  [env: SLACK_WEBHOOK_URL=]
      --hoodi-rpc-url <URL>      [env: HOODI_RPC_URL=]
      --sepolia-rpc-url <URL>    [env: SEPOLIA_RPC_URL=]
      --mainnet-rpc-url <URL>    [env: MAINNET_RPC_URL=]
      --execute                  Replayer will execute blocks
      --prove                    Replayer will prove blocks

How to test

To periodically execute the latest Hoodi blocks, run:

cargo run --release -p ethrex-replayer --bin ethrex-replayer -- --hoodi-rpc-url http://65.108.69.58:8545 --execute

ilitteri and others added 30 commits August 7, 2025 15:05
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@Copilot Copilot AI review requested due to automatic review settings August 20, 2025 21:22
@tomip01 tomip01 requested a review from a team as a code owner August 20, 2025 21:22
@tomip01 tomip01 assigned tomip01 and ilitteri and unassigned tomip01 Aug 20, 2025
@tomip01 tomip01 added L2 Rollup client L1 Ethereum client labels Aug 20, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR removes the redb database backend from the codebase and adds a new replayer tool for automated block execution/proving. The changes focus on streamlining the database architecture while introducing tooling for periodic replay runs across different networks.

  • Remove redb database support entirely, keeping only libmdbx as the database backend
  • Refactor execution witness data structures to use a simpler, more consistent format
  • Add a new replayer tool that can execute or prove latest blocks from public networks with Slack notifications

Reviewed Changes

Copilot reviewed 49 out of 51 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tooling/replayer/src/* New replayer tool for periodic block execution/proving with Slack integration
crates/storage/* Remove all redb backend code and dependencies
crates/common/types/block_execution_witness.rs Major refactoring of witness data structures
crates/common/config/* New config crate for network configurations
crates/networking/rpc/debug/* Move execution witness RPC code to separate module
Comments suppressed due to low confidence (1)

crates/common/types/block_execution_witness.rs:174

  • [nitpick] Using expect with a panic message in production code should be avoided. Consider using proper error handling and returning a Result type instead.
                            Trie::from_nodes(None, &[]).expect("failed to create empty trie")

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

let (result, _index, _remaining_handles) = select_all(revalidation_handles).await;
result
} => {
handle_rpc_revalidation_handle_result(res, opts.hoodi_rpc_url.unwrap(), opts.slack_webhook_url.clone()).await; // TODO: change hoodi rpc to generic
Copy link
Preview

Copilot AI Aug 20, 2025

Choose a reason for hiding this comment

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

This line will panic if hoodi_rpc_url is None. The code assumes it exists but this is not guaranteed. Consider using the actual failed RPC URL from the revalidation handle result instead.

Suggested change
handle_rpc_revalidation_handle_result(res, opts.hoodi_rpc_url.unwrap(), opts.slack_webhook_url.clone()).await; // TODO: change hoodi rpc to generic
let ((result, url), _index, _remaining_handles) = select_all(revalidation_handles).await;
(result, url)
} => {
let (res, url) = res;
handle_rpc_revalidation_handle_result(res, url, opts.slack_webhook_url.clone()).await;

Copilot uses AI. Check for mistakes.

)
.await
.unwrap_or_else(|e| {
tracing::error!("Failed to notify Slack about invalid Sepolia RPC: {e}");
Copy link
Preview

Copilot AI Aug 20, 2025

Choose a reason for hiding this comment

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

The error message hardcodes 'Sepolia RPC' but this function is called generically for any RPC URL. The error message should reflect the actual RPC URL that failed.

Suggested change
tracing::error!("Failed to notify Slack about invalid Sepolia RPC: {e}");
network: Network,
slack_webhook_url: Option<Url>,
) {
if let Err(e) = res {
tracing::error!("RPC URL `{}` for network `{}` failed: {}", rpc_url, network, e);
try_notify_no_longer_valid_rpc_to_slack(
rpc_url,
network,
slack_webhook_url,
)
.await
.unwrap_or_else(|e| {
tracing::error!("Failed to notify Slack about invalid RPC URL `{}` for network `{}`: {}", rpc_url, network, e);

Copilot uses AI. Check for mistakes.

let hours = total_seconds / 3600;
let minutes = (total_seconds % 3600) / 60;
let seconds = total_seconds % 60;
let milliseconds = total_seconds / 1000;
Copy link
Preview

Copilot AI Aug 20, 2025

Choose a reason for hiding this comment

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

This calculation is incorrect. It should be duration.subsec_millis() or (duration.as_millis() % 1000) to get the millisecond component. Currently it's dividing total seconds by 1000, which will always be 0 for durations less than 1000 seconds.

Suggested change
let milliseconds = total_seconds / 1000;
let milliseconds = duration.subsec_millis();

Copilot uses AI. Check for mistakes.

}
Err(e) => {
error!("{e}");
todo!("Retry with eth_getProofs")
Copy link
Preview

Copilot AI Aug 20, 2025

Choose a reason for hiding this comment

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

The todo! macro will panic at runtime. This should be replaced with proper error handling or a placeholder implementation that doesn't cause the program to crash.

Suggested change
todo!("Retry with eth_getProofs")
return Err(eyre::eyre!(
"Failed to retrieve witness for block {requested_block_number}: {e}. Retry with eth_getProofs not yet implemented."
));

Copilot uses AI. Check for mistakes.

.await?;
}
let elapsed = start.elapsed().unwrap_or_else(|e| {
panic!("SystemTime::elapsed failed: {e}");
Copy link
Preview

Copilot AI Aug 20, 2025

Choose a reason for hiding this comment

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

[nitpick] Using panic! inside unwrap_or_else defeats the purpose of graceful error handling. Consider logging the error and using a default duration instead of panicking.

Suggested change
panic!("SystemTime::elapsed failed: {e}");
tracing::error!("SystemTime::elapsed failed: {e}. Using default duration of 12 seconds.");
Duration::from_secs(12)

Copilot uses AI. Check for mistakes.

Copy link

github-actions bot commented Aug 20, 2025

Lines of code report

Total lines added: 714
Total lines removed: 7
Total lines changed: 721

Detailed view
+-------------------------------------------------------+-------+------+
| File                                                  | Lines | Diff |
+-------------------------------------------------------+-------+------+
| ethrex/cmd/ethrex_replay/src/cli.rs                   | 401   | -1   |
+-------------------------------------------------------+-------+------+
| ethrex/cmd/ethrex_replay/src/lib.rs                   | 6     | +6   |
+-------------------------------------------------------+-------+------+
| ethrex/cmd/ethrex_replay/src/main.rs                  | 26    | -6   |
+-------------------------------------------------------+-------+------+
| ethrex/tooling/replayer/src/block_execution_report.rs | 295   | +295 |
+-------------------------------------------------------+-------+------+
| ethrex/tooling/replayer/src/main.rs                   | 379   | +379 |
+-------------------------------------------------------+-------+------+
| ethrex/tooling/replayer/src/slack.rs                  | 34    | +34  |
+-------------------------------------------------------+-------+------+

@xqft xqft moved this to In Review in ethrex_l2 Aug 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
L1 Ethereum client L2 Rollup client
Projects
Status: No status
Status: In Review
Development

Successfully merging this pull request may close these issues.

3 participants