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 fn new_analyzed(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self {
121 Self::LegacyAnalyzed(LegacyAnalyzedBytecode::new(
122 bytecode,
123 original_len,
124 jump_table,
125 ))
126 }
127
128 #[inline]
132 pub fn bytecode(&self) -> &Bytes {
133 match self {
134 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
135 Self::Eof(eof) => &eof.body.code,
136 Self::Eip7702(code) => code.raw(),
137 }
138 }
139
140 pub fn bytecode_ptr(&self) -> *const u8 {
145 self.bytecode().as_ptr()
146 }
147
148 #[inline]
150 pub fn bytes(&self) -> Bytes {
151 self.bytes_ref().clone()
152 }
153
154 #[inline]
156 pub fn bytes_ref(&self) -> &Bytes {
157 match self {
158 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
159 Self::Eof(eof) => &eof.raw,
160 Self::Eip7702(code) => code.raw(),
161 }
162 }
163
164 #[inline]
166 pub fn bytes_slice(&self) -> &[u8] {
167 self.bytes_ref()
168 }
169
170 #[inline]
172 pub fn original_bytes(&self) -> Bytes {
173 match self {
174 Self::LegacyAnalyzed(analyzed) => analyzed.original_bytes(),
175 Self::Eof(eof) => eof.raw().clone(),
176 Self::Eip7702(eip7702) => eip7702.raw().clone(),
177 }
178 }
179
180 #[inline]
182 pub fn original_byte_slice(&self) -> &[u8] {
183 match self {
184 Self::LegacyAnalyzed(analyzed) => analyzed.original_byte_slice(),
185 Self::Eof(eof) => eof.raw(),
186 Self::Eip7702(eip7702) => eip7702.raw(),
187 }
188 }
189
190 #[inline]
192 pub fn len(&self) -> usize {
193 self.original_byte_slice().len()
194 }
195
196 #[inline]
198 pub fn is_empty(&self) -> bool {
199 self.len() == 0
200 }
201}
202
203#[cfg(test)]
204mod tests {
205 use super::{Bytecode, Eof};
206 use std::sync::Arc;
207
208 #[test]
209 fn eof_arc_clone() {
210 let eof = Arc::new(Eof::default());
211 let bytecode = Bytecode::Eof(Arc::clone(&eof));
212
213 let cloned_bytecode = bytecode.clone();
215 if let Bytecode::Eof(original_arc) = bytecode {
216 if let Bytecode::Eof(cloned_arc) = cloned_bytecode {
217 assert!(Arc::ptr_eq(&original_arc, &cloned_arc));
218 } else {
219 panic!("Cloned bytecode is not Eof");
220 }
221 } else {
222 panic!("Original bytecode is not Eof");
223 }
224 }
225}