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:
@ -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
|
||||
|
Reference in New Issue
Block a user