Skip to content

refactor(l1, l2, levm): remove l2 feature flag from crates ethrex-vm and ethrex-levm #3367

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

Merged
merged 35 commits into from
Jun 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b8b3e3e
Add `ethrex-l2-rpc` crate
ilitteri Jun 26, 2025
c851fba
Remove feature l2 from rpc crate
ilitteri Jun 26, 2025
9920eaf
Move `init_rollup_store` to `l2::initializers`
ilitteri Jun 26, 2025
2aab6db
Remove last piece of l2 code from rpc crate
ilitteri Jun 26, 2025
0faf575
Add a TODO
ilitteri Jun 26, 2025
721479a
Reject blob transactions in l2
ilitteri Jun 26, 2025
aa40204
Clean dead code
ilitteri Jun 26, 2025
56fd63e
Add clippy allow
ilitteri Jun 26, 2025
6feefca
Fix lint
ilitteri Jun 26, 2025
87ccd57
Fix lint
ilitteri Jun 26, 2025
6637c1c
Remove type aliases
ilitteri Jun 26, 2025
26d3bf7
Use namespace instead of import aliasing
ilitteri Jun 26, 2025
4d14da5
Refactor
ilitteri Jun 26, 2025
cb573d2
Replace allow with expect for clippy lint
ilitteri Jun 26, 2025
1c87759
Remove unused imports
ilitteri Jun 26, 2025
28843a6
Move l2 precompiles logic to new module
ilitteri Jun 26, 2025
39a509f
Remove feature flag from hooks public API
ilitteri Jun 26, 2025
3023b88
Use the correct functions
ilitteri Jun 26, 2025
88bc9a2
Replace get_hooks
ilitteri Jun 26, 2025
8b09883
Remove `l2` feature flag from `levm`
ilitteri Jun 27, 2025
fd971be
Remove `l2` feature flag from `vm` crate
ilitteri Jun 27, 2025
32557eb
Implement `BlockchainType` and fix compilation
ilitteri Jun 27, 2025
137ca29
Merge branch 'main' of github.com:lambdaclass/ethrex into remove_l2_f…
ilitteri Jun 27, 2025
1fe36d4
Fix l2 command
ilitteri Jun 27, 2025
cda4244
Remove last occurrences of `ethrex-vm/l2` import
ilitteri Jun 27, 2025
0860942
Fix `p_256_verify_test`
ilitteri Jun 27, 2025
1c7f2a5
Update crates/vm/backends/revm/mod.rs
ilitteri Jun 27, 2025
68d0524
Fix stateless execution
ilitteri Jun 27, 2025
93efc4a
Update crates/vm/levm/bench/revm_comparison/src/levm_bench.rs
ilitteri Jun 27, 2025
fc24bb8
Remove unused function
ilitteri Jun 27, 2025
5b4e65a
Halt when non L2 LEVM functions are called in L2
ilitteri Jun 27, 2025
3943c13
Merge branch 'main' of github.com:lambdaclass/ethrex into remove_l2_f…
ilitteri Jun 30, 2025
5b7cb79
Fix merge
ilitteri Jun 30, 2025
f03a828
Merge branch 'main' into remove_l2_feature_flag_from_levm
ilitteri Jun 30, 2025
ac7e661
Update cmd/ef_tests/state/runner/levm_runner.rs
ilitteri Jun 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions cmd/ef_tests/blockchain/test_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
types::{BlockChainExpectedException, BlockExpectedException, BlockWithRLP, TestUnit},
};
use ethrex_blockchain::{
Blockchain,
Blockchain, BlockchainType,
error::{ChainError, InvalidBlockError},
fork_choice::apply_fork_choice,
};
Expand Down Expand Up @@ -69,7 +69,10 @@ pub async fn run_ef_test(test_key: &str, test: &TestUnit, evm: EvmEngine) -> Res
// Check world_state
check_prestate_against_db(test_key, test, &store);

let blockchain = Blockchain::new(evm, store.clone());
// Blockchain EF tests are meant for L1.
let blockchain_type = BlockchainType::L1;

let blockchain = Blockchain::new(evm, store.clone(), blockchain_type);
// Execute all blocks in test
for block_fixture in test.blocks.iter() {
let expects_exception = block_fixture.expect_exception.is_some();
Expand Down
1 change: 0 additions & 1 deletion cmd/ef_tests/state/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ path = "./lib.rs"
default = ["c-kzg", "blst"]
c-kzg = ["ethrex-vm/c-kzg", "ethrex-levm/c-kzg", "ethrex-common/c-kzg"]
blst = ["ethrex-vm/blst"]
l2 = ["ethrex-vm/l2", "ethrex-levm/l2"]

[[test]]
name = "all"
Expand Down
3 changes: 2 additions & 1 deletion cmd/ef_tests/state/runner/levm_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use ethrex_levm::{
db::gen_db::GeneralizedDatabase,
errors::{ExecutionReport, TxValidationError, VMError},
tracing::LevmCallTracer,
vm::VM,
vm::{VM, VMType},
};
use ethrex_rlp::encode::RLPEncode;
use ethrex_vm::backends;
Expand Down Expand Up @@ -201,6 +201,7 @@ pub fn prepare_vm_for_tx<'a>(
db,
&tx,
LevmCallTracer::disabled(),
VMType::L1, // TODO: Should we run the EF tests with L2?
))
}

Expand Down
1 change: 0 additions & 1 deletion cmd/ethrex/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ l2 = [
"dep:ethrex-l2-common",
"dep:ethrex-sdk",
"dep:ethrex-l2-rpc",
"ethrex-vm/l2",
"ethrex-blockchain/l2",
"ethrex-storage-rollup",
]
Expand Down
8 changes: 6 additions & 2 deletions cmd/ethrex/bench/build_block_benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use criterion::{
measurement::{Measurement, ValueFormatter},
};
use ethrex_blockchain::{
Blockchain,
Blockchain, BlockchainType,
payload::{BuildPayloadArgs, PayloadBuildResult, create_payload},
};
use ethrex_common::{
Expand Down Expand Up @@ -261,7 +261,11 @@ pub fn build_block_benchmark(c: &mut Criterion<GasMeasurement>) {
.collect();

let (store_with_genesis, genesis) = setup_genesis(&addresses).await;
let block_chain = Blockchain::new(EvmEngine::LEVM, store_with_genesis.clone());
let block_chain = Blockchain::new(
EvmEngine::LEVM,
store_with_genesis.clone(),
BlockchainType::L1, // TODO: Should we support L2?
);
fill_mempool(&block_chain, accounts).await;

(block_chain, genesis.get_block(), store_with_genesis)
Expand Down
6 changes: 5 additions & 1 deletion cmd/ethrex/bench/import_blocks_benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use ethrex::{
networks::Network,
utils::set_datadir,
};
use ethrex_blockchain::BlockchainType;
use ethrex_vm::EvmEngine;

#[inline]
Expand All @@ -15,7 +16,9 @@ fn block_import() {

let evm_engine = EvmEngine::default();

let network = Network::from("../../fixtures/genesis/perf-ci.json");
let blockchain_type = BlockchainType::default(); // TODO: Should we support L2?

let network = Network::from("../../test_data/genesis-perf-ci.json");
let genesis = network
.get_genesis()
.expect("Failed to generate genesis from file");
Expand All @@ -25,6 +28,7 @@ fn block_import() {
data_dir,
genesis,
evm_engine,
blockchain_type,
))
.expect("Failed to import blocks on the Tokio runtime");
}
Expand Down
16 changes: 12 additions & 4 deletions cmd/ethrex/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
};

use clap::{ArgAction, Parser as ClapParser, Subcommand as ClapSubcommand};
use ethrex_blockchain::error::ChainError;
use ethrex_blockchain::{BlockchainType, error::ChainError};
use ethrex_common::types::Genesis;
use ethrex_p2p::{sync::SyncMode, types::Node};
use ethrex_rlp::encode::RLPEncode;
Expand Down Expand Up @@ -241,6 +241,8 @@ pub enum Subcommand {
path: String,
#[arg(long = "removedb", action = ArgAction::SetTrue)]
removedb: bool,
#[arg(long, action = ArgAction::SetTrue)]
l2: bool,
},
#[command(
name = "export",
Expand Down Expand Up @@ -290,7 +292,7 @@ impl Subcommand {
Subcommand::RemoveDB { datadir, force } => {
remove_db(&datadir, force);
}
Subcommand::Import { path, removedb } => {
Subcommand::Import { path, removedb, l2 } => {
if removedb {
Box::pin(async {
Self::RemoveDB {
Expand All @@ -305,7 +307,12 @@ impl Subcommand {

let network = &opts.network;
let genesis = network.get_genesis()?;
import_blocks(&path, &opts.datadir, genesis, opts.evm).await?;
let blockchain_type = if l2 {
BlockchainType::L2
} else {
BlockchainType::L1
};
import_blocks(&path, &opts.datadir, genesis, opts.evm, blockchain_type).await?;
}
Subcommand::Export { path, first, last } => {
export_blocks(&path, &opts.datadir, first, last).await
Expand Down Expand Up @@ -354,10 +361,11 @@ pub async fn import_blocks(
data_dir: &str,
genesis: Genesis,
evm: EvmEngine,
blockchain_type: BlockchainType,
) -> Result<(), ChainError> {
let data_dir = set_datadir(data_dir);
let store = init_store(&data_dir, genesis).await;
let blockchain = init_blockchain(evm, store.clone());
let blockchain = init_blockchain(evm, store.clone(), blockchain_type);
let path_metadata = metadata(path).expect("Failed to read path");
let blocks = if path_metadata.is_dir() {
let mut blocks = vec![];
Expand Down
3 changes: 2 additions & 1 deletion cmd/ethrex/ethrex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use ethrex::{
},
utils::{NodeConfigFile, set_datadir, store_node_config_file},
};
use ethrex_blockchain::BlockchainType;
use ethrex_p2p::{kademlia::KademliaTable, network::peer_table, types::NodeRecord};
#[cfg(feature = "sync-test")]
use ethrex_storage::Store;
Expand Down Expand Up @@ -78,7 +79,7 @@ async fn main() -> eyre::Result<()> {
#[cfg(feature = "sync-test")]
set_sync_block(&store).await;

let blockchain = init_blockchain(opts.evm, store.clone());
let blockchain = init_blockchain(opts.evm, store.clone(), BlockchainType::L1);

let signer = get_signer(&data_dir);

Expand Down
10 changes: 7 additions & 3 deletions cmd/ethrex/initializers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
networks::{self, Network, PublicNetwork},
utils::{get_client_version, parse_socket_addr, read_jwtsecret_file, read_node_config_file},
};
use ethrex_blockchain::Blockchain;
use ethrex_blockchain::{Blockchain, BlockchainType};
use ethrex_common::types::Genesis;
use ethrex_p2p::{
kademlia::KademliaTable,
Expand Down Expand Up @@ -82,9 +82,13 @@ pub fn open_store(data_dir: &str) -> Store {
}
}

pub fn init_blockchain(evm_engine: EvmEngine, store: Store) -> Arc<Blockchain> {
pub fn init_blockchain(
evm_engine: EvmEngine,
store: Store,
blockchain_type: BlockchainType,
) -> Arc<Blockchain> {
info!("Initiating blockchain with EVM: {}", evm_engine);
Blockchain::new(evm_engine, store).into()
Blockchain::new(evm_engine, store, blockchain_type).into()
}

#[allow(clippy::too_many_arguments)]
Expand Down
4 changes: 3 additions & 1 deletion cmd/ethrex/l2/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
utils::{NodeConfigFile, parse_private_key, set_datadir, store_node_config_file},
};
use clap::Subcommand;
use ethrex_blockchain::BlockchainType;
use ethrex_common::{
Address, U256,
types::{BYTES_PER_BLOB, BlobsBundle, BlockHeader, batch::Batch, bytes_from_blob},
Expand Down Expand Up @@ -136,7 +137,8 @@ impl Command {
let store = init_store(&data_dir, genesis).await;
let rollup_store = l2::initializers::init_rollup_store(&rollup_store_dir).await;

let blockchain = init_blockchain(opts.node_opts.evm, store.clone());
let blockchain =
init_blockchain(opts.node_opts.evm, store.clone(), BlockchainType::L2);

let signer = get_signer(&data_dir);

Expand Down
2 changes: 1 addition & 1 deletion cmd/ethrex_replay/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,5 @@ charming = { version = "0.4.0", features = ["ssr"] }
risc0 = ["zkvm_interface/risc0", "ethrex-prover/risc0"]
sp1 = ["zkvm_interface/sp1", "ethrex-prover/sp1"]
gpu = ["ethrex-prover/gpu"]
l2 = ["ethrex-vm/l2", "zkvm_interface/l2", "ethrex-l2/l2"]
l2 = ["zkvm_interface/l2", "ethrex-l2/l2"]
ci = []
5 changes: 4 additions & 1 deletion cmd/ethrex_replay/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ enum SubcommandExecute {
help = "Name or ChainID of the network to use"
)]
network: String,
#[arg(long, required = false)]
l2: bool,
},
}

Expand Down Expand Up @@ -117,11 +119,12 @@ impl SubcommandExecute {
tx,
rpc_url,
network,
l2,
} => {
let chain_config = get_chain_config(&network)?;
let block_number = get_tx_block(&tx, &rpc_url).await?;
let cache = get_blockdata(&rpc_url, chain_config, block_number).await?;
let (receipt, transitions) = run_tx(cache, &tx).await?;
let (receipt, transitions) = run_tx(cache, &tx, l2).await?;
print_receipt(receipt);
for transition in transitions {
print_transition(transition);
Expand Down
21 changes: 17 additions & 4 deletions cmd/ethrex_replay/src/run.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::cache::Cache;
use ethrex_common::types::{AccountUpdate, ELASTICITY_MULTIPLIER, Receipt};
use ethrex_levm::db::{CacheDB, gen_db::GeneralizedDatabase};
use ethrex_levm::{
db::{CacheDB, gen_db::GeneralizedDatabase},
vm::VMType,
};
use ethrex_vm::{DynVmDatabase, Evm, EvmEngine, backends::levm::LEVM};
use eyre::Ok;
use std::sync::Arc;
Expand Down Expand Up @@ -58,7 +61,11 @@ pub async fn prove(cache: Cache) -> eyre::Result<String> {
Ok(serde_json::to_string(&out.0)?)
}

pub async fn run_tx(cache: Cache, tx_id: &str) -> eyre::Result<(Receipt, Vec<AccountUpdate>)> {
pub async fn run_tx(
cache: Cache,
tx_id: &str,
l2: bool,
) -> eyre::Result<(Receipt, Vec<AccountUpdate>)> {
let block = cache
.blocks
.first()
Expand All @@ -67,16 +74,22 @@ pub async fn run_tx(cache: Cache, tx_id: &str) -> eyre::Result<(Receipt, Vec<Acc
let mut prover_db = cache.witness;
prover_db.rebuild_tries()?;

let vm_type = if l2 { VMType::L2 } else { VMType::L1 };

let changes = {
let store: Arc<DynVmDatabase> = Arc::new(Box::new(prover_db.clone()));
let mut db = GeneralizedDatabase::new(store.clone(), CacheDB::new());
LEVM::prepare_block(block, &mut db)?;
LEVM::prepare_block(block, &mut db, vm_type)?;
LEVM::get_state_transitions(&mut db)?
};
prover_db.apply_account_updates(&changes)?;

for (tx, tx_sender) in block.body.get_transactions_with_sender()? {
let mut vm = Evm::new(EvmEngine::LEVM, prover_db.clone());
let mut vm = if l2 {
Evm::new_for_l2(EvmEngine::LEVM, prover_db.clone())?
} else {
Evm::new_for_l1(EvmEngine::LEVM, prover_db.clone())
};
let (receipt, _) = vm.execute_tx(tx, &block.header, &mut remaining_gas, tx_sender)?;
let account_updates = vm.get_state_transitions()?;
prover_db.apply_account_updates(&account_updates)?;
Expand Down
31 changes: 26 additions & 5 deletions crates/blockchain/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use ethrex_common::{Address, H256, TrieLogger};
use ethrex_metrics::metrics;
use ethrex_storage::{Store, UpdateBatch, error::StoreError, hash_address, hash_key};
use ethrex_vm::backends::levm::db::DatabaseLogger;
use ethrex_vm::{BlockExecutionResult, DynVmDatabase, Evm, EvmEngine};
use ethrex_vm::{BlockExecutionResult, DynVmDatabase, Evm, EvmEngine, EvmError};
use mempool::Mempool;
use std::collections::HashMap;
use std::sync::atomic::{AtomicBool, Ordering};
Expand All @@ -45,6 +45,13 @@ use ethrex_common::types::BlobsBundle;
//TODO: Implement a struct Chain or BlockChain to encapsulate
//functionality and canonical chain state and config

#[derive(Debug, Clone, Default)]
pub enum BlockchainType {
#[default]
L1,
L2,
}

#[derive(Debug)]
pub struct Blockchain {
pub evm_engine: EvmEngine,
Expand All @@ -54,6 +61,7 @@ pub struct Blockchain {
/// This will be set to true once the initial sync has taken place and wont be set to false after
/// This does not reflect whether there is an ongoing sync process
is_synced: AtomicBool,
pub r#type: BlockchainType,
}

#[derive(Debug, Clone)]
Expand All @@ -62,12 +70,13 @@ pub struct BatchBlockProcessingFailure {
pub failed_block_hash: H256,
}
impl Blockchain {
pub fn new(evm_engine: EvmEngine, store: Store) -> Self {
pub fn new(evm_engine: EvmEngine, store: Store, blockchain_type: BlockchainType) -> Self {
Self {
evm_engine,
storage: store,
mempool: Mempool::new(),
is_synced: AtomicBool::new(false),
r#type: blockchain_type,
}
}

Expand All @@ -77,6 +86,7 @@ impl Blockchain {
storage: store,
mempool: Mempool::new(),
is_synced: AtomicBool::new(false),
r#type: BlockchainType::default(),
}
}

Expand All @@ -98,7 +108,7 @@ impl Blockchain {
validate_block(block, &parent_header, &chain_config, ELASTICITY_MULTIPLIER)?;

let vm_db = StoreVmDatabase::new(self.storage.clone(), block.header.parent_hash);
let mut vm = Evm::new(self.evm_engine, vm_db);
let mut vm = self.new_evm(vm_db)?;
let execution_result = vm.execute_block(block)?;
let account_updates = vm.get_state_transitions()?;

Expand Down Expand Up @@ -170,7 +180,10 @@ impl Blockchain {
let vm_db: DynVmDatabase =
Box::new(StoreVmDatabase::new(self.storage.clone(), parent_hash));
let logger = Arc::new(DatabaseLogger::new(Arc::new(Mutex::new(Box::new(vm_db)))));
let mut vm = Evm::new_from_db(logger.clone());
let mut vm = match self.r#type {
BlockchainType::L1 => Evm::new_from_db_for_l1(logger.clone()),
BlockchainType::L2 => Evm::new_from_db_for_l2(logger.clone()),
};

// Re-execute block with logger
vm.execute_block(block)?;
Expand Down Expand Up @@ -442,7 +455,7 @@ impl Blockchain {
first_block_header.parent_hash,
block_hash_cache,
);
let mut vm = Evm::new(self.evm_engine, vm_db);
let mut vm = self.new_evm(vm_db).map_err(|e| (e.into(), None))?;

let blocks_len = blocks.len();
let mut all_receipts: Vec<(BlockHash, Vec<Receipt>)> = Vec::with_capacity(blocks_len);
Expand Down Expand Up @@ -776,6 +789,14 @@ impl Blockchain {

Ok(result)
}

pub fn new_evm(&self, vm_db: StoreVmDatabase) -> Result<Evm, EvmError> {
let evm = match self.r#type {
BlockchainType::L1 => Evm::new_for_l1(self.evm_engine, vm_db),
BlockchainType::L2 => Evm::new_for_l2(self.evm_engine, vm_db)?,
};
Ok(evm)
}
}

pub fn validate_requests_hash(
Expand Down
Loading
Loading