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): implement EIP7702 - Set EOA account code #1672

Merged
merged 96 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from 91 commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
c91c930
scaffolding: deserialize ef_test's EIP7702 txs
fborello-lambda Jan 9, 2025
da0e92b
feat: add checks for tx_type 4
fborello-lambda Jan 9, 2025
07632f4
chore: lint
fborello-lambda Jan 9, 2025
21bb98e
wip: add behavior section
fborello-lambda Jan 10, 2025
8298c3d
should be reverted: bump-up revm version so we can compare results ag…
fborello-lambda Jan 13, 2025
96f8a06
dbg: can't use Message::parse_slice
fborello-lambda Jan 13, 2025
ba959e0
dbg(wip)
fborello-lambda Jan 13, 2025
9db8979
dbg(wip)
fborello-lambda Jan 13, 2025
7085718
dbg(wip)
fborello-lambda Jan 14, 2025
87d6427
wip: EXTCODECOPY, EXTCODEHASH, EXTCODESIZE integration
fborello-lambda Jan 14, 2025
5ecbca1
wip: CALL* opcodes integration
fborello-lambda Jan 14, 2025
8c58f7f
wip: add intrinsic_gas calculations for auth_list
fborello-lambda Jan 14, 2025
c8ffe0d
wip: rm unwrap
fborello-lambda Jan 15, 2025
76b590c
dbg(wip)
fborello-lambda Jan 15, 2025
851fd24
dbg(wip)
fborello-lambda Jan 15, 2025
dc067d9
dbg(wip): add account_exists() function
fborello-lambda Jan 15, 2025
019e67b
dbg(wip)
fborello-lambda Jan 15, 2025
c8982aa
dbg(wip)
fborello-lambda Jan 15, 2025
2fb85b8
dbg: fix gas calculations of CALL* opcodes
fborello-lambda Jan 16, 2025
2277c5f
dbg: do not remove cached account if tx reverts
fborello-lambda Jan 16, 2025
75fadac
Accound should have been cached
fborello-lambda Jan 17, 2025
110d04c
dbg: wip
fborello-lambda Jan 17, 2025
c37a6b1
chore: improve code
fborello-lambda Jan 17, 2025
21adf5c
Add dbgs
ilitteri Jan 17, 2025
f0ffb9d
Filter test
ilitteri Jan 17, 2025
6b60adc
dbg: gas problems
fborello-lambda Jan 20, 2025
ce42c8b
chore: minor improvements
fborello-lambda Jan 20, 2025
21c2450
Merge branch 'main' into levm/eip7702
fborello-lambda Jan 20, 2025
5c61fff
fix(levm): precompiles bug
fborello-lambda Jan 20, 2025
997049d
chore: improve code
fborello-lambda Jan 20, 2025
8d05ded
dbg: fix some account_warming.json test
fborello-lambda Jan 21, 2025
e5a3b17
chore: rm prev change
fborello-lambda Jan 21, 2025
a615b4a
Remove Linter warning
lima-limon-inc Jan 21, 2025
73b31d5
fix: create_code test
fborello-lambda Jan 21, 2025
daa8c2c
dbg: gas tests
fborello-lambda Jan 21, 2025
facb25a
fix: revm ef_tests decoder
fborello-lambda Jan 21, 2025
b62ac20
Add if branch for when there's delegation code inside the call
lima-limon-inc Jan 21, 2025
f376638
Merge branch 'levm/eip7702' of github.com:lambdaclass/ethrex into lev…
lima-limon-inc Jan 21, 2025
8e3da10
Forgot funciton
lima-limon-inc Jan 21, 2025
cce01d0
dbg: increase_balance after set_eip7702_code() is called
fborello-lambda Jan 21, 2025
d210f85
Merge branch 'levm/eip7702' of github.com:lambdaclass/ethrex into lev…
fborello-lambda Jan 21, 2025
397119c
dbg: refactor nested if inside execute()
fborello-lambda Jan 21, 2025
27aa8e0
dbg: gas tests, temporary solution
fborello-lambda Jan 21, 2025
5553209
fix: eip7623
fborello-lambda Jan 22, 2025
f49ca78
Remove debugging if
lima-limon-inc Jan 22, 2025
f6c7f44
Add comment explaining why this check
lima-limon-inc Jan 22, 2025
12e4774
dbg: wip
fborello-lambda Jan 22, 2025
0e70b8f
chore: rm dbg! statements
fborello-lambda Jan 22, 2025
a17a1aa
dbg: touch the auth_address 'pointed' address
fborello-lambda Jan 22, 2025
628b170
chore: rm dbg! statements
fborello-lambda Jan 22, 2025
857ec75
dbg: fix all tests
fborello-lambda Jan 22, 2025
e3dc3fe
Remove extra variable
lima-limon-inc Jan 22, 2025
f20b07b
Slight refactor + slight comments
lima-limon-inc Jan 22, 2025
bc0eaf5
chore: revert revm bump
fborello-lambda Jan 22, 2025
4effebc
Merge branch 'levm/eip7702' of github.com:lambdaclass/ethrex into lev…
fborello-lambda Jan 22, 2025
3c5b486
chore: revert revm bump
fborello-lambda Jan 22, 2025
4f2853a
chore: revert revm bump
fborello-lambda Jan 22, 2025
5e7e212
chore: revert revm bump
fborello-lambda Jan 22, 2025
d2e73b6
Apply clippy suggestion
lima-limon-inc Jan 22, 2025
0d4f256
Remove unused fields
lima-limon-inc Jan 22, 2025
9ee14e8
chore: revert Cargo.lock changes
fborello-lambda Jan 22, 2025
683be85
chore: rm unneeded code
fborello-lambda Jan 22, 2025
78e3aab
chore: tidy-up
fborello-lambda Jan 22, 2025
ba005ee
chore: tidy-up
fborello-lambda Jan 22, 2025
25642b5
chore: linter
fborello-lambda Jan 22, 2025
8323b0d
Merge branch 'main' into levm/eip7702
fborello-lambda Jan 22, 2025
b26c65a
Add comment explaining needed toolchain and compiler versions
lima-limon-inc Jan 22, 2025
3977e3c
Merge branch 'levm/eip7702' of github.com:lambdaclass/ethrex into lev…
lima-limon-inc Jan 22, 2025
b87f213
chore: comment
fborello-lambda Jan 22, 2025
11d6800
Update crates/vm/levm/src/vm.rs
fborello-lambda Jan 22, 2025
94c3070
Update crates/vm/levm/src/vm.rs
fborello-lambda Jan 22, 2025
3f37d16
Update crates/vm/levm/src/vm.rs
fborello-lambda Jan 22, 2025
0b3d648
chore: linter
fborello-lambda Jan 22, 2025
aec44b9
Merge branch 'levm/eip7702' of github.com:lambdaclass/ethrex into lev…
fborello-lambda Jan 22, 2025
18111d3
refactor: Rename `was_delegated` to `has_delegation`
lima-limon-inc Jan 22, 2025
8cbeb31
Merge branch 'levm/eip7702' of github.com:lambdaclass/ethrex into lev…
lima-limon-inc Jan 22, 2025
0926f36
Merge branch 'main' into levm/eip7702
fborello-lambda Jan 22, 2025
2c72ea5
Update crates/vm/levm/src/errors.rs
fborello-lambda Jan 22, 2025
f66c681
Update crates/vm/levm/src/opcode_handlers/environment.rs
fborello-lambda Jan 22, 2025
c993e94
pr_comments: implement suggestions
fborello-lambda Jan 22, 2025
e20895c
Update crates/vm/levm/src/vm.rs
fborello-lambda Jan 22, 2025
050d9d6
Update crates/vm/levm/src/vm.rs
fborello-lambda Jan 22, 2025
b1dd292
Update crates/vm/levm/src/vm.rs
fborello-lambda Jan 22, 2025
884e669
Update crates/vm/levm/src/vm.rs
fborello-lambda Jan 22, 2025
034f7de
Update crates/vm/levm/src/vm.rs
fborello-lambda Jan 22, 2025
1042d6f
fix: Remove mutable reference from `get_account_no_push_cache`.
lima-limon-inc Jan 22, 2025
f0c3d7d
pr_comments: implement suggestions
fborello-lambda Jan 22, 2025
5f03383
Merge branch 'levm/eip7702' of github.com:lambdaclass/ethrex into lev…
lima-limon-inc Jan 22, 2025
9219dd9
fix: linter error
lima-limon-inc Jan 22, 2025
4194c7c
chore: linter
fborello-lambda Jan 22, 2025
72845a0
fix: performance? Check the cache BEFORE checking the db.
lima-limon-inc Jan 22, 2025
a5af389
Update crates/vm/levm/src/vm.rs
fborello-lambda Jan 23, 2025
a193974
chore: linter
fborello-lambda Jan 23, 2025
4849d06
Remove one linter error
lima-limon-inc Jan 23, 2025
d353846
Merge branch 'levm/eip7702' of github.com:lambdaclass/ethrex into lev…
lima-limon-inc Jan 23, 2025
c9ab6ca
Revert "Remove one linter error"
lima-limon-inc Jan 23, 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
5 changes: 3 additions & 2 deletions cmd/ef_tests/levm/runner/levm_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,6 @@ pub fn prepare_vm_for_tx(vector: &TestVector, test: &EFTest) -> Result<VM, EFTes
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>>()
});
Expand Down Expand Up @@ -242,6 +240,9 @@ fn exception_is_expected(
) | (
TransactionExpectedException::InitcodeSizeExceeded,
VMError::TxValidation(TxValidationError::InitcodeSizeExceeded)
) | (
TransactionExpectedException::Type4TxContractCreation,
VMError::TxValidation(TxValidationError::Type4TxContractCreation)
)
)
})
Expand Down
43 changes: 22 additions & 21 deletions cmd/ef_tests/levm/runner/revm_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,32 +137,33 @@ pub fn prepare_revm_for_tx<'state>(
.collect();

let authorization_list = None;

// WARNING: Do not delete the following.
// 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.
// NOTE:
// - rust 1.82.X is needed
// - rust-toolchain 1.82.X is needed (this can be found in ethrex/crates/vm/levm/rust-toolchain.toml)
/*
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 authorization_list = tx.authorization_list.clone().map(|list| {
list.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::<Vec<SignedAuthorization>>()
.into()
});
*/

let tx_env = RevmTxEnv {
caller: tx.sender.0.into(),
gas_limit: tx.gas_limit,
Expand Down
9 changes: 9 additions & 0 deletions crates/vm/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ cfg_if::cfg_if! {
}
}

fn account_exists(&self, address: CoreAddress) -> bool {
let acc_info = self
.store
.get_account_info_by_hash(self.block_hash, address)
.unwrap();

acc_info.is_some()
}

fn get_storage_slot(&self, address: CoreAddress, key: CoreH256) -> CoreU256 {
self.store
.get_storage_at_hash(self.block_hash, address, key)
Expand Down
18 changes: 18 additions & 0 deletions crates/vm/levm/src/constants.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
use ethrex_core::{H256, U256};
use k256::{
elliptic_curve::{bigint::Encoding, Curve},
Secp256k1,
};
use std::sync::LazyLock;

pub const WORD_SIZE_IN_BYTES: U256 = U256([32, 0, 0, 0]);
pub const WORD_SIZE_IN_BYTES_USIZE: usize = 32;
Expand Down Expand Up @@ -50,3 +55,16 @@ pub const VALID_BLOB_PREFIXES: [u8; 2] = [0x01, 0x02];
// 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]);

// EIP7702 - EOA Load Code
pub static SECP256K1_ORDER: LazyLock<U256> =
LazyLock::new(|| U256::from_big_endian(&Secp256k1::ORDER.to_be_bytes()));
pub static SECP256K1_ORDER_OVER2: LazyLock<U256> =
LazyLock::new(|| *SECP256K1_ORDER / U256::from(2));
pub const MAGIC: u8 = 0x05;
pub const SET_CODE_DELEGATION_BYTES: [u8; 3] = [0xef, 0x01, 0x00];
// Set the code of authority to be 0xef0100 || address. This is a delegation designation.
// len(SET_CODE_DELEGATION_BYTES) == 3 + len(Address) == 20 -> 23
pub const EIP7702_DELEGATED_CODE_LEN: usize = 23;
pub const PER_AUTH_BASE_COST: u64 = 12500;
pub const PER_EMPTY_ACCOUNT_COST: u64 = 25000;
5 changes: 5 additions & 0 deletions crates/vm/levm/src/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub trait Database {
fn get_account_info(&self, address: Address) -> AccountInfo;
fn get_storage_slot(&self, address: Address, key: H256) -> U256;
fn get_block_hash(&self, block_number: u64) -> Option<H256>;
fn account_exists(&self, address: Address) -> bool;
}

#[derive(Debug, Default)]
Expand Down Expand Up @@ -58,6 +59,10 @@ impl Database for Db {
.clone()
}

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

fn get_storage_slot(&self, address: Address, key: H256) -> U256 {
// both `original_value` and `current_value` should work here because they have the same values on Db
self.accounts
Expand Down
2 changes: 2 additions & 0 deletions crates/vm/levm/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ pub enum InternalError {
InvalidPrecompileAddress,
#[error("Spec Id doesn't match to any fork")]
InvalidSpecId,
#[error("Account should had been delegated")]
AccountNotDelegated,
}

#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error, Serialize, Deserialize)]
Expand Down
55 changes: 37 additions & 18 deletions crates/vm/levm/src/opcode_handlers/environment.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use crate::{
call_frame::CallFrame,
constants::SET_CODE_DELEGATION_BYTES,
errors::{InternalError, OpcodeSuccess, VMError},
gas_cost::{self},
memory::{self, calculate_memory_size},
vm::{word_to_address, VM},
vm::{has_delegation, word_to_address, VM},
};
use ethrex_core::U256;
use keccak_hash::keccak;
Expand Down Expand Up @@ -279,11 +280,16 @@ impl VM {

let (account_info, address_was_cold) = self.access_account(address);

// https://eips.ethereum.org/EIPS/eip-7702#delegation-designation
let is_delegation = has_delegation(&account_info)?;

self.increase_consumed_gas(current_call_frame, gas_cost::extcodesize(address_was_cold)?)?;

current_call_frame
.stack
.push(account_info.bytecode.len().into())?;
current_call_frame.stack.push(if is_delegation {
SET_CODE_DELEGATION_BYTES[..2].len().into()
} else {
account_info.bytecode.len().into()
})?;

Ok(OpcodeSuccess::Continue)
}
Expand All @@ -306,6 +312,9 @@ impl VM {

let new_memory_size = calculate_memory_size(dest_offset, size)?;

// https://eips.ethereum.org/EIPS/eip-7702#delegation-designation
let is_delegation = has_delegation(&account_info)?;

self.increase_consumed_gas(
current_call_frame,
gas_cost::extcodecopy(
Expand All @@ -320,18 +329,18 @@ impl VM {
return Ok(OpcodeSuccess::Continue);
}

let bytecode = if is_delegation {
SET_CODE_DELEGATION_BYTES[..2].into()
} else {
account_info.bytecode
};

let mut data = vec![0u8; size];
if offset < account_info.bytecode.len().into() {
if offset < bytecode.len().into() {
let offset: usize = offset
.try_into()
.map_err(|_| VMError::Internal(InternalError::ConversionError))?;
for (i, byte) in account_info
.bytecode
.iter()
.skip(offset)
.take(size)
.enumerate()
{
for (i, byte) in bytecode.iter().skip(offset).take(size).enumerate() {
if let Some(data_byte) = data.get_mut(i) {
*data_byte = *byte;
}
Expand Down Expand Up @@ -424,16 +433,26 @@ impl VM {

let (account_info, address_was_cold) = self.access_account(address);

// https://eips.ethereum.org/EIPS/eip-7702#delegation-designation
let is_delegation = has_delegation(&account_info)?;

self.increase_consumed_gas(current_call_frame, gas_cost::extcodehash(address_was_cold)?)?;

// An account is considered empty when it has no code and zero nonce and zero balance. [EIP-161]
if account_info.is_empty() {
current_call_frame.stack.push(U256::zero())?;
return Ok(OpcodeSuccess::Continue);
if is_delegation {
let hash =
U256::from_big_endian(keccak(&SET_CODE_DELEGATION_BYTES[..2]).as_fixed_bytes());
current_call_frame.stack.push(hash)?;
} else {
// An account is considered empty when it has no code and zero nonce and zero balance. [EIP-161]
if account_info.is_empty() {
current_call_frame.stack.push(U256::zero())?;
return Ok(OpcodeSuccess::Continue);
}

let hash = U256::from_big_endian(keccak(account_info.bytecode).as_fixed_bytes());
current_call_frame.stack.push(hash)?;
}

let hash = U256::from_big_endian(keccak(account_info.bytecode).as_fixed_bytes());
current_call_frame.stack.push(hash)?;
Ok(OpcodeSuccess::Continue)
}
}
Loading
Loading