From b3fce55628ae5d30c6d7f341278f6d0fccc52576 Mon Sep 17 00:00:00 2001 From: fborello-lambda Date: Fri, 1 Nov 2024 17:53:32 -0300 Subject: [PATCH] continue with tests --- crates/l2/proposer/prover_server.rs | 2 +- crates/l2/utils/save_prover_state.rs | 96 ++++++++++++++++++++-------- crates/vm/execution_db.rs | 18 ++++-- 3 files changed, 82 insertions(+), 34 deletions(-) diff --git a/crates/l2/proposer/prover_server.rs b/crates/l2/proposer/prover_server.rs index 0795e3e9b..8d42b82ce 100644 --- a/crates/l2/proposer/prover_server.rs +++ b/crates/l2/proposer/prover_server.rs @@ -218,7 +218,7 @@ impl ProverServer { let block = Block::new(header, body); - let db = ExecutionDB::from_exec(&block, &self.store).map_err(|err| err.to_string())?; + let (db, _) = ExecutionDB::from_exec(&block, &self.store).map_err(|err| err.to_string())?; let parent_header = self .store diff --git a/crates/l2/utils/save_prover_state.rs b/crates/l2/utils/save_prover_state.rs index 6b644702d..ddd8c2901 100644 --- a/crates/l2/utils/save_prover_state.rs +++ b/crates/l2/utils/save_prover_state.rs @@ -1,12 +1,11 @@ use directories::ProjectDirs; use ethereum_rust_storage::AccountUpdate; use serde::{Deserialize, Serialize}; -use std::fs::File; +use std::fs::{create_dir, File}; use std::path::PathBuf; use std::{ fs::create_dir_all, - io::{BufReader, BufWriter, Read, Write}, - path::Path, + io::{BufWriter, Write}, }; #[derive(Serialize, Deserialize, Debug, Clone, Copy)] @@ -15,9 +14,16 @@ pub enum StateFileType { AccountUpdates, } +const DEFAULT_DATADIR: &str = "ethereum_rust_l2"; + #[inline(always)] fn default_datadir() -> Result> { - let path_buf_data_dir = ProjectDirs::from("", "", "ethereum_rust_l2") + create_datadir(DEFAULT_DATADIR) +} + +#[inline(always)] +fn create_datadir(dir_name: &str) -> Result> { + let path_buf_data_dir = ProjectDirs::from("", "", dir_name) .ok_or_else(|| Box::::from("Couldn't get project_dir."))? .data_local_dir() .to_path_buf(); @@ -38,7 +44,12 @@ fn create_state_file_for_block_number( ) -> Result> { let path_buf = get_state_dir_for_block(block_number)?; if let Some(parent) = path_buf.parent() { - create_dir_all(parent)?; + if let Err(e) = create_dir_all(parent) { + if e.kind() != std::io::ErrorKind::AlreadyExists { + eprintln!("Directory already exists: {:?}", parent); + return Err(e.into()); + } + } } let block_number = path_buf @@ -47,6 +58,7 @@ fn create_state_file_for_block_number( .to_string_lossy(); let block_number = block_number.parse::()?; + let file_path = match state_file_type { StateFileType::AccountUpdates => { path_buf.join(format!("account_updates{block_number}.json")) @@ -54,6 +66,13 @@ fn create_state_file_for_block_number( StateFileType::Proof => path_buf.join(format!("proof_{block_number}.json")), }; + if let Err(e) = create_dir(&path_buf) { + if e.kind() != std::io::ErrorKind::AlreadyExists { + return Err(e.into()); + } + eprintln!("Directory already exists: {:?}", path_buf); + } + File::create(file_path).map_err(Into::into) } @@ -111,27 +130,13 @@ fn get_latest_block_state_path() -> Result> #[cfg(test)] mod tests { + use ethereum_rust_blockchain::add_block; + use ethereum_rust_storage::{EngineType, Store}; + use ethereum_rust_vm::execution_db::ExecutionDB; + use super::*; use crate::utils::test_data_io; - use std::fs::{self, create_dir_all}; - use std::path::{Path, PathBuf}; - - fn default_datadir_test() -> Result> { - let path_buf_data_dir = ProjectDirs::from("", "", "test_state") - .ok_or_else(|| Box::::from("Couldn't get project_dir."))? - .data_local_dir() - .to_path_buf(); - Ok(path_buf_data_dir) - } - - fn get_state_dir_for_block_test( - block_number: u64, - ) -> Result> { - let mut path_buf = default_datadir_test()?; - path_buf.push(block_number.to_string()); - - Ok(path_buf) - } + use std::fs::{self}; #[test] fn test_state_file_integration() -> Result<(), Box> { @@ -142,12 +147,49 @@ mod tests { } path.push("test_data"); - let chain_file_path = path.join("chain.rlp"); + let chain_file_path = path.join("l2-loadtest.rlp"); + let genesis_file_path = path.join("genesis-l2.json"); + + let store = Store::new("memory", EngineType::InMemory).expect("Failed to create Store"); + + let genesis = test_data_io::read_genesis_file(genesis_file_path.to_str().unwrap()); + store.add_initial_state(genesis.clone()).unwrap(); let blocks = test_data_io::read_chain_file(chain_file_path.to_str().unwrap()); - let last_block = blocks.last().unwrap().clone(); + for block in &blocks { + add_block(block, &store).unwrap(); + } + + let mut account_updates_vec: Vec = Vec::new(); + + for block in &blocks { + let (_, account_updates) = + ExecutionDB::from_exec(blocks.last().unwrap(), &store).unwrap(); + + account_updates_vec = account_updates; + + persist_state_in_block_state_path( + block.header.number, + StateFileType::AccountUpdates, + None, + Some(&account_updates_vec), + )?; + } + + let latest_block_path = get_latest_block_state_path()?; + + assert_eq!( + latest_block_path + .file_name() + .unwrap() + .to_string_lossy() + .parse::()?, + blocks.len() as u64 + ); + + // Read account_updates back todo - fs::remove_dir_all(default_datadir_test()?)?; + fs::remove_dir_all(default_datadir()?)?; Ok(()) } diff --git a/crates/vm/execution_db.rs b/crates/vm/execution_db.rs index 2366f6342..299dcbd51 100644 --- a/crates/vm/execution_db.rs +++ b/crates/vm/execution_db.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use ethereum_rust_core::types::{Block, ChainConfig}; -use ethereum_rust_storage::Store; +use ethereum_rust_storage::{AccountUpdate, Store}; use revm::{ primitives::{ AccountInfo as RevmAccountInfo, Address as RevmAddress, Bytecode as RevmBytecode, @@ -34,8 +34,12 @@ pub struct ExecutionDB { } impl ExecutionDB { - /// Creates a database by executing a block, without performing any validation. - pub fn from_exec(block: &Block, store: &Store) -> Result { + /// Creates a database and returns the ExecutionDB and account_updates by executing a block, + /// without performing any validation. + pub fn from_exec( + block: &Block, + store: &Store, + ) -> Result<(Self, Vec), ExecutionDBError> { // TODO: perform validation to exit early let mut state = evm_state(store.clone(), block.header.parent_hash); @@ -55,7 +59,7 @@ impl ExecutionDB { let mut storage = HashMap::new(); let block_hashes = HashMap::new(); // TODO: `block_hashes` remains empty for now - for account_update in account_updates { + for account_update in &account_updates { let address = RevmAddress::from_slice(account_update.address.as_bytes()); let account_info = store_wrapper .basic(address)? @@ -78,13 +82,15 @@ impl ExecutionDB { storage.insert(address, account_storage); } - Ok(Self { + let execution_db = Self { accounts, code, storage, block_hashes, chain_config, - }) + }; + + Ok((execution_db, account_updates)) } pub fn get_chain_config(&self) -> ChainConfig {