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