1use alloc::boxed::Box;
4use core::{
5 marker::PhantomData,
6 ops::{Deref, DerefMut},
7};
8
9use crate::{
10 Control, ExitException, Machine, Opcode,
11 eval::*,
12 runtime::{GasState, RuntimeBackend, RuntimeConfig, RuntimeEnvironment, RuntimeState},
13 trap::CallCreateTrap,
14};
15
16pub trait Etable<H> {
19 type State;
21 type Trap;
23
24 fn eval(
30 &self,
31 machine: &mut Machine<Self::State>,
32 handle: &mut H,
33 position: usize,
34 ) -> Control<Self::Trap>;
35}
36
37pub struct Chained<E1, E2>(pub E1, pub E2);
40
41impl<S, H, Tr, E1, E2> Etable<H> for Chained<E1, E2>
42where
43 E1: Etable<H, State = S, Trap = Tr>,
44 E2: Etable<H, State = S, Trap = Tr>,
45{
46 type State = S;
47 type Trap = Tr;
48
49 fn eval(&self, machine: &mut Machine<S>, handle: &mut H, position: usize) -> Control<Tr> {
50 let ret1 = self.0.eval(machine, handle, position);
51
52 if let Control::NoAction = ret1 {
53 self.1.eval(machine, handle, position)
54 } else {
55 ret1
56 }
57 }
58}
59
60pub struct Tracing<EPre, E, EPost>(pub EPre, pub E, pub EPost);
62
63impl<S, H, Tr, EPre, E, EPost> Etable<H> for Tracing<EPre, E, EPost>
64where
65 EPre: Etable<H, State = S, Trap = Tr>,
66 E: Etable<H, State = S, Trap = Tr>,
67 EPost: Etable<H, State = S, Trap = Tr>,
68{
69 type State = S;
70 type Trap = Tr;
71
72 fn eval(&self, machine: &mut Machine<S>, handle: &mut H, position: usize) -> Control<Tr> {
73 let _ = self.0.eval(machine, handle, position);
74 let ret = self.1.eval(machine, handle, position);
75 let _ = self.2.eval(machine, handle, position);
76
77 ret
78 }
79}
80
81pub type Efn<S, H, Tr> = fn(&mut Machine<S>, &mut H, usize) -> Control<Tr>;
83
84pub struct Single<S, H, Tr, F = Efn<S, H, Tr>>(F, PhantomData<(S, H, Tr)>);
86
87unsafe impl<S, H, Tr, F: Send> Send for Single<S, H, Tr, F> {}
88unsafe impl<S, H, Tr, F: Sync> Sync for Single<S, H, Tr, F> {}
89
90impl<S, H, Tr, F> Deref for Single<S, H, Tr, F> {
91 type Target = F;
92
93 fn deref(&self) -> &F {
94 &self.0
95 }
96}
97
98impl<S, H, Tr, F> DerefMut for Single<S, H, Tr, F> {
99 fn deref_mut(&mut self) -> &mut F {
100 &mut self.0
101 }
102}
103
104impl<S, H, Tr, F> Single<S, H, Tr, F> {
105 pub fn new(single: F) -> Self {
107 Self(single, PhantomData)
108 }
109}
110
111impl<S, H, Tr, F> Etable<H> for Single<S, H, Tr, F>
112where
113 F: Fn(&mut Machine<S>, &mut H, usize) -> Control<Tr>,
114{
115 type State = S;
116 type Trap = Tr;
117
118 fn eval(&self, machine: &mut Machine<S>, handle: &mut H, position: usize) -> Control<Tr> {
119 self.0(machine, handle, position)
120 }
121}
122
123pub enum MultiEfn<S, H, Tr, F = Efn<S, H, Tr>> {
125 Leaf(F),
127 Node(Box<MultiEtable<S, H, Tr, F>>),
129}
130
131unsafe impl<S, H, Tr, F: Send> Send for MultiEfn<S, H, Tr, F> {}
132unsafe impl<S, H, Tr, F: Sync> Sync for MultiEfn<S, H, Tr, F> {}
133
134pub struct MultiEtable<S, H, Tr, F = Efn<S, H, Tr>>(
136 [MultiEfn<S, H, Tr, F>; 256],
137 PhantomData<(S, H, Tr)>,
138);
139
140unsafe impl<S, H, Tr, F: Send> Send for MultiEtable<S, H, Tr, F> {}
141unsafe impl<S, H, Tr, F: Sync> Sync for MultiEtable<S, H, Tr, F> {}
142
143impl<S, H, Tr, F> Deref for MultiEtable<S, H, Tr, F> {
144 type Target = [MultiEfn<S, H, Tr, F>; 256];
145
146 fn deref(&self) -> &[MultiEfn<S, H, Tr, F>; 256] {
147 &self.0
148 }
149}
150
151impl<S, H, Tr, F> DerefMut for MultiEtable<S, H, Tr, F> {
152 fn deref_mut(&mut self) -> &mut [MultiEfn<S, H, Tr, F>; 256] {
153 &mut self.0
154 }
155}
156
157impl<S, H, Tr, F> From<DispatchEtable<S, H, Tr, F>> for MultiEtable<S, H, Tr, F> {
158 fn from(etable: DispatchEtable<S, H, Tr, F>) -> Self {
159 Self(etable.0.map(|v| MultiEfn::Leaf(v)), PhantomData)
160 }
161}
162
163impl<S, H, Tr, F> Etable<H> for MultiEtable<S, H, Tr, F>
164where
165 F: Fn(&mut Machine<S>, &mut H, usize) -> Control<Tr>,
166{
167 type State = S;
168 type Trap = Tr;
169
170 fn eval(&self, machine: &mut Machine<S>, handle: &mut H, position: usize) -> Control<Tr> {
171 let opcode = Opcode(machine.code()[position]);
172
173 match &self[opcode.as_usize()] {
174 MultiEfn::Leaf(f) => f(machine, handle, position),
175 MultiEfn::Node(n) => {
176 let nextpos = position + 1;
177 if nextpos >= machine.code.len() {
178 return Control::Exit(ExitException::PCUnderflow.into());
179 }
180
181 match n.eval(machine, handle, nextpos) {
182 Control::Continue(c) => Control::Continue(c + 1),
183 ctrl => ctrl,
184 }
185 }
186 }
187 }
188}
189
190pub struct DispatchEtable<S, H, Tr, F = Efn<S, H, Tr>>([F; 256], PhantomData<(S, H, Tr)>);
192
193unsafe impl<S, H, Tr, F: Send> Send for DispatchEtable<S, H, Tr, F> {}
194unsafe impl<S, H, Tr, F: Sync> Sync for DispatchEtable<S, H, Tr, F> {}
195
196impl<S, H, Tr, F> Deref for DispatchEtable<S, H, Tr, F> {
197 type Target = [F; 256];
198
199 fn deref(&self) -> &[F; 256] {
200 &self.0
201 }
202}
203
204impl<S, H, Tr, F> DerefMut for DispatchEtable<S, H, Tr, F> {
205 fn deref_mut(&mut self) -> &mut [F; 256] {
206 &mut self.0
207 }
208}
209
210impl<S, H, Tr, F> From<Single<S, H, Tr, F>> for DispatchEtable<S, H, Tr, F>
211where
212 F: Copy,
213{
214 fn from(single: Single<S, H, Tr, F>) -> Self {
215 Self([single.0; 256], PhantomData)
216 }
217}
218
219impl<S, H, Tr, F> Etable<H> for DispatchEtable<S, H, Tr, F>
220where
221 F: Fn(&mut Machine<S>, &mut H, usize) -> Control<Tr>,
222{
223 type State = S;
224 type Trap = Tr;
225
226 fn eval(&self, machine: &mut Machine<S>, handle: &mut H, position: usize) -> Control<Tr> {
227 let opcode = Opcode(machine.code()[position]);
228
229 self[opcode.as_usize()](machine, handle, position)
230 }
231}
232
233impl<S, H, Tr, F> DispatchEtable<S, H, Tr, F>
234where
235 F: Fn(&mut Machine<S>, &mut H, usize) -> Control<Tr>,
236{
237 pub fn wrap<FW, FR>(self, wrapper: FW) -> DispatchEtable<S, H, Tr, FR>
239 where
240 FW: Fn(F, Opcode) -> FR,
241 FR: Fn(&mut Machine<S>, &mut H, usize) -> Control<Tr>,
242 {
243 let mut current_opcode = Opcode(0);
244 DispatchEtable(
245 self.0.map(|f| {
246 let fr = wrapper(f, current_opcode);
247 if current_opcode != Opcode(255) {
248 current_opcode.0 += 1;
249 }
250 fr
251 }),
252 PhantomData,
253 )
254 }
255}
256
257impl<S, H, Tr> DispatchEtable<S, H, Tr> {
258 #[must_use]
260 pub const fn none() -> Self {
261 Self([eval_unknown as _; 256], PhantomData)
262 }
263
264 #[must_use]
266 pub const fn pass() -> Self {
267 Self([eval_pass as _; 256], PhantomData)
268 }
269
270 #[must_use]
272 pub const fn core() -> Self {
273 let mut table = [eval_unknown as _; 256];
274
275 table[Opcode::STOP.as_usize()] = eval_stop as _;
276 table[Opcode::ADD.as_usize()] = eval_add as _;
277 table[Opcode::MUL.as_usize()] = eval_mul as _;
278 table[Opcode::SUB.as_usize()] = eval_sub as _;
279 table[Opcode::DIV.as_usize()] = eval_div as _;
280 table[Opcode::SDIV.as_usize()] = eval_sdiv as _;
281 table[Opcode::MOD.as_usize()] = eval_mod as _;
282 table[Opcode::SMOD.as_usize()] = eval_smod as _;
283 table[Opcode::ADDMOD.as_usize()] = eval_addmod as _;
284 table[Opcode::MULMOD.as_usize()] = eval_mulmod as _;
285 table[Opcode::EXP.as_usize()] = eval_exp as _;
286 table[Opcode::SIGNEXTEND.as_usize()] = eval_signextend as _;
287
288 table[Opcode::LT.as_usize()] = eval_lt as _;
289 table[Opcode::GT.as_usize()] = eval_gt as _;
290 table[Opcode::SLT.as_usize()] = eval_slt as _;
291 table[Opcode::SGT.as_usize()] = eval_sgt as _;
292 table[Opcode::EQ.as_usize()] = eval_eq as _;
293 table[Opcode::ISZERO.as_usize()] = eval_iszero as _;
294 table[Opcode::AND.as_usize()] = eval_and as _;
295 table[Opcode::OR.as_usize()] = eval_or as _;
296 table[Opcode::XOR.as_usize()] = eval_xor as _;
297 table[Opcode::NOT.as_usize()] = eval_not as _;
298 table[Opcode::BYTE.as_usize()] = eval_byte as _;
299
300 table[Opcode::SHL.as_usize()] = eval_shl as _;
301 table[Opcode::SHR.as_usize()] = eval_shr as _;
302 table[Opcode::SAR.as_usize()] = eval_sar as _;
303
304 table[Opcode::CALLDATALOAD.as_usize()] = eval_calldataload as _;
305 table[Opcode::CALLDATASIZE.as_usize()] = eval_calldatasize as _;
306 table[Opcode::CALLDATACOPY.as_usize()] = eval_calldatacopy as _;
307 table[Opcode::CODESIZE.as_usize()] = eval_codesize as _;
308 table[Opcode::CODECOPY.as_usize()] = eval_codecopy as _;
309
310 table[Opcode::POP.as_usize()] = eval_pop as _;
311 table[Opcode::MLOAD.as_usize()] = eval_mload as _;
312 table[Opcode::MSTORE.as_usize()] = eval_mstore as _;
313 table[Opcode::MSTORE8.as_usize()] = eval_mstore8 as _;
314
315 table[Opcode::JUMP.as_usize()] = eval_jump as _;
316 table[Opcode::JUMPI.as_usize()] = eval_jumpi as _;
317 table[Opcode::PC.as_usize()] = eval_pc as _;
318 table[Opcode::MSIZE.as_usize()] = eval_msize as _;
319
320 table[Opcode::JUMPDEST.as_usize()] = eval_jumpdest as _;
321 table[Opcode::MCOPY.as_usize()] = eval_mcopy as _;
322
323 table[Opcode::PUSH0.as_usize()] = eval_push0 as _;
324 table[Opcode::PUSH1.as_usize()] = eval_push1 as _;
325 table[Opcode::PUSH2.as_usize()] = eval_push2 as _;
326 table[Opcode::PUSH3.as_usize()] = eval_push3 as _;
327 table[Opcode::PUSH4.as_usize()] = eval_push4 as _;
328 table[Opcode::PUSH5.as_usize()] = eval_push5 as _;
329 table[Opcode::PUSH6.as_usize()] = eval_push6 as _;
330 table[Opcode::PUSH7.as_usize()] = eval_push7 as _;
331 table[Opcode::PUSH8.as_usize()] = eval_push8 as _;
332 table[Opcode::PUSH9.as_usize()] = eval_push9 as _;
333 table[Opcode::PUSH10.as_usize()] = eval_push10 as _;
334 table[Opcode::PUSH11.as_usize()] = eval_push11 as _;
335 table[Opcode::PUSH12.as_usize()] = eval_push12 as _;
336 table[Opcode::PUSH13.as_usize()] = eval_push13 as _;
337 table[Opcode::PUSH14.as_usize()] = eval_push14 as _;
338 table[Opcode::PUSH15.as_usize()] = eval_push15 as _;
339 table[Opcode::PUSH16.as_usize()] = eval_push16 as _;
340 table[Opcode::PUSH17.as_usize()] = eval_push17 as _;
341 table[Opcode::PUSH18.as_usize()] = eval_push18 as _;
342 table[Opcode::PUSH19.as_usize()] = eval_push19 as _;
343 table[Opcode::PUSH20.as_usize()] = eval_push20 as _;
344 table[Opcode::PUSH21.as_usize()] = eval_push21 as _;
345 table[Opcode::PUSH22.as_usize()] = eval_push22 as _;
346 table[Opcode::PUSH23.as_usize()] = eval_push23 as _;
347 table[Opcode::PUSH24.as_usize()] = eval_push24 as _;
348 table[Opcode::PUSH25.as_usize()] = eval_push25 as _;
349 table[Opcode::PUSH26.as_usize()] = eval_push26 as _;
350 table[Opcode::PUSH27.as_usize()] = eval_push27 as _;
351 table[Opcode::PUSH28.as_usize()] = eval_push28 as _;
352 table[Opcode::PUSH29.as_usize()] = eval_push29 as _;
353 table[Opcode::PUSH30.as_usize()] = eval_push30 as _;
354 table[Opcode::PUSH31.as_usize()] = eval_push31 as _;
355 table[Opcode::PUSH32.as_usize()] = eval_push32 as _;
356
357 table[Opcode::DUP1.as_usize()] = eval_dup1 as _;
358 table[Opcode::DUP2.as_usize()] = eval_dup2 as _;
359 table[Opcode::DUP3.as_usize()] = eval_dup3 as _;
360 table[Opcode::DUP4.as_usize()] = eval_dup4 as _;
361 table[Opcode::DUP5.as_usize()] = eval_dup5 as _;
362 table[Opcode::DUP6.as_usize()] = eval_dup6 as _;
363 table[Opcode::DUP7.as_usize()] = eval_dup7 as _;
364 table[Opcode::DUP8.as_usize()] = eval_dup8 as _;
365 table[Opcode::DUP9.as_usize()] = eval_dup9 as _;
366 table[Opcode::DUP10.as_usize()] = eval_dup10 as _;
367 table[Opcode::DUP11.as_usize()] = eval_dup11 as _;
368 table[Opcode::DUP12.as_usize()] = eval_dup12 as _;
369 table[Opcode::DUP13.as_usize()] = eval_dup13 as _;
370 table[Opcode::DUP14.as_usize()] = eval_dup14 as _;
371 table[Opcode::DUP15.as_usize()] = eval_dup15 as _;
372 table[Opcode::DUP16.as_usize()] = eval_dup16 as _;
373
374 table[Opcode::SWAP1.as_usize()] = eval_swap1 as _;
375 table[Opcode::SWAP2.as_usize()] = eval_swap2 as _;
376 table[Opcode::SWAP3.as_usize()] = eval_swap3 as _;
377 table[Opcode::SWAP4.as_usize()] = eval_swap4 as _;
378 table[Opcode::SWAP5.as_usize()] = eval_swap5 as _;
379 table[Opcode::SWAP6.as_usize()] = eval_swap6 as _;
380 table[Opcode::SWAP7.as_usize()] = eval_swap7 as _;
381 table[Opcode::SWAP8.as_usize()] = eval_swap8 as _;
382 table[Opcode::SWAP9.as_usize()] = eval_swap9 as _;
383 table[Opcode::SWAP10.as_usize()] = eval_swap10 as _;
384 table[Opcode::SWAP11.as_usize()] = eval_swap11 as _;
385 table[Opcode::SWAP12.as_usize()] = eval_swap12 as _;
386 table[Opcode::SWAP13.as_usize()] = eval_swap13 as _;
387 table[Opcode::SWAP14.as_usize()] = eval_swap14 as _;
388 table[Opcode::SWAP15.as_usize()] = eval_swap15 as _;
389 table[Opcode::SWAP16.as_usize()] = eval_swap16 as _;
390
391 table[Opcode::RETURN.as_usize()] = eval_return as _;
392
393 table[Opcode::REVERT.as_usize()] = eval_revert as _;
394
395 table[Opcode::INVALID.as_usize()] = eval_invalid as _;
396
397 Self(table, PhantomData)
398 }
399}
400
401impl<S, H: RuntimeEnvironment + RuntimeBackend, Tr> DispatchEtable<S, H, Tr>
402where
403 S: AsRef<RuntimeState> + AsMut<RuntimeState> + AsRef<RuntimeConfig> + GasState,
404 Tr: From<CallCreateTrap>,
405{
406 #[must_use]
408 pub const fn runtime() -> Self {
409 let mut table = Self::core();
410
411 table.0[Opcode::SHA3.as_usize()] = eval_sha3 as _;
412
413 table.0[Opcode::ADDRESS.as_usize()] = eval_address as _;
414 table.0[Opcode::BALANCE.as_usize()] = eval_balance as _;
415 table.0[Opcode::ORIGIN.as_usize()] = eval_origin as _;
416 table.0[Opcode::CALLER.as_usize()] = eval_caller as _;
417 table.0[Opcode::CALLVALUE.as_usize()] = eval_callvalue as _;
418
419 table.0[Opcode::GASPRICE.as_usize()] = eval_gasprice as _;
420 table.0[Opcode::EXTCODESIZE.as_usize()] = eval_extcodesize as _;
421 table.0[Opcode::EXTCODECOPY.as_usize()] = eval_extcodecopy as _;
422 table.0[Opcode::RETURNDATASIZE.as_usize()] = eval_returndatasize as _;
423 table.0[Opcode::RETURNDATACOPY.as_usize()] = eval_returndatacopy as _;
424 table.0[Opcode::EXTCODEHASH.as_usize()] = eval_extcodehash as _;
425
426 table.0[Opcode::BLOCKHASH.as_usize()] = eval_blockhash as _;
427 table.0[Opcode::COINBASE.as_usize()] = eval_coinbase as _;
428 table.0[Opcode::TIMESTAMP.as_usize()] = eval_timestamp as _;
429 table.0[Opcode::NUMBER.as_usize()] = eval_number as _;
430 table.0[Opcode::DIFFICULTY.as_usize()] = eval_difficulty as _;
431 table.0[Opcode::GASLIMIT.as_usize()] = eval_gaslimit as _;
432 table.0[Opcode::CHAINID.as_usize()] = eval_chainid as _;
433 table.0[Opcode::SELFBALANCE.as_usize()] = eval_selfbalance as _;
434 table.0[Opcode::BASEFEE.as_usize()] = eval_basefee as _;
435 table.0[Opcode::BLOBHASH.as_usize()] = eval_blobhash as _;
436 table.0[Opcode::BLOBBASEFEE.as_usize()] = eval_blobbasefee as _;
437
438 table.0[Opcode::SLOAD.as_usize()] = eval_sload as _;
439 table.0[Opcode::SSTORE.as_usize()] = eval_sstore as _;
440
441 table.0[Opcode::GAS.as_usize()] = eval_gas as _;
442
443 table.0[Opcode::TLOAD.as_usize()] = eval_tload as _;
444 table.0[Opcode::TSTORE.as_usize()] = eval_tstore as _;
445
446 table.0[Opcode::LOG0.as_usize()] = eval_log0 as _;
447 table.0[Opcode::LOG1.as_usize()] = eval_log1 as _;
448 table.0[Opcode::LOG2.as_usize()] = eval_log2 as _;
449 table.0[Opcode::LOG3.as_usize()] = eval_log3 as _;
450 table.0[Opcode::LOG4.as_usize()] = eval_log4 as _;
451
452 table.0[Opcode::CREATE.as_usize()] = eval_call_create_trap as _;
453 table.0[Opcode::CALL.as_usize()] = eval_call_create_trap as _;
454 table.0[Opcode::CALLCODE.as_usize()] = eval_call_create_trap as _;
455
456 table.0[Opcode::DELEGATECALL.as_usize()] = eval_call_create_trap as _;
457 table.0[Opcode::CREATE2.as_usize()] = eval_call_create_trap as _;
458
459 table.0[Opcode::STATICCALL.as_usize()] = eval_call_create_trap as _;
460
461 table.0[Opcode::SUICIDE.as_usize()] = eval_suicide as _;
462
463 table
464 }
465}