revm_bytecode/
bytecode.rs1use crate::{
9 eip7702::{Eip7702Bytecode, EIP7702_MAGIC_BYTES},
10 BytecodeDecodeError, Eof, JumpTable, LegacyAnalyzedBytecode, LegacyRawBytecode,
11 EOF_MAGIC_BYTES,
12};
13use core::fmt::Debug;
14use primitives::{keccak256, Address, Bytes, B256, KECCAK_EMPTY};
15use std::sync::Arc;
16
17#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20pub enum Bytecode {
21 LegacyAnalyzed(LegacyAnalyzedBytecode),
23 Eof(Arc<Eof>),
25 Eip7702(Eip7702Bytecode),
27}
28
29impl Default for Bytecode {
30 #[inline]
31 fn default() -> Self {
32 Self::new()
33 }
34}
35
36impl Bytecode {
37 #[inline]
39 pub fn new() -> Self {
40 Self::LegacyAnalyzed(LegacyAnalyzedBytecode::default())
41 }
42
43 #[inline]
45 pub fn legacy_jump_table(&self) -> Option<&JumpTable> {
46 match &self {
47 Self::LegacyAnalyzed(analyzed) => Some(analyzed.jump_table()),
48 _ => None,
49 }
50 }
51
52 pub fn hash_slow(&self) -> B256 {
54 if self.is_empty() {
55 KECCAK_EMPTY
56 } else {
57 keccak256(self.original_byte_slice())
58 }
59 }
60
61 #[inline]
63 pub const fn eof(&self) -> Option<&Arc<Eof>> {
64 match self {
65 Self::Eof(eof) => Some(eof),
66 _ => None,
67 }
68 }
69
70 #[inline]
72 pub const fn is_eof(&self) -> bool {
73 matches!(self, Self::Eof(_))
74 }
75
76 pub const fn is_eip7702(&self) -> bool {
78 matches!(self, Self::Eip7702(_))
79 }
80
81 #[inline]
83 pub fn new_legacy(raw: Bytes) -> Self {
84 Self::LegacyAnalyzed(LegacyRawBytecode(raw).into_analyzed())
85 }
86
87 #[inline]
93 pub fn new_raw(bytecode: Bytes) -> Self {
94 Self::new_raw_checked(bytecode).expect("Expect correct EOF bytecode")
95 }
96
97 #[inline]
99 pub fn new_eip7702(address: Address) -> Self {
100 Self::Eip7702(Eip7702Bytecode::new(address))
101 }
102
103 #[inline]
107 pub fn new_raw_checked(bytes: Bytes) -> Result<Self, BytecodeDecodeError> {
108 let prefix = bytes.get(..2);
109 match prefix {
110 Some(prefix) if prefix == &EOF_MAGIC_BYTES => {
111 let eof = Eof::decode(bytes)?;
112 Ok(Self::Eof(Arc::new(eof)))
113 }
114 Some(prefix) if prefix == &EIP7702_MAGIC_BYTES => {
115 let eip7702 = Eip7702Bytecode::new_raw(bytes)?;
116 Ok(Self::Eip7702(eip7702))
117 }
118 _ => Ok(Self::new_legacy(bytes)),
119 }
120 }
121
122 pub fn new_analyzed(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self {
128 Self::LegacyAnalyzed(LegacyAnalyzedBytecode::new(
129 bytecode,
130 original_len,
131 jump_table,
132 ))
133 }
134
135 #[inline]
139 pub fn bytecode(&self) -> &Bytes {
140 match self {
141 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
142 Self::Eof(eof) => &eof.body.code,
143 Self::Eip7702(code) => code.raw(),
144 }
145 }
146
147 pub fn bytecode_ptr(&self) -> *const u8 {
152 self.bytecode().as_ptr()
153 }
154
155 #[inline]
157 pub fn bytes(&self) -> Bytes {
158 self.bytes_ref().clone()
159 }
160
161 #[inline]
163 pub fn bytes_ref(&self) -> &Bytes {
164 match self {
165 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
166 Self::Eof(eof) => &eof.raw,
167 Self::Eip7702(code) => code.raw(),
168 }
169 }
170
171 #[inline]
173 pub fn bytes_slice(&self) -> &[u8] {
174 self.bytes_ref()
175 }
176
177 #[inline]
179 pub fn original_bytes(&self) -> Bytes {
180 match self {
181 Self::LegacyAnalyzed(analyzed) => analyzed.original_bytes(),
182 Self::Eof(eof) => eof.raw().clone(),
183 Self::Eip7702(eip7702) => eip7702.raw().clone(),
184 }
185 }
186
187 #[inline]
189 pub fn original_byte_slice(&self) -> &[u8] {
190 match self {
191 Self::LegacyAnalyzed(analyzed) => analyzed.original_byte_slice(),
192 Self::Eof(eof) => eof.raw(),
193 Self::Eip7702(eip7702) => eip7702.raw(),
194 }
195 }
196
197 #[inline]
199 pub fn len(&self) -> usize {
200 self.original_byte_slice().len()
201 }
202
203 #[inline]
205 pub fn is_empty(&self) -> bool {
206 self.len() == 0
207 }
208
209 #[inline]
212 pub fn iter_opcodes(&self) -> crate::iterator::BytecodeIterator<'_> {
213 crate::iterator::BytecodeIterator::new(self)
214 }
215}
216
217#[cfg(test)]
218mod tests {
219 use super::{Bytecode, Eof};
220 use std::sync::Arc;
221
222 #[test]
223 fn eof_arc_clone() {
224 let eof = Arc::new(Eof::default());
225 let bytecode = Bytecode::Eof(Arc::clone(&eof));
226
227 let cloned_bytecode = bytecode.clone();
229 if let Bytecode::Eof(original_arc) = bytecode {
230 if let Bytecode::Eof(cloned_arc) = cloned_bytecode {
231 assert!(Arc::ptr_eq(&original_arc, &cloned_arc));
232 } else {
233 panic!("Cloned bytecode is not Eof");
234 }
235 } else {
236 panic!("Original bytecode is not Eof");
237 }
238 }
239}