revm_interpreter/
interpreter_types.rs

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