revm_bytecode/
bytecode.rs1use crate::{
2 eip7702::{Eip7702Bytecode, EIP7702_MAGIC_BYTES},
3 BytecodeDecodeError, Eof, JumpTable, LegacyAnalyzedBytecode, LegacyRawBytecode,
4 EOF_MAGIC_BYTES,
5};
6use core::fmt::Debug;
7use primitives::{keccak256, Address, Bytes, B256, KECCAK_EMPTY};
8use std::sync::Arc;
9
10#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub enum Bytecode {
14 LegacyAnalyzed(LegacyAnalyzedBytecode),
16 Eof(Arc<Eof>),
18 Eip7702(Eip7702Bytecode),
20}
21
22impl Default for Bytecode {
23 #[inline]
24 fn default() -> Self {
25 Self::new()
26 }
27}
28
29impl Bytecode {
30 #[inline]
32 pub fn new() -> Self {
33 Self::LegacyAnalyzed(LegacyAnalyzedBytecode::default())
34 }
35
36 #[inline]
38 pub fn legacy_jump_table(&self) -> Option<&JumpTable> {
39 match &self {
40 Self::LegacyAnalyzed(analyzed) => Some(analyzed.jump_table()),
41 _ => None,
42 }
43 }
44
45 pub fn hash_slow(&self) -> B256 {
47 if self.is_empty() {
48 KECCAK_EMPTY
49 } else {
50 keccak256(self.original_byte_slice())
51 }
52 }
53
54 #[inline]
56 pub const fn eof(&self) -> Option<&Arc<Eof>> {
57 match self {
58 Self::Eof(eof) => Some(eof),
59 _ => None,
60 }
61 }
62
63 #[inline]
65 pub const fn is_eof(&self) -> bool {
66 matches!(self, Self::Eof(_))
67 }
68
69 pub const fn is_eip7702(&self) -> bool {
71 matches!(self, Self::Eip7702(_))
72 }
73
74 #[inline]
76 pub fn new_legacy(raw: Bytes) -> Self {
77 Self::LegacyAnalyzed(LegacyRawBytecode(raw).into_analyzed())
78 }
79
80 #[inline]
86 pub fn new_raw(bytecode: Bytes) -> Self {
87 Self::new_raw_checked(bytecode).expect("Expect correct EOF bytecode")
88 }
89
90 #[inline]
92 pub fn new_eip7702(address: Address) -> Self {
93 Self::Eip7702(Eip7702Bytecode::new(address))
94 }
95
96 #[inline]
100 pub fn new_raw_checked(bytes: Bytes) -> Result<Self, BytecodeDecodeError> {
101 let prefix = bytes.get(..2);
102 match prefix {
103 Some(prefix) if prefix == &EOF_MAGIC_BYTES => {
104 let eof = Eof::decode(bytes)?;
105 Ok(Self::Eof(Arc::new(eof)))
106 }
107 Some(prefix) if prefix == &EIP7702_MAGIC_BYTES => {
108 let eip7702 = Eip7702Bytecode::new_raw(bytes)?;
109 Ok(Self::Eip7702(eip7702))
110 }
111 _ => Ok(Self::new_legacy(bytes)),
112 }
113 }
114
115 pub unsafe fn new_analyzed(
122 bytecode: Bytes,
123 original_len: usize,
124 jump_table: JumpTable,
125 ) -> Self {
126 Self::LegacyAnalyzed(LegacyAnalyzedBytecode::new(
127 bytecode,
128 original_len,
129 jump_table,
130 ))
131 }
132
133 #[inline]
137 pub fn bytecode(&self) -> &Bytes {
138 match self {
139 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
140 Self::Eof(eof) => &eof.body.code,
141 Self::Eip7702(code) => code.raw(),
142 }
143 }
144
145 pub fn bytecode_ptr(&self) -> *const u8 {
150 self.bytecode().as_ptr()
151 }
152
153 #[inline]
155 pub fn bytes(&self) -> Bytes {
156 self.bytes_ref().clone()
157 }
158
159 #[inline]
161 pub fn bytes_ref(&self) -> &Bytes {
162 match self {
163 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
164 Self::Eof(eof) => &eof.raw,
165 Self::Eip7702(code) => code.raw(),
166 }
167 }
168
169 #[inline]
171 pub fn bytes_slice(&self) -> &[u8] {
172 self.bytes_ref()
173 }
174
175 #[inline]
177 pub fn original_bytes(&self) -> Bytes {
178 match self {
179 Self::LegacyAnalyzed(analyzed) => analyzed.original_bytes(),
180 Self::Eof(eof) => eof.raw().clone(),
181 Self::Eip7702(eip7702) => eip7702.raw().clone(),
182 }
183 }
184
185 #[inline]
187 pub fn original_byte_slice(&self) -> &[u8] {
188 match self {
189 Self::LegacyAnalyzed(analyzed) => analyzed.original_byte_slice(),
190 Self::Eof(eof) => eof.raw(),
191 Self::Eip7702(eip7702) => eip7702.raw(),
192 }
193 }
194
195 #[inline]
197 pub fn len(&self) -> usize {
198 self.original_byte_slice().len()
199 }
200
201 #[inline]
203 pub fn is_empty(&self) -> bool {
204 self.len() == 0
205 }
206}
207
208#[cfg(test)]
209mod tests {
210 use super::{Bytecode, Eof};
211 use std::sync::Arc;
212
213 #[test]
214 fn eof_arc_clone() {
215 let eof = Arc::new(Eof::default());
216 let bytecode = Bytecode::Eof(Arc::clone(&eof));
217
218 let cloned_bytecode = bytecode.clone();
220 if let Bytecode::Eof(original_arc) = bytecode {
221 if let Bytecode::Eof(cloned_arc) = cloned_bytecode {
222 assert!(Arc::ptr_eq(&original_arc, &cloned_arc));
223 } else {
224 panic!("Cloned bytecode is not Eof");
225 }
226 } else {
227 panic!("Original bytecode is not Eof");
228 }
229 }
230}