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}