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 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 pub const fn is_eip7702(&self) -> bool {
58 matches!(self, Self::Eip7702(_))
59 }
60
61 #[inline]
63 pub fn new_legacy(raw: Bytes) -> Self {
64 Self::LegacyAnalyzed(LegacyRawBytecode(raw).into_analyzed())
65 }
66
67 #[inline]
73 pub fn new_raw(bytecode: Bytes) -> Self {
74 Self::new_raw_checked(bytecode).expect("Expect correct bytecode")
75 }
76
77 #[inline]
79 pub fn new_eip7702(address: Address) -> Self {
80 Self::Eip7702(Eip7702Bytecode::new(address))
81 }
82
83 #[inline]
87 pub fn new_raw_checked(bytes: Bytes) -> Result<Self, BytecodeDecodeError> {
88 let prefix = bytes.get(..2);
89 match prefix {
90 Some(prefix) if prefix == &EIP7702_MAGIC_BYTES => {
91 let eip7702 = Eip7702Bytecode::new_raw(bytes)?;
92 Ok(Self::Eip7702(eip7702))
93 }
94 _ => Ok(Self::new_legacy(bytes)),
95 }
96 }
97
98 pub fn new_analyzed(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self {
104 Self::LegacyAnalyzed(LegacyAnalyzedBytecode::new(
105 bytecode,
106 original_len,
107 jump_table,
108 ))
109 }
110
111 #[inline]
113 pub fn bytecode(&self) -> &Bytes {
114 match self {
115 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
116 Self::Eip7702(code) => code.raw(),
117 }
118 }
119
120 pub fn bytecode_ptr(&self) -> *const u8 {
122 self.bytecode().as_ptr()
123 }
124
125 #[inline]
127 pub fn bytes(&self) -> Bytes {
128 self.bytes_ref().clone()
129 }
130
131 #[inline]
133 pub fn bytes_ref(&self) -> &Bytes {
134 match self {
135 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
136 Self::Eip7702(code) => code.raw(),
137 }
138 }
139
140 #[inline]
142 pub fn bytes_slice(&self) -> &[u8] {
143 self.bytes_ref()
144 }
145
146 #[inline]
148 pub fn original_bytes(&self) -> Bytes {
149 match self {
150 Self::LegacyAnalyzed(analyzed) => analyzed.original_bytes(),
151 Self::Eip7702(eip7702) => eip7702.raw().clone(),
152 }
153 }
154
155 #[inline]
157 pub fn original_byte_slice(&self) -> &[u8] {
158 match self {
159 Self::LegacyAnalyzed(analyzed) => analyzed.original_byte_slice(),
160 Self::Eip7702(eip7702) => eip7702.raw(),
161 }
162 }
163
164 #[inline]
166 pub fn len(&self) -> usize {
167 self.original_byte_slice().len()
168 }
169
170 #[inline]
172 pub fn is_empty(&self) -> bool {
173 self.len() == 0
174 }
175
176 #[inline]
179 pub fn iter_opcodes(&self) -> crate::BytecodeIterator<'_> {
180 crate::BytecodeIterator::new(self)
181 }
182}