aboutsummaryrefslogtreecommitdiffstats
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/ethapi/api.go33
1 files changed, 18 insertions, 15 deletions
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index ab8478929..1ffb5a180 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -580,12 +580,12 @@ type CallArgs struct {
Data hexutil.Bytes `json:"data"`
}
-func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config) ([]byte, *big.Int, error) {
+func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config) ([]byte, *big.Int, bool, error) {
defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
state, header, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
if state == nil || err != nil {
- return nil, common.Big0, err
+ return nil, common.Big0, false, err
}
// Set sender address or use a default if none specified
addr := args.From
@@ -623,7 +623,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
// Get a new instance of the EVM.
evm, vmError, err := s.b.GetEVM(ctx, msg, state, header, vmCfg)
if err != nil {
- return nil, common.Big0, err
+ return nil, common.Big0, false, err
}
// Wait for the context to be done and cancel the evm. Even if the
// EVM has finished, cancelling may be done (repeatedly)
@@ -635,26 +635,28 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
// Setup the gas pool (also for unmetered requests)
// and apply the message.
gp := new(core.GasPool).AddGas(math.MaxBig256)
- // TODO utilize failed flag to help gas estimation
- res, gas, _, err := core.ApplyMessage(evm, msg, gp)
+ res, gas, failed, err := core.ApplyMessage(evm, msg, gp)
if err := vmError(); err != nil {
- return nil, common.Big0, err
+ return nil, common.Big0, false, err
}
- return res, gas, err
+ return res, gas, failed, err
}
// Call executes the given transaction on the state for the given block number.
// It doesn't make and changes in the state/blockchain and is useful to execute and retrieve values.
func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (hexutil.Bytes, error) {
- result, _, err := s.doCall(ctx, args, blockNr, vm.Config{DisableGasMetering: true})
+ result, _, _, err := s.doCall(ctx, args, blockNr, vm.Config{DisableGasMetering: true})
return (hexutil.Bytes)(result), err
}
// EstimateGas returns an estimate of the amount of gas needed to execute the given transaction.
func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (*hexutil.Big, error) {
// Binary search the gas requirement, as it may be higher than the amount used
- var lo, hi uint64
- if (*big.Int)(&args.Gas).Sign() != 0 {
+ var (
+ lo uint64 = params.TxGas - 1
+ hi uint64
+ )
+ if (*big.Int)(&args.Gas).Uint64() >= params.TxGas {
hi = (*big.Int)(&args.Gas).Uint64()
} else {
// Retrieve the current pending block to act as the gas ceiling
@@ -669,10 +671,10 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (*
mid := (hi + lo) / 2
(*big.Int)(&args.Gas).SetUint64(mid)
- _, gas, err := s.doCall(ctx, args, rpc.PendingBlockNumber, vm.Config{})
+ _, _, failed, err := s.doCall(ctx, args, rpc.PendingBlockNumber, vm.Config{})
- // If the transaction became invalid or used all the gas (failed), raise the gas limit
- if err != nil || gas.Cmp((*big.Int)(&args.Gas)) == 0 {
+ // If the transaction became invalid or execution failed, raise the gas limit
+ if err != nil || failed {
lo = mid
continue
}
@@ -683,10 +685,11 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (*
}
// ExecutionResult groups all structured logs emitted by the EVM
-// while replaying a transaction in debug mode as well as the amount of
-// gas used and the return value
+// while replaying a transaction in debug mode as well as transaction
+// execution status, the amount of gas used and the return value
type ExecutionResult struct {
Gas *big.Int `json:"gas"`
+ Failed bool `json:"failed"`
ReturnValue string `json:"returnValue"`
StructLogs []StructLogRes `json:"structLogs"`
}