Skip to content

refactor(l2): add check for transaction state diff size #2616

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

Closed
wants to merge 53 commits into from

Conversation

tomip01
Copy link
Contributor

@tomip01 tomip01 commented Apr 28, 2025

Motivation

This PR exists to avoid cloning the context and the execution cache if the transaction exceeds the state diff size allowed for that block.

Description

  • Move the actual size verification inside the execution of the transaction inside the VM crate.
  • Create a new l2_utils file for that verification.
  • Add function to get account updates without clearing the cache.
  • Create a new type of error for this type of verification, StateDiffSizeError.
  • Add new cache for storing all the reads made to the database.

Comparison against main
How to replicate:
Inside crates/l2

  • Terminal 1: init-l1
  • Terminal 2: make deploy-l1 update-system-contracts init-l2
  • Terminal 3: cargo run --manifest-path ../../cmd/load_test/Cargo.toml -- -k ../../test_data/private_keys.txt -t erc20 -N 1000 -n http://localhost:1729

For Terminal 3 if necessary run ulimit -n 65536 before the command.

Comparison at 255 seconds (arbitrary timestamp):
main: Waiting for transactions to be included from 0000bd19f707ca481886244bdd20bd6b8a81bd3e. Nonce: 69. Needs: 1000. Percentage: 6.9%. Elapsed time: 255s.
this PR: Waiting for transactions to be included from 0000bd19f707ca481886244bdd20bd6b8a81bd3e. Nonce: 567. Needs: 1000. Percentage: 56.699999999999996%. Elapsed time: 255s.
The performance increase in this particular scenario is around 8x.

Closes #2413

tomip01 added 3 commits April 25, 2025 16:51

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo
Copy link

github-actions bot commented Apr 28, 2025

Lines of code report

Total lines added: 294
Total lines removed: 87
Total lines changed: 381

Detailed view
+--------------------------------------------------------------+-------+------+
| File                                                         | Lines | Diff |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/blockchain/payload.rs                          | 563   | +11  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/l2/sequencer/block_producer/payload_builder.rs | 138   | -87  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/vm/backends/levm/l2_utils.rs                   | 95    | +95  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/vm/backends/levm/mod.rs                        | 717   | +81  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/vm/backends/mod.rs                             | 283   | +42  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/vm/constants.rs                                | 21    | +9   |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/vm/errors.rs                                   | 121   | +2   |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/vm/levm/bench/revm_comparison/src/lib.rs       | 169   | +1   |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/vm/levm/src/db/gen_db.rs                       | 236   | +36  |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/vm/levm/src/utils.rs                           | 421   | +9   |
+--------------------------------------------------------------+-------+------+
| ethrex/crates/vm/levm/src/vm.rs                              | 344   | +8   |
+--------------------------------------------------------------+-------+------+

tomip01 added 4 commits April 28, 2025 12:23

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo
@tomip01 tomip01 changed the title L2/limit state diff refactor(l2): add check for transaction state diff size Apr 28, 2025
@tomip01 tomip01 marked this pull request as ready for review April 28, 2025 18:13
@tomip01 tomip01 requested a review from a team as a code owner April 28, 2025 18:13

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
@tomip01 tomip01 self-assigned this Apr 28, 2025
@tomip01 tomip01 added the L2 Rollup client label Apr 28, 2025

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo
tomip01 added 3 commits April 28, 2025 17:20

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo
@tomip01 tomip01 marked this pull request as draft April 29, 2025 19:53
Copy link

github-actions bot commented Apr 29, 2025

Benchmark Results Comparison

PR Results

Benchmark Results: Factorial

Command Mean [ms] Min [ms] Max [ms] Relative
revm_Factorial 236.2 ± 1.6 233.9 240.0 1.00
levm_Factorial 817.8 ± 14.8 803.7 848.3 3.46 ± 0.07

Benchmark Results: Factorial - Recursive

Command Mean [s] Min [s] Max [s] Relative
revm_FactorialRecursive 1.432 ± 0.088 1.338 1.547 1.00
levm_FactorialRecursive 12.987 ± 0.083 12.896 13.142 9.07 ± 0.56

Benchmark Results: Fibonacci

Command Mean [ms] Min [ms] Max [ms] Relative
revm_Fibonacci 208.0 ± 1.9 203.8 210.7 1.00
levm_Fibonacci 811.5 ± 8.1 801.9 828.3 3.90 ± 0.05

Benchmark Results: ManyHashes

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ManyHashes 8.5 ± 0.0 8.5 8.6 1.00
levm_ManyHashes 17.2 ± 0.1 17.0 17.5 2.01 ± 0.02

Benchmark Results: BubbleSort

Command Mean [s] Min [s] Max [s] Relative
revm_BubbleSort 3.217 ± 0.041 3.169 3.310 1.00
levm_BubbleSort 5.503 ± 0.032 5.458 5.543 1.71 ± 0.02

Benchmark Results: ERC20 - Transfer

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ERC20Transfer 250.1 ± 3.6 247.1 258.6 1.00
levm_ERC20Transfer 498.3 ± 8.5 491.4 514.5 1.99 ± 0.04

Benchmark Results: ERC20 - Mint

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ERC20Mint 139.3 ± 0.6 138.6 140.2 1.00
levm_ERC20Mint 316.1 ± 2.5 313.3 322.2 2.27 ± 0.02

Benchmark Results: ERC20 - Approval

Command Mean [s] Min [s] Max [s] Relative
revm_ERC20Approval 1.037 ± 0.005 1.031 1.044 1.00
levm_ERC20Approval 1.866 ± 0.010 1.851 1.879 1.80 ± 0.01

Main Results

Benchmark Results: Factorial

Command Mean [ms] Min [ms] Max [ms] Relative
revm_Factorial 249.4 ± 19.7 241.5 305.1 1.00
levm_Factorial 813.2 ± 6.0 803.1 821.6 3.26 ± 0.26

Benchmark Results: Factorial - Recursive

Command Mean [s] Min [s] Max [s] Relative
revm_FactorialRecursive 1.467 ± 0.090 1.342 1.576 1.00
levm_FactorialRecursive 12.976 ± 0.070 12.892 13.122 8.85 ± 0.54

Benchmark Results: Fibonacci

Command Mean [ms] Min [ms] Max [ms] Relative
revm_Fibonacci 220.2 ± 6.6 211.7 237.4 1.00
levm_Fibonacci 814.0 ± 12.0 803.9 836.3 3.70 ± 0.12

Benchmark Results: ManyHashes

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ManyHashes 8.8 ± 0.1 8.7 9.1 1.00
levm_ManyHashes 17.1 ± 0.0 17.0 17.1 1.94 ± 0.03

Benchmark Results: BubbleSort

Command Mean [s] Min [s] Max [s] Relative
revm_BubbleSort 3.247 ± 0.029 3.221 3.322 1.00
levm_BubbleSort 5.732 ± 0.505 5.494 7.125 1.77 ± 0.16

Benchmark Results: ERC20 - Transfer

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ERC20Transfer 250.7 ± 2.2 248.4 254.8 1.00
levm_ERC20Transfer 497.7 ± 4.6 492.5 506.6 1.99 ± 0.03

Benchmark Results: ERC20 - Mint

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ERC20Mint 140.5 ± 0.6 139.8 141.8 1.00
levm_ERC20Mint 320.1 ± 3.6 317.1 327.2 2.28 ± 0.03

Benchmark Results: ERC20 - Approval

Command Mean [s] Min [s] Max [s] Relative
revm_ERC20Approval 1.047 ± 0.011 1.037 1.069 1.00
levm_ERC20Approval 1.865 ± 0.012 1.853 1.884 1.78 ± 0.02

tomip01 added 8 commits April 29, 2025 17:24

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo
JereSalo added 3 commits May 6, 2025 17:47

Verified

This commit was signed with the committer’s verified signature.
JereSalo Jeremías Salomón

Verified

This commit was signed with the committer’s verified signature.
JereSalo Jeremías Salomón
nit

Verified

This commit was signed with the committer’s verified signature.
JereSalo Jeremías Salomón
Comment on lines 90 to 95
if is_withdrawal_l2(tx, receipt)? {
actual_size += L2_WITHDRAWAL_SIZE;
}
if is_deposit_l2(tx) {
actual_size += L2_DEPOSIT_SIZE;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder why we do these checks. Aren't these modifications just contemplated in the calculated account_updates?

Copy link
Contributor

Choose a reason for hiding this comment

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

Aren't these modifications just contemplated in the calculated account_updates?

No. From the list of account_updates we can't tell wheter a change in the balance was due to a deposit, a withdrawal or a simple transfer. We can only determine that by examining the transaction.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh ok. I thought that the L2_DEPOSIT_SIZE and L2_WITHDRAWAL_SIZE were actually measuring changes performed to accounts that were reflected in account_updates but they are measuring something else. My bad. Thanks

Verified

This commit was signed with the committer’s verified signature.
JereSalo Jeremías Salomón
@JereSalo JereSalo marked this pull request as ready for review May 8, 2025 13:24
JereSalo added 4 commits May 8, 2025 18:38

Verified

This commit was signed with the committer’s verified signature.
JereSalo Jeremías Salomón

Verified

This commit was signed with the committer’s verified signature.
JereSalo Jeremías Salomón

Verified

This commit was signed with the committer’s verified signature.
JereSalo Jeremías Salomón

Verified

This commit was signed with the committer’s verified signature.
JereSalo Jeremías Salomón

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Comment on lines +159 to +163
Err(ChainError::EvmError(ethrex_vm::EvmError::StateDiffSizeError)) => {
debug!(
"Skipping transaction: {}, doesn't fit in blob_size",
tx_hash
);
Copy link
Contributor

Choose a reason for hiding this comment

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

How are we recovering the previous state? Are the account_updates of this tx being excluded?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice catch! corrected here e5ea196

@@ -172,6 +172,7 @@ pub struct PayloadBuildContext {
pub store: Store,
pub vm: Evm,
pub account_updates: Vec<AccountUpdate>,
pub acc_state_diff_size: Option<usize>,
Copy link
Contributor

@avilagaston9 avilagaston9 May 12, 2025

Choose a reason for hiding this comment

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

I think we should discuss this, we don't want our L1 to have L2 stuff. Can't we have a vm.execute_tx_l2?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah you are probably right. We have to think what's the best choice we have so that we don't mix L2 fields with the L1.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I second the idea of having an execute_tx_l2 type function to not interfere on the rest of the code

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 here ba83914

Comment on lines 14 to 33

// transactions_root(H256) + receipts_root(H256) + parent_hash(H256) + gas_limit(u64) + gas_used(u64) + timestamp(u64)
// block_number(u64) + base_fee_per_gas(u64)
// 32bytes + 32bytes + 32bytes + 8bytes + 8bytes + 8bytes + 8bytes + 8bytes
pub const LAST_HEADER_FIELDS_SIZE: usize = 136;

// address(H160) + amount(U256) + tx_hash(H256).
// 20bytes + 32bytes + 32bytes.
pub const L2_WITHDRAWAL_SIZE: usize = 84;

// address(H160) + amount(U256).
// 20bytes + 32bytes
pub const L2_DEPOSIT_SIZE: usize = 52;

pub static COMMON_BRIDGE_L2_ADDRESS: LazyLock<Address> = LazyLock::new(|| {
Address::from_slice(&[
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff,
])
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Added this comment to #2655.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice! I added the link to the issue for better clarity
5ee1e62

tomip01 added 4 commits May 13, 2025 11:56

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo
@tomip01 tomip01 force-pushed the l2/limit-state-diff branch from 23be6f8 to e5ea196 Compare May 14, 2025 13:44
tomip01 and others added 4 commits May 14, 2025 10:45

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo

Verified

This commit was signed with the committer’s verified signature.
tomip01 Tomás Paradelo
Comment on lines +316 to +323
// We want to restore to the initial state, this includes reverting the changes made by the prepare execution
// and the changes made by the execution itself.
#[cfg(feature = "l2")]
{
let current_backup: &mut CallFrameBackup =
&mut self.current_call_frame_mut()?.call_frame_backup;
merge_callframe_backup(current_backup, callframe_backup);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I used the feature flag option instead of creating a new function execute_l2() because the changes are small and does not change the API. Should I go for the new function instead?

.ok_or(VMError::OutOfBounds)?
.call_frame_backup;

if let Err(e) = update_state_diff_size(acc_state_diff_size, tx, &report.logs, db) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I believe you should be able to call restore_cache inside the if statement instead of doing it manually

@tomip01 tomip01 marked this pull request as draft May 15, 2025 19:32
@JereSalo
Copy link
Contributor

Closing because this turned out to be huge and can (and will) be split into 2 or more PRs.

@JereSalo JereSalo closed this May 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
L2 Rollup client
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

l2/levm: add execute mode to levm that returns account updates size
4 participants