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

@ -803,16 +803,19 @@ func (b *Block) Call(ctx context.Context, args struct {
return nil, err
}
}
result, gas, failed, err := ethapi.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, vm.Config{}, 5*time.Second, b.backend.RPCGasCap())
result, err := ethapi.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, vm.Config{}, 5*time.Second, b.backend.RPCGasCap())
if err != nil {
return nil, err
}
status := hexutil.Uint64(1)
if failed {
if result.Failed() {
status = 0
}
return &CallResult{
data: hexutil.Bytes(result),
gasUsed: hexutil.Uint64(gas),
data: result.Return(),
gasUsed: hexutil.Uint64(result.UsedGas),
status: status,
}, err
}, nil
}
func (b *Block) EstimateGas(ctx context.Context, args struct {
@ -869,16 +872,19 @@ func (p *Pending) Call(ctx context.Context, args struct {
Data ethapi.CallArgs
}) (*CallResult, error) {
pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
result, gas, failed, err := ethapi.DoCall(ctx, p.backend, args.Data, pendingBlockNr, nil, vm.Config{}, 5*time.Second, p.backend.RPCGasCap())
result, err := ethapi.DoCall(ctx, p.backend, args.Data, pendingBlockNr, nil, vm.Config{}, 5*time.Second, p.backend.RPCGasCap())
if err != nil {
return nil, err
}
status := hexutil.Uint64(1)
if failed {
if result.Failed() {
status = 0
}
return &CallResult{
data: hexutil.Bytes(result),
gasUsed: hexutil.Uint64(gas),
data: result.Return(),
gasUsed: hexutil.Uint64(result.UsedGas),
status: status,
}, err
}, nil
}
func (p *Pending) EstimateGas(ctx context.Context, args struct {