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: apply latest EIP-7702 changes #1850

Merged
merged 9 commits into from
Dec 7, 2024
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
254 changes: 163 additions & 91 deletions Cargo.lock

Large diffs are not rendered by default.

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
2 changes: 1 addition & 1 deletion crates/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ alloy-eip2930 = { version = "0.1", default-features = false }
alloy-eip7702 = { version = "0.4", default-features = false, features = [
"k256",
] }
alloy-primitives = { version = "0.8.8", default-features = false, features = [
alloy-primitives = { version = "0.8", default-features = false, features = [
"rlp",
"map",
] }
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
8 changes: 4 additions & 4 deletions crates/revm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ ethers-providers = { version = "2.0", optional = true }
ethers-core = { version = "2.0", optional = true }

# alloydb
alloy-provider = { version = "0.5.4", optional = true, default-features = false }
alloy-eips = { version = "0.5.4", optional = true, default-features = false }
alloy-transport = { version = "0.5.4", optional = true, default-features = false }
alloy-provider = { version = "0.7", optional = true, default-features = false }
alloy-eips = { version = "0.7", optional = true, default-features = false }
alloy-transport = { version = "0.7", optional = true, default-features = false }

[dev-dependencies]
alloy-sol-types = { version = "0.8.2", default-features = false, features = [
Expand All @@ -66,7 +66,7 @@ criterion = "0.5"
indicatif = "0.17"
reqwest = { version = "0.12" }
rstest = "0.22.0"
alloy-provider = "0.5.3"
alloy-provider = "0.7"

[features]
default = ["std", "c-kzg", "secp256k1", "portable", "blst"]
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
81 changes: 17 additions & 64 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,
InterpreterResult, SStoreResult, SelfDestructResult, StateLoad,
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, EIP7702_MAGIC_HASH, EOF_MAGIC_BYTES, EOF_MAGIC_HASH, U256,
},
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
4 changes: 2 additions & 2 deletions crates/revm/src/db/alloydb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
};
use alloy_eips::BlockId;
use alloy_provider::{
network::{BlockResponse, HeaderResponse},
network::{primitives::HeaderResponse, BlockResponse},
Network, Provider,
};
use alloy_transport::{Transport, TransportError};
Expand Down Expand Up @@ -129,7 +129,7 @@ impl<T: Transport + Clone, N: Network, P: Provider<T, N>> DatabaseRef for AlloyD
let block = self.block_on(
self.provider
// SAFETY: We know number <= u64::MAX, so we can safely convert it to u64
.get_block_by_number(number.into(), false),
.get_block_by_number(number.into(), false.into()),
)?;
// SAFETY: If the number is given, the block is supposed to be finalized, so unwrapping is safe.
Ok(B256::new(*block.unwrap().header().hash()))
Expand Down
Loading