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 ( | ||||
| 	"fmt" | ||||
| 	"hash" | ||||
| 	"sync/atomic" | ||||
|  | ||||
| @@ -137,7 +136,7 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter { | ||||
| // | ||||
| // It's important to note that any errors returned by the interpreter should be | ||||
| // considered a revert-and-consume-all-gas operation except for | ||||
| // errExecutionReverted which means revert-and-keep-gas-left. | ||||
| // ErrExecutionReverted which means revert-and-keep-gas-left. | ||||
| func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) { | ||||
| 	if in.intPool == nil { | ||||
| 		in.intPool = poolOfIntPools.get() | ||||
| @@ -223,13 +222,13 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( | ||||
| 		op = contract.GetOp(pc) | ||||
| 		operation := in.cfg.JumpTable[op] | ||||
| 		if !operation.valid { | ||||
| 			return nil, fmt.Errorf("invalid opcode 0x%x", int(op)) | ||||
| 			return nil, &ErrInvalidOpCode{opcode: op} | ||||
| 		} | ||||
| 		// Validate stack | ||||
| 		if sLen := stack.len(); sLen < operation.minStack { | ||||
| 			return nil, fmt.Errorf("stack underflow (%d <=> %d)", sLen, operation.minStack) | ||||
| 			return nil, &ErrStackUnderflow{stackLen: sLen, required: operation.minStack} | ||||
| 		} else if sLen > operation.maxStack { | ||||
| 			return nil, fmt.Errorf("stack limit reached %d (%d)", sLen, operation.maxStack) | ||||
| 			return nil, &ErrStackOverflow{stackLen: sLen, limit: operation.maxStack} | ||||
| 		} | ||||
| 		// If the operation is valid, enforce and write restrictions | ||||
| 		if in.readOnly && in.evm.chainRules.IsByzantium { | ||||
| @@ -239,7 +238,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( | ||||
| 			// account to the others means the state is modified and should also | ||||
| 			// return with an error. | ||||
| 			if operation.writes || (op == CALL && stack.Back(2).Sign() != 0) { | ||||
| 				return nil, errWriteProtection | ||||
| 				return nil, ErrWriteProtection | ||||
| 			} | ||||
| 		} | ||||
| 		// Static portion of gas | ||||
| @@ -256,12 +255,12 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( | ||||
| 		if operation.memorySize != nil { | ||||
| 			memSize, overflow := operation.memorySize(stack) | ||||
| 			if overflow { | ||||
| 				return nil, errGasUintOverflow | ||||
| 				return nil, ErrGasUintOverflow | ||||
| 			} | ||||
| 			// memory is expanded in words of 32 bytes. Gas | ||||
| 			// is also calculated in words. | ||||
| 			if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow { | ||||
| 				return nil, errGasUintOverflow | ||||
| 				return nil, ErrGasUintOverflow | ||||
| 			} | ||||
| 		} | ||||
| 		// Dynamic portion of gas | ||||
| @@ -301,7 +300,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( | ||||
| 		case err != nil: | ||||
| 			return nil, err | ||||
| 		case operation.reverts: | ||||
| 			return res, errExecutionReverted | ||||
| 			return res, ErrExecutionReverted | ||||
| 		case operation.halts: | ||||
| 			return res, nil | ||||
| 		case !operation.jumps: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user