revm_bytecode/
bytecode.rs1use crate::{
8 eip7702::{Eip7702Bytecode, EIP7702_MAGIC_BYTES},
9 BytecodeDecodeError, JumpTable, LegacyAnalyzedBytecode, LegacyRawBytecode,
10};
11use primitives::{
12 alloy_primitives::Sealable, keccak256, Address, Bytes, OnceLock, B256, KECCAK_EMPTY,
13};
14use std::sync::Arc;
15
16#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub enum Bytecode {
20 Eip7702(Arc<Eip7702Bytecode>),
22 LegacyAnalyzed(Arc<LegacyAnalyzedBytecode>),
24}
25
26impl Default for Bytecode {
27 #[inline]
28 fn default() -> Self {
29 Self::new()
30 }
31}
32
33impl Sealable for Bytecode {
34 #[inline]
35 fn hash_slow(&self) -> B256 {
36 self.hash_slow()
37 }
38}
39
40impl Bytecode {
41 #[inline]
43 pub fn new() -> Self {
44 static DEFAULT_BYTECODE: OnceLock<Bytecode> = OnceLock::new();
45 DEFAULT_BYTECODE
46 .get_or_init(|| Self::LegacyAnalyzed(Arc::new(LegacyAnalyzedBytecode::default())))
47 .clone()
48 }
49
50 #[inline]
52 pub fn legacy_jump_table(&self) -> Option<&JumpTable> {
53 match &self {
54 Self::LegacyAnalyzed(analyzed) => Some(analyzed.jump_table()),
55 _ => None,
56 }
57 }
58
59 #[inline]
61 pub fn hash_slow(&self) -> B256 {
62 if self.is_empty() {
63 KECCAK_EMPTY
64 } else {
65 keccak256(self.original_byte_slice())
66 }
67 }
68
69 #[inline]
71 pub const fn is_eip7702(&self) -> bool {
72 matches!(self, Self::Eip7702(_))
73 }
74
75 #[inline]
77 pub fn new_legacy(raw: Bytes) -> Self {
78 Self::LegacyAnalyzed(Arc::new(LegacyRawBytecode(raw).into_analyzed()))
79 }
80
81 #[inline]
87 pub fn new_raw(bytecode: Bytes) -> Self {
88 Self::new_raw_checked(bytecode).expect("Expect correct bytecode")
89 }
90
91 #[inline]
93 pub fn new_eip7702(address: Address) -> Self {
94 Self::Eip7702(Arc::new(Eip7702Bytecode::new(address)))
95 }
96
97 #[inline]
101 pub fn new_raw_checked(bytes: Bytes) -> Result<Self, BytecodeDecodeError> {
102 let prefix = bytes.get(..2);
103 match prefix {
104 Some(prefix) if prefix == &EIP7702_MAGIC_BYTES => {
105 let eip7702 = Eip7702Bytecode::new_raw(bytes)?;
106 Ok(Self::Eip7702(Arc::new(eip7702)))
107 }
108 _ => Ok(Self::new_legacy(bytes)),
109 }
110 }
111
112 #[inline]
118 pub fn new_analyzed(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self {
119 Self::LegacyAnalyzed(Arc::new(LegacyAnalyzedBytecode::new(
120 bytecode,
121 original_len,
122 jump_table,
123 )))
124 }
125
126 #[inline]
128 pub fn bytecode(&self) -> &Bytes {
129 match self {
130 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
131 Self::Eip7702(code) => code.raw(),
132 }
133 }
134
135 #[inline]
137 pub fn bytecode_ptr(&self) -> *const u8 {
138 self.bytecode().as_ptr()
139 }
140
141 #[inline]
143 pub fn bytes(&self) -> Bytes {
144 self.bytes_ref().clone()
145 }
146
147 #[inline]
149 pub fn bytes_ref(&self) -> &Bytes {
150 match self {
151 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
152 Self::Eip7702(code) => code.raw(),
153 }
154 }
155
156 #[inline]
158 pub fn bytes_slice(&self) -> &[u8] {
159 self.bytes_ref()
160 }
161
162 #[inline]
164 pub fn original_bytes(&self) -> Bytes {
165 match self {
166 Self::LegacyAnalyzed(analyzed) => analyzed.original_bytes(),
167 Self::Eip7702(eip7702) => eip7702.raw().clone(),
168 }
169 }
170
171 #[inline]
173 pub fn original_byte_slice(&self) -> &[u8] {
174 match self {
175 Self::LegacyAnalyzed(analyzed) => analyzed.original_byte_slice(),
176 Self::Eip7702(eip7702) => eip7702.raw(),
177 }
178 }
179
180 #[inline]
182 pub fn len(&self) -> usize {
183 self.original_byte_slice().len()
184 }
185
186 #[inline]
188 pub fn is_empty(&self) -> bool {
189 self.len() == 0
190 }
191
192 #[inline]
195 pub fn iter_opcodes(&self) -> crate::BytecodeIterator<'_> {
196 crate::BytecodeIterator::new(self)
197 }
198}