Skip to content
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

feat(levm): cache refactor #1314

Merged
merged 57 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from 53 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
4de7a5e
Do not skip `VMTests`
ilitteri Nov 19, 2024
33b948f
Refactor runner
ilitteri Nov 21, 2024
950f2aa
Isolate EF test parsing
ilitteri Nov 21, 2024
9eaab48
Fix initial state loading
ilitteri Nov 21, 2024
cdc76d4
Fix types
ilitteri Nov 21, 2024
e389c73
Fix deserialization
ilitteri Nov 21, 2024
a28aa00
Refactor report module
ilitteri Nov 21, 2024
f72bd3f
Rename test file and modules
ilitteri Nov 21, 2024
798ca19
Ignore report file
ilitteri Nov 21, 2024
0df3e41
Chore
ilitteri Nov 21, 2024
1391e03
Merge main
ilitteri Nov 21, 2024
3e7ece3
Revert "Merge main"
ilitteri Nov 21, 2024
50cf7af
Merge branch 'main' of github.com:lambdaclass/lambda_ethereum_rust in…
ilitteri Nov 21, 2024
221990c
Update cmd/ef_tests/levm/runner/levm_runner.rs
ilitteri Nov 22, 2024
a437508
Fix
ilitteri Nov 22, 2024
12333c1
Fix parsing
ilitteri Nov 22, 2024
0e51cf8
Fix parsing
ilitteri Nov 22, 2024
3171a94
We do not need a mutable reference to the current call frame for comp…
ilitteri Nov 22, 2024
1985654
Refactor `op_balance`
ilitteri Nov 26, 2024
b94ad31
Refactor `op_extcodesize`
ilitteri Nov 26, 2024
e56ee1c
Refactor `op_extcodehash`
ilitteri Nov 26, 2024
553e998
Refactor `op_extcodecopy`
ilitteri Nov 26, 2024
722c8e3
Refactor `op_call`
ilitteri Nov 26, 2024
7d9b957
Leftovers
ilitteri Nov 26, 2024
f574d87
Refactor `op_callcode`
ilitteri Nov 26, 2024
8a1785d
Add memory expansion cost functions
ilitteri Nov 26, 2024
cce5db9
Refactor `op_delegatecall`
ilitteri Nov 26, 2024
c0a71c3
Refactor `op_delegatecall` leftovers
ilitteri Nov 26, 2024
f9dded0
Refactor `op_staticcall`
ilitteri Nov 26, 2024
6af6ce3
Refactor transaction validation
ilitteri Nov 26, 2024
08c545b
Refactor `op_sload`
ilitteri Nov 26, 2024
e80ed33
Refactor `op_sstore`
ilitteri Nov 26, 2024
fe459a4
Leftovers
ilitteri Nov 26, 2024
4cdabdc
Refactor DB module
ilitteri Nov 26, 2024
c6cc570
Add new account implementations
ilitteri Nov 26, 2024
7dca7b4
Leftovers
ilitteri Nov 26, 2024
6ad91e5
Encapsulate account modifications
ilitteri Nov 26, 2024
02517f9
Fix compilation
ilitteri Nov 27, 2024
8cb2fee
Use `checked_next_multiple_of`
ilitteri Nov 27, 2024
9e95552
Merge branch 'main' of github.com:lambdaclass/lambda_ethereum_rust in…
ilitteri Nov 27, 2024
1073d38
Fix compilation
ilitteri Nov 27, 2024
aeaaf59
Fix extcodecopy
ilitteri Nov 27, 2024
87e0de6
Merge branch 'main' into refactor_levm_new_state
ilitteri Nov 27, 2024
781aa0b
Merge branch 'main' of github.com:lambdaclass/lambda_ethereum_rust in…
ilitteri Nov 27, 2024
fd23ff2
remove leftover dbg
ilitteri Nov 27, 2024
9cf371e
Add todo
ilitteri Nov 27, 2024
fc469b8
Remove comment
ilitteri Nov 27, 2024
729e035
Update crates/vm/levm/src/vm.rs
ilitteri Nov 27, 2024
a3382c7
Fix `touched_storage_slots`
ilitteri Nov 27, 2024
f580d6c
Caller, callee, and coinbase are warm by default
ilitteri Nov 27, 2024
f725ec7
Merge branch 'main' into refactor_levm_new_state
ilitteri Nov 28, 2024
d335af3
Merge branch 'main' of github.com:lambdaclass/lambda_ethereum_rust in…
ilitteri Nov 28, 2024
647f5aa
Merge branch 'main' into refactor_levm_new_state
ilitteri Nov 28, 2024
765f5ee
Merge branch 'main' of github.com:lambdaclass/lambda_ethereum_rust in…
ilitteri Nov 28, 2024
c83a496
Remove commented code
ilitteri Nov 28, 2024
0835db6
Add constants for SSTORE
ilitteri Nov 28, 2024
d78436a
Leftover
ilitteri Nov 28, 2024
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
4 changes: 2 additions & 2 deletions cmd/ef_tests/levm/runner/levm_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use ethrex_core::{
H256, U256,
};
use ethrex_levm::{
db::Cache,
db::CacheDB,
errors::{TransactionReport, VMError},
vm::VM,
Environment,
Expand Down Expand Up @@ -98,7 +98,7 @@ pub fn prepare_vm_for_tx(vector: &TestVector, test: &EFTest) -> Result<VM, EFTes
test.transactions.get(vector).unwrap().value,
test.transactions.get(vector).unwrap().data.clone(),
db,
Cache::default(),
CacheDB::default(),
)
.map_err(|err| EFTestRunnerError::VMInitializationFailed(err.to_string()))
}
Expand Down
29 changes: 12 additions & 17 deletions crates/vm/levm/src/account.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use crate::{
constants::EMPTY_CODE_HASH,
errors::{InternalError, VMError},
};
use crate::constants::EMPTY_CODE_HASH;
use bytes::Bytes;
use ethrex_core::{H256, U256};
use keccak_hash::keccak;
Expand All @@ -19,6 +16,14 @@ impl AccountInfo {
pub fn is_empty(&self) -> bool {
self.balance.is_zero() && self.nonce == 0 && self.bytecode.is_empty()
}

pub fn has_code(&self) -> bool {
!(self.bytecode.is_empty() || self.bytecode_hash() == EMPTY_CODE_HASH)
}

pub fn bytecode_hash(&self) -> H256 {
keccak(self.bytecode.as_ref()).0.into()
}
}

#[derive(Clone, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
Expand Down Expand Up @@ -59,12 +64,12 @@ impl Account {
}
}

pub fn has_code(&self) -> Result<bool, VMError> {
Ok(!(self.info.bytecode.is_empty() || self.bytecode_hash() == EMPTY_CODE_HASH))
pub fn has_code(&self) -> bool {
self.info.has_code()
}

pub fn bytecode_hash(&self) -> H256 {
keccak(self.info.bytecode.as_ref()).0.into()
self.info.bytecode_hash()
}

pub fn is_empty(&self) -> bool {
Expand All @@ -90,14 +95,4 @@ impl Account {
self.info.nonce = nonce;
self
}

// TODO: Replace nonce increments with this or cache's analog (currently does not have senders)
pub fn increment_nonce(&mut self) -> Result<(), VMError> {
self.info.nonce = self
.info
.nonce
.checked_add(1)
.ok_or(VMError::Internal(InternalError::NonceOverflowed))?;
Ok(())
}
}
8 changes: 3 additions & 5 deletions crates/vm/levm/src/constants.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use ethrex_core::{H256, U256};

pub const WORD_SIZE_IN_BYTES: U256 = U256([32, 0, 0, 0]);
pub const WORD_SIZE_IN_BYTES_USIZE: usize = 32;

pub const SUCCESS_FOR_CALL: i32 = 1;
pub const REVERT_FOR_CALL: i32 = 0;
pub const HALT_FOR_CALL: i32 = 2;
Expand Down Expand Up @@ -42,11 +45,6 @@ pub const TARGET_BLOB_GAS_PER_BLOCK: U256 = U256([393216, 0, 0, 0]); // TARGET_B
pub const MIN_BASE_FEE_PER_BLOB_GAS: U256 = U256([1, 0, 0, 0]);
pub const BLOB_BASE_FEE_UPDATE_FRACTION: U256 = U256([3338477, 0, 0, 0]);

// Storage constants
pub const COLD_STORAGE_ACCESS_COST: U256 = U256([2100, 0, 0, 0]);
pub const WARM_ADDRESS_ACCESS_COST: U256 = U256([100, 0, 0, 0]);
pub const BALANCE_COLD_ADDRESS_ACCESS_COST: U256 = U256([2600, 0, 0, 0]);

// Block constants
pub const LAST_AVAILABLE_BLOCK_LIMIT: U256 = U256([256, 0, 0, 0]);
pub const MAX_BLOCK_GAS_LIMIT: U256 = U256([30_000_000, 0, 0, 0]);
35 changes: 35 additions & 0 deletions crates/vm/levm/src/db/cache.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::Account;
use ethrex_core::Address;
use std::collections::HashMap;

pub type CacheDB = HashMap<Address, Account>;

pub fn get_account<'cache>(
cached_accounts: &'cache CacheDB,
address: &Address,
) -> Option<&'cache Account> {
cached_accounts.get(address)
}

pub fn get_account_mut<'cache>(
cached_accounts: &'cache mut CacheDB,
address: &Address,
) -> Option<&'cache mut Account> {
cached_accounts.get_mut(address)
}

pub fn insert_account(
cached_accounts: &mut CacheDB,
address: Address,
account: Account,
) -> Option<Account> {
cached_accounts.insert(address, account)
}

pub fn remove_account(cached_accounts: &mut CacheDB, address: &Address) -> Option<Account> {
cached_accounts.remove(address)
}

pub fn is_account_cached(cached_accounts: &CacheDB, address: &Address) -> bool {
cached_accounts.contains_key(address)
}
71 changes: 4 additions & 67 deletions crates/vm/levm/src/db.rs → crates/vm/levm/src/db/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::{
account::{Account, AccountInfo, StorageSlot},
errors::{InternalError, VMError},
};
use crate::account::{Account, AccountInfo, StorageSlot};
use ethrex_core::{Address, H256, U256};
use std::collections::HashMap;

pub mod cache;
pub use cache::CacheDB;

pub trait Database {
fn get_account_info(&self, address: Address) -> AccountInfo;
fn get_storage_slot(&self, address: Address, key: H256) -> U256;
Expand Down Expand Up @@ -73,66 +73,3 @@ impl Database for Db {
self.block_hashes.get(&block_number).cloned()
}
}

#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub struct Cache {
pub accounts: HashMap<Address, Account>,
}

impl Cache {
pub fn get_account(&self, address: Address) -> Option<&Account> {
self.accounts.get(&address)
}

pub fn get_mut_account(&mut self, address: Address) -> Option<&mut Account> {
self.accounts.get_mut(&address)
}

pub fn get_storage_slot(&self, address: Address, key: H256) -> Option<StorageSlot> {
self.get_account(address)?.storage.get(&key).cloned()
}

pub fn add_account(&mut self, address: &Address, account: &Account) {
self.accounts.insert(*address, account.clone());
}

pub fn write_account_storage(
&mut self,
address: &Address,
key: H256,
slot: StorageSlot,
) -> Result<(), VMError> {
self.accounts
.get_mut(address)
.ok_or(VMError::Internal(
InternalError::AccountShouldHaveBeenCached,
))?
.storage
.insert(key, slot);
Ok(())
}

// TODO: Replace nonce increments with this (currently does not have senders)
pub fn increment_account_nonce(&mut self, address: &Address) -> Result<(), VMError> {
if let Some(account) = self.accounts.get_mut(address) {
account.info.nonce = account
.info
.nonce
.checked_add(1)
.ok_or(VMError::Internal(InternalError::NonceOverflowed))?;
}
Ok(())
}

pub fn is_account_cached(&self, address: &Address) -> bool {
self.accounts.contains_key(address)
}

pub fn is_slot_cached(&self, address: &Address, key: H256) -> bool {
self.is_account_cached(address)
&& self
.get_account(*address)
.map(|account| account.storage.contains_key(&key))
.unwrap_or(false)
}
}
10 changes: 6 additions & 4 deletions crates/vm/levm/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ pub enum VMError {
GasRefundsOverflow,
#[error("Memory size overflows")]
MemorySizeOverflow,
#[error("Nonce overflowed")]
NonceOverflow,
#[error("Nonce underflowed")]
NonceUnderflow,
// OutOfGas
#[error("Out Of Gas")]
OutOfGas(#[from] OutOfGasError),
Expand All @@ -88,14 +92,12 @@ pub enum OutOfGasError {
MaxGasLimitExceeded,
#[error("Arithmetic operation divided by zero in gas calculation")]
ArithmeticOperationDividedByZero,
#[error("Memory Expansion Cost Overflow")]
MemoryExpansionCostOverflow,
}

#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error, Serialize, Deserialize)]
pub enum InternalError {
#[error("Overflowed when incrementing nonce")]
NonceOverflowed,
#[error("Underflowed when incrementing nonce")]
NonceUnderflowed,
#[error("Overflowed when incrementing program counter")]
PCOverflowed,
#[error("Underflowed when decrementing program counter")]
Expand Down
Loading
Loading