revm_rwasm_bytecode/
bytecode.rs1use crate::{
8 eip7702::{Eip7702Bytecode, EIP7702_MAGIC_BYTES},
9 ownable_account::{OwnableAccountBytecode, OWNABLE_ACCOUNT_MAGIC_BYTES},
10 rwasm::{RwasmBytecode, RWASM_MAGIC_BYTES},
11 BytecodeDecodeError, JumpTable, LegacyAnalyzedBytecode, LegacyRawBytecode,
12};
13use core::fmt::Debug;
14use primitives::{keccak256, Address, Bytes, B256, KECCAK_EMPTY};
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(Eip7702Bytecode),
22 LegacyAnalyzed(LegacyAnalyzedBytecode),
24 Rwasm(RwasmBytecode),
26 OwnableAccount(OwnableAccountBytecode),
28}
29
30impl Default for Bytecode {
31 #[inline]
32 fn default() -> Self {
33 Self::new()
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 pub fn hash_slow(&self) -> B256 {
55 if self.is_empty() {
56 KECCAK_EMPTY
57 } else {
58 keccak256(self.original_byte_slice())
59 }
60 }
61
62 pub const fn is_eip7702(&self) -> bool {
64 matches!(self, Self::Eip7702(_))
65 }
66
67 pub const fn is_ownable_account(&self) -> bool {
69 matches!(self, Self::OwnableAccount(_))
70 }
71
72 #[inline]
74 pub fn new_legacy(raw: Bytes) -> Self {
75 Self::LegacyAnalyzed(LegacyRawBytecode(raw).into_analyzed())
76 }
77
78 #[inline]
84 pub fn new_raw(bytecode: Bytes) -> Self {
85 Self::new_raw_checked(bytecode).expect("Expect correct bytecode")
86 }
87
88 #[inline]
90 pub fn new_eip7702(address: Address) -> Self {
91 Self::Eip7702(Eip7702Bytecode::new(address))
92 }
93
94 #[inline]
96 pub fn new_rwasm(raw_rwasm_module: Bytes) -> Self {
97 Self::Rwasm(RwasmBytecode::new(raw_rwasm_module).expect("Expect correct bytecode"))
98 }
99
100 #[inline]
102 pub fn new_ownable_account(address: Address, metadata: Bytes) -> Self {
103 Self::OwnableAccount(OwnableAccountBytecode::new(address, metadata))
104 }
105
106 #[inline]
110 pub fn new_raw_checked(bytes: Bytes) -> Result<Self, BytecodeDecodeError> {
111 let prefix = bytes.get(..2);
112 match prefix {
113 Some(prefix) if prefix == &EIP7702_MAGIC_BYTES => {
114 let eip7702 = Eip7702Bytecode::new_raw(bytes)?;
115 Ok(Self::Eip7702(eip7702))
116 }
117 Some(prefix) if prefix == &OWNABLE_ACCOUNT_MAGIC_BYTES => {
118 let instance = OwnableAccountBytecode::new_raw(bytes)?;
119 Ok(Self::OwnableAccount(instance))
120 }
121 Some(prefix) if prefix == &RWASM_MAGIC_BYTES => {
122 let bytecode = RwasmBytecode::new(bytes)?;
123 Ok(Self::Rwasm(bytecode))
124 }
125 _ => Ok(Self::new_legacy(bytes)),
126 }
127 }
128
129 pub fn new_analyzed(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self {
135 Self::LegacyAnalyzed(LegacyAnalyzedBytecode::new(
136 bytecode,
137 original_len,
138 jump_table,
139 ))
140 }
141
142 #[inline]
144 pub fn bytecode(&self) -> &Bytes {
145 match self {
146 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
147 Self::Eip7702(code) => code.raw(),
148 Self::OwnableAccount(code) => code.raw(),
149 Self::Rwasm(code) => code.raw(),
150 }
151 }
152
153 pub fn bytecode_ptr(&self) -> *const u8 {
155 self.bytecode().as_ptr()
156 }
157
158 #[inline]
160 pub fn bytes(&self) -> Bytes {
161 self.bytes_ref().clone()
162 }
163
164 #[inline]
166 pub fn bytes_ref(&self) -> &Bytes {
167 match self {
168 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
169 Self::Eip7702(code) => code.raw(),
170 Self::OwnableAccount(code) => code.raw(),
171 Self::Rwasm(code) => code.raw(),
172 }
173 }
174
175 #[inline]
177 pub fn bytes_slice(&self) -> &[u8] {
178 self.bytes_ref()
179 }
180
181 #[inline]
183 pub fn original_bytes(&self) -> Bytes {
184 match self {
185 Self::LegacyAnalyzed(analyzed) => analyzed.original_bytes(),
186 Self::Eip7702(eip7702) => eip7702.raw().clone(),
187 Self::OwnableAccount(metadata) => metadata.raw().clone(),
188 Self::Rwasm(bytes) => bytes.raw().clone(),
189 }
190 }
191
192 #[inline]
194 pub fn original_byte_slice(&self) -> &[u8] {
195 match self {
196 Self::LegacyAnalyzed(analyzed) => analyzed.original_byte_slice(),
197 Self::Eip7702(eip7702) => eip7702.raw(),
198 Self::OwnableAccount(data) => data.raw(),
199 Self::Rwasm(bytes) => bytes.raw(),
200 }
201 }
202
203 #[inline]
205 pub fn len(&self) -> usize {
206 self.original_byte_slice().len()
207 }
208
209 #[inline]
211 pub fn is_empty(&self) -> bool {
212 self.len() == 0
213 }
214
215 #[inline]
218 pub fn iter_opcodes(&self) -> crate::BytecodeIterator<'_> {
219 crate::BytecodeIterator::new(self)
220 }
221}