From 43a685a98568fbf054f2a6c23610b00809312d1b Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Thu, 7 Nov 2024 23:04:54 +0400 Subject: [PATCH] feat: apply latest EIP-7702 changes --- crates/interpreter/src/gas/calc.rs | 4 +- crates/interpreter/src/host.rs | 4 +- crates/interpreter/src/host/dummy.rs | 8 +- crates/interpreter/src/instructions/host.rs | 13 ++-- crates/primitives/src/eip7702.rs | 3 +- crates/primitives/src/eip7702/bytecode.rs | 6 ++ crates/primitives/src/lib.rs | 1 + crates/revm/src/context.rs | 6 +- crates/revm/src/context/inner_evm_context.rs | 79 ++++---------------- 9 files changed, 41 insertions(+), 83 deletions(-) diff --git a/crates/interpreter/src/gas/calc.rs b/crates/interpreter/src/gas/calc.rs index a56261859b..62a2c642df 100644 --- a/crates/interpreter/src/gas/calc.rs +++ b/crates/interpreter/src/gas/calc.rs @@ -125,9 +125,9 @@ pub const fn verylowcopy_cost(len: u64) -> Option { /// `EXTCODECOPY` opcode cost calculation. #[inline] -pub const fn extcodecopy_cost(spec_id: SpecId, len: u64, load: Eip7702CodeLoad<()>) -> Option { +pub const fn extcodecopy_cost(spec_id: SpecId, len: u64, is_cold: bool) -> Option { let base_gas = if spec_id.is_enabled_in(SpecId::BERLIN) { - warm_cold_cost_with_delegation(load) + warm_cold_cost(is_cold) } else if spec_id.is_enabled_in(SpecId::TANGERINE) { 700 } else { diff --git a/crates/interpreter/src/host.rs b/crates/interpreter/src/host.rs index 231b1a315c..9b6274e64b 100644 --- a/crates/interpreter/src/host.rs +++ b/crates/interpreter/src/host.rs @@ -22,10 +22,10 @@ pub trait Host { fn balance(&mut self, address: Address) -> Option>; /// Get code of `address` and if the account is cold. - fn code(&mut self, address: Address) -> Option>; + fn code(&mut self, address: Address) -> Option>; /// Get code hash of `address` and if the account is cold. - fn code_hash(&mut self, address: Address) -> Option>; + fn code_hash(&mut self, address: Address) -> Option>; /// Get storage value of `address` at `index` and if the account is cold. fn sload(&mut self, address: Address, index: U256) -> Option>; diff --git a/crates/interpreter/src/host/dummy.rs b/crates/interpreter/src/host/dummy.rs index 602fb512da..955d250f47 100644 --- a/crates/interpreter/src/host/dummy.rs +++ b/crates/interpreter/src/host/dummy.rs @@ -4,7 +4,7 @@ use crate::{ }; use std::vec::Vec; -use super::{AccountLoad, Eip7702CodeLoad, StateLoad}; +use super::{AccountLoad, StateLoad}; /// A dummy [Host] implementation. #[derive(Clone, Debug, Default, PartialEq, Eq)] @@ -60,13 +60,13 @@ impl Host for DummyHost { } #[inline] - fn code(&mut self, _address: Address) -> Option> { + fn code(&mut self, _address: Address) -> Option> { Some(Default::default()) } #[inline] - fn code_hash(&mut self, _address: Address) -> Option> { - Some(Eip7702CodeLoad::new_not_delegated(KECCAK_EMPTY, false)) + fn code_hash(&mut self, _address: Address) -> Option> { + Some(StateLoad::new(KECCAK_EMPTY, false)) } #[inline] diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index 612cbac5c1..e708120647 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -1,5 +1,5 @@ use crate::{ - gas::{self, warm_cold_cost, warm_cold_cost_with_delegation}, + gas::{self, warm_cold_cost}, interpreter::Interpreter, primitives::{Bytes, Log, LogData, Spec, SpecId::*, B256, U256}, Host, InstructionResult, @@ -46,9 +46,8 @@ pub fn extcodesize(interpreter: &mut Interpreter, interpreter.instruction_result = InstructionResult::FatalExternalError; return; }; - let (code, load) = code.into_components(); if SPEC::enabled(BERLIN) { - gas!(interpreter, warm_cold_cost_with_delegation(load)); + gas!(interpreter, warm_cold_cost(code.is_cold)); } else if SPEC::enabled(TANGERINE) { gas!(interpreter, 700); } else { @@ -66,15 +65,14 @@ pub fn extcodehash(interpreter: &mut Interpreter, interpreter.instruction_result = InstructionResult::FatalExternalError; return; }; - let (code_hash, load) = code_hash.into_components(); if SPEC::enabled(BERLIN) { - gas!(interpreter, warm_cold_cost_with_delegation(load)) + gas!(interpreter, warm_cold_cost(code_hash.is_cold)) } else if SPEC::enabled(ISTANBUL) { gas!(interpreter, 700); } else { gas!(interpreter, 400); } - push_b256!(interpreter, code_hash); + push_b256!(interpreter, *code_hash); } pub fn extcodecopy(interpreter: &mut Interpreter, host: &mut H) { @@ -87,10 +85,9 @@ pub fn extcodecopy(interpreter: &mut Interpreter, }; let len = as_usize_or_fail!(interpreter, len_u256); - let (code, load) = code.into_components(); gas_or_fail!( interpreter, - gas::extcodecopy_cost(SPEC::SPEC_ID, len as u64, load) + gas::extcodecopy_cost(SPEC::SPEC_ID, len as u64, code.is_cold) ); if len == 0 { return; diff --git a/crates/primitives/src/eip7702.rs b/crates/primitives/src/eip7702.rs index 9571f086f1..7a1d19764f 100644 --- a/crates/primitives/src/eip7702.rs +++ b/crates/primitives/src/eip7702.rs @@ -6,7 +6,8 @@ pub use authorization_list::{ SignedAuthorization, }; pub use bytecode::{ - Eip7702Bytecode, Eip7702DecodeError, EIP7702_MAGIC, EIP7702_MAGIC_BYTES, EIP7702_VERSION, + Eip7702Bytecode, Eip7702DecodeError, EIP7702_MAGIC, EIP7702_MAGIC_BYTES, EIP7702_MAGIC_HASH, + EIP7702_VERSION, }; // Base cost of updating authorized account. diff --git a/crates/primitives/src/eip7702/bytecode.rs b/crates/primitives/src/eip7702/bytecode.rs index 268f2c4aa6..622188e8ce 100644 --- a/crates/primitives/src/eip7702/bytecode.rs +++ b/crates/primitives/src/eip7702/bytecode.rs @@ -1,6 +1,12 @@ +use alloy_primitives::{b256, B256}; + use crate::{bytes, Address, Bytes}; use core::fmt; +/// Hash of EF01 bytes that is used for EXTCODEHASH when called from legacy bytecode. +pub const EIP7702_MAGIC_HASH: B256 = + b256!("eadcdba66a79ab5dce91622d1d75c8cff5cff0b96944c3bf1072cd08ce018329"); + /// EIP-7702 Version Magic in u16 form. pub const EIP7702_MAGIC: u16 = 0xEF01; diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 137c3f1989..a9963fa4f1 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -32,6 +32,7 @@ pub use constants::*; pub use eip7702::{ Authorization, AuthorizationList, Eip7702Bytecode, Eip7702DecodeError, RecoveredAuthority, RecoveredAuthorization, Signature, SignedAuthorization, EIP7702_MAGIC, EIP7702_MAGIC_BYTES, + EIP7702_MAGIC_HASH, }; pub use env::*; diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index 14d1b12d9d..b592f3d14f 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -8,7 +8,7 @@ pub use context_precompiles::{ }; pub use evm_context::EvmContext; pub use inner_evm_context::InnerEvmContext; -use revm_interpreter::{as_u64_saturated, Eip7702CodeLoad, StateLoad}; +use revm_interpreter::{as_u64_saturated, StateLoad}; use crate::{ db::{Database, EmptyDB}, @@ -145,14 +145,14 @@ impl Host for Context { .ok() } - fn code(&mut self, address: Address) -> Option> { + fn code(&mut self, address: Address) -> Option> { self.evm .code(address) .map_err(|e| self.evm.error = Err(e)) .ok() } - fn code_hash(&mut self, address: Address) -> Option> { + fn code_hash(&mut self, address: Address) -> Option> { self.evm .code_hash(address) .map_err(|e| self.evm.error = Err(e)) diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index bc2b956efb..06855dc58a 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -1,7 +1,7 @@ use crate::{ db::Database, interpreter::{ - analysis::to_analysed, gas, return_ok, AccountLoad, Eip7702CodeLoad, InstructionResult, + analysis::to_analysed, gas, return_ok, AccountLoad, InstructionResult, InterpreterResult, SStoreResult, SelfDestructResult, StateLoad, }, journaled_state::JournaledState, @@ -9,7 +9,7 @@ use crate::{ AccessListItem, Account, Address, AnalysisKind, Bytecode, Bytes, CfgEnv, EVMError, Env, Eof, HashSet, Spec, SpecId::{self, *}, - B256, EOF_MAGIC_BYTES, EOF_MAGIC_HASH, U256, + B256, EIP7702_MAGIC_BYTES, EOF_MAGIC_BYTES, EOF_MAGIC_HASH, U256, EIP7702_MAGIC_HASH }, JournalCheckpoint, }; @@ -175,45 +175,20 @@ impl InnerEvmContext { /// /// In case of EOF account it will return `EOF_MAGIC` (0xEF00) as code. #[inline] - pub fn code( - &mut self, - address: Address, - ) -> Result, EVMError> { + pub fn code(&mut self, address: Address) -> Result, EVMError> { let a = self.journaled_state.load_code(address, &mut self.db)?; // SAFETY: safe to unwrap as load_code will insert code if it is empty. let code = a.info.code.as_ref().unwrap(); - if code.is_eof() { - return Ok(Eip7702CodeLoad::new_not_delegated( - EOF_MAGIC_BYTES.clone(), - a.is_cold, - )); - } - - if let Bytecode::Eip7702(code) = code { - let address = code.address(); - let is_cold = a.is_cold; - - let delegated_account = self.journaled_state.load_code(address, &mut self.db)?; - // SAFETY: safe to unwrap as load_code will insert code if it is empty. - let delegated_code = delegated_account.info.code.as_ref().unwrap(); - - let bytes = if delegated_code.is_eof() { - EOF_MAGIC_BYTES.clone() - } else { - delegated_code.original_bytes() - }; - - return Ok(Eip7702CodeLoad::new( - StateLoad::new(bytes, is_cold), - delegated_account.is_cold, - )); - } + let code = if code.is_eof() { + EOF_MAGIC_BYTES.clone() + } else if code.is_eip7702() { + EIP7702_MAGIC_BYTES.clone() + } else { + code.original_bytes() + }; - Ok(Eip7702CodeLoad::new_not_delegated( - code.original_bytes(), - a.is_cold, - )) + Ok(StateLoad::new(code, a.is_cold)) } /// Get code hash of address. @@ -221,45 +196,23 @@ impl InnerEvmContext { /// In case of EOF account it will return `EOF_MAGIC_HASH` /// (the hash of `0xEF00`). #[inline] - pub fn code_hash( - &mut self, - address: Address, - ) -> Result, EVMError> { + pub fn code_hash(&mut self, address: Address) -> Result, EVMError> { let acc = self.journaled_state.load_code(address, &mut self.db)?; if acc.is_empty() { - return Ok(Eip7702CodeLoad::new_not_delegated(B256::ZERO, acc.is_cold)); + return Ok(StateLoad::new(B256::ZERO, acc.is_cold)); } // SAFETY: safe to unwrap as load_code will insert code if it is empty. let code = acc.info.code.as_ref().unwrap(); - // If bytecode is EIP-7702 then we need to load the delegated account. - if let Bytecode::Eip7702(code) = code { - let address = code.address(); - let is_cold = acc.is_cold; - - let delegated_account = self.journaled_state.load_code(address, &mut self.db)?; - - let hash = if delegated_account.is_empty() { - B256::ZERO - } else if delegated_account.info.code.as_ref().unwrap().is_eof() { - EOF_MAGIC_HASH - } else { - delegated_account.info.code_hash - }; - - return Ok(Eip7702CodeLoad::new( - StateLoad::new(hash, is_cold), - delegated_account.is_cold, - )); - } - let hash = if code.is_eof() { EOF_MAGIC_HASH + } else if code.is_eip7702() { + EIP7702_MAGIC_HASH } else { acc.info.code_hash }; - Ok(Eip7702CodeLoad::new_not_delegated(hash, acc.is_cold)) + Ok(StateLoad::new(hash, acc.is_cold)) } /// Load storage slot, if storage is not present inside the account then it will be loaded from database.