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