Skip to content

Commit 649b7c5

Browse files
authored
feat(EOF): EXTCODECOPY,EXTCODESIZE,EXTCODEHASH eof support (#1504)
* feat(EOF): EXTCODECOPY,EXTCODESIZE,EXTCODEHASH eof support * eof magic bytes from array * clippy
1 parent e244ac4 commit 649b7c5

File tree

7 files changed

+40
-15
lines changed

7 files changed

+40
-15
lines changed

crates/interpreter/src/host.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::primitives::{Address, Bytecode, Env, Log, B256, U256};
1+
use crate::primitives::{Address, Bytes, Env, Log, B256, U256};
22

33
mod dummy;
44
pub use dummy::DummyHost;
@@ -23,7 +23,7 @@ pub trait Host {
2323
fn balance(&mut self, address: Address) -> Option<(U256, bool)>;
2424

2525
/// Get code of `address` and if the account is cold.
26-
fn code(&mut self, address: Address) -> Option<(Bytecode, bool)>;
26+
fn code(&mut self, address: Address) -> Option<(Bytes, bool)>;
2727

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

crates/interpreter/src/host/dummy.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use crate::primitives::{hash_map::Entry, Bytecode, HashMap, U256};
21
use crate::{
3-
primitives::{Address, Env, Log, B256, KECCAK_EMPTY},
2+
primitives::{hash_map::Entry, Address, Bytes, Env, HashMap, Log, B256, KECCAK_EMPTY, U256},
43
Host, SStoreResult, SelfDestructResult,
54
};
65
use std::vec::Vec;
@@ -61,8 +60,8 @@ impl Host for DummyHost {
6160
}
6261

6362
#[inline]
64-
fn code(&mut self, _address: Address) -> Option<(Bytecode, bool)> {
65-
Some((Bytecode::default(), false))
63+
fn code(&mut self, _address: Address) -> Option<(Bytes, bool)> {
64+
Some((Bytes::default(), false))
6665
}
6766

6867
#[inline]

crates/interpreter/src/instructions/host.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub fn extcodecopy<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter,
9999
// Note: this can't panic because we resized memory to fit.
100100
interpreter
101101
.shared_memory
102-
.set_data(memory_offset, code_offset, len, &code.original_bytes());
102+
.set_data(memory_offset, code_offset, len, &code);
103103
}
104104

105105
pub fn blockhash<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {

crates/primitives/src/bytecode.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pub mod eof;
22
pub mod legacy;
33

4-
pub use eof::Eof;
4+
pub use eof::{Eof, EOF_MAGIC, EOF_MAGIC_BYTES, EOF_MAGIC_HASH};
55
pub use legacy::{JumpTable, LegacyAnalyzedBytecode};
66

77
use crate::{keccak256, Bytes, B256, KECCAK_EMPTY};

crates/primitives/src/bytecode/eof.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,20 @@ pub use body::EofBody;
77
pub use header::EofHeader;
88
pub use types_section::TypesSection;
99

10-
use crate::Bytes;
10+
use crate::{b256, bytes, Bytes, B256};
1111
use core::cmp::min;
1212
use std::{vec, vec::Vec};
1313

14+
/// Hash of EF00 bytes that is used for EXTCODEHASH when called from legacy bytecode.
15+
pub const EOF_MAGIC_HASH: B256 =
16+
b256!("9dbf3648db8210552e9c4f75c6a1c3057c0ca432043bd648be15fe7be05646f5");
17+
18+
/// EOF Magic in u16 form.
19+
pub const EOF_MAGIC: u16 = 0xEF00;
20+
21+
/// EOF magic number in array form.
22+
pub static EOF_MAGIC_BYTES: Bytes = bytes!("ef00");
23+
1424
/// EOF - Ethereum Object Format.
1525
///
1626
/// It consist of a header, body and raw original bytes Specified in EIP.

crates/revm/src/context.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use revm_interpreter::as_usize_saturated;
1313
use crate::{
1414
db::{Database, EmptyDB},
1515
interpreter::{Host, LoadAccountResult, SStoreResult, SelfDestructResult},
16-
primitives::{Address, Bytecode, Env, HandlerCfg, Log, B256, BLOCK_HASH_HISTORY, U256},
16+
primitives::{Address, Bytes, Env, HandlerCfg, Log, B256, BLOCK_HASH_HISTORY, U256},
1717
};
1818
use std::boxed::Box;
1919

@@ -146,7 +146,7 @@ impl<EXT, DB: Database> Host for Context<EXT, DB> {
146146
.ok()
147147
}
148148

149-
fn code(&mut self, address: Address) -> Option<(Bytecode, bool)> {
149+
fn code(&mut self, address: Address) -> Option<(Bytes, bool)> {
150150
self.evm
151151
.code(address)
152152
.map_err(|e| self.evm.error = Err(e))

crates/revm/src/context/inner_evm_context.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
keccak256, Account, Address, AnalysisKind, Bytecode, Bytes, CreateScheme, EVMError, Env,
1111
Eof, HashSet, Spec,
1212
SpecId::{self, *},
13-
B256, U256,
13+
B256, EOF_MAGIC_BYTES, EOF_MAGIC_HASH, U256,
1414
},
1515
FrameOrResult, JournalCheckpoint, CALL_STACK_LIMIT,
1616
};
@@ -160,21 +160,37 @@ impl<DB: Database> InnerEvmContext<DB> {
160160
.map(|(acc, is_cold)| (acc.info.balance, is_cold))
161161
}
162162

163-
/// Return account code and if address is cold loaded.
163+
/// Return account code bytes and if address is cold loaded.
164+
///
165+
/// In case of EOF account it will return `EOF_MAGIC` (0xEF00) as code.
164166
#[inline]
165-
pub fn code(&mut self, address: Address) -> Result<(Bytecode, bool), EVMError<DB::Error>> {
167+
pub fn code(&mut self, address: Address) -> Result<(Bytes, bool), EVMError<DB::Error>> {
166168
self.journaled_state
167169
.load_code(address, &mut self.db)
168-
.map(|(a, is_cold)| (a.info.code.clone().unwrap(), is_cold))
170+
.map(|(a, is_cold)| {
171+
// SAFETY: safe to unwrap as load_code will insert code if it is empty.
172+
let code = a.info.code.as_ref().unwrap();
173+
if code.is_eof() {
174+
(EOF_MAGIC_BYTES.clone(), is_cold)
175+
} else {
176+
(code.original_bytes().clone(), is_cold)
177+
}
178+
})
169179
}
170180

171181
/// Get code hash of address.
182+
///
183+
/// In case of EOF account it will return `EOF_MAGIC_HASH`
184+
/// (the hash of `0xEF00`).
172185
#[inline]
173186
pub fn code_hash(&mut self, address: Address) -> Result<(B256, bool), EVMError<DB::Error>> {
174187
let (acc, is_cold) = self.journaled_state.load_code(address, &mut self.db)?;
175188
if acc.is_empty() {
176189
return Ok((B256::ZERO, is_cold));
177190
}
191+
if let Some(true) = acc.info.code.as_ref().map(|code| code.is_eof()) {
192+
return Ok((EOF_MAGIC_HASH, is_cold));
193+
}
178194
Ok((acc.info.code_hash, is_cold))
179195
}
180196

0 commit comments

Comments
 (0)