Skip to content

Conversation

@avilagaston9
Copy link
Contributor

@avilagaston9 avilagaston9 commented Dec 22, 2025

Motivation

To provide a quicker response to debug_executionWitness requests.

Description

This PR generates execution witnesses during payload execution and stores them for a period of time (128 blocks).

  • Adds the node flag generate-witness.
  • After successfully executing a payload received via the newPayload message, if the generate-witness flag is enabled, the node will generate and store the ExecutionWitness for that block.
  • Upon receiving a debug_executionWitness request, the node first checks if it has the witness in storage and only generates it as a fallback.

Measurements

execution_witness_measurements.md contains a comparative analysis of debug_executionWitness latency for pre-generated vs on-demand execution witnesses.

Checklist

  • Updated STORE_SCHEMA_VERSION (crates/storage/lib.rs) if the PR includes breaking changes to the Store requiring a re-sync.

@github-actions
Copy link

github-actions bot commented Dec 22, 2025

Lines of code report

Total lines added: 355
Total lines removed: 0
Total lines changed: 355

Detailed view
+---------------------------------------------------------+-------+------+
| File                                                    | Lines | Diff |
+---------------------------------------------------------+-------+------+
| ethrex/cmd/ethrex/cli.rs                                | 811   | +9   |
+---------------------------------------------------------+-------+------+
| ethrex/cmd/ethrex/initializers.rs                       | 495   | +1   |
+---------------------------------------------------------+-------+------+
| ethrex/cmd/ethrex/l2/initializers.rs                    | 347   | +1   |
+---------------------------------------------------------+-------+------+
| ethrex/crates/blockchain/blockchain.rs                  | 1813  | +231 |
+---------------------------------------------------------+-------+------+
| ethrex/crates/networking/rpc/debug/execution_witness.rs | 234   | +14  |
+---------------------------------------------------------+-------+------+
| ethrex/crates/storage/api/tables.rs                     | 23    | +2   |
+---------------------------------------------------------+-------+------+
| ethrex/crates/storage/store.rs                          | 2669  | +83  |
+---------------------------------------------------------+-------+------+
| ethrex/crates/vm/levm/src/db/gen_db.rs                  | 412   | +11  |
+---------------------------------------------------------+-------+------+
| ethrex/crates/vm/levm/src/hooks/l2_hook.rs              | 568   | +3   |
+---------------------------------------------------------+-------+------+

@avilagaston9 avilagaston9 marked this pull request as ready for review December 23, 2025 21:17
Copilot AI review requested due to automatic review settings December 23, 2025 21:17
@avilagaston9 avilagaston9 requested review from a team and ManuelBilbao as code owners December 23, 2025 21:17
@ethrex-project-sync ethrex-project-sync bot moved this to In Review in ethrex_l1 Dec 23, 2025
Copy link
Contributor

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 implements caching for execution witnesses to improve response times for debug_executionWitness requests. The implementation stores the last 128 execution witnesses in the database after successful block execution via the Engine API.

Key changes:

  • Adds a --generate-witness CLI flag to enable witness generation and caching
  • Stores execution witnesses after newPayload execution when the flag is enabled
  • Implements cache lookup in debug_executionWitness as a fast path before generating witnesses on-demand

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
docs/CLI.md Documents the new --generate-witness flag and fixes whitespace formatting
crates/storage/api/tables.rs Adds EXECUTION_WITNESSES table definition to store cached witnesses
crates/storage/store.rs Implements witness storage, retrieval, and cleanup logic with MAX_WITNESSES=128 limit
crates/networking/rpc/rpc.rs Adds generate_witness field to RpcApiContext to propagate the flag
crates/networking/rpc/engine/payload.rs Generates and stores witness after successful payload execution
crates/networking/rpc/debug/execution_witness.rs Checks cache before generating witness for single-block requests
crates/networking/rpc/test_utils.rs Adds generate_witness=false to test contexts
crates/l2/networking/rpc/rpc.rs Propagates generate_witness parameter in L2 RPC initialization
cmd/ethrex/l2/initializers.rs Passes generate_witness flag to L2 RPC API
cmd/ethrex/initializers.rs Passes generate_witness flag to L1 RPC API
cmd/ethrex/cli.rs Defines --generate-witness CLI argument with default false

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link

github-actions bot commented Jan 7, 2026

Benchmark Results Comparison

No significant difference was registered for any benchmark run.

Detailed Results

Benchmark Results: BubbleSort

Command Mean [s] Min [s] Max [s] Relative
main_revm_BubbleSort 2.963 ± 0.008 2.953 2.982 1.00
main_levm_BubbleSort 3.068 ± 0.027 3.045 3.140 1.04 ± 0.01
pr_revm_BubbleSort 3.128 ± 0.456 2.960 4.425 1.06 ± 0.15
pr_levm_BubbleSort 3.075 ± 0.011 3.066 3.103 1.04 ± 0.00

Benchmark Results: ERC20Approval

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_ERC20Approval 973.7 ± 11.2 963.6 998.9 1.00 ± 0.02
main_levm_ERC20Approval 1097.9 ± 11.2 1083.4 1120.9 1.13 ± 0.02
pr_revm_ERC20Approval 972.9 ± 9.4 965.6 997.6 1.00
pr_levm_ERC20Approval 1107.2 ± 13.9 1091.4 1134.9 1.14 ± 0.02

Benchmark Results: ERC20Mint

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_ERC20Mint 133.7 ± 0.5 133.2 135.0 1.00
main_levm_ERC20Mint 165.8 ± 4.4 162.7 177.5 1.24 ± 0.03
pr_revm_ERC20Mint 135.1 ± 1.5 133.1 137.1 1.01 ± 0.01
pr_levm_ERC20Mint 166.3 ± 1.6 164.2 168.3 1.24 ± 0.01

Benchmark Results: ERC20Transfer

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_ERC20Transfer 230.7 ± 1.0 229.6 232.5 1.00
main_levm_ERC20Transfer 278.7 ± 2.9 275.2 283.9 1.21 ± 0.01
pr_revm_ERC20Transfer 232.9 ± 2.2 230.6 238.2 1.01 ± 0.01
pr_levm_ERC20Transfer 280.5 ± 2.6 278.1 285.7 1.22 ± 0.01

Benchmark Results: Factorial

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_Factorial 227.7 ± 1.5 225.0 230.9 1.00 ± 0.02
main_levm_Factorial 268.6 ± 8.9 264.6 293.7 1.18 ± 0.04
pr_revm_Factorial 227.1 ± 3.8 225.0 237.9 1.00
pr_levm_Factorial 267.7 ± 5.3 264.7 282.6 1.18 ± 0.03

Benchmark Results: FactorialRecursive

Command Mean [s] Min [s] Max [s] Relative
main_revm_FactorialRecursive 1.656 ± 0.049 1.551 1.728 1.00
main_levm_FactorialRecursive 8.367 ± 0.055 8.288 8.439 5.05 ± 0.15
pr_revm_FactorialRecursive 1.707 ± 0.029 1.673 1.764 1.03 ± 0.04
pr_levm_FactorialRecursive 8.404 ± 0.027 8.368 8.433 5.07 ± 0.15

Benchmark Results: Fibonacci

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_Fibonacci 208.6 ± 1.1 206.4 210.1 1.01 ± 0.01
main_levm_Fibonacci 267.8 ± 2.4 264.6 271.0 1.29 ± 0.01
pr_revm_Fibonacci 207.0 ± 0.8 205.8 208.3 1.00
pr_levm_Fibonacci 259.4 ± 4.6 251.9 264.0 1.25 ± 0.02

Benchmark Results: FibonacciRecursive

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_FibonacciRecursive 882.1 ± 8.0 874.1 897.0 1.20 ± 0.06
main_levm_FibonacciRecursive 737.1 ± 36.8 681.1 787.6 1.00
pr_revm_FibonacciRecursive 912.7 ± 8.8 900.9 924.9 1.24 ± 0.06
pr_levm_FibonacciRecursive 763.8 ± 28.4 702.8 809.8 1.04 ± 0.06

Benchmark Results: ManyHashes

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_ManyHashes 8.2 ± 0.0 8.1 8.3 1.00
main_levm_ManyHashes 9.1 ± 0.1 9.0 9.1 1.11 ± 0.01
pr_revm_ManyHashes 8.2 ± 0.1 8.2 8.3 1.01 ± 0.01
pr_levm_ManyHashes 9.1 ± 0.1 9.0 9.5 1.11 ± 0.02

Benchmark Results: MstoreBench

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_MstoreBench 259.6 ± 4.5 255.3 270.5 1.07 ± 0.02
main_levm_MstoreBench 243.5 ± 1.2 241.7 244.9 1.01 ± 0.01
pr_revm_MstoreBench 263.2 ± 9.5 256.2 280.9 1.09 ± 0.04
pr_levm_MstoreBench 242.2 ± 1.7 240.6 245.7 1.00

Benchmark Results: Push

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_Push 292.5 ± 0.9 291.0 293.9 1.00
main_levm_Push 319.8 ± 33.4 306.7 414.7 1.09 ± 0.11
pr_revm_Push 292.6 ± 1.8 290.2 295.9 1.00 ± 0.01
pr_levm_Push 305.0 ± 2.4 302.3 311.0 1.04 ± 0.01

Benchmark Results: SstoreBench_no_opt

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_SstoreBench_no_opt 175.4 ± 6.5 168.8 192.1 1.96 ± 0.08
main_levm_SstoreBench_no_opt 90.4 ± 2.8 87.5 96.8 1.01 ± 0.03
pr_revm_SstoreBench_no_opt 175.7 ± 5.3 169.0 189.0 1.97 ± 0.06
pr_levm_SstoreBench_no_opt 89.4 ± 1.0 87.9 91.8 1.00


let threshold = latest_block_number - MAX_WITNESSES;

self.get_oldest_witness_number()?
Copy link
Contributor

Choose a reason for hiding this comment

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

This could be an if-let

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done 263e0e5!

@JereSalo JereSalo self-requested a review January 8, 2026 20:09
@avilagaston9 avilagaston9 changed the title feat(l1): cache execution witnesses feat(l1): generate execution witnesses during payload execution Jan 8, 2026
Copy link
Contributor

@JereSalo JereSalo left a comment

Choose a reason for hiding this comment

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

  1. We should specify in the CLI flag more accurately that its purpose is to generate witnesses for blocks after being synced with the network and to also cache them.
    suggested help = "After syncing blocks from the network, generate execution witnesses for the synced blocks and store them in the local witness cache."

  2. A better name for the flag in my opinion would be cache-witnesses instead.

  3. generate_witness_from_account_updates and generate_witness_for_blocks_with_fee_configs are very untidy. We should at least open an issue because they are a pain to read IMO and they can be improved.

I have yet to review other things but I will submit this review for now.


let vm_db = StoreVmDatabase::new(self.storage.clone(), parent_header.clone())?;
let vm = self.new_evm(vm_db)?;
let (mut vm, logger) = if self.options.generate_witness && self.is_synced() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd add a quick comment here saying what the purpose of this code is. Like just to execute with the database logger in order to generate the witness in one execution instead of executing more than once for this goal.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done aa754b7!

/// Oldest witness block column family: [`Vec<u8>`] => [`Vec<u8>`]
/// - [`Vec<u8>`] = `b"oldest_witness_block"`
/// - [`Vec<u8>`] = `oldest_block_number.to_le_bytes()`
pub const OLDEST_WITNESS_BLOCK: &str = "oldest_witness_block";
Copy link
Contributor

Choose a reason for hiding this comment

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

The name is okay but it'd be good to specify that it's a number, like OLDEST_WITNESS_BLOCK_NUMBER

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done 14173ad!

Comment on lines 28 to 30
pub current_accounts_state: CacheDB,
pub initial_accounts_state: CacheDB,
pub previous_tx_accounts_state: CacheDB,
Copy link
Contributor

Choose a reason for hiding this comment

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

We should add comments to each because it may be confusing

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done aa754b7!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

L1 Ethereum client

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

5 participants