1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
extern crate alloc; mod eval; mod context; mod interrupt; mod handler; pub use evm_core::*; pub use crate::context::{CreateScheme, CallScheme, Context}; pub use crate::interrupt::{Resolve, ResolveCall, ResolveCreate}; pub use crate::handler::Handler; use alloc::rc::Rc; macro_rules! step { ( $self:expr, $handler:expr, $return:tt $($err:path)?; $($ok:path)? ) => ({ if let Some((opcode, stack)) = $self.machine.inspect() { match $handler.pre_validate(&$self.context, opcode, stack) { Ok(()) => (), Err(error) => { $self.machine.exit(error.into()); $self.status = Err(error.into()); }, } } match $self.status.clone() { Ok(()) => (), Err(exit) => { #[allow(unused_parens)] $return $($err)*(Capture::Exit(exit)) }, } match $self.machine.step() { Ok(()) => $($ok)?(()), Err(Capture::Exit(exit)) => { $self.status = Err(exit); #[allow(unused_parens)] $return $($err)*(Capture::Exit(exit)) }, Err(Capture::Trap(opcode)) => { match eval::eval($self, opcode, $handler) { eval::Control::Continue => $($ok)?(()), eval::Control::CallInterrupt(interrupt) => { let resolve = ResolveCall::new($self); #[allow(unused_parens)] $return $($err)*(Capture::Trap(Resolve::Call(interrupt, resolve))) }, eval::Control::CreateInterrupt(interrupt) => { let resolve = ResolveCreate::new($self); #[allow(unused_parens)] $return $($err)*(Capture::Trap(Resolve::Create(interrupt, resolve))) }, eval::Control::Exit(exit) => { $self.machine.exit(exit.into()); $self.status = Err(exit); #[allow(unused_parens)] $return $($err)*(Capture::Exit(exit)) }, } }, } }); } pub struct Runtime { machine: Machine, status: Result<(), ExitReason>, return_data_buffer: Vec<u8>, context: Context, } impl Runtime { pub fn new( code: Rc<Vec<u8>>, data: Rc<Vec<u8>>, stack_limit: usize, memory_limit: usize, context: Context, ) -> Self { Self { machine: Machine::new(code, data, stack_limit, memory_limit), status: Ok(()), return_data_buffer: Vec::new(), context, } } pub fn machine(&self) -> &Machine { &self.machine } pub fn step<'a, H: Handler>( &'a mut self, handler: &mut H, ) -> Result<(), Capture<ExitReason, Resolve<'a, H>>> { step!(self, handler, return Err; Ok) } pub fn run<'a, H: Handler>( &'a mut self, handler: &mut H, ) -> Capture<ExitReason, Resolve<'a, H>> { loop { step!(self, handler, return;) } } }