aboutsummaryrefslogtreecommitdiffstats
path: root/internal
diff options
context:
space:
mode:
authorgary rong <garyrong0905@gmail.com>2017-11-15 00:26:31 +0800
committerPéter Szilágyi <peterke@gmail.com>2017-11-15 00:26:31 +0800
commit984c25ac406e86255b289a3d7fec4cd91a17707f (patch)
treea4bb78bca0e88cf7ec034eea7480b2b12e92a14b /internal
parenta3128f909918b40501bd284b09ee6cb0d45ccb93 (diff)
downloaddexon-984c25ac406e86255b289a3d7fec4cd91a17707f.tar.gz
dexon-984c25ac406e86255b289a3d7fec4cd91a17707f.tar.zst
dexon-984c25ac406e86255b289a3d7fec4cd91a17707f.zip
accounts, internal: fail if no suitable estimated gas found (#15477)
* accounts, internal: return an error if no suitable estimated gas found * accounts, internal: minor polishes on the gas estimator
Diffstat (limited to 'internal')
-rw-r--r--internal/ethapi/api.go39
1 files changed, 26 insertions, 13 deletions
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index 1ffb5a180..59a29d722 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -649,12 +649,14 @@ func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr r
return (hexutil.Bytes)(result), err
}
-// EstimateGas returns an estimate of the amount of gas needed to execute the given transaction.
+// EstimateGas returns an estimate of the amount of gas needed to execute the
+// given transaction against the current pending block.
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
+ // Determine the lowest and highest possible gas limits to binary search in between
var (
- lo uint64 = params.TxGas - 1
- hi uint64
+ lo uint64 = params.TxGas - 1
+ hi uint64
+ cap uint64
)
if (*big.Int)(&args.Gas).Uint64() >= params.TxGas {
hi = (*big.Int)(&args.Gas).Uint64()
@@ -666,20 +668,31 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (*
}
hi = block.GasLimit().Uint64()
}
- for lo+1 < hi {
- // Take a guess at the gas, and check transaction validity
- mid := (hi + lo) / 2
- (*big.Int)(&args.Gas).SetUint64(mid)
+ cap = hi
+ // Create a helper to check if a gas allowance results in an executable transaction
+ executable := func(gas uint64) bool {
+ (*big.Int)(&args.Gas).SetUint64(gas)
_, _, failed, err := s.doCall(ctx, args, rpc.PendingBlockNumber, vm.Config{})
-
- // If the transaction became invalid or execution failed, raise the gas limit
if err != nil || failed {
+ return false
+ }
+ return true
+ }
+ // Execute the binary search and hone in on an executable gas limit
+ for lo+1 < hi {
+ mid := (hi + lo) / 2
+ if !executable(mid) {
lo = mid
- continue
+ } else {
+ hi = mid
+ }
+ }
+ // Reject the transaction as invalid if it still fails at the highest allowance
+ if hi == cap {
+ if !executable(hi) {
+ return nil, fmt.Errorf("gas required exceeds allowance or always failing transaction")
}
- // Otherwise assume the transaction succeeded, lower the gas limit
- hi = mid
}
return (*hexutil.Big)(new(big.Int).SetUint64(hi)), nil
}