mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-24 08:49:29 +00:00
core: fix the incorrect regular gas used
This commit is contained in:
parent
22bfedc4b3
commit
324ccdffe1
4 changed files with 28 additions and 21 deletions
|
|
@ -737,8 +737,12 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
|||
)
|
||||
if contractCreation {
|
||||
var result vm.GasBudget
|
||||
// Capture the forwarded regular-gas amount BEFORE ForwardAll consumes
|
||||
// it, so Absorb can back out state-gas spillover from
|
||||
// UsedRegularGas per EIP-8037 (EELS semantics).
|
||||
forwardedR := st.gasRemaining.RegularGas
|
||||
ret, _, result, vmerr = st.evm.Create(msg.From, msg.Data, st.gasRemaining.ForwardAll(), value)
|
||||
st.gasRemaining.Absorb(result)
|
||||
st.gasRemaining.Absorb(result, forwardedR)
|
||||
} else {
|
||||
// Increment the nonce for the next transaction.
|
||||
st.state.SetNonce(msg.From, st.state.GetNonce(msg.From)+1, tracing.NonceChangeEoACall)
|
||||
|
|
@ -756,8 +760,9 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
|||
}
|
||||
// Execute the transaction's call.
|
||||
var result vm.GasBudget
|
||||
forwardedR := st.gasRemaining.RegularGas
|
||||
ret, result, vmerr = st.evm.Call(msg.From, st.to(), msg.Data, st.gasRemaining.ForwardAll(), value)
|
||||
st.gasRemaining.Absorb(result)
|
||||
st.gasRemaining.Absorb(result, forwardedR)
|
||||
}
|
||||
// If this was a failed contract creation, refund the account creation costs.
|
||||
if rules.IsAmsterdam {
|
||||
|
|
|
|||
|
|
@ -162,11 +162,10 @@ func (c *Contract) refundState(s uint64, logger *tracing.Hooks, reason tracing.G
|
|||
}
|
||||
}
|
||||
|
||||
// refundGas absorbs a sub-call's leftover GasBudget into this contract's gas
|
||||
// state. Thin wrapper around GasBudget.Absorb with tracer integration.
|
||||
func (c *Contract) refundGas(child GasBudget, logger *tracing.Hooks, reason tracing.GasChangeReason) {
|
||||
// refundGas absorbs a sub-call's leftover GasBudget into this contract's gas state.
|
||||
func (c *Contract) refundGas(child GasBudget, forwarded uint64, logger *tracing.Hooks, reason tracing.GasChangeReason) {
|
||||
prior := c.Gas
|
||||
c.Gas.Absorb(child)
|
||||
c.Gas.Absorb(child, forwarded)
|
||||
if logger.HasGasHook() && reason != tracing.GasChangeIgnored {
|
||||
logger.EmitGasChange(prior.AsTracing(), c.Gas.AsTracing(), reason)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -293,18 +293,21 @@ func (g GasBudget) Exit(err error) GasBudget {
|
|||
}
|
||||
|
||||
// Absorb merges a sub-call's leftover GasBudget into this (caller's) running
|
||||
// budget. The caller's UsedRegularGas is reclaimed by the unused forwarded
|
||||
// regular gas (which was pre-charged in full at call entry); the state
|
||||
// reservoir is overwritten with the child's leftover; and the child's signed
|
||||
// net state-gas usage is added to the caller's accumulator.
|
||||
// budget. Additionally, it does an EIP-8037 spillover correction:
|
||||
// state-gas that spilled into the regular pool inside the child frame is
|
||||
// excluded from the UsedRegularGas.
|
||||
//
|
||||
// Invariant maintained by all callers: at the moment of this call, the
|
||||
// caller's UsedRegularGas already accounts for the FULL forwarded regular
|
||||
// gas (as if the child had consumed all of it). On halt, child.RegularGas
|
||||
// is 0 so the reclaim is a no-op.
|
||||
func (g *GasBudget) Absorb(child GasBudget) {
|
||||
// spillover = forwarded - child.RegularGas - child.UsedRegularGas
|
||||
//
|
||||
// forwarded is the regular-gas amount that was passed to the child at call
|
||||
// entry (i.e., the regular initial of the child's GasBudget).
|
||||
func (g *GasBudget) Absorb(child GasBudget, forwarded uint64) {
|
||||
spillover := forwarded - child.RegularGas - child.UsedRegularGas
|
||||
|
||||
g.UsedRegularGas -= child.RegularGas
|
||||
g.RegularGas += child.RegularGas
|
||||
g.StateGas = child.StateGas
|
||||
g.UsedStateGas += child.UsedStateGas
|
||||
|
||||
g.UsedRegularGas -= spillover
|
||||
}
|
||||
|
|
|
|||
|
|
@ -675,7 +675,7 @@ func opCreate(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
}
|
||||
scope.Stack.push(&stackvalue)
|
||||
|
||||
scope.Contract.refundGas(result, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
scope.Contract.refundGas(result, forward, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
if evm.chainRules.IsAmsterdam && suberr != nil {
|
||||
scope.Contract.Gas.RefundState(params.AccountCreationSize * evm.Context.CostPerStateByte)
|
||||
}
|
||||
|
|
@ -710,7 +710,7 @@ func opCreate2(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
stackvalue.SetBytes(addr.Bytes())
|
||||
}
|
||||
scope.Stack.push(&stackvalue)
|
||||
scope.Contract.refundGas(result, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
scope.Contract.refundGas(result, forward, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
// If the creation frame reverts or halts exceptionally, the charged state-gas
|
||||
// is refilled back to the state reservoir in Amsterdam.
|
||||
|
|
@ -760,7 +760,7 @@ func opCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
if err == nil || err == ErrExecutionReverted {
|
||||
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
scope.Contract.refundGas(result, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
scope.Contract.refundGas(result, gas, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
// If the call frame reverts or halts exceptionally, the charged state-gas
|
||||
// is refilled back to the state reservoir in Amsterdam.
|
||||
|
|
@ -807,7 +807,7 @@ func opCallCode(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
|
||||
scope.Contract.refundGas(result, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
scope.Contract.refundGas(result, gas, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
evm.returnData = ret
|
||||
return ret, nil
|
||||
|
|
@ -836,7 +836,7 @@ func opDelegateCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
if err == nil || err == ErrExecutionReverted {
|
||||
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
scope.Contract.refundGas(result, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
scope.Contract.refundGas(result, gas, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
evm.returnData = ret
|
||||
return ret, nil
|
||||
|
|
@ -866,7 +866,7 @@ func opStaticCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
|
||||
scope.Contract.refundGas(result, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
scope.Contract.refundGas(result, gas, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
evm.returnData = ret
|
||||
return ret, nil
|
||||
|
|
|
|||
Loading…
Reference in a new issue