revm_bytecode/
bytecode.rs1use crate::{
8 eip7702::{Eip7702Bytecode, EIP7702_MAGIC_BYTES},
9 BytecodeDecodeError, JumpTable, LegacyAnalyzedBytecode, LegacyRawBytecode,
10};
11use primitives::{alloy_primitives::Sealable, 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 Sealable for Bytecode {
31 #[inline]
32 fn hash_slow(&self) -> B256 {
33 self.hash_slow()
34 }
35}
36
37impl Bytecode {
38 #[inline]
40 pub fn new() -> Self {
41 Self::LegacyAnalyzed(LegacyAnalyzedBytecode::default())
42 }
43
44 #[inline]
46 pub fn legacy_jump_table(&self) -> Option<&JumpTable> {
47 match &self {
48 Self::LegacyAnalyzed(analyzed) => Some(analyzed.jump_table()),
49 _ => None,
50 }
51 }
52
53 #[inline]
55 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 is_eip7702(&self) -> bool {
66 matches!(self, Self::Eip7702(_))
67 }
68
69 #[inline]
71 pub fn new_legacy(raw: Bytes) -> Self {
72 Self::LegacyAnalyzed(LegacyRawBytecode(raw).into_analyzed())
73 }
74
75 #[inline]
81 pub fn new_raw(bytecode: Bytes) -> Self {
82 Self::new_raw_checked(bytecode).expect("Expect correct bytecode")
83 }
84
85 #[inline]
87 pub fn new_eip7702(address: Address) -> Self {
88 Self::Eip7702(Eip7702Bytecode::new(address))
89 }
90
91 #[inline]
95 pub fn new_raw_checked(bytes: Bytes) -> Result<Self, BytecodeDecodeError> {
96 let prefix = bytes.get(..2);
97 match prefix {
98 Some(prefix) if prefix == &EIP7702_MAGIC_BYTES => {
99 let eip7702 = Eip7702Bytecode::new_raw(bytes)?;
100 Ok(Self::Eip7702(eip7702))
101 }
102 _ => Ok(Self::new_legacy(bytes)),
103 }
104 }
105
106 #[inline]
112 pub fn new_analyzed(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self {
113 Self::LegacyAnalyzed(LegacyAnalyzedBytecode::new(
114 bytecode,
115 original_len,
116 jump_table,
117 ))
118 }
119
120 #[inline]
122 pub fn bytecode(&self) -> &Bytes {
123 match self {
124 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
125 Self::Eip7702(code) => code.raw(),
126 }
127 }
128
129 #[inline]
131 pub fn bytecode_ptr(&self) -> *const u8 {
132 self.bytecode().as_ptr()
133 }
134
135 #[inline]
137 pub fn bytes(&self) -> Bytes {
138 self.bytes_ref().clone()
139 }
140
141 #[inline]
143 pub fn bytes_ref(&self) -> &Bytes {
144 match self {
145 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
146 Self::Eip7702(code) => code.raw(),
147 }
148 }
149
150 #[inline]
152 pub fn bytes_slice(&self) -> &[u8] {
153 self.bytes_ref()
154 }
155
156 #[inline]
158 pub fn original_bytes(&self) -> Bytes {
159 match self {
160 Self::LegacyAnalyzed(analyzed) => analyzed.original_bytes(),
161 Self::Eip7702(eip7702) => eip7702.raw().clone(),
162 }
163 }
164
165 #[inline]
167 pub fn original_byte_slice(&self) -> &[u8] {
168 match self {
169 Self::LegacyAnalyzed(analyzed) => analyzed.original_byte_slice(),
170 Self::Eip7702(eip7702) => eip7702.raw(),
171 }
172 }
173
174 #[inline]
176 pub fn len(&self) -> usize {
177 self.original_byte_slice().len()
178 }
179
180 #[inline]
182 pub fn is_empty(&self) -> bool {
183 self.len() == 0
184 }
185
186 #[inline]
189 pub fn iter_opcodes(&self) -> crate::BytecodeIterator<'_> {
190 crate::BytecodeIterator::new(self)
191 }
192}