mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
core, eth/gasestimator: hard guess at a possible required gas
This commit is contained in:
parent
bfcb350f36
commit
a0b41b670f
2 changed files with 33 additions and 10 deletions
|
|
@ -32,9 +32,10 @@ import (
|
|||
// ExecutionResult includes all output after executing given evm
|
||||
// message no matter the execution itself is successful or not.
|
||||
type ExecutionResult struct {
|
||||
UsedGas uint64 // Total used gas but include the refunded gas
|
||||
Err error // Any error encountered during the execution(listed in core/vm/errors.go)
|
||||
ReturnData []byte // Returned data from evm(function result or data supplied with revert opcode)
|
||||
UsedGas uint64 // Total used gas, not including the refunded gas
|
||||
RefundedGas uint64 // Total gas refunded after execution
|
||||
Err error // Any error encountered during the execution(listed in core/vm/errors.go)
|
||||
ReturnData []byte // Returned data from evm(function result or data supplied with revert opcode)
|
||||
}
|
||||
|
||||
// Unwrap returns the internal evm error which allows us for further
|
||||
|
|
@ -419,12 +420,13 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
|||
ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, msg.Value)
|
||||
}
|
||||
|
||||
var gasRefund uint64
|
||||
if !rules.IsLondon {
|
||||
// Before EIP-3529: refunds were capped to gasUsed / 2
|
||||
st.refundGas(params.RefundQuotient)
|
||||
gasRefund = st.refundGas(params.RefundQuotient)
|
||||
} else {
|
||||
// After EIP-3529: refunds are capped to gasUsed / 5
|
||||
st.refundGas(params.RefundQuotientEIP3529)
|
||||
gasRefund = st.refundGas(params.RefundQuotientEIP3529)
|
||||
}
|
||||
effectiveTip := msg.GasPrice
|
||||
if rules.IsLondon {
|
||||
|
|
@ -442,13 +444,14 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
|||
}
|
||||
|
||||
return &ExecutionResult{
|
||||
UsedGas: st.gasUsed(),
|
||||
Err: vmerr,
|
||||
ReturnData: ret,
|
||||
UsedGas: st.gasUsed(),
|
||||
RefundedGas: gasRefund,
|
||||
Err: vmerr,
|
||||
ReturnData: ret,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (st *StateTransition) refundGas(refundQuotient uint64) {
|
||||
func (st *StateTransition) refundGas(refundQuotient uint64) uint64 {
|
||||
// Apply refund counter, capped to a refund quotient
|
||||
refund := st.gasUsed() / refundQuotient
|
||||
if refund > st.state.GetRefund() {
|
||||
|
|
@ -463,6 +466,8 @@ func (st *StateTransition) refundGas(refundQuotient uint64) {
|
|||
// Also return remaining gas to the block gas counter so it is
|
||||
// available for the next transaction.
|
||||
st.gp.AddGas(st.gasRemaining)
|
||||
|
||||
return refund
|
||||
}
|
||||
|
||||
// gasUsed returns the amount of gas used up by the state transition.
|
||||
|
|
|
|||
|
|
@ -129,6 +129,24 @@ func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uin
|
|||
// limit for these cases anyway.
|
||||
lo = result.UsedGas - 1
|
||||
|
||||
// There's a fairly high chance for the transaction to execute successfully
|
||||
// with gasLimit set to the first execution's usedGas + gasRefund. Explicitly
|
||||
// check that gas amount and use as a limit for the binary search.
|
||||
optimisticGasLimit := (result.UsedGas + result.RefundedGas + params.CallStipend) * 64 / 63
|
||||
if optimisticGasLimit < hi {
|
||||
failed, _, err = execute(ctx, call, opts, optimisticGasLimit)
|
||||
if err != nil {
|
||||
// This should not happen under normal conditions since if we make it this far the
|
||||
// transaction had run without error at least once before.
|
||||
log.Error("Execution error in estimate gas", "err", err)
|
||||
return 0, nil, err
|
||||
}
|
||||
if failed {
|
||||
lo = optimisticGasLimit
|
||||
} else {
|
||||
hi = optimisticGasLimit
|
||||
}
|
||||
}
|
||||
// Binary search for the smallest gas limit that allows the tx to execute successfully.
|
||||
for lo+1 < hi {
|
||||
if opts.ErrorRatio > 0 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue