Skip to content

Commit

Permalink
feat: apply latest EIP-7702 changes
Browse files Browse the repository at this point in the history
  • Loading branch information
klkvr committed Nov 7, 2024
1 parent 900409f commit 43a685a
Show file tree
Hide file tree
Showing 9 changed files with 41 additions and 83 deletions.
4 changes: 2 additions & 2 deletions crates/interpreter/src/gas/calc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ pub const fn verylowcopy_cost(len: u64) -> Option<u64> {

/// `EXTCODECOPY` opcode cost calculation.
#[inline]
pub const fn extcodecopy_cost(spec_id: SpecId, len: u64, load: Eip7702CodeLoad<()>) -> Option<u64> {
pub const fn extcodecopy_cost(spec_id: SpecId, len: u64, is_cold: bool) -> Option<u64> {
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 {
Expand Down
4 changes: 2 additions & 2 deletions crates/interpreter/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ pub trait Host {
fn balance(&mut self, address: Address) -> Option<StateLoad<U256>>;

/// Get code of `address` and if the account is cold.
fn code(&mut self, address: Address) -> Option<Eip7702CodeLoad<Bytes>>;
fn code(&mut self, address: Address) -> Option<StateLoad<Bytes>>;

/// Get code hash of `address` and if the account is cold.
fn code_hash(&mut self, address: Address) -> Option<Eip7702CodeLoad<B256>>;
fn code_hash(&mut self, address: Address) -> Option<StateLoad<B256>>;

/// Get storage value of `address` at `index` and if the account is cold.
fn sload(&mut self, address: Address, index: U256) -> Option<StateLoad<U256>>;
Expand Down
8 changes: 4 additions & 4 deletions crates/interpreter/src/host/dummy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -60,13 +60,13 @@ impl Host for DummyHost {
}

#[inline]
fn code(&mut self, _address: Address) -> Option<Eip7702CodeLoad<Bytes>> {
fn code(&mut self, _address: Address) -> Option<StateLoad<Bytes>> {
Some(Default::default())
}

#[inline]
fn code_hash(&mut self, _address: Address) -> Option<Eip7702CodeLoad<B256>> {
Some(Eip7702CodeLoad::new_not_delegated(KECCAK_EMPTY, false))
fn code_hash(&mut self, _address: Address) -> Option<StateLoad<B256>> {
Some(StateLoad::new(KECCAK_EMPTY, false))
}

#[inline]
Expand Down
13 changes: 5 additions & 8 deletions crates/interpreter/src/instructions/host.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -46,9 +46,8 @@ pub fn extcodesize<H: Host + ?Sized, SPEC: Spec>(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 {
Expand All @@ -66,15 +65,14 @@ pub fn extcodehash<H: Host + ?Sized, SPEC: Spec>(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<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
Expand All @@ -87,10 +85,9 @@ pub fn extcodecopy<H: Host + ?Sized, SPEC: Spec>(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;
Expand Down
3 changes: 2 additions & 1 deletion crates/primitives/src/eip7702.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 6 additions & 0 deletions crates/primitives/src/eip7702/bytecode.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down
1 change: 1 addition & 0 deletions crates/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;

Expand Down
6 changes: 3 additions & 3 deletions crates/revm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -145,14 +145,14 @@ impl<EXT, DB: Database> Host for Context<EXT, DB> {
.ok()
}

fn code(&mut self, address: Address) -> Option<Eip7702CodeLoad<Bytes>> {
fn code(&mut self, address: Address) -> Option<StateLoad<Bytes>> {
self.evm
.code(address)
.map_err(|e| self.evm.error = Err(e))
.ok()
}

fn code_hash(&mut self, address: Address) -> Option<Eip7702CodeLoad<B256>> {
fn code_hash(&mut self, address: Address) -> Option<StateLoad<B256>> {
self.evm
.code_hash(address)
.map_err(|e| self.evm.error = Err(e))
Expand Down
79 changes: 16 additions & 63 deletions crates/revm/src/context/inner_evm_context.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
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,
primitives::{
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,
};
Expand Down Expand Up @@ -175,91 +175,44 @@ impl<DB: Database> InnerEvmContext<DB> {
///
/// In case of EOF account it will return `EOF_MAGIC` (0xEF00) as code.
#[inline]
pub fn code(
&mut self,
address: Address,
) -> Result<Eip7702CodeLoad<Bytes>, EVMError<DB::Error>> {
pub fn code(&mut self, address: Address) -> Result<StateLoad<Bytes>, EVMError<DB::Error>> {
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.
///
/// 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<Eip7702CodeLoad<B256>, EVMError<DB::Error>> {
pub fn code_hash(&mut self, address: Address) -> Result<StateLoad<B256>, EVMError<DB::Error>> {
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.
Expand Down

0 comments on commit 43a685a

Please sign in to comment.