revm_bytecode/
bytecode.rs1use crate::{
8 eip7702::{Eip7702Bytecode, EIP7702_MAGIC_BYTES},
9 BytecodeDecodeError, JumpTable, LegacyAnalyzedBytecode, LegacyRawBytecode,
10};
11use primitives::{keccak256, Address, Bytes, B256, KECCAK_EMPTY};
12
13#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16pub enum Bytecode {
17 Eip7702(Eip7702Bytecode),
19 LegacyAnalyzed(LegacyAnalyzedBytecode),
21}
22
23impl Default for Bytecode {
24 #[inline]
25 fn default() -> Self {
26 Self::new()
27 }
28}
29
30impl Bytecode {
31 #[inline]
33 pub fn new() -> Self {
34 Self::LegacyAnalyzed(LegacyAnalyzedBytecode::default())
35 }
36
37 #[inline]
39 pub fn legacy_jump_table(&self) -> Option<&JumpTable> {
40 match &self {
41 Self::LegacyAnalyzed(analyzed) => Some(analyzed.jump_table()),
42 _ => None,
43 }
44 }
45
46 #[inline]
48 pub fn hash_slow(&self) -> B256 {
49 if self.is_empty() {
50 KECCAK_EMPTY
51 } else {
52 keccak256(self.original_byte_slice())
53 }
54 }
55
56 #[inline]
58 pub const fn is_eip7702(&self) -> bool {
59 matches!(self, Self::Eip7702(_))
60 }
61
62 #[inline]
64 pub fn new_legacy(raw: Bytes) -> Self {
65 Self::LegacyAnalyzed(LegacyRawBytecode(raw).into_analyzed())
66 }
67
68 #[inline]
74 pub fn new_raw(bytecode: Bytes) -> Self {
75 Self::new_raw_checked(bytecode).expect("Expect correct bytecode")
76 }
77
78 #[inline]
80 pub fn new_eip7702(address: Address) -> Self {
81 Self::Eip7702(Eip7702Bytecode::new(address))
82 }
83
84 #[inline]
88 pub fn new_raw_checked(bytes: Bytes) -> Result<Self, BytecodeDecodeError> {
89 let prefix = bytes.get(..2);
90 match prefix {
91 Some(prefix) if prefix == &EIP7702_MAGIC_BYTES => {
92 let eip7702 = Eip7702Bytecode::new_raw(bytes)?;
93 Ok(Self::Eip7702(eip7702))
94 }
95 _ => Ok(Self::new_legacy(bytes)),
96 }
97 }
98
99 #[inline]
105 pub fn new_analyzed(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self {
106 Self::LegacyAnalyzed(LegacyAnalyzedBytecode::new(
107 bytecode,
108 original_len,
109 jump_table,
110 ))
111 }
112
113 #[inline]
115 pub fn bytecode(&self) -> &Bytes {
116 match self {
117 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
118 Self::Eip7702(code) => code.raw(),
119 }
120 }
121
122 #[inline]
124 pub fn bytecode_ptr(&self) -> *const u8 {
125 self.bytecode().as_ptr()
126 }
127
128 #[inline]
130 pub fn bytes(&self) -> Bytes {
131 self.bytes_ref().clone()
132 }
133
134 #[inline]
136 pub fn bytes_ref(&self) -> &Bytes {
137 match self {
138 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
139 Self::Eip7702(code) => code.raw(),
140 }
141 }
142
143 #[inline]
145 pub fn bytes_slice(&self) -> &[u8] {
146 self.bytes_ref()
147 }
148
149 #[inline]
151 pub fn original_bytes(&self) -> Bytes {
152 match self {
153 Self::LegacyAnalyzed(analyzed) => analyzed.original_bytes(),
154 Self::Eip7702(eip7702) => eip7702.raw().clone(),
155 }
156 }
157
158 #[inline]
160 pub fn original_byte_slice(&self) -> &[u8] {
161 match self {
162 Self::LegacyAnalyzed(analyzed) => analyzed.original_byte_slice(),
163 Self::Eip7702(eip7702) => eip7702.raw(),
164 }
165 }
166
167 #[inline]
169 pub fn len(&self) -> usize {
170 self.original_byte_slice().len()
171 }
172
173 #[inline]
175 pub fn is_empty(&self) -> bool {
176 self.len() == 0
177 }
178
179 #[inline]
182 pub fn iter_opcodes(&self) -> crate::BytecodeIterator<'_> {
183 crate::BytecodeIterator::new(self)
184 }
185}