aurora_evm/core/
mod.rs

1//! Core layer for EVM.
2
3#[cfg(not(feature = "std"))]
4pub mod prelude {
5    pub use alloc::{borrow::Cow, rc::Rc, vec, vec::Vec};
6}
7#[cfg(feature = "std")]
8pub mod prelude {
9    pub use std::{borrow::Cow, rc::Rc, vec::Vec};
10}
11
12mod error;
13mod eval;
14mod external;
15mod memory;
16mod opcode;
17mod stack;
18pub mod utils;
19mod valids;
20
21pub use error::{Capture, ExitError, ExitFatal, ExitReason, ExitRevert, ExitSucceed, Trap};
22pub use external::ExternalOperation;
23pub use memory::Memory;
24pub use opcode::Opcode;
25pub use stack::Stack;
26pub use valids::Valids;
27
28use core::ops::Range;
29use eval::{eval, Control};
30use prelude::*;
31use primitive_types::{H160, U256};
32use utils::USIZE_MAX;
33
34/// Core execution layer for EVM.
35pub struct Machine {
36    /// Program data.
37    data: Rc<Vec<u8>>,
38    /// Program code.
39    code: Rc<Vec<u8>>,
40    /// Program counter.
41    position: Result<usize, ExitReason>,
42    /// Return value.
43    return_range: Range<U256>,
44    /// Code validity maps.
45    valids: Valids,
46    /// Memory.
47    memory: Memory,
48    /// Stack.
49    stack: Stack,
50}
51
52/// EVM interpreter handler.
53pub trait InterpreterHandler {
54    fn before_eval(&mut self);
55
56    fn after_eval(&mut self);
57
58    /// # Errors
59    /// Return `ExitError`
60    fn before_bytecode(
61        &mut self,
62        opcode: Opcode,
63        pc: usize,
64        machine: &Machine,
65        address: &H160,
66    ) -> Result<(), ExitError>;
67
68    // Only invoked if #[cfg(feature = "tracing")]
69    fn after_bytecode(&mut self, result: &Result<(), Capture<ExitReason, Trap>>, machine: &Machine);
70}
71
72impl Machine {
73    /// Reference of machine stack.
74    #[must_use]
75    pub const fn stack(&self) -> &Stack {
76        &self.stack
77    }
78    /// Mutable reference of machine stack.
79    pub fn stack_mut(&mut self) -> &mut Stack {
80        &mut self.stack
81    }
82    /// Reference of machine memory.
83    #[must_use]
84    pub const fn memory(&self) -> &Memory {
85        &self.memory
86    }
87    /// Mutable reference of machine memory.
88    pub fn memory_mut(&mut self) -> &mut Memory {
89        &mut self.memory
90    }
91    /// Return a reference of the program counter.
92    pub const fn position(&self) -> &Result<usize, ExitReason> {
93        &self.position
94    }
95
96    /// Create a new machine with given code and data.
97    #[must_use]
98    pub fn new(
99        code: Rc<Vec<u8>>,
100        data: Rc<Vec<u8>>,
101        stack_limit: usize,
102        memory_limit: usize,
103    ) -> Self {
104        let valids = Valids::new(&code[..]);
105
106        Self {
107            data,
108            code,
109            position: Ok(0),
110            return_range: U256::zero()..U256::zero(),
111            valids,
112            memory: Memory::new(memory_limit),
113            stack: Stack::new(stack_limit),
114        }
115    }
116
117    /// Explicit exit of the machine. Further step will return error.
118    pub fn exit(&mut self, reason: ExitReason) {
119        self.position = Err(reason);
120    }
121
122    /// Inspect the machine's next opcode and current stack.
123    #[must_use]
124    pub fn inspect(&self) -> Option<(Opcode, &Stack)> {
125        let Ok(position) = self.position else {
126            return None;
127        };
128        self.code.get(position).map(|v| (Opcode(*v), &self.stack))
129    }
130
131    /// Copy and get the return value of the machine, if any.
132    #[must_use]
133    pub fn return_value(&self) -> Vec<u8> {
134        if self.return_range.start > USIZE_MAX {
135            vec![0; (self.return_range.end - self.return_range.start).as_usize()]
136        } else if self.return_range.end > USIZE_MAX {
137            let mut ret = self.memory.get(
138                self.return_range.start.as_usize(),
139                usize::MAX - self.return_range.start.as_usize(),
140            );
141
142            let new_len = (self.return_range.end - self.return_range.start).as_usize();
143            if ret.len() < new_len {
144                ret.resize(new_len, 0);
145            }
146            ret
147        } else {
148            self.memory.get(
149                self.return_range.start.as_usize(),
150                (self.return_range.end - self.return_range.start).as_usize(),
151            )
152        }
153    }
154
155    /// Loop stepping the machine, until it stops.
156    pub fn run(&mut self) -> Capture<ExitReason, Trap> {
157        let mut handler = SimpleInterpreterHandler::default();
158        let address = H160::default();
159        loop {
160            match self.step(&mut handler, &address) {
161                Ok(()) => (),
162                Err(res) => return res,
163            }
164        }
165    }
166
167    /// Step the machine, executing until exit or trap.
168    ///
169    /// # Errors
170    /// Return `Capture<ExitReason, Trap>`
171    #[inline]
172    pub fn step<H: InterpreterHandler>(
173        &mut self,
174        handler: &mut H,
175        address: &H160,
176    ) -> Result<(), Capture<ExitReason, Trap>> {
177        let position = *self
178            .position
179            .as_ref()
180            .map_err(|reason| Capture::Exit(reason.clone()))?;
181        match eval(self, position, handler, address) {
182            Control::Exit(e) => {
183                self.position = Err(e.clone());
184                Err(Capture::Exit(e))
185            }
186            Control::Trap(opcode) => Err(Capture::Trap(opcode)),
187            Control::Continue(_) | Control::Jump(_) => Ok(()),
188        }
189    }
190}
191
192pub struct SimpleInterpreterHandler {
193    pub executed: u64,
194    pub profile: [u64; 256],
195    pub address: H160,
196}
197
198impl SimpleInterpreterHandler {
199    #[must_use]
200    pub const fn new(address: H160) -> Self {
201        Self {
202            executed: 0,
203            profile: [0; 256],
204            address,
205        }
206    }
207}
208
209impl Default for SimpleInterpreterHandler {
210    fn default() -> Self {
211        Self {
212            executed: 0,
213            profile: [0; 256],
214            address: H160::default(),
215        }
216    }
217}
218
219impl InterpreterHandler for SimpleInterpreterHandler {
220    fn before_eval(&mut self) {}
221
222    fn after_eval(&mut self) {}
223
224    #[inline]
225    fn before_bytecode(
226        &mut self,
227        opcode: Opcode,
228        _pc: usize,
229        _machine: &Machine,
230        _address: &H160,
231    ) -> Result<(), ExitError> {
232        self.executed += 1;
233        self.profile[opcode.as_usize()] += 1;
234        Ok(())
235    }
236
237    #[inline]
238    fn after_bytecode(
239        &mut self,
240        _result: &Result<(), Capture<ExitReason, Trap>>,
241        _machine: &Machine,
242    ) {
243    }
244}