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

chore(levm): ef_tests parser for eip7702 #1749

Merged
merged 4 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 17 additions & 1 deletion cmd/ef_tests/levm/deserialize.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::types::{EFTest, EFTestAccessListItem, EFTests, TransactionExpectedException};
use crate::types::{
EFTest, EFTestAccessListItem, EFTestAuthorizationListTuple, EFTests,
TransactionExpectedException,
};
use bytes::Bytes;
use ethrex_core::{H256, U256};
use serde::{Deserialize, Deserializer};
Expand Down Expand Up @@ -194,6 +197,18 @@ where
Ok(Some(final_access_lists))
}

pub fn deserialize_authorization_lists<'de, D>(
deserializer: D,
) -> Result<Option<Vec<EFTestAuthorizationListTuple>>, D::Error>
where
D: serde::Deserializer<'de>,
{
let authorization_list: Option<Vec<EFTestAuthorizationListTuple>> =
Option::<Vec<EFTestAuthorizationListTuple>>::deserialize(deserializer)?;

Ok(authorization_list)
}

pub fn deserialize_u256_optional_safe<'de, D>(deserializer: D) -> Result<Option<U256>, D::Error>
where
D: serde::Deserializer<'de>,
Expand Down Expand Up @@ -322,6 +337,7 @@ impl<'de> Deserialize<'de> for EFTests {
.get(data_id)
.cloned()
.unwrap_or_default(),
authorization_list: raw_tx.authorization_list.clone(),
};
transactions.insert((data_id, gas_limit_id, value_id), tx);
}
Expand Down
19 changes: 18 additions & 1 deletion cmd/ef_tests/levm/runner/levm_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use ethrex_core::{
use ethrex_levm::{
db::CacheDB,
errors::{TransactionReport, TxValidationError, VMError},
vm::VM,
vm::{AuthorizationTuple, VM},
Environment,
};
use ethrex_storage::AccountUpdate;
Expand Down Expand Up @@ -88,6 +88,22 @@ pub fn prepare_vm_for_tx(vector: &TestVector, test: &EFTest) -> Result<VM, EFTes
.map(|arg| (arg.address, arg.storage_keys.clone()))
.collect();

// Check if the tx has the authorization_lists field implemented by eip7702.
let authorization_list = tx.authorization_list.clone().map(|list| {
list.iter()
.map(|auth_tuple| AuthorizationTuple {
chain_id: auth_tuple.chain_id,
address: auth_tuple.address,
nonce: auth_tuple.nonce,
v: auth_tuple.v,
r_signature: auth_tuple.r,
s_signature: auth_tuple.s,
// If the signer is not present, set it to Address::zero()
signer: auth_tuple.signer.unwrap_or_default(),
})
.collect::<Vec<AuthorizationTuple>>()
});

VM::new(
tx.to.clone(),
Environment {
Expand Down Expand Up @@ -116,6 +132,7 @@ pub fn prepare_vm_for_tx(vector: &TestVector, test: &EFTest) -> Result<VM, EFTes
db,
CacheDB::default(),
access_lists,
authorization_list,
)
.map_err(|err| EFTestRunnerError::VMInitializationFailed(err.to_string()))
}
Expand Down
29 changes: 28 additions & 1 deletion cmd/ef_tests/levm/runner/revm_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,33 @@ pub fn prepare_revm_for_tx<'state>(
})
.collect();

let authorization_list = None;
// The latest version of revm(19.3.0) is needed.
// Update it in every Cargo.toml.
// revm-inspectors and revm-primitives have to be bumped too.
/*
let revm_authorization_list: Vec<SignedAuthorization> = tx
.authorization_list
.clone()
.unwrap_or_default()
.iter()
.map(|auth_t| {
SignedAuthorization::new_unchecked(
Authorization {
chain_id: RevmU256::from_le_bytes(auth_t.chain_id.to_little_endian()),
address: RevmAddress(auth_t.address.0.into()),
nonce: auth_t.nonce,
},
auth_t.v.as_u32() as u8,
RevmU256::from_le_bytes(auth_t.r.to_little_endian()),
RevmU256::from_le_bytes(auth_t.s.to_little_endian()),
)
})
.collect();

let authorization_list = Some(revm_authorization_list.into());
*/

let tx_env = RevmTxEnv {
caller: tx.sender.0.into(),
gas_limit: tx.gas_limit,
Expand All @@ -160,7 +187,7 @@ pub fn prepare_revm_for_tx<'state>(
max_fee_per_blob_gas: tx
.max_fee_per_blob_gas
.map(|fee| RevmU256::from_limbs(fee.0)),
authorization_list: None,
authorization_list,
};

let evm_builder = Revm::builder()
Expand Down
25 changes: 23 additions & 2 deletions cmd/ef_tests/levm/types.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::{
deserialize::{
deserialize_access_lists, deserialize_ef_post_value_indexes,
deserialize_h256_vec_optional_safe, deserialize_hex_bytes, deserialize_hex_bytes_vec,
deserialize_access_lists, deserialize_authorization_lists,
deserialize_ef_post_value_indexes, deserialize_h256_vec_optional_safe,
deserialize_hex_bytes, deserialize_hex_bytes_vec,
deserialize_transaction_expected_exception, deserialize_u256_optional_safe,
deserialize_u256_safe, deserialize_u256_valued_hashmap_safe, deserialize_u256_vec_safe,
deserialize_u64_safe, deserialize_u64_vec_safe,
Expand Down Expand Up @@ -286,6 +287,23 @@ pub struct EFTestAccessListItem {
pub storage_keys: Vec<H256>,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct EFTestAuthorizationListTuple {
#[serde(deserialize_with = "deserialize_u256_safe")]
pub chain_id: U256,
pub address: Address,
#[serde(deserialize_with = "deserialize_u64_safe")]
pub nonce: u64,
#[serde(deserialize_with = "deserialize_u256_safe")]
pub v: U256,
#[serde(deserialize_with = "deserialize_u256_safe")]
pub r: U256,
#[serde(deserialize_with = "deserialize_u256_safe")]
pub s: U256,
pub signer: Option<Address>,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EFTestRawTransaction {
Expand All @@ -312,6 +330,8 @@ pub struct EFTestRawTransaction {
pub blob_versioned_hashes: Option<Vec<H256>>,
#[serde(default, deserialize_with = "deserialize_access_lists")]
pub access_lists: Option<Vec<Vec<EFTestAccessListItem>>>,
#[serde(default, deserialize_with = "deserialize_authorization_lists")]
pub authorization_list: Option<Vec<EFTestAuthorizationListTuple>>,
}

#[derive(Debug, Deserialize)]
Expand All @@ -331,4 +351,5 @@ pub struct EFTestTransaction {
pub max_fee_per_blob_gas: Option<U256>,
pub blob_versioned_hashes: Vec<H256>,
pub access_list: Vec<EFTestAccessListItem>,
pub authorization_list: Option<Vec<EFTestAuthorizationListTuple>>,
}
17 changes: 1 addition & 16 deletions crates/vm/levm/src/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,9 @@ impl Environment {
pub fn default_from_address(origin: Address) -> Self {
Self {
origin,
refunded_gas: 0,
gas_limit: u64::MAX,
spec_id: Default::default(),
block_number: Default::default(),
coinbase: Default::default(),
timestamp: Default::default(),
prev_randao: Default::default(),
chain_id: U256::one(),
base_fee_per_gas: Default::default(),
gas_price: Default::default(),
block_excess_blob_gas: Default::default(),
block_blob_gas_used: Default::default(),
tx_blob_hashes: Default::default(),
tx_max_priority_fee_per_gas: Default::default(),
tx_max_fee_per_gas: Default::default(),
tx_max_fee_per_blob_gas: Default::default(),
block_gas_limit: Default::default(),
transient_storage: Default::default(),
..Default::default()
}
}
}
8 changes: 7 additions & 1 deletion crates/vm/levm/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@ pub enum TxValidationError {
Type3TxBlobCountExceeded,
#[error("Type3TxContractCreation")]
Type3TxContractCreation,
#[error("Type 4 transactions are not supported before the Prague fork")]
Type4TxPreFork,
#[error("Type4TxAuthorizationListIsEmpty")]
Type4TxAuthorizationListIsEmpty,
#[error("Type4TxContractCreation")]
Type4TxContractCreation,
#[error("Gas limit price product overflow")]
GasLimitPriceProductOverflow,
#[error("Gas limit is too low")]
Expand Down Expand Up @@ -148,7 +154,7 @@ pub enum InternalError {
ArithmeticOperationUnderflow,
#[error("Arithmetic operation divided by zero")]
ArithmeticOperationDividedByZero,
#[error("Accound should have been cached")]
#[error("Account should have been cached")]
AccountShouldHaveBeenCached,
#[error("Tried to convert one type to another")]
ConversionError,
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 @@ -104,5 +104,6 @@ pub fn new_vm_with_ops_addr_bal_db(
Arc::new(db),
cache,
Vec::new(),
None,
)
}
17 changes: 17 additions & 0 deletions crates/vm/levm/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ pub struct VM {
pub cache: CacheDB,
pub tx_kind: TxKind,
pub access_list: AccessList,
pub authorization_list: Option<AuthorizationList>,
}

pub fn address_to_word(address: Address) -> U256 {
Expand All @@ -88,6 +89,19 @@ pub struct AccessListItem {

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

type AuthorizationList = Vec<AuthorizationTuple>;
// TODO: We have to implement this in ethrex_core
#[derive(Debug, Clone, Default, Copy)]
pub struct AuthorizationTuple {
pub chain_id: U256,
pub address: Address,
pub nonce: u64,
pub v: U256,
pub r_signature: U256,
pub s_signature: U256,
pub signer: Address,
}

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 @@ -133,6 +147,7 @@ impl VM {
db: Arc<dyn Database>,
mut cache: CacheDB,
access_list: AccessList,
authorization_list: Option<AuthorizationList>,
) -> Result<Self, VMError> {
// Maybe this decision should be made in an upper layer

Expand Down Expand Up @@ -204,6 +219,7 @@ impl VM {
cache,
tx_kind: to,
access_list,
authorization_list,
})
}
TxKind::Create => {
Expand Down Expand Up @@ -246,6 +262,7 @@ impl VM {
cache,
tx_kind: TxKind::Create,
access_list,
authorization_list,
})
}
}
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 @@ -3891,6 +3891,7 @@ fn caller_op() {
Arc::new(db),
cache,
Vec::new(),
None,
)
.unwrap();

Expand Down Expand Up @@ -3934,6 +3935,7 @@ fn origin_op() {
Arc::new(db),
cache,
Vec::new(),
None,
)
.unwrap();

Expand Down Expand Up @@ -4004,6 +4006,7 @@ fn address_op() {
Arc::new(db),
cache,
Vec::new(),
None,
)
.unwrap();

Expand Down Expand Up @@ -4051,6 +4054,7 @@ fn selfbalance_op() {
Arc::new(db),
cache,
Vec::new(),
None,
)
.unwrap();

Expand Down Expand Up @@ -4095,6 +4099,7 @@ fn callvalue_op() {
Arc::new(db),
cache,
Vec::new(),
None,
)
.unwrap();

Expand Down Expand Up @@ -4138,6 +4143,7 @@ fn codesize_op() {
Arc::new(db),
cache,
Vec::new(),
None,
)
.unwrap();

Expand Down Expand Up @@ -4180,6 +4186,7 @@ fn gasprice_op() {
Arc::new(db),
cache,
Vec::new(),
None,
)
.unwrap();

Expand Down Expand Up @@ -4238,6 +4245,7 @@ fn codecopy_op() {
Arc::new(db),
cache,
Vec::new(),
None,
)
.unwrap();

Expand Down
4 changes: 4 additions & 0 deletions crates/vm/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ cfg_if::cfg_if! {
store_wrapper,
CacheDB::new(),
vec![],
None
)
.map_err(EvmError::from)?;

Expand Down Expand Up @@ -325,6 +326,9 @@ cfg_if::cfg_if! {
db,
block_cache,
tx.access_list(),
// TODO: Here we should pass the tx.authorization_list
// We have to implement the EIP7702 tx in ethrex_core
None
)?;

vm.transact()
Expand Down
Loading