diff options
-rw-r--r-- | tests/ethtest/main.go | 3 | ||||
-rw-r--r-- | vm/errors.go | 51 | ||||
-rw-r--r-- | vm/execution.go | 4 | ||||
-rw-r--r-- | vm/vm_debug.go | 6 |
4 files changed, 58 insertions, 6 deletions
diff --git a/tests/ethtest/main.go b/tests/ethtest/main.go index e19892557..1f2a15e1c 100644 --- a/tests/ethtest/main.go +++ b/tests/ethtest/main.go @@ -63,7 +63,7 @@ func RunVmTest(js string) (failed int) { // When an error is returned it doesn't always mean the tests fails. // Have to come up with some conditional failing mechanism. if err != nil { - helper.Log.Infoln(err) + log.Println(err) } rexp := helper.FromHex(test.Out) @@ -96,6 +96,7 @@ func RunVmTest(js string) (failed int) { } func main() { + helper.Logger.SetLogLevel(5) if len(os.Args) == 1 { log.Fatalln("no json supplied") } diff --git a/vm/errors.go b/vm/errors.go new file mode 100644 index 000000000..ab011bd62 --- /dev/null +++ b/vm/errors.go @@ -0,0 +1,51 @@ +package vm + +import ( + "fmt" + "math/big" +) + +type OutOfGasError struct { + req, has *big.Int +} + +func OOG(req, has *big.Int) OutOfGasError { + return OutOfGasError{req, has} +} + +func (self OutOfGasError) Error() string { + return fmt.Sprintf("out of gas! require %v, have %v", self.req, self.has) +} + +func IsOOGErr(err error) bool { + _, ok := err.(OutOfGasError) + return ok +} + +type StackError struct { + req, has int +} + +func StackErr(req, has int) StackError { + return StackError{req, has} +} + +func (self StackError) Error() string { + return fmt.Sprintf("stack error! require %v, have %v", self.req, self.has) +} + +func IsStack(err error) bool { + _, ok := err.(StackError) + return ok +} + +type DepthError struct{} + +func (self DepthError) Error() string { + return fmt.Sprintf("Max call depth exceeded (%d)", MaxCallDepth) +} + +func IsDepthErr(err error) bool { + _, ok := err.(DepthError) + return ok +} diff --git a/vm/execution.go b/vm/execution.go index bd174d64e..c518c4b57 100644 --- a/vm/execution.go +++ b/vm/execution.go @@ -36,7 +36,7 @@ func (self *Execution) exec(code, caddr []byte, caller ClosureRef) (ret []byte, snapshot := env.State().Copy() defer func() { - if err != nil { + if IsDepthErr(err) || IsOOGErr(err) { env.State().Set(snapshot) } }() @@ -76,7 +76,7 @@ func (self *Execution) exec(code, caddr []byte, caller ClosureRef) (ret []byte, if self.vm.Depth() == MaxCallDepth { c.UseGas(self.Gas) - return c.Return(nil), fmt.Errorf("Max call depth exceeded (%d)", MaxCallDepth) + return c.Return(nil), DepthError{} } // Executer the closure and get the return value (if any) diff --git a/vm/vm_debug.go b/vm/vm_debug.go index fe004046c..b44604121 100644 --- a/vm/vm_debug.go +++ b/vm/vm_debug.go @@ -107,7 +107,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { step++ // Get the memory location of pc - op = OpCode(closure.Get(pc).Uint()) + op = closure.GetOp(int(pc.Uint64())) // XXX Leave this Println intact. Don't change this to the log system. // Used for creating diffs between implementations @@ -246,11 +246,11 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { if !closure.UseGas(gas) { self.Endl() - err := fmt.Errorf("Insufficient gas for %v. req %v has %v", op, gas, closure.Gas) + tmp := new(big.Int).Set(closure.Gas) closure.UseGas(closure.Gas) - return closure.Return(nil), err + return closure.Return(nil), OOG(gas, tmp) } mem.Resize(newMemSize.Uint64()) |