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 primitives::{
14 alloy_primitives::Sealable, keccak256, Address, Bytes, OnceLock, B256, KECCAK_EMPTY,
15};
16use std::sync::Arc;
17
18#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21pub enum Bytecode {
22 Eip7702(Arc<Eip7702Bytecode>),
24 LegacyAnalyzed(Arc<LegacyAnalyzedBytecode>),
26 Rwasm(RwasmBytecode),
28 OwnableAccount(OwnableAccountBytecode),
30}
31
32impl Default for Bytecode {
33 #[inline]
34 fn default() -> Self {
35 Self::new()
36 }
37}
38
39impl Sealable for Bytecode {
40 #[inline]
41 fn hash_slow(&self) -> B256 {
42 self.hash_slow()
43 }
44}
45
46impl Bytecode {
47 #[inline]
49 pub fn new() -> Self {
50 static DEFAULT_BYTECODE: OnceLock<Bytecode> = OnceLock::new();
51 DEFAULT_BYTECODE
52 .get_or_init(|| Self::LegacyAnalyzed(Arc::new(LegacyAnalyzedBytecode::default())))
53 .clone()
54 }
55
56 #[inline]
58 pub fn legacy_jump_table(&self) -> Option<&JumpTable> {
59 match &self {
60 Self::LegacyAnalyzed(analyzed) => Some(analyzed.jump_table()),
61 _ => None,
62 }
63 }
64
65 #[inline]
67 pub fn hash_slow(&self) -> B256 {
68 if self.is_empty() {
69 KECCAK_EMPTY
70 } else {
71 keccak256(self.original_byte_slice())
72 }
73 }
74
75 #[inline]
77 pub const fn is_eip7702(&self) -> bool {
78 matches!(self, Self::Eip7702(_))
79 }
80
81 pub const fn is_ownable_account(&self) -> bool {
83 matches!(self, Self::OwnableAccount(_))
84 }
85
86 #[inline]
88 pub fn new_legacy(raw: Bytes) -> Self {
89 Self::LegacyAnalyzed(Arc::new(LegacyRawBytecode(raw).into_analyzed()))
90 }
91
92 #[inline]
98 pub fn new_raw(bytecode: Bytes) -> Self {
99 Self::new_raw_checked(bytecode).expect("Expect correct bytecode")
100 }
101
102 #[inline]
104 pub fn new_eip7702(address: Address) -> Self {
105 Self::Eip7702(Arc::new(Eip7702Bytecode::new(address)))
106 }
107
108 #[inline]
110 pub fn new_rwasm(raw_rwasm_module: Bytes) -> Self {
111 Self::Rwasm(RwasmBytecode::new(raw_rwasm_module).expect("Expect correct bytecode"))
112 }
113
114 #[inline]
116 pub fn new_ownable_account(address: Address, metadata: Bytes) -> Self {
117 Self::OwnableAccount(OwnableAccountBytecode::new(address, metadata))
118 }
119
120 #[inline]
124 pub fn new_raw_checked(bytes: Bytes) -> Result<Self, BytecodeDecodeError> {
125 let prefix = bytes.get(..2);
126 match prefix {
127 Some(prefix) if prefix == &EIP7702_MAGIC_BYTES => {
128 let eip7702 = Eip7702Bytecode::new_raw(bytes)?;
129 Ok(Self::Eip7702(Arc::new(eip7702)))
130 }
131 Some(prefix) if prefix == &OWNABLE_ACCOUNT_MAGIC_BYTES => {
132 let instance = OwnableAccountBytecode::new_raw(bytes)?;
133 Ok(Self::OwnableAccount(instance))
134 }
135 Some(prefix) if prefix == &RWASM_MAGIC_BYTES => {
136 let bytecode = RwasmBytecode::new(bytes)?;
137 Ok(Self::Rwasm(bytecode))
138 }
139 _ => Ok(Self::new_legacy(bytes)),
140 }
141 }
142
143 #[inline]
149 pub fn new_analyzed(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self {
150 Self::LegacyAnalyzed(Arc::new(LegacyAnalyzedBytecode::new(
151 bytecode,
152 original_len,
153 jump_table,
154 )))
155 }
156
157 #[inline]
159 pub fn bytecode(&self) -> &Bytes {
160 match self {
161 Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
162 Self::Eip7702(code) => code.raw(),
163 Self::OwnableAccount(code) => code.raw(),
164 Self::Rwasm(code) => code.raw(),
165 }
166 }
167
168 #[inline]
170 pub fn bytecode_ptr(&self) -> *const u8 {
171 self.bytecode().as_ptr()
172 }
173
174 #[inline]
176 pub fn bytes(&self) -> Bytes {
177 self.bytes_ref().clone()
178 }
179
180 #[inline]
182 pub fn bytes_ref(&self) -> &Bytes {
183 self.bytecode()
184 }
185
186 #[inline]
188 pub fn bytes_slice(&self) -> &[u8] {
189 self.bytes_ref()
190 }
191
192 #[inline]
194 pub fn original_bytes(&self) -> Bytes {
195 match self {
196 Self::LegacyAnalyzed(analyzed) => analyzed.original_bytes(),
197 Self::Eip7702(eip7702) => eip7702.raw().clone(),
198 Self::OwnableAccount(metadata) => metadata.raw().clone(),
199 Self::Rwasm(bytes) => bytes.raw().clone(),
200 }
201 }
202
203 #[inline]
205 pub fn original_byte_slice(&self) -> &[u8] {
206 match self {
207 Self::LegacyAnalyzed(analyzed) => analyzed.original_byte_slice(),
208 Self::Eip7702(eip7702) => eip7702.raw(),
209 Self::OwnableAccount(data) => data.raw(),
210 Self::Rwasm(bytes) => bytes.raw(),
211 }
212 }
213
214 #[inline]
216 pub fn len(&self) -> usize {
217 self.original_byte_slice().len()
218 }
219
220 #[inline]
222 pub fn is_empty(&self) -> bool {
223 self.len() == 0
224 }
225
226 #[inline]
229 pub fn iter_opcodes(&self) -> crate::BytecodeIterator<'_> {
230 crate::BytecodeIterator::new(self)
231 }
232}