From 5e80e00d2e103424dcddfd061c817189026fb1da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20W=C3=BCstholz?= Date: Tue, 23 May 2017 10:43:22 +0200 Subject: [PATCH] core/vm: enable optional EVM error collection in interpreter --- core/vm/evm.go | 5 +++++ core/vm/interpreter.go | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/core/vm/evm.go b/core/vm/evm.go index 69c8ec4787..94d1779ccd 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -104,6 +104,11 @@ type EVM struct { // global (to this context) ethereum virtual machine // used throughout the execution of the tx. interpreter *Interpreter + // InterpreterErrors contain the errors returned by the EVM. The errors + // aren't consensus errors but rather errors that were returned by + // invalid opcodes, stack over and underflow, etc. This slice will only + // be populated if the CollectEVMErrors option is enabled. + InterpreterErrors []EVMError // abort is used to abort the EVM calling operations // NOTE: must be set atomically abort int32 diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 0d6038cbbf..f6aeeb9ffc 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -28,6 +28,8 @@ import ( type Config struct { // Debug enabled debugging Interpreter options Debug bool + // CollectEVMErrors enables EVM error collecting + CollectEVMErrors bool // Tracer is the op code logger Tracer Tracer // NoRecursion disabled Interpreter call, callcode, @@ -41,6 +43,15 @@ type Config struct { JumpTable [256]operation } +type EVMError struct { + Err error + Depth int +} + +func (e EVMError) Error() string { + return fmt.Sprintf("%d: %v", e.Depth, e.Err) +} + // Interpreter is used to run Ethereum based contracts and will utilise the // passed environment to query external sources for state information. // The Interpreter will run the byte code VM based on the passed @@ -154,6 +165,12 @@ func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err er } }() } + if in.cfg.CollectEVMErrors { + defer func() { + in.evm.InterpreterErrors = append(in.evm.InterpreterErrors, EVMError{Err: err, Depth: in.evm.depth}) + }() + } + // The Interpreter main run loop (contextual). This loop runs until either an // explicit STOP, RETURN or SELFDESTRUCT is executed, an error occurred during // the execution of one of the operations or until the done flag is set by the