revm_primitives/
bytecode.rs
1pub mod eof;
2pub mod legacy;
3
4pub use eof::{Eof, EOF_MAGIC, EOF_MAGIC_BYTES, EOF_MAGIC_HASH};
5pub use legacy::{JumpTable, LegacyAnalyzedBytecode};
6
7use crate::{
8 eip7702::bytecode::Eip7702DecodeError, keccak256, Bytes, Eip7702Bytecode, B256,
9 EIP7702_MAGIC_BYTES, KECCAK_EMPTY,
10};
11use alloy_primitives::Address;
12use core::fmt::Debug;
13use eof::EofDecodeError;
14use std::{fmt, sync::Arc};
15
16#[derive(Clone, Debug, PartialEq, Eq, Hash)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub enum Bytecode {
20 LegacyRaw(Bytes),
22 LegacyAnalyzed(LegacyAnalyzedBytecode),
24 Eof(Arc<Eof>),
26 Eip7702(Eip7702Bytecode),
28}
29
30impl Default for Bytecode {
31 #[inline]
32 fn default() -> Self {
33 Self::new()
35 }
36}
37
38impl Bytecode {
39 #[inline]
41 pub fn new() -> Self {
42 Self::LegacyAnalyzed(LegacyAnalyzedBytecode::default())
43 }
44
45 #[inline]
47 pub fn legacy_jump_table(&self) -> Option<&JumpTable> {
48 match &self {
49 Self::LegacyAnalyzed(analyzed) => Some(analyzed.jump_table()),
50 _ => None,
51 }
52 }
53
54 pub fn hash_slow(&self) -> B256 {
56 if self.is_empty() {
57 KECCAK_EMPTY
58 } else {
59 keccak256(self.original_byte_slice())
60 }
61 }
62
63 #[inline]
65 pub const fn eof(&self) -> Option<&Arc<Eof>> {
66 match self {
67 Self::Eof(eof) => Some(eof),
68 _ => None,
69 }
70 }
71
72 #[inline]
74 pub const fn is_eof(&self) -> bool {
75 matches!(self, Self::Eof(_))
76 }
77
78 pub const fn is_eip7702(&self) -> bool {
80 matches!(self, Self::Eip7702(_))
81 }
82
83 #[inline]
85 pub fn new_legacy(raw: Bytes) -> Self {
86 Self::LegacyRaw(raw)
87 }
88
89 #[inline]
95 pub fn new_raw(bytecode: Bytes) -> Self {
96 Self::new_raw_checked(bytecode).expect("Expect correct EOF bytecode")
97 }
98
99 #[inline]
101 pub fn new_eip7702(address: Address) -> Self {
102 Self::Eip7702(Eip7702Bytecode::new(address))
103 }
104
105 #[inline]
109 pub fn new_raw_checked(bytecode: Bytes) -> Result<Self, BytecodeDecodeError> {
110 let prefix = bytecode.get(..2);
111 match prefix {
112 Some(prefix) if prefix == &EOF_MAGIC_BYTES => {
113 let eof = Eof::decode(bytecode)?;
114 Ok(Self::Eof(Arc::new(eof)))
115 }
116 Some(prefix) if prefix == &EIP7702_MAGIC_BYTES => {
117 let eip7702 = Eip7702Bytecode::new_raw(bytecode)?;
118 Ok(Self::Eip7702(eip7702))
119 }
120 _ => Ok(Self::LegacyRaw(bytecode)),
121 }
122 }
123
124 pub unsafe fn new_analyzed(
131 bytecode: Bytes,
132 original_len: usize,
133 jump_table: JumpTable,
134 ) -> Self {
135 Self::LegacyAnalyzed(LegacyAnalyzedBytecode::new(
136 bytecode,
137 original_len,
138 jump_table,
139 ))
140 }
141
142 #[inline]
146 pub fn bytecode(&self) -> &Bytes {
147 match self {
148 Self::LegacyRaw(bytes) => bytes,
149 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
150 Self::Eof(eof) => eof
151 .body
152 .code(0)
153 .expect("Valid EOF has at least one code section"),
154 Self::Eip7702(code) => code.raw(),
155 }
156 }
157
158 pub fn is_execution_ready(&self) -> bool {
160 !matches!(self, Self::LegacyRaw(_))
161 }
162
163 #[inline]
165 pub fn bytes(&self) -> Bytes {
166 match self {
167 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode().clone(),
168 _ => self.original_bytes(),
169 }
170 }
171
172 #[inline]
174 pub fn bytes_slice(&self) -> &[u8] {
175 match self {
176 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
177 _ => self.original_byte_slice(),
178 }
179 }
180
181 #[inline]
183 pub fn original_bytes(&self) -> Bytes {
184 match self {
185 Self::LegacyRaw(bytes) => bytes.clone(),
186 Self::LegacyAnalyzed(analyzed) => analyzed.original_bytes(),
187 Self::Eof(eof) => eof.raw().clone(),
188 Self::Eip7702(eip7702) => eip7702.raw().clone(),
189 }
190 }
191
192 #[inline]
194 pub fn original_byte_slice(&self) -> &[u8] {
195 match self {
196 Self::LegacyRaw(bytes) => bytes,
197 Self::LegacyAnalyzed(analyzed) => analyzed.original_byte_slice(),
198 Self::Eof(eof) => eof.raw(),
199 Self::Eip7702(eip7702) => eip7702.raw(),
200 }
201 }
202
203 #[inline]
205 pub fn len(&self) -> usize {
206 self.original_byte_slice().len()
207 }
208
209 #[inline]
211 pub fn is_empty(&self) -> bool {
212 self.len() == 0
213 }
214}
215
216#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
218#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
219pub enum BytecodeDecodeError {
220 Eof(EofDecodeError),
222 Eip7702(Eip7702DecodeError),
224}
225
226impl From<EofDecodeError> for BytecodeDecodeError {
227 fn from(error: EofDecodeError) -> Self {
228 Self::Eof(error)
229 }
230}
231
232impl From<Eip7702DecodeError> for BytecodeDecodeError {
233 fn from(error: Eip7702DecodeError) -> Self {
234 Self::Eip7702(error)
235 }
236}
237
238#[cfg(feature = "std")]
239impl std::error::Error for BytecodeDecodeError {}
240
241impl fmt::Display for BytecodeDecodeError {
242 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
243 match self {
244 Self::Eof(e) => fmt::Display::fmt(e, f),
245 Self::Eip7702(e) => fmt::Display::fmt(e, f),
246 }
247 }
248}
249
250#[cfg(test)]
251mod tests {
252 use super::{Bytecode, Eof};
253 use std::sync::Arc;
254
255 #[test]
256 fn eof_arc_clone() {
257 let eof = Arc::new(Eof::default());
258 let bytecode = Bytecode::Eof(Arc::clone(&eof));
259
260 let cloned_bytecode = bytecode.clone();
262 if let Bytecode::Eof(original_arc) = bytecode {
263 if let Bytecode::Eof(cloned_arc) = cloned_bytecode {
264 assert!(Arc::ptr_eq(&original_arc, &cloned_arc));
265 } else {
266 panic!("Cloned bytecode is not Eof");
267 }
268 } else {
269 panic!("Original bytecode is not Eof");
270 }
271 }
272}