Skip to content

Commit

Permalink
feat(levm): access lists support (#1447)
Browse files Browse the repository at this point in the history
**Motivation**

Access lists are not currently supported, this PR aims to add this
feature.

**Description**
The vm::new now receives the access lists and adds to warm addresses and
slots sets
  • Loading branch information
maximopalopoli authored Dec 10, 2024
1 parent 36f46f7 commit a55b6bf
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 3 deletions.
7 changes: 7 additions & 0 deletions cmd/ef_tests/levm/runner/levm_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ pub fn prepare_vm_for_tx(vector: &TestVector, test: &EFTest) -> Result<VM, EFTes
InternalError::FirstRunInternal("Failed to get transaction".to_owned()),
))?;

let access_lists = tx
.access_list
.iter()
.map(|arg| (arg.address, arg.storage_keys.clone()))
.collect();

VM::new(
tx.to.clone(),
Environment {
Expand All @@ -107,6 +113,7 @@ pub fn prepare_vm_for_tx(vector: &TestVector, test: &EFTest) -> Result<VM, EFTes
tx.data.clone(),
db,
CacheDB::default(),
access_lists,
)
.map_err(|err| EFTestRunnerError::VMInitializationFailed(err.to_string()))
}
Expand Down
4 changes: 4 additions & 0 deletions crates/vm/levm/src/gas_cost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ pub const CALLDATA_COST_NON_ZERO_BYTE: U256 = U256([16, 0, 0, 0]);
// Blob gas costs
pub const BLOB_GAS_PER_BLOB: U256 = U256([131072, 0, 0, 0]);

// Access lists costs
pub const ACCESS_LIST_STORAGE_KEY_COST: U256 = U256([1900, 0, 0, 0]);
pub const ACCESS_LIST_ADDRESS_COST: U256 = U256([2400, 0, 0, 0]);

pub fn exp(exponent: U256) -> Result<U256, OutOfGasError> {
let exponent_byte_size = (exponent
.bits()
Expand Down
1 change: 1 addition & 0 deletions crates/vm/levm/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,6 @@ pub fn new_vm_with_ops_addr_bal_db(
Default::default(),
Arc::new(db),
cache,
Vec::new(),
)
}
46 changes: 43 additions & 3 deletions crates/vm/levm/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use crate::{
InternalError, OpcodeSuccess, OutOfGasError, ResultReason, TransactionReport, TxResult,
TxValidationError, VMError,
},
gas_cost::{self, fake_exponential, BLOB_GAS_PER_BLOB, CREATE_BASE_COST},
gas_cost::{
self, fake_exponential, ACCESS_LIST_ADDRESS_COST, ACCESS_LIST_STORAGE_KEY_COST,
BLOB_GAS_PER_BLOB, CREATE_BASE_COST,
},
memory,
opcodes::Opcode,
AccountInfo,
Expand Down Expand Up @@ -52,6 +55,7 @@ pub struct VM {
pub db: Arc<dyn Database>,
pub cache: CacheDB,
pub tx_kind: TxKind,
pub access_list: AccessList,
}

pub fn address_to_word(address: Address) -> U256 {
Expand All @@ -71,6 +75,15 @@ pub fn word_to_address(word: U256) -> Address {
Address::from_slice(&bytes[12..])
}

// Taken from cmd/ef_tests/ethrex/types.rs, didn't want to fight dependencies yet
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct AccessListItem {
pub address: Address,
pub storage_keys: Vec<H256>,
}

type AccessList = Vec<(Address, Vec<H256>)>;

pub fn get_valid_jump_destinations(code: &Bytes) -> Result<HashSet<usize>, VMError> {
let mut valid_jump_destinations = HashSet::new();
let mut pc = 0;
Expand Down Expand Up @@ -115,13 +128,25 @@ impl VM {
calldata: Bytes,
db: Arc<dyn Database>,
mut cache: CacheDB,
access_list: AccessList,
) -> Result<Self, VMError> {
// Maybe this decision should be made in an upper layer

// Add sender, coinbase and recipient (in the case of a Call) to cache [https://www.evm.codes/about#access_list]
let mut default_touched_accounts =
HashSet::from_iter([env.origin, env.coinbase].iter().cloned());

let mut default_touched_storage_slots: HashMap<Address, HashSet<H256>> = HashMap::new();

for (address, keys) in access_list.clone() {
default_touched_accounts.insert(address);
let mut warm_slots = HashSet::new();
for slot in keys {
warm_slots.insert(slot);
}
default_touched_storage_slots.insert(address, warm_slots);
}

match to {
TxKind::Call(address_to) => {
default_touched_accounts.insert(address_to);
Expand Down Expand Up @@ -162,6 +187,7 @@ impl VM {
accrued_substate: substate,
cache,
tx_kind: to,
access_list,
})
}
TxKind::Create => {
Expand Down Expand Up @@ -205,10 +231,10 @@ impl VM {
accrued_substate: substate,
cache,
tx_kind: TxKind::Create,
access_list,
})
}
}
// TODO: https://github.com/lambdaclass/ethrex/issues/1088
}

pub fn execute(
Expand Down Expand Up @@ -435,7 +461,21 @@ impl VM {
}

// Access List Cost
// TODO: Implement access list cost.
let mut access_lists_cost = U256::zero();
for (_, keys) in self.access_list.clone() {
access_lists_cost = access_lists_cost
.checked_add(ACCESS_LIST_ADDRESS_COST)
.ok_or(OutOfGasError::ConsumedGasOverflow)?;
for _ in keys {
access_lists_cost = access_lists_cost
.checked_add(ACCESS_LIST_STORAGE_KEY_COST)
.ok_or(OutOfGasError::ConsumedGasOverflow)?;
}
}

intrinsic_gas = intrinsic_gas
.checked_add(access_lists_cost)
.ok_or(OutOfGasError::ConsumedGasOverflow)?;

self.increase_consumed_gas(initial_call_frame, intrinsic_gas)
.map_err(|_| TxValidationError::IntrinsicGasTooLow)?;
Expand Down
8 changes: 8 additions & 0 deletions crates/vm/levm/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4165,6 +4165,7 @@ fn caller_op() {
Default::default(),
Arc::new(db),
cache,
Vec::new(),
)
.unwrap();

Expand Down Expand Up @@ -4207,6 +4208,7 @@ fn origin_op() {
Default::default(),
Arc::new(db),
cache,
Vec::new(),
)
.unwrap();

Expand Down Expand Up @@ -4276,6 +4278,7 @@ fn address_op() {
Default::default(),
Arc::new(db),
cache,
Vec::new(),
)
.unwrap();

Expand Down Expand Up @@ -4322,6 +4325,7 @@ fn selfbalance_op() {
Default::default(),
Arc::new(db),
cache,
Vec::new(),
)
.unwrap();

Expand Down Expand Up @@ -4365,6 +4369,7 @@ fn callvalue_op() {
Default::default(),
Arc::new(db),
cache,
Vec::new(),
)
.unwrap();

Expand Down Expand Up @@ -4407,6 +4412,7 @@ fn codesize_op() {
Default::default(),
Arc::new(db),
cache,
Vec::new(),
)
.unwrap();

Expand Down Expand Up @@ -4448,6 +4454,7 @@ fn gasprice_op() {
Default::default(),
Arc::new(db),
cache,
Vec::new(),
)
.unwrap();

Expand Down Expand Up @@ -4505,6 +4512,7 @@ fn codecopy_op() {
Default::default(),
Arc::new(db),
cache,
Vec::new(),
)
.unwrap();

Expand Down
1 change: 1 addition & 0 deletions crates/vm/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ cfg_if::cfg_if! {
tx.data().clone(),
db,
CacheDB::default(),
tx.access_list(),
)?;

vm.transact()
Expand Down

0 comments on commit a55b6bf

Please sign in to comment.