revm_interpreter/interpreter_types.rs
1use crate::{instructions::utility::IntoAddress, CallInput, InstructionResult, InterpreterAction};
2use core::{
3 cell::Ref,
4 ops::{Deref, Range},
5};
6use primitives::{hardfork::SpecId, Address, Bytes, B256, U256};
7
8/// Helper function to read immediates data from the bytecode
9pub trait Immediates {
10 /// Reads next 16 bits as signed integer from the bytecode.
11 #[inline]
12 fn read_i16(&self) -> i16 {
13 self.read_u16() as i16
14 }
15 /// Reads next 16 bits as unsigned integer from the bytecode.
16 fn read_u16(&self) -> u16;
17
18 /// Reads next 8 bits as signed integer from the bytecode.
19 #[inline]
20 fn read_i8(&self) -> i8 {
21 self.read_u8() as i8
22 }
23
24 /// Reads next 8 bits as unsigned integer from the bytecode.
25 fn read_u8(&self) -> u8;
26
27 /// Reads next 16 bits as signed integer from the bytecode at given offset.
28 #[inline]
29 fn read_offset_i16(&self, offset: isize) -> i16 {
30 self.read_offset_u16(offset) as i16
31 }
32
33 /// Reads next 16 bits as unsigned integer from the bytecode at given offset.
34 fn read_offset_u16(&self, offset: isize) -> u16;
35
36 /// Reads next `len` bytes from the bytecode.
37 ///
38 /// Used by PUSH opcode.
39 fn read_slice(&self, len: usize) -> &[u8];
40}
41
42/// Trait for fetching inputs of the call.
43pub trait InputsTr {
44 /// Returns target address of the call.
45 fn target_address(&self) -> Address;
46 /// Returns bytecode address of the call. For DELEGATECALL this address will be different from target address.
47 /// And if initcode is called this address will be [`None`].
48 fn bytecode_address(&self) -> Option<&Address>;
49 /// Returns caller address of the call.
50 fn caller_address(&self) -> Address;
51 /// Returns input of the call.
52 fn input(&self) -> &CallInput;
53 /// Returns call value of the call.
54 fn call_value(&self) -> U256;
55 /// Returns the call depth of the frame this interpreter executes (0 for the first frame).
56 fn depth(&self) -> usize;
57}
58
59/// Trait needed for legacy bytecode.
60///
61/// Used in [`bytecode::opcode::CODECOPY`] and [`bytecode::opcode::CODESIZE`] opcodes.
62pub trait LegacyBytecode {
63 /// Returns current bytecode original length. Used in [`bytecode::opcode::CODESIZE`] opcode.
64 fn bytecode_len(&self) -> usize;
65 /// Returns current bytecode original slice. Used in [`bytecode::opcode::CODECOPY`] opcode.
66 fn bytecode_slice(&self) -> &[u8];
67}
68
69/// Trait for Interpreter to be able to jump
70pub trait Jumps {
71 /// Relative jumps does not require checking for overflow.
72 fn relative_jump(&mut self, offset: isize);
73 /// Absolute jumps require checking for overflow and if target is a jump destination
74 /// from jump table.
75 fn absolute_jump(&mut self, offset: usize);
76 /// Check legacy jump destination from jump table.
77 fn is_valid_legacy_jump(&mut self, offset: usize) -> bool;
78 /// Returns current program counter.
79 fn pc(&self) -> usize;
80 /// Returns instruction opcode.
81 fn opcode(&self) -> u8;
82}
83
84/// Trait for Interpreter memory operations.
85pub trait MemoryTr {
86 /// Sets memory data at given offset from data with a given data_offset and len.
87 ///
88 /// # Panics
89 ///
90 /// Panics if range is out of scope of allocated memory.
91 fn set_data(&mut self, memory_offset: usize, data_offset: usize, len: usize, data: &[u8]);
92
93 /// Inner clone part of memory from global context to local context.
94 /// This is used to clone calldata to memory.
95 ///
96 /// # Panics
97 ///
98 /// Panics if range is out of scope of allocated memory.
99 fn set_data_from_global(
100 &mut self,
101 memory_offset: usize,
102 data_offset: usize,
103 len: usize,
104 data_range: Range<usize>,
105 );
106
107 /// Memory slice with global range. This range
108 ///
109 /// # Panics
110 ///
111 /// Panics if range is out of scope of allocated memory.
112 fn global_slice(&self, range: Range<usize>) -> Ref<'_, [u8]>;
113
114 /// Offset of local context of memory.
115 fn local_memory_offset(&self) -> usize;
116
117 /// Sets memory data at given offset.
118 ///
119 /// # Panics
120 ///
121 /// Panics if range is out of scope of allocated memory.
122 fn set(&mut self, memory_offset: usize, data: &[u8]);
123
124 /// Returns memory size.
125 fn size(&self) -> usize;
126
127 /// Copies memory data from source to destination.
128 ///
129 /// # Panics
130 /// Panics if range is out of scope of allocated memory.
131 fn copy(&mut self, destination: usize, source: usize, len: usize);
132
133 /// Memory slice with range
134 ///
135 /// # Panics
136 ///
137 /// Panics if range is out of scope of allocated memory.
138 fn slice(&self, range: Range<usize>) -> Ref<'_, [u8]>;
139
140 /// Memory slice len
141 ///
142 /// Uses [`slice`][MemoryTr::slice] internally.
143 fn slice_len(&self, offset: usize, len: usize) -> impl Deref<Target = [u8]> + '_ {
144 self.slice(offset..offset + len)
145 }
146
147 /// Resizes memory to new size
148 ///
149 /// # Note
150 ///
151 /// It checks if the memory allocation fits under gas cap.
152 fn resize(&mut self, new_size: usize) -> bool;
153
154 /// Returns `true` if the `new_words` for the current context memory will
155 /// make the shared buffer length exceed the `memory_limit`.
156 #[cfg(feature = "memory_limit")]
157 fn limit_reached(&self, new_words: usize) -> bool;
158}
159
160/// Functions needed for Interpreter Stack operations.
161pub trait StackTr {
162 /// Returns stack length.
163 fn len(&self) -> usize;
164
165 /// Returns stack content.
166 fn data(&self) -> &[U256];
167
168 /// Returns `true` if stack is empty.
169 fn is_empty(&self) -> bool {
170 self.len() == 0
171 }
172
173 /// Clears the stack.
174 fn clear(&mut self);
175
176 /// Pushes values to the stack.
177 ///
178 /// Returns `true` if push was successful, `false` if stack overflow.
179 ///
180 /// # Note
181 /// Error is internally set in interpreter.
182 #[must_use]
183 fn push(&mut self, value: U256) -> bool;
184
185 /// Pushes slice to the stack.
186 ///
187 /// Returns `true` if push was successful, `false` if stack overflow.
188 ///
189 /// # Note
190 /// Error is internally set in interpreter.
191 #[must_use]
192 fn push_slice(&mut self, slice: &[u8]) -> bool;
193
194 /// Pushes B256 value to the stack.
195 ///
196 /// Internally converts B256 to U256 and then calls [`StackTr::push`].
197 #[must_use]
198 fn push_b256(&mut self, value: B256) -> bool {
199 self.push(value.into())
200 }
201
202 /// Pops value from the stack.
203 #[must_use]
204 fn popn<const N: usize>(&mut self) -> Option<[U256; N]>;
205
206 /// Pop N values from the stack and return top value.
207 #[must_use]
208 fn popn_top<const POPN: usize>(&mut self) -> Option<([U256; POPN], &mut U256)>;
209
210 /// Returns top value from the stack.
211 #[must_use]
212 fn top(&mut self) -> Option<&mut U256> {
213 self.popn_top().map(|([], top)| top)
214 }
215
216 /// Pops one value from the stack.
217 #[must_use]
218 fn pop(&mut self) -> Option<U256> {
219 self.popn::<1>().map(|[value]| value)
220 }
221
222 /// Pops address from the stack.
223 ///
224 /// Internally call [`StackTr::pop`] and converts [`U256`] into [`Address`].
225 #[must_use]
226 fn pop_address(&mut self) -> Option<Address> {
227 self.pop().map(|value| value.into_address())
228 }
229
230 /// Exchanges two values on the stack.
231 ///
232 /// Indexes are based from the top of the stack.
233 /// `n` is the first index, and the second index is calculated as `n + m`.
234 ///
235 /// Returns `true` if swap was successful, `false` if stack underflow.
236 #[must_use]
237 fn exchange(&mut self, n: usize, m: usize) -> bool;
238
239 /// Duplicates the `N`th value from the top of the stack.
240 ///
241 /// Index is based from the top of the stack.
242 ///
243 /// Returns `true` if duplicate was successful, `false` if stack underflow.
244 #[must_use]
245 fn dup(&mut self, n: usize) -> bool;
246}
247
248/// Returns return data.
249pub trait ReturnData {
250 /// Returns return data.
251 fn buffer(&self) -> &Bytes;
252
253 /// Sets return buffer.
254 fn set_buffer(&mut self, bytes: Bytes);
255
256 /// Clears return buffer.
257 fn clear(&mut self) {
258 self.set_buffer(Bytes::new());
259 }
260}
261
262/// Trait controls execution of the loop.
263pub trait LoopControl {
264 /// Returns `true` if the loop should continue.
265 fn is_not_end(&self) -> bool;
266 /// Is end of the loop.
267 #[inline]
268 fn is_end(&self) -> bool {
269 !self.is_not_end()
270 }
271 /// Sets the `end` flag internally. Action should be taken after.
272 fn reset_action(&mut self);
273 /// Set return action.
274 fn set_action(&mut self, action: InterpreterAction);
275 /// Returns the current action.
276 fn action(&mut self) -> &mut Option<InterpreterAction>;
277 /// Returns instruction result
278 #[inline]
279 fn instruction_result(&mut self) -> Option<InstructionResult> {
280 self.action()
281 .as_ref()
282 .and_then(|action| action.instruction_result())
283 }
284}
285
286/// Runtime flags that control interpreter execution behavior.
287pub trait RuntimeFlag {
288 /// Returns true if the current execution context is static (read-only).
289 fn is_static(&self) -> bool;
290 /// Returns the current EVM specification ID.
291 fn spec_id(&self) -> SpecId;
292}
293
294/// Trait for interpreter execution.
295pub trait Interp {
296 /// The instruction type.
297 type Instruction;
298 /// The action type returned after execution.
299 type Action;
300
301 /// Runs the interpreter with the given instruction table.
302 fn run(&mut self, instructions: &[Self::Instruction; 256]) -> Self::Action;
303}
304
305/// Trait defining the component types used by an interpreter implementation.
306pub trait InterpreterTypes {
307 /// Stack implementation type.
308 type Stack: StackTr;
309 /// Memory implementation type.
310 type Memory: MemoryTr;
311 /// Bytecode implementation type.
312 type Bytecode: Jumps + Immediates + LoopControl + LegacyBytecode;
313 /// Return data implementation type.
314 type ReturnData: ReturnData;
315 /// Input data implementation type.
316 type Input: InputsTr;
317 /// Runtime flags implementation type.
318 type RuntimeFlag: RuntimeFlag;
319 /// Extended functionality type.
320 type Extend;
321 /// Output type for execution results.
322 type Output;
323}