From 9d6f065cb5e50f795962a08036ad722af922b417 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Thu, 15 Apr 2021 18:47:59 +0300 Subject: [PATCH 1/3] feat: allow returning error value from precompile Signed-off-by: Yaroslav Bolyukin --- src/executor/mod.rs | 2 +- src/executor/stack/mod.rs | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/executor/mod.rs b/src/executor/mod.rs index 8dee8150c..fa04afcd1 100644 --- a/src/executor/mod.rs +++ b/src/executor/mod.rs @@ -5,4 +5,4 @@ mod stack; -pub use self::stack::{StackExecutor, MemoryStackState, StackState, StackSubstateMetadata, StackExitKind}; +pub use self::stack::{PrecompileOutput, StackExecutor, MemoryStackState, StackState, StackSubstateMetadata, StackExitKind}; diff --git a/src/executor/stack/mod.rs b/src/executor/stack/mod.rs index 8ff7ac508..48d5ca7ac 100644 --- a/src/executor/stack/mod.rs +++ b/src/executor/stack/mod.rs @@ -79,10 +79,21 @@ impl<'config> StackSubstateMetadata<'config> { } } +pub struct PrecompileOutput(pub ExitReason, pub Vec, pub u64); + +impl From, u64), ExitError>> for PrecompileOutput { + fn from(value: Result<(ExitSucceed, Vec, u64), ExitError>) -> Self { + match value { + Ok((succeed, value, gas)) => Self(ExitReason::Succeed(succeed), value, gas), + Err(error) => Self(ExitReason::Error(error), Vec::new(), 0), + } + } +} + /// Stack-based executor. pub struct StackExecutor<'config, S> { config: &'config Config, - precompile: fn(H160, &[u8], Option, &Context) -> Option, u64), ExitError>>, + precompile: fn(H160, &[u8], Option, &Context) -> Option, state: S, } @@ -91,7 +102,7 @@ fn no_precompile( _input: &[u8], _target_gas: Option, _context: &Context, -) -> Option, u64), ExitError>> { +) -> Option { None } @@ -115,7 +126,7 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { pub fn new_with_precompile( state: S, config: &'config Config, - precompile: fn(H160, &[u8], Option, &Context) -> Option, u64), ExitError>>, + precompile: fn(H160, &[u8], Option, &Context) -> Option, ) -> Self { Self { config, @@ -523,18 +534,27 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { } } - if let Some(ret) = (self.precompile)(code_address, &input, Some(gas_limit), &context) { - return match ret { - Ok((s, out, cost)) => { + if let Some(PrecompileOutput(reason, out, cost)) = (self.precompile)(code_address, &input, Some(gas_limit), &context) { + match &reason { + ExitReason::Succeed(_) => { let _ = self.state.metadata_mut().gasometer.record_cost(cost); let _ = self.exit_substate(StackExitKind::Succeeded); - Capture::Exit((ExitReason::Succeed(s), out)) }, - Err(e) => { + ExitReason::Revert(_) => { + let _ = self.state.metadata_mut().gasometer.record_cost(cost); + let _ = self.exit_substate(StackExitKind::Reverted); + }, + ExitReason::Error(_) => { + let _ = self.state.metadata_mut().gasometer.record_cost(cost); + let _ = self.exit_substate(StackExitKind::Failed); + }, + ExitReason::Fatal(_) => { + self.state.metadata_mut().gasometer.fail(); let _ = self.exit_substate(StackExitKind::Failed); - Capture::Exit((ExitReason::Error(e), Vec::new())) }, } + + return Capture::Exit((reason, out)); } let mut runtime = Runtime::new( From e667bc507590bc67024e5d12c65241d4aef2a1b9 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Thu, 29 Apr 2021 17:35:11 +0300 Subject: [PATCH 2/3] feat: return logs from precompile Signed-off-by: Yaroslav Bolyukin --- src/executor/mod.rs | 2 +- src/executor/stack/mod.rs | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/executor/mod.rs b/src/executor/mod.rs index fa04afcd1..a54fb2d68 100644 --- a/src/executor/mod.rs +++ b/src/executor/mod.rs @@ -5,4 +5,4 @@ mod stack; -pub use self::stack::{PrecompileOutput, StackExecutor, MemoryStackState, StackState, StackSubstateMetadata, StackExitKind}; +pub use self::stack::{PrecompileLog, PrecompileOutput, StackExecutor, MemoryStackState, StackState, StackSubstateMetadata, StackExitKind}; diff --git a/src/executor/stack/mod.rs b/src/executor/stack/mod.rs index 48d5ca7ac..72ee602bc 100644 --- a/src/executor/stack/mod.rs +++ b/src/executor/stack/mod.rs @@ -79,13 +79,14 @@ impl<'config> StackSubstateMetadata<'config> { } } -pub struct PrecompileOutput(pub ExitReason, pub Vec, pub u64); +pub struct PrecompileLog(pub H160, pub Vec, pub Vec); +pub struct PrecompileOutput(pub ExitReason, pub Vec, pub u64, pub Vec); impl From, u64), ExitError>> for PrecompileOutput { fn from(value: Result<(ExitSucceed, Vec, u64), ExitError>) -> Self { match value { - Ok((succeed, value, gas)) => Self(ExitReason::Succeed(succeed), value, gas), - Err(error) => Self(ExitReason::Error(error), Vec::new(), 0), + Ok((succeed, value, gas)) => Self(ExitReason::Succeed(succeed), value, gas, Vec::new()), + Err(error) => Self(ExitReason::Error(error), Vec::new(), 0, Vec::new()), } } } @@ -534,7 +535,10 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { } } - if let Some(PrecompileOutput(reason, out, cost)) = (self.precompile)(code_address, &input, Some(gas_limit), &context) { + if let Some(PrecompileOutput(reason, out, cost, logs)) = (self.precompile)(code_address, &input, Some(gas_limit), &context) { + for log in logs { + let _ = self.log(log.0, log.1, log.2); + } match &reason { ExitReason::Succeed(_) => { let _ = self.state.metadata_mut().gasometer.record_cost(cost); From 081b56a17b8e587655bf45cacc1c823265530b50 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Mon, 31 May 2021 16:22:00 +0300 Subject: [PATCH 3/3] feat: impl From for PrecompileOutput Signed-off-by: Yaroslav Bolyukin --- src/executor/stack/mod.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/executor/stack/mod.rs b/src/executor/stack/mod.rs index 26aa3f5a0..5e7e983cf 100644 --- a/src/executor/stack/mod.rs +++ b/src/executor/stack/mod.rs @@ -88,6 +88,17 @@ pub struct PrecompileOutput { pub logs: Vec, } +impl From for PrecompileOutput { + fn from(err: ExitError) -> Self { + Self { + exit_status: ExitReason::Error(err), + cost: 0, + output: Default::default(), + logs: Default::default(), + } + } +} + /// Stack-based executor. pub struct StackExecutor<'config, S> { config: &'config Config,