revm_interpreter/
interpreter_types.rs

1use crate::{Gas, InstructionResult, InterpreterAction};
2use bytecode::eof::CodeInfo;
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    fn read_i16(&self) -> i16;
9    fn read_u16(&self) -> u16;
10
11    fn read_i8(&self) -> i8;
12    fn read_u8(&self) -> u8;
13
14    fn read_offset_i16(&self, offset: isize) -> i16;
15    fn read_offset_u16(&self, offset: isize) -> u16;
16
17    fn read_slice(&self, len: usize) -> &[u8];
18}
19
20/// Trait for fetching inputs of the call.
21pub trait InputsTr {
22    fn target_address(&self) -> Address;
23    fn caller_address(&self) -> Address;
24    fn input(&self) -> &[u8];
25    fn call_value(&self) -> U256;
26}
27
28/// Trait needed for legacy bytecode.
29///
30/// Used in [`bytecode::opcode::CODECOPY`] and [`bytecode::opcode::CODESIZE`] opcodes.
31pub trait LegacyBytecode {
32    /// Returns current bytecode original length. Used in [`bytecode::opcode::CODESIZE`] opcode.
33    fn bytecode_len(&self) -> usize;
34    /// Returns current bytecode original slice. Used in [`bytecode::opcode::CODECOPY`] opcode.
35    fn bytecode_slice(&self) -> &[u8];
36}
37
38/// Trait for Interpreter to be able to jump
39pub trait Jumps {
40    /// Relative jumps does not require checking for overflow.
41    fn relative_jump(&mut self, offset: isize);
42    /// Absolute jumps require checking for overflow and if target is a jump destination
43    /// from jump table.
44    fn absolute_jump(&mut self, offset: usize);
45    /// Check legacy jump destination from jump table.
46    fn is_valid_legacy_jump(&mut self, offset: usize) -> bool;
47    /// Returns current program counter.
48    fn pc(&self) -> usize;
49    /// Returns instruction opcode.
50    fn opcode(&self) -> u8;
51}
52
53/// Trait for Interpreter memory operations.
54pub trait MemoryTr {
55    /// Sets memory data at given offset from data with a given data_offset and len.
56    ///
57    /// # Panics
58    ///
59    /// Panics if range is out of scope of allocated memory.
60    fn set_data(&mut self, memory_offset: usize, data_offset: usize, len: usize, data: &[u8]);
61    /// Sets memory data at given offset.
62    ///
63    /// # Panics
64    ///
65    /// Panics if range is out of scope of allocated memory.
66    fn set(&mut self, memory_offset: usize, data: &[u8]);
67
68    /// Returns memory size.
69    fn size(&self) -> usize;
70
71    /// Copies memory data from source to destination.
72    ///
73    /// # Panics
74    /// Panics if range is out of scope of allocated memory.
75    fn copy(&mut self, destination: usize, source: usize, len: usize);
76
77    /// Memory slice with range
78    ///
79    /// # Panics
80    ///
81    /// Panics if range is out of scope of allocated memory.
82    fn slice(&self, range: Range<usize>) -> impl Deref<Target = [u8]> + '_;
83
84    /// Memory slice len
85    ///
86    /// Uses [`slice`][MemoryTr::slice] internally.
87    fn slice_len(&self, offset: usize, len: usize) -> impl Deref<Target = [u8]> + '_ {
88        self.slice(offset..offset + len)
89    }
90
91    /// Resizes memory to new size
92    ///
93    /// # Note
94    ///
95    /// It checks memory limits.
96    fn resize(&mut self, new_size: usize) -> bool;
97}
98
99/// Returns EOF containers. Used by [`bytecode::opcode::RETURNCONTRACT`] and [`bytecode::opcode::EOFCREATE`] opcodes.
100pub trait EofContainer {
101    /// Returns EOF container at given index.
102    fn eof_container(&self, index: usize) -> Option<&Bytes>;
103}
104
105/// Handles EOF introduced sub routine calls.
106pub trait SubRoutineStack {
107    /// Returns sub routine stack length.
108    fn len(&self) -> usize;
109
110    /// Returns `true` if sub routine stack is empty.
111    fn is_empty(&self) -> bool {
112        self.len() == 0
113    }
114
115    /// Returns current sub routine index.
116    fn routine_idx(&self) -> usize;
117
118    /// Sets new code section without touching subroutine stack.
119    ///
120    /// This is used for [`bytecode::opcode::JUMPF`] opcode. Where
121    /// tail call is performed.
122    fn set_routine_idx(&mut self, idx: usize);
123
124    /// Pushes a new frame to the stack and new code index.
125    fn push(&mut self, old_program_counter: usize, new_idx: usize) -> bool;
126
127    /// Pops previous subroutine, sets previous code index and returns program counter.
128    fn pop(&mut self) -> Option<usize>;
129}
130
131/// Functions needed for Interpreter Stack operations.
132pub trait StackTr {
133    /// Returns stack length.
134    fn len(&self) -> usize;
135
136    /// Returns `true` if stack is empty.
137    fn is_empty(&self) -> bool {
138        self.len() == 0
139    }
140
141    /// Pushes values to the stack.
142    ///
143    /// Returns `true` if push was successful, `false` if stack overflow.
144    ///
145    /// # Note
146    /// Error is internally set in interpreter.
147    #[must_use]
148    fn push(&mut self, value: U256) -> bool;
149
150    /// Pushes B256 value to the stack.
151    ///
152    /// Internally converts B256 to U256 and then calls [`StackTr::push`].
153    #[must_use]
154    fn push_b256(&mut self, value: B256) -> bool {
155        self.push(value.into())
156    }
157
158    /// Pops value from the stack.
159    #[must_use]
160    fn popn<const N: usize>(&mut self) -> Option<[U256; N]>;
161
162    /// Pop N values from the stack and return top value.
163    #[must_use]
164    fn popn_top<const POPN: usize>(&mut self) -> Option<([U256; POPN], &mut U256)>;
165
166    /// Returns top value from the stack.
167    #[must_use]
168    fn top(&mut self) -> Option<&mut U256> {
169        self.popn_top::<0>().map(|(_, top)| top)
170    }
171
172    /// Pops one value from the stack.
173    #[must_use]
174    fn pop(&mut self) -> Option<U256> {
175        self.popn::<1>().map(|[value]| value)
176    }
177
178    /// Pops address from the stack.
179    ///
180    /// Internally call [`StackTr::pop`] and converts [`U256`] into [`Address`].
181    #[must_use]
182    fn pop_address(&mut self) -> Option<Address> {
183        self.pop().map(|value| Address::from(value.to_be_bytes()))
184    }
185
186    /// Exchanges two values on the stack.
187    ///
188    /// Indexes are based from the top of the stack.
189    ///
190    /// Returns `true` if swap was successful, `false` if stack underflow.
191    #[must_use]
192    fn exchange(&mut self, n: usize, m: usize) -> bool;
193
194    /// Duplicates the `N`th value from the top of the stack.
195    ///
196    /// Index is based from the top of the stack.
197    ///
198    /// Returns `true` if duplicate was successful, `false` if stack underflow.
199    #[must_use]
200    fn dup(&mut self, n: usize) -> bool;
201}
202
203/// EOF data fetching.
204pub trait EofData {
205    /// Returns EOF data.
206    fn data(&self) -> &[u8];
207    /// Returns EOF data slice.
208    fn data_slice(&self, offset: usize, len: usize) -> &[u8];
209    /// Returns EOF data size.
210    fn data_size(&self) -> usize;
211}
212
213/// EOF code info.
214pub trait EofCodeInfo {
215    /// Returns code information containing stack information.
216    fn code_info(&self, idx: usize) -> Option<&CodeInfo>;
217
218    /// Returns program counter at the start of code section.
219    fn code_section_pc(&self, idx: usize) -> Option<usize>;
220}
221
222/// Returns return data.
223pub trait ReturnData {
224    /// Returns return data.
225    fn buffer(&self) -> &[u8];
226
227    /// Sets return buffer.
228    fn set_buffer(&mut self, bytes: Bytes);
229
230    /// Clears return buffer.
231    fn clear(&mut self) {
232        self.set_buffer(Bytes::new());
233    }
234}
235
236pub trait LoopControl {
237    fn set_instruction_result(&mut self, result: InstructionResult);
238    fn set_next_action(&mut self, action: InterpreterAction, result: InstructionResult);
239    fn gas(&self) -> &Gas;
240    fn gas_mut(&mut self) -> &mut Gas;
241    fn instruction_result(&self) -> InstructionResult;
242    fn take_next_action(&mut self) -> InterpreterAction;
243}
244
245pub trait RuntimeFlag {
246    fn is_static(&self) -> bool;
247    fn is_eof(&self) -> bool;
248    fn is_eof_init(&self) -> bool;
249    fn spec_id(&self) -> SpecId;
250}
251
252pub trait Interp {
253    type Instruction;
254    type Action;
255
256    fn run(&mut self, instructions: &[Self::Instruction; 256]) -> Self::Action;
257}
258
259pub trait InterpreterTypes {
260    type Stack: StackTr;
261    type Memory: MemoryTr;
262    type Bytecode: Jumps + Immediates + LegacyBytecode + EofData + EofContainer + EofCodeInfo;
263    type ReturnData: ReturnData;
264    type Input: InputsTr;
265    type SubRoutineStack: SubRoutineStack;
266    type Control: LoopControl;
267    type RuntimeFlag: RuntimeFlag;
268    type Extend;
269    type Output;
270}