Skip to content

fix(l2): limit block to blob size#2292

Merged
jrchatruc merged 52 commits into
mainfrom
l2/limit_block_to_blob_size
Apr 16, 2025
Merged

fix(l2): limit block to blob size#2292
jrchatruc merged 52 commits into
mainfrom
l2/limit_block_to_blob_size

Conversation

@avilagaston9

@avilagaston9 avilagaston9 commented Mar 21, 2025

Copy link
Copy Markdown
Contributor

Motivation

With our current implementation, if a block state diff exceeds the blob size, we are unable to commit that block.

Description

This PR provides an initial solution by calculating the state diff size after including each transaction in the block. If the size exceeds the blob limit, the previous state is restored and transactions continue to be added from the remaining senders in the mempool.

Observations

  • blockchain::build_payload was "replicated" in block_producer/payload_builder.rs with two key differences:
    • It doesn't call blockchain::apply_system_operations.
    • It uses a custom L2 implementation of fill_transactions which adds the logic described above.
  • Some functions in blockchain are now public to allow access from payload_builder.
  • PayloadBuildContext now contains am owned Block instead of a mutable reference of it, as we need to be able to clone the PayloadBuildContext to restore a previous state.
  • PayloadBuildContext is cloned before each transaction execution, which may impact performance.
  • After each transaction, vm.get_state_transitions() is called to compute the state diff size.
  • Since REVM::vm.get_state_transitions() mutates the PayloadBuildContext, we need to clone it to avoid unintended changes.
  • An accounts_info_cache is used to prevent calling get_account_info on every tx execution.

Warning

  • REVM: Payload building is 10x slower due to frequent clone() calls.
  • LEVM: Payload building is 100x slower because LEVM::get_state_transitions internally calls get_account_info.

These issues will be addressed in future PRs.

@github-actions

github-actions Bot commented Mar 21, 2025

Copy link
Copy Markdown

Lines of code report

Total lines added: 349
Total lines removed: 25
Total lines changed: 374

Detailed view
+--------------------------------------------------------------+-------+------+
| File                                                         | Lines | Diff |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/blockchain/payload.rs                          | 548   | -3   |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/sequencer/block_producer.rs                 | 111   | +5   |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/sequencer/block_producer/payload_builder.rs | 225   | +225 |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/sequencer/errors.rs                         | 181   | +11  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/sequencer/l1_committer.rs                   | 383   | -22  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/sequencer/state_diff.rs                     | 466   | +56  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/utils/error.rs                              | 22    | +5   |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/utils/helpers.rs                            | 24    | +24  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/utils/mod.rs                                | 6     | +1   |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/networking/rpc/engine/payload.rs               | 684   | +1   |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/vm/backends/mod.rs                             | 242   | +1   |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/vm/backends/revm/db.rs                         | 225   | +19  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/vm/levm/src/vm.rs                              | 440   | +1   |
+--------------------------------------------------------------+-------+------+

Comment thread crates/blockchain/payload.rs Outdated
Comment thread crates/blockchain/payload.rs Outdated
Comment thread crates/blockchain/payload.rs Outdated
Execution(Box<revm::db::CacheDB<ExecutionDB>>),
}

impl Clone for EvmState {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This was needed to restore the previous EVM state after executing a transaction whose resulting state diff doesn't fit in a blob.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

That merits a code comment I believe. My first instinct in a few months after seeing this would be to try and convert it into a derive, breaking the logic. Can't be the only one.

Also, where this differs from the derive(Clone) should also be commented. I guess it's the cache clone at the end?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The problem was that revm::db::State doesn't implement the Clone trait. I added a comment here: dc9d5d8!

@avilagaston9 avilagaston9 self-assigned this Mar 21, 2025
@avilagaston9 avilagaston9 marked this pull request as ready for review March 21, 2025 22:27
@avilagaston9 avilagaston9 requested a review from a team as a code owner March 21, 2025 22:27
Comment thread crates/blockchain/payload.rs Outdated
context.account_updates = account_updates;
Ok(())
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

the idea is not to pollute l1 with a lot of l2 code, can't this go inside l2 crate?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Moved tol2/sequencer/block_producer/payload_builder.rs!

@avilagaston9 avilagaston9 marked this pull request as draft March 25, 2025 13:17
@avilagaston9

Copy link
Copy Markdown
Contributor Author

Let's add a similar "short circuit" if the current state diff size is too close to the limit for almost any meaningful transaction to get through, similar to this check for gas
@jrchatruc

Added in 3169adb!

@github-actions

github-actions Bot commented Apr 3, 2025

Copy link
Copy Markdown

Benchmark Results Comparison

PR Results

Benchmark Results: Factorial

Command Mean [ms] Min [ms] Max [ms] Relative
revm_Factorial 240.3 ± 2.2 239.1 246.4 1.00
levm_Factorial 803.6 ± 3.0 799.3 808.8 3.34 ± 0.03

Benchmark Results: Factorial - Recursive

Command Mean [s] Min [s] Max [s] Relative
revm_FactorialRecursive 1.427 ± 0.095 1.319 1.572 1.00
levm_FactorialRecursive 13.893 ± 0.020 13.866 13.916 9.73 ± 0.65

Benchmark Results: Fibonacci

Command Mean [ms] Min [ms] Max [ms] Relative
revm_Fibonacci 215.2 ± 0.7 214.3 216.4 1.00
levm_Fibonacci 792.0 ± 6.3 783.3 801.1 3.68 ± 0.03

Benchmark Results: ManyHashes

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ManyHashes 9.0 ± 0.3 8.6 9.7 1.00
levm_ManyHashes 16.7 ± 0.4 16.3 17.6 1.86 ± 0.07

Benchmark Results: BubbleSort

Command Mean [s] Min [s] Max [s] Relative
revm_BubbleSort 3.220 ± 0.046 3.187 3.346 1.00
levm_BubbleSort 5.707 ± 0.040 5.619 5.756 1.77 ± 0.03

Benchmark Results: ERC20 - Transfer

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ERC20Transfer 248.2 ± 7.4 244.0 268.2 1.00
levm_ERC20Transfer 487.9 ± 4.1 482.5 494.7 1.97 ± 0.06

Benchmark Results: ERC20 - Mint

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ERC20Mint 139.1 ± 0.6 137.8 139.9 1.00
levm_ERC20Mint 318.5 ± 5.3 313.5 328.4 2.29 ± 0.04

Benchmark Results: ERC20 - Approval

Command Mean [s] Min [s] Max [s] Relative
revm_ERC20Approval 1.034 ± 0.010 1.025 1.059 1.00
levm_ERC20Approval 1.866 ± 0.014 1.850 1.893 1.80 ± 0.02

Main Results

Benchmark Results: Factorial

Command Mean [ms] Min [ms] Max [ms] Relative
revm_Factorial 239.9 ± 1.0 239.1 241.7 1.00
levm_Factorial 804.7 ± 6.7 797.6 820.8 3.35 ± 0.03

Benchmark Results: Factorial - Recursive

Command Mean [s] Min [s] Max [s] Relative
revm_FactorialRecursive 1.415 ± 0.085 1.312 1.527 1.00
levm_FactorialRecursive 13.922 ± 0.050 13.870 14.001 9.84 ± 0.59

Benchmark Results: Fibonacci

Command Mean [ms] Min [ms] Max [ms] Relative
revm_Fibonacci 219.8 ± 6.9 214.7 237.5 1.00
levm_Fibonacci 798.4 ± 10.6 782.3 823.4 3.63 ± 0.12

Benchmark Results: ManyHashes

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ManyHashes 8.6 ± 0.1 8.5 8.7 1.00
levm_ManyHashes 16.5 ± 0.2 16.2 16.8 1.93 ± 0.03

Benchmark Results: BubbleSort

Command Mean [s] Min [s] Max [s] Relative
revm_BubbleSort 3.202 ± 0.030 3.175 3.279 1.00
levm_BubbleSort 5.692 ± 0.154 5.569 6.012 1.78 ± 0.05

Benchmark Results: ERC20 - Transfer

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ERC20Transfer 246.7 ± 3.3 243.8 252.7 1.00
levm_ERC20Transfer 488.5 ± 4.1 481.8 495.0 1.98 ± 0.03

Benchmark Results: ERC20 - Mint

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ERC20Mint 139.9 ± 0.9 138.9 141.4 1.00
levm_ERC20Mint 314.2 ± 2.1 310.7 317.0 2.25 ± 0.02

Benchmark Results: ERC20 - Approval

Command Mean [s] Min [s] Max [s] Relative
revm_ERC20Approval 1.026 ± 0.009 1.020 1.049 1.00
levm_ERC20Approval 1.859 ± 0.022 1.833 1.892 1.81 ± 0.03

Comment on lines +115 to +120
if !blob_txs.is_empty() && context.blobs_bundle.blobs.len() >= max_blob_number_per_block {
debug!("No more blob gas to run blob transactions");
blob_txs.clear();
}
// Fetch the next transactions
let (head_tx, is_blob) = match (plain_txs.peek(), blob_txs.peek()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we won't support blob txs in the L2, so maybe this is unnecessary

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Yeah, we almost certainly won't support them, but I would tackle this in a separate PR where we remove all blob txs support on the L2

Comment on lines +230 to +238
async fn check_state_diff_size(
acc_withdrawals_size: &mut usize,
acc_deposits_size: &mut usize,
acc_state_diff_size: &mut usize,
tx: Transaction,
receipt: &Receipt,
context: &mut PayloadBuildContext,
accounts_info_cache: &mut HashMap<Address, Option<AccountInfo>>,
) -> Result<bool, BlockProducerError> {

Copy link
Copy Markdown
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 doc comment saying what changes it'll do to the mut variables. Also maybe consider rename the function to something like update_state_diff_size

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 0a1050a!

@jrchatruc jrchatruc enabled auto-merge April 16, 2025 14:55
@jrchatruc jrchatruc added this pull request to the merge queue Apr 16, 2025
Merged via the queue into main with commit febb4dd Apr 16, 2025
@jrchatruc jrchatruc deleted the l2/limit_block_to_blob_size branch April 16, 2025 15:21
pedrobergamini pushed a commit to pedrobergamini/ethrex that referenced this pull request Aug 24, 2025
…lass#2357)

**Motivation**

Noticed on lambdaclass#2292 that the majority of the time in
`LEVM::get_state_transitions()` was spent on calls to
`get_account_info()`. While looking for areas to improve, I found that
we were calling `get_account_info()` three times instead of reusing the
value returned in the first call.

**Description**

Removes the repeated calls to `get_account_info`.

Testing locally shows a `2x` speed improvement in
`payload_builder::build_payload()` implemented in lambdaclass#2292.

Closes None
pedrobergamini pushed a commit to pedrobergamini/ethrex that referenced this pull request Aug 24, 2025
**Motivation**

With our current implementation, if a block state diff exceeds the blob
size, we are unable to commit that block.

**Description**

This PR provides an initial solution by calculating the state diff size
after including each transaction in the block. If the size exceeds the
blob limit, the previous state is restored and transactions continue to
be added from the remaining senders in the mempool.

**Observations**
- `blockchain::build_payload` was "replicated" in
`block_producer/payload_builder.rs` with two key differences:
    - It doesn't call `blockchain::apply_system_operations`.
- It uses a custom L2 implementation of `fill_transactions` which adds
the logic described above.
- Some functions in `blockchain` are now public to allow access from
`payload_builder`.
- `PayloadBuildContext` now contains am owned `Block` instead of a
mutable reference of it, as we need to be able to clone the
`PayloadBuildContext` to restore a previous state.
- `PayloadBuildContext` is cloned before each transaction execution,
which may impact performance.
- After each transaction, `vm.get_state_transitions()` is called to
compute the state diff size.
- Since `REVM::vm.get_state_transitions()` mutates the
`PayloadBuildContext`, we need to clone it to avoid unintended changes.
- An `accounts_info_cache` is used to prevent calling `get_account_info`
on every tx execution.

> [!WARNING]
> - **REVM**: Payload building is **10x slower** due to frequent
`clone()` calls.
> - **LEVM**: Payload building is **100x slower** because
`LEVM::get_state_transitions` internally calls `get_account_info`.
>
> *These issues will be addressed in future PRs.*
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.

6 participants