mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
feat: gasUsed use result.UsedGas (#45)
This commit is contained in:
parent
69c7e7b917
commit
aedf42a155
1 changed files with 0 additions and 147 deletions
|
|
@ -2,7 +2,6 @@ package eth
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"math"
|
||||
|
|
@ -19,8 +18,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
|
||||
// "github.com/DeBankDeFi/eth/txtrace"
|
||||
|
|
@ -249,7 +246,6 @@ func (api *PreExecAPI) TraceMany(ctx context.Context, origins []PreArgs) ([]PreR
|
|||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(origins); i++ {
|
||||
stateOld := state.Copy()
|
||||
origin := origins[i]
|
||||
if origin.Nonce == nil {
|
||||
preResList = append(preResList, PreResult{
|
||||
|
|
@ -347,150 +343,7 @@ func (api *PreExecAPI) TraceMany(ctx context.Context, origins []PreArgs) ([]PreR
|
|||
Msg: (preRes.Trace)[0].Error,
|
||||
}
|
||||
}
|
||||
if preRes.Error.Code == 0 {
|
||||
gasLimit := header.GasLimit
|
||||
gasCap := api.e.APIBackend.RPCGasCap()
|
||||
if gasLimit > gasCap {
|
||||
gasLimit = gasCap
|
||||
}
|
||||
usedGas := api.doEstimateGas(ctx, txArgs, header, stateOld, gasLimit)
|
||||
log.Debug("doEstimateGas", "usedGas", usedGas)
|
||||
if usedGas > 0 {
|
||||
preRes.GasUsed = usedGas
|
||||
}
|
||||
}
|
||||
preResList = append(preResList, preRes)
|
||||
}
|
||||
return preResList, nil
|
||||
}
|
||||
|
||||
func (api *PreExecAPI) doEstimateGas(ctx context.Context, args ethapi.TransactionArgs, header *types.Header, state *state.StateDB, gasLimit uint64) uint64 {
|
||||
// Binary search the gas requirement, as it may be higher than the amount used
|
||||
var (
|
||||
lo uint64 = params.TxGas - 1
|
||||
hi uint64
|
||||
)
|
||||
// Use zero address if sender unspecified.
|
||||
if args.From == nil {
|
||||
args.From = new(common.Address)
|
||||
}
|
||||
// Determine the highest gas limit can be used during the estimation.
|
||||
if args.Gas != nil && uint64(*args.Gas) >= params.TxGas {
|
||||
hi = uint64(*args.Gas)
|
||||
} else {
|
||||
hi = gasLimit
|
||||
}
|
||||
// Normalize the max fee per gas the call is willing to spend.
|
||||
var feeCap *big.Int
|
||||
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
|
||||
return 0
|
||||
} else if args.GasPrice != nil {
|
||||
feeCap = args.GasPrice.ToInt()
|
||||
} else if args.MaxFeePerGas != nil {
|
||||
feeCap = args.MaxFeePerGas.ToInt()
|
||||
} else {
|
||||
feeCap = common.Big0
|
||||
}
|
||||
// Recap the highest gas limit with account's available balance.
|
||||
if feeCap.BitLen() != 0 {
|
||||
balance := state.GetBalance(*args.From) // from can't be nil
|
||||
available := new(big.Int).Set(balance)
|
||||
if args.Value != nil {
|
||||
if args.Value.ToInt().Cmp(available) >= 0 {
|
||||
return 0
|
||||
}
|
||||
available.Sub(available, args.Value.ToInt())
|
||||
}
|
||||
allowance := new(big.Int).Div(available, feeCap)
|
||||
|
||||
// If the allowance is larger than maximum uint64, skip checking
|
||||
if allowance.IsUint64() && hi > allowance.Uint64() {
|
||||
transfer := args.Value
|
||||
if transfer == nil {
|
||||
transfer = new(hexutil.Big)
|
||||
}
|
||||
log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance,
|
||||
"sent", transfer.ToInt(), "maxFeePerGas", feeCap, "fundable", allowance)
|
||||
hi = allowance.Uint64()
|
||||
}
|
||||
}
|
||||
// Recap the highest gas allowance with specified gascap.
|
||||
if gasLimit != 0 && hi > gasLimit {
|
||||
hi = gasLimit
|
||||
}
|
||||
cap := hi
|
||||
|
||||
// Create a helper to check if a gas allowance results in an executable transaction
|
||||
executable := func(gas uint64) (bool, *core.ExecutionResult, error) {
|
||||
args.Gas = (*hexutil.Uint64)(&gas)
|
||||
|
||||
result, err := api.doCallCopy(ctx, args, header, state)
|
||||
log.Debug("doCallCopy", "result", result, "err", err)
|
||||
if err != nil {
|
||||
if errors.Is(err, core.ErrIntrinsicGas) {
|
||||
return true, nil, nil // Special case, raise gas limit
|
||||
}
|
||||
return true, nil, err // Bail out
|
||||
}
|
||||
return result.Failed(), result, nil
|
||||
}
|
||||
|
||||
// Execute the binary search and hone in on an executable gas limit
|
||||
for lo+1 < hi {
|
||||
mid := (hi + lo) / 2
|
||||
failed, _, err := executable(mid)
|
||||
|
||||
// If the error is not nil(consensus error), it means the provided message
|
||||
// call or transaction will never be accepted no matter how much gas it is
|
||||
// assigned. Return the error directly, don't struggle any more.
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
if failed {
|
||||
lo = mid
|
||||
} else {
|
||||
hi = mid
|
||||
}
|
||||
}
|
||||
// Reject the transaction as invalid if it still fails at the highest allowance
|
||||
if hi == cap {
|
||||
failed, result, err := executable(hi)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
if failed {
|
||||
if result != nil && result.Err != vm.ErrOutOfGas {
|
||||
if len(result.Revert()) > 0 {
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
}
|
||||
// Otherwise, the specified gas cap is too low
|
||||
return 0
|
||||
}
|
||||
}
|
||||
return hi
|
||||
}
|
||||
|
||||
func (api *PreExecAPI) doCallCopy(ctx context.Context, args ethapi.TransactionArgs, header *types.Header, state *state.StateDB) (*core.ExecutionResult, error) {
|
||||
stateNew := state.Copy()
|
||||
// Get a new instance of the EVM.
|
||||
msg, err := args.ToMessage(api.e.APIBackend.RPCGasCap(), header.BaseFee)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
evm, vmError, err := api.e.APIBackend.GetEVM(ctx, msg, stateNew, header, &vm.Config{NoBaseFee: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Execute the message.
|
||||
gp := new(core.GasPool).AddGas(math.MaxUint64)
|
||||
result, err := core.ApplyMessage(evm, msg, gp)
|
||||
if err := vmError(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("err: %w (supplied gas %d)", err, msg.Gas())
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue