1#[cfg(not(feature = "std"))]
4pub mod prelude {
5 pub use alloc::{borrow::Cow, rc::Rc, vec, vec::Vec};
6}
7#[cfg(feature = "std")]
8pub mod prelude {
9 pub use std::{borrow::Cow, rc::Rc, vec::Vec};
10}
11
12mod error;
13mod eval;
14mod external;
15mod memory;
16mod opcode;
17mod stack;
18pub mod utils;
19mod valids;
20
21pub use error::{Capture, ExitError, ExitFatal, ExitReason, ExitRevert, ExitSucceed, Trap};
22pub use external::ExternalOperation;
23pub use memory::Memory;
24pub use opcode::Opcode;
25pub use stack::Stack;
26pub use valids::Valids;
27
28use crate::utils::U256_ZERO;
29use core::ops::Range;
30use eval::{eval, Control};
31use prelude::*;
32use primitive_types::{H160, U256};
33use utils::USIZE_MAX;
34
35pub struct Machine {
37 data: Rc<Vec<u8>>,
39 code: Rc<Vec<u8>>,
41 position: Result<usize, ExitReason>,
43 return_range: Range<U256>,
45 valids: Valids,
47 memory: Memory,
49 stack: Stack,
51}
52
53pub trait InterpreterHandler {
55 fn before_bytecode(
58 &mut self,
59 opcode: Opcode,
60 pc: usize,
61 machine: &Machine,
62 address: &H160,
63 ) -> Result<(), ExitError>;
64
65 #[cfg(feature = "tracing")]
67 fn after_bytecode(&mut self, result: &Result<(), Capture<ExitReason, Trap>>, machine: &Machine);
68}
69
70impl Machine {
71 #[must_use]
73 pub const fn stack(&self) -> &Stack {
74 &self.stack
75 }
76 pub const fn stack_mut(&mut self) -> &mut Stack {
78 &mut self.stack
79 }
80 #[must_use]
82 pub const fn memory(&self) -> &Memory {
83 &self.memory
84 }
85 pub const fn memory_mut(&mut self) -> &mut Memory {
87 &mut self.memory
88 }
89 pub const fn position(&self) -> &Result<usize, ExitReason> {
91 &self.position
92 }
93
94 #[must_use]
96 pub fn new(
97 code: Rc<Vec<u8>>,
98 data: Rc<Vec<u8>>,
99 stack_limit: usize,
100 memory_limit: usize,
101 ) -> Self {
102 let valids = Valids::new(&code[..]);
103
104 Self {
105 data,
106 code,
107 position: Ok(0),
108 return_range: U256_ZERO..U256_ZERO,
109 valids,
110 memory: Memory::new(memory_limit),
111 stack: Stack::new(stack_limit),
112 }
113 }
114
115 pub fn exit(&mut self, reason: ExitReason) {
117 self.position = Err(reason);
118 }
119
120 #[must_use]
122 pub fn inspect(&self) -> Option<(Opcode, &Stack)> {
123 let Ok(position) = self.position else {
124 return None;
125 };
126 self.code.get(position).map(|v| (Opcode(*v), &self.stack))
127 }
128
129 #[must_use]
131 pub fn return_value(&self) -> Vec<u8> {
132 if self.return_range.start > USIZE_MAX {
133 vec![0; (self.return_range.end - self.return_range.start).as_usize()]
134 } else if self.return_range.end > USIZE_MAX {
135 let mut ret = self.memory.get(
136 self.return_range.start.as_usize(),
137 usize::MAX - self.return_range.start.as_usize(),
138 );
139
140 let new_len = (self.return_range.end - self.return_range.start).as_usize();
141 if ret.len() < new_len {
142 ret.resize(new_len, 0);
143 }
144 ret
145 } else {
146 self.memory.get(
147 self.return_range.start.as_usize(),
148 (self.return_range.end - self.return_range.start).as_usize(),
149 )
150 }
151 }
152
153 #[inline]
158 pub fn step<H: InterpreterHandler>(
159 &mut self,
160 handler: &mut H,
161 address: &H160,
162 ) -> Result<(), Capture<ExitReason, Trap>> {
163 let position = *self
164 .position
165 .as_ref()
166 .map_err(|reason| Capture::Exit(reason.clone()))?;
167 match eval(self, position, handler, address) {
168 Control::Exit(e) => {
169 self.position = Err(e.clone());
170 Err(Capture::Exit(e))
171 }
172 Control::Trap(opcode) => Err(Capture::Trap(opcode)),
173 Control::Continue(_) | Control::Jump(_) => Ok(()),
174 }
175 }
176}