revm_interpreter/
interpreter_types.rs

1use bytecode::eof::TypesSection;
2use specification::hardfork::SpecId;
3
4use crate::{Gas, InstructionResult, InterpreterAction};
5use core::ops::{Deref, Range};
6use primitives::{Address, Bytes, B256, U256};
7
8/// Helper function to read immediates data from the bytecode
9pub trait Immediates {
10    fn read_i16(&self) -> i16;
11    fn read_u16(&self) -> u16;
12
13    fn read_i8(&self) -> i8;
14    fn read_u8(&self) -> u8;
15
16    fn read_offset_i16(&self, offset: isize) -> i16;
17    fn read_offset_u16(&self, offset: isize) -> u16;
18
19    fn read_slice(&self, len: usize) -> &[u8];
20}
21
22pub trait InputsTr {
23    fn target_address(&self) -> Address;
24    fn caller_address(&self) -> Address;
25    fn input(&self) -> &[u8];
26    fn call_value(&self) -> U256;
27}
28
29pub trait LegacyBytecode {
30    fn bytecode_len(&self) -> usize;
31    fn bytecode_slice(&self) -> &[u8];
32}
33
34/// Trait for interpreter to be able to jump
35pub trait Jumps {
36    /// Relative jumps does not require checking for overflow.
37    fn relative_jump(&mut self, offset: isize);
38    /// Absolute jumps require checking for overflow and if target is a jump destination
39    /// from jump table.
40    fn absolute_jump(&mut self, offset: usize);
41    /// Check legacy jump destination from jump table.
42    fn is_valid_legacy_jump(&mut self, offset: usize) -> bool;
43    /// Returns current program counter.
44    fn pc(&self) -> usize;
45    /// Returns instruction opcode.
46    fn opcode(&self) -> u8;
47}
48
49pub trait MemoryTr {
50    fn set_data(&mut self, memory_offset: usize, data_offset: usize, len: usize, data: &[u8]);
51    fn set(&mut self, memory_offset: usize, data: &[u8]);
52
53    fn size(&self) -> usize;
54    fn copy(&mut self, destination: usize, source: usize, len: usize);
55
56    /// Memory slice with range
57    ///
58    /// # Panics
59    /// Panics if range is out of scope of allocated memory.
60    fn slice(&self, range: Range<usize>) -> impl Deref<Target = [u8]> + '_;
61
62    /// Memory slice len
63    ///
64    /// Uses [`slice`][MemoryTr::slice] internally.
65    fn slice_len(&self, offset: usize, len: usize) -> impl Deref<Target = [u8]> + '_ {
66        self.slice(offset..offset + len)
67    }
68
69    /// Resizes memory to new size
70    ///
71    /// # Note
72    /// It checks memory limits.
73    fn resize(&mut self, new_size: usize) -> bool;
74}
75
76pub trait EofContainer {
77    fn eof_container(&self, index: usize) -> Option<&Bytes>;
78}
79
80pub trait SubRoutineStack {
81    fn len(&self) -> usize;
82
83    fn is_empty(&self) -> bool {
84        self.len() == 0
85    }
86
87    fn routine_idx(&self) -> usize;
88
89    /// Sets new code section without touching subroutine stack.
90    fn set_routine_idx(&mut self, idx: usize);
91
92    /// Pushes a new frame to the stack and new code index.
93    fn push(&mut self, old_program_counter: usize, new_idx: usize) -> bool;
94
95    /// Pops previous subroutine, sets previous code index and returns program counter.
96    fn pop(&mut self) -> Option<usize>;
97
98    // /// Returns code info from EOF body.
99    // fn eof_code_info(&self, idx: usize) -> Option<&TypesSection>;
100}
101
102pub trait StackTr {
103    /// Returns stack length.
104    fn len(&self) -> usize;
105
106    /// Returns `true` if stack is empty.
107    fn is_empty(&self) -> bool {
108        self.len() == 0
109    }
110
111    /// Pushes values to the stack.
112    ///
113    /// Returns `true` if push was successful, `false` if stack overflow.
114    ///
115    /// # Note
116    /// Error is internally set in interpreter.
117    #[must_use]
118    fn push(&mut self, value: U256) -> bool;
119
120    #[must_use]
121    fn push_b256(&mut self, value: B256) -> bool {
122        self.push(value.into())
123    }
124
125    /// Pops value from the stack.
126    #[must_use]
127    fn popn<const N: usize>(&mut self) -> Option<[U256; N]>;
128
129    /// Pop N values from the stack and return top value.
130    #[must_use]
131    fn popn_top<const POPN: usize>(&mut self) -> Option<([U256; POPN], &mut U256)>;
132
133    /// Returns top value from the stack.
134    #[must_use]
135    fn top(&mut self) -> Option<&mut U256> {
136        self.popn_top::<0>().map(|(_, top)| top)
137    }
138
139    /// Pops one value from the stack.
140    #[must_use]
141    fn pop(&mut self) -> Option<U256> {
142        self.popn::<1>().map(|[value]| value)
143    }
144
145    #[must_use]
146    fn pop_address(&mut self) -> Option<Address> {
147        self.pop().map(|value| Address::from(value.to_be_bytes()))
148    }
149
150    /// Exchanges two values on the stack.
151    ///
152    /// Indexes are based from the top of the stack.
153    ///
154    /// Returns `true` if swap was successful, `false` if stack underflow.
155    #[must_use]
156    fn exchange(&mut self, n: usize, m: usize) -> bool;
157
158    /// Duplicates the `N`th value from the top of the stack.
159    ///
160    /// Index is based from the top of the stack.
161    ///
162    /// Returns `true` if duplicate was successful, `false` if stack underflow.
163    #[must_use]
164    fn dup(&mut self, n: usize) -> bool;
165}
166
167pub trait EofData {
168    fn data(&self) -> &[u8];
169    fn data_slice(&self, offset: usize, len: usize) -> &[u8];
170    fn data_size(&self) -> usize;
171}
172
173pub trait EofCodeInfo {
174    /// Returns code information containing stack information.
175    fn code_section_info(&self, idx: usize) -> Option<&TypesSection>;
176
177    /// Returns program counter at the start of code section.
178    fn code_section_pc(&self, idx: usize) -> Option<usize>;
179}
180
181pub trait ReturnData {
182    fn buffer(&self) -> &[u8];
183    fn buffer_mut(&mut self) -> &mut Bytes;
184}
185
186pub trait LoopControl {
187    fn set_instruction_result(&mut self, result: InstructionResult);
188    fn set_next_action(&mut self, action: InterpreterAction, result: InstructionResult);
189    fn gas(&mut self) -> &mut Gas;
190    fn instruction_result(&self) -> InstructionResult;
191    fn take_next_action(&mut self) -> InterpreterAction;
192}
193
194pub trait RuntimeFlag {
195    fn is_static(&self) -> bool;
196    fn is_eof(&self) -> bool;
197    fn is_eof_init(&self) -> bool;
198    fn spec_id(&self) -> SpecId;
199}
200
201pub trait Interp {
202    type Instruction;
203    type Action;
204
205    fn run(&mut self, instructions: &[Self::Instruction; 256]) -> Self::Action;
206}
207
208pub trait InterpreterTypes {
209    type Stack: StackTr;
210    type Memory: MemoryTr;
211    type Bytecode: Jumps + Immediates + LegacyBytecode + EofData + EofContainer + EofCodeInfo;
212    type ReturnData: ReturnData;
213    type Input: InputsTr;
214    type SubRoutineStack: SubRoutineStack;
215    type Control: LoopControl;
216    type RuntimeFlag: RuntimeFlag;
217    type Extend;
218}