all: seperate consensus error and evm internal error (#20830)

* all: seperate consensus error and evm internal error

There are actually two types of error will be returned when
a tranaction/message call is executed: (a) consensus error
(b) evm internal error. The former should be converted to
a consensus issue, e.g. The sender doesn't enough asset to
purchase the gas it specifies. The latter is allowed since
evm itself is a blackbox and internal error is allowed to happen.

This PR emphasizes the difference by introducing a executionResult
structure. The evm error is embedded inside. So if any error
returned, it indicates consensus issue happens.

And also this PR improve the `EstimateGas` API to return the concrete
revert reason if the transaction always fails

* all: polish

* accounts/abi/bind/backends: add tests

* accounts/abi/bind/backends, internal: cleanup error message

* all: address comments

* core: fix lint

* accounts, core, eth, internal: address comments

* accounts, internal: resolve revert reason if possible

* accounts, internal: address comments
This commit is contained in:
gary rong
2020-04-22 16:25:36 +08:00
committed by GitHub
parent c60c0c97e7
commit b9df7ecdc3
33 changed files with 550 additions and 238 deletions

View File

@ -17,7 +17,6 @@
package vm
import (
"errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
@ -28,13 +27,8 @@ import (
)
var (
bigZero = new(big.Int)
tt255 = math.BigPow(2, 255)
errWriteProtection = errors.New("evm: write protection")
errReturnDataOutOfBounds = errors.New("evm: return data out of bounds")
errExecutionReverted = errors.New("evm: execution reverted")
errMaxCodeSizeExceeded = errors.New("evm: max code size exceeded")
errInvalidJump = errors.New("evm: invalid jump destination")
bigZero = new(big.Int)
tt255 = math.BigPow(2, 255)
)
func opAdd(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
@ -468,7 +462,7 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, callContext *call
defer interpreter.intPool.put(memOffset, dataOffset, length, end)
if !end.IsUint64() || uint64(len(interpreter.returnData)) < end.Uint64() {
return nil, errReturnDataOutOfBounds
return nil, ErrReturnDataOutOfBounds
}
callContext.memory.Set(memOffset.Uint64(), length.Uint64(), interpreter.returnData[dataOffset.Uint64():end.Uint64()])
@ -643,7 +637,7 @@ func opSstore(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]
func opJump(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
pos := callContext.stack.pop()
if !callContext.contract.validJumpdest(pos) {
return nil, errInvalidJump
return nil, ErrInvalidJump
}
*pc = pos.Uint64()
@ -655,7 +649,7 @@ func opJumpi(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]b
pos, cond := callContext.stack.pop(), callContext.stack.pop()
if cond.Sign() != 0 {
if !callContext.contract.validJumpdest(pos) {
return nil, errInvalidJump
return nil, ErrInvalidJump
}
*pc = pos.Uint64()
} else {
@ -712,7 +706,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]
callContext.contract.Gas += returnGas
interpreter.intPool.put(value, offset, size)
if suberr == errExecutionReverted {
if suberr == ErrExecutionReverted {
return res, nil
}
return nil, nil
@ -740,7 +734,7 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([
callContext.contract.Gas += returnGas
interpreter.intPool.put(endowment, offset, size, salt)
if suberr == errExecutionReverted {
if suberr == ErrExecutionReverted {
return res, nil
}
return nil, nil
@ -766,7 +760,7 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]by
} else {
callContext.stack.push(interpreter.intPool.get().SetUint64(1))
}
if err == nil || err == errExecutionReverted {
if err == nil || err == ErrExecutionReverted {
callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
callContext.contract.Gas += returnGas
@ -795,7 +789,7 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) (
} else {
callContext.stack.push(interpreter.intPool.get().SetUint64(1))
}
if err == nil || err == errExecutionReverted {
if err == nil || err == ErrExecutionReverted {
callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
callContext.contract.Gas += returnGas
@ -820,7 +814,7 @@ func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, callContext *callCt
} else {
callContext.stack.push(interpreter.intPool.get().SetUint64(1))
}
if err == nil || err == errExecutionReverted {
if err == nil || err == ErrExecutionReverted {
callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
callContext.contract.Gas += returnGas
@ -845,7 +839,7 @@ func opStaticCall(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx)
} else {
callContext.stack.push(interpreter.intPool.get().SetUint64(1))
}
if err == nil || err == errExecutionReverted {
if err == nil || err == ErrExecutionReverted {
callContext.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
callContext.contract.Gas += returnGas