diff --git a/core/src/lib.rs b/core/src/lib.rs index 038bf919c..c32d52878 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -66,6 +66,22 @@ impl Machine { pub fn position(&self) -> &Result { &self.position } + /// Return a reference of the return range. + pub fn return_range(&self) -> &Range { + &self.return_range + } + /// Return a reference of the valids. + pub fn valids(&self) -> &Valids { + &self.valids + } + /// Return a reference of the return range. + pub fn code(&mut self) -> Vec { + self.code.to_vec() + } + /// Return a reference of the valids. + pub fn data(&self) -> Vec { + self.data.to_vec() + } /// Create a new machine with given code and data. pub fn new( diff --git a/runtime/src/eval/system.rs b/runtime/src/eval/system.rs index 81ee5a642..a23966c2a 100644 --- a/runtime/src/eval/system.rs +++ b/runtime/src/eval/system.rs @@ -406,6 +406,8 @@ pub fn call(runtime: &mut Runtime, scheme: CallScheme, handler: &mut gas, scheme == CallScheme::StaticCall, context, + out_offset, + out_len, ) { Capture::Exit((reason, return_data)) => { runtime.return_data_buffer = return_data; diff --git a/runtime/src/handler.rs b/runtime/src/handler.rs index 4c3aea80a..75413d97e 100644 --- a/runtime/src/handler.rs +++ b/runtime/src/handler.rs @@ -101,6 +101,8 @@ pub trait Handler { target_gas: Option, is_static: bool, context: Context, + memory_offset: U256, + offset_len: U256, ) -> Capture<(ExitReason, Vec), Self::CallInterrupt>; /// Feed in call feedback. fn call_feedback(&mut self, _feedback: Self::CallFeedback) -> Result<(), ExitError> { diff --git a/runtime/src/interrupt.rs b/runtime/src/interrupt.rs index 1742fd86d..f7d06cb66 100644 --- a/runtime/src/interrupt.rs +++ b/runtime/src/interrupt.rs @@ -1,4 +1,4 @@ -use crate::{ExitFatal, Handler, Runtime}; +use crate::{Handler, Runtime}; /// Interrupt resolution. pub enum Resolve<'a, 'config, H: Handler> { @@ -9,6 +9,7 @@ pub enum Resolve<'a, 'config, H: Handler> { } /// Create interrupt resolution. +#[allow(dead_code)] pub struct ResolveCreate<'a, 'config> { runtime: &'a mut Runtime<'config>, } @@ -19,16 +20,8 @@ impl<'a, 'config> ResolveCreate<'a, 'config> { } } -impl<'a, 'config> Drop for ResolveCreate<'a, 'config> { - fn drop(&mut self) { - self.runtime.status = Err(ExitFatal::UnhandledInterrupt.into()); - self.runtime - .machine - .exit(ExitFatal::UnhandledInterrupt.into()); - } -} - /// Call interrupt resolution. +#[allow(dead_code)] pub struct ResolveCall<'a, 'config> { runtime: &'a mut Runtime<'config>, } @@ -38,12 +31,3 @@ impl<'a, 'config> ResolveCall<'a, 'config> { Self { runtime } } } - -impl<'a, 'config> Drop for ResolveCall<'a, 'config> { - fn drop(&mut self) { - self.runtime.status = Err(ExitFatal::UnhandledInterrupt.into()); - self.runtime - .machine - .exit(ExitFatal::UnhandledInterrupt.into()); - } -} diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 04cb7010d..e16e1b840 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -151,6 +151,11 @@ impl<'config> Runtime<'config> { &mut self.machine } + /// Get a reference to the return buffer + pub fn return_data_buffer(&mut self) -> &mut Vec { + &mut self.return_data_buffer + } + /// Get a reference to the execution context. pub fn context(&self) -> &Context { &self.context diff --git a/src/executor/stack/executor.rs b/src/executor/stack/executor.rs index 87062974b..888e08d35 100644 --- a/src/executor/stack/executor.rs +++ b/src/executor/stack/executor.rs @@ -227,10 +227,17 @@ pub trait StackState<'config>: Backend { } } +/// Data returned by a precompile on success. +#[derive(Debug, Eq, PartialEq, Clone)] +pub enum PrecompileOutputType { + Exit(ExitSucceed), + Trap, +} + /// Data returned by a precompile on success. #[derive(Debug, Eq, PartialEq, Clone)] pub struct PrecompileOutput { - pub exit_status: ExitSucceed, + pub output_type: PrecompileOutputType, pub output: Vec, } @@ -921,11 +928,20 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> }) { return match result { Ok(PrecompileOutput { - exit_status, + output_type, output, }) => { - let _ = self.exit_substate(StackExitKind::Succeeded); - Capture::Exit((ExitReason::Succeed(exit_status), output)) + if let PrecompileOutputType::Exit(exit_status) = output_type { + let _ = self.exit_substate(StackExitKind::Succeeded); + Capture::Exit((ExitReason::Succeed(exit_status), output)) + } else { + Capture::Exit(( + ExitReason::Error(ExitError::Other(std::borrow::Cow::Borrowed( + "Unsupported", + ))), + output, + )) + } } Err(PrecompileFailure::Error { exit_status }) => { let _ = self.exit_substate(StackExitKind::Failed); @@ -1134,6 +1150,8 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Handler target_gas: Option, is_static: bool, context: Context, + _memory_offset: U256, + _offset_len: U256, ) -> Capture<(ExitReason, Vec), Self::CallInterrupt> { self.call_inner( code_address, @@ -1156,6 +1174,8 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Handler target_gas: Option, is_static: bool, context: Context, + _memory_offset: U256, + _offset_len: U256, ) -> Capture<(ExitReason, Vec), Self::CallInterrupt> { let capture = self.call_inner( code_address, @@ -1215,13 +1235,13 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Handler } } -struct StackExecutorHandle<'inner, 'config, 'precompiles, S, P> { - executor: &'inner mut StackExecutor<'config, 'precompiles, S, P>, - code_address: H160, - input: &'inner [u8], - gas_limit: Option, - context: &'inner Context, - is_static: bool, +pub struct StackExecutorHandle<'inner, 'config, 'precompiles, S, P> { + pub executor: &'inner mut StackExecutor<'config, 'precompiles, S, P>, + pub code_address: H160, + pub input: &'inner [u8], + pub gas_limit: Option, + pub context: &'inner Context, + pub is_static: bool, } impl<'inner, 'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> PrecompileHandle @@ -1283,6 +1303,8 @@ impl<'inner, 'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Pr gas_limit, is_static, context.clone(), + U256::default(), + U256::default(), ) { Capture::Exit((s, v)) => (s, v), Capture::Trap(_) => unreachable!("Trap is infaillible since StackExecutor is sync"), diff --git a/src/executor/stack/memory.rs b/src/executor/stack/memory.rs index 0ec07eabf..a1479279d 100644 --- a/src/executor/stack/memory.rs +++ b/src/executor/stack/memory.rs @@ -38,6 +38,23 @@ impl<'config> MemoryStackSubstate<'config> { } } + pub fn from_state( + metadata: StackSubstateMetadata<'config>, + logs: Vec, + accounts: BTreeMap, + storages: BTreeMap<(H160, H256), H256>, + deletes: BTreeSet, + ) -> Self { + Self { + metadata, + parent: None, + logs, + accounts, + storages, + deletes, + } + } + pub fn logs(&self) -> &[Log] { &self.logs } @@ -46,6 +63,18 @@ impl<'config> MemoryStackSubstate<'config> { &mut self.logs } + pub fn accounts(&self) -> &BTreeMap { + &self.accounts + } + + pub fn storages(&self) -> &BTreeMap<(H160, H256), H256> { + &self.storages + } + + pub fn deletes(&self) -> &BTreeSet { + &self.deletes + } + pub fn metadata(&self) -> &StackSubstateMetadata<'config> { &self.metadata } @@ -555,6 +584,14 @@ impl<'backend, 'config, B: Backend> MemoryStackState<'backend, 'config, B> { } } + pub fn new_with_substate(substate: MemoryStackSubstate<'config>, backend: &'backend B) -> Self { + Self { backend, substate } + } + + pub fn substate(&self) -> &MemoryStackSubstate { + &self.substate + } + /// Returns a mutable reference to an account given its address pub fn account_mut(&mut self, address: H160) -> &mut MemoryStackAccount { self.substate.account_mut(address, self.backend) diff --git a/src/executor/stack/mod.rs b/src/executor/stack/mod.rs index 5bb448a7a..46b5ee309 100644 --- a/src/executor/stack/mod.rs +++ b/src/executor/stack/mod.rs @@ -6,8 +6,9 @@ mod executor; mod memory; pub use self::executor::{ - Accessed, PrecompileFailure, PrecompileFn, PrecompileHandle, PrecompileOutput, PrecompileSet, - StackExecutor, StackExitKind, StackState, StackSubstateMetadata, + Accessed, PrecompileFailure, PrecompileFn, PrecompileHandle, PrecompileOutput, + PrecompileOutputType, PrecompileSet, StackExecutor, StackExecutorHandle, StackExitKind, + StackState, StackSubstateMetadata, }; pub use self::memory::{MemoryStackAccount, MemoryStackState, MemoryStackSubstate};