core/vm: change exit halt

This commit is contained in:
Gary Rong 2026-05-21 11:33:12 +08:00
parent ce25997091
commit bf69a15de6
2 changed files with 25 additions and 26 deletions

View file

@ -255,8 +255,6 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
evm.captureEnd(evm.depth, startGas, result, ret, err)
}(gas)
}
initialStateGas := gas.StateGas
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
return nil, gas.Preserved(), ErrDepth
@ -281,7 +279,7 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
wgas := evm.AccessEvents.CodeHashGas(addr, true, gas.RegularGas, false)
if _, ok := gas.ChargeRegular(wgas); !ok {
evm.StateDB.RevertToSnapshot(snapshot)
return nil, gas.ExitHalt(initialStateGas), ErrOutOfGas
return nil, gas.ExitHalt(), ErrOutOfGas
}
}
@ -316,7 +314,7 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
}
// Calculate the remaining gas at the end of frame
exitGas := gas.Exit(err, initialStateGas)
exitGas := gas.Exit(err)
if err != nil {
evm.StateDB.RevertToSnapshot(snapshot)
@ -345,8 +343,6 @@ func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byt
evm.captureEnd(evm.depth, startGas, result, ret, err)
}(gas)
}
initialStateGas := gas.StateGas
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
return nil, gas.Preserved(), ErrDepth
@ -370,7 +366,7 @@ func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byt
}
// Calculate the remaining gas at the end of frame
exitGas := gas.Exit(err, initialStateGas)
exitGas := gas.Exit(err)
if err != nil {
evm.StateDB.RevertToSnapshot(snapshot)
@ -398,8 +394,6 @@ func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address,
evm.captureEnd(evm.depth, startGas, result, ret, err)
}(gas)
}
initialStateGas := gas.StateGas
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
return nil, gas.Preserved(), ErrDepth
@ -417,7 +411,7 @@ func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address,
}
// Calculate the remaining gas at the end of frame
exitGas := gas.Exit(err, initialStateGas)
exitGas := gas.Exit(err)
if err != nil {
evm.StateDB.RevertToSnapshot(snapshot)
@ -443,8 +437,6 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b
evm.captureEnd(evm.depth, startGas, result, ret, err)
}(gas)
}
initialStateGas := gas.StateGas
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
return nil, gas.Preserved(), ErrDepth
@ -472,7 +464,7 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b
}
// Calculate the remaining gas at the end of frame
exitGas := gas.Exit(err, initialStateGas)
exitGas := gas.Exit(err)
if err != nil {
evm.StateDB.RevertToSnapshot(snapshot)
if err != ErrExecutionReverted {
@ -499,8 +491,6 @@ func (evm *EVM) create(caller common.Address, code []byte, gas GasBudget, value
err = ErrNonceUintOverflow
}
}
initialStateGas := gas.StateGas
if err == nil {
evm.StateDB.SetNonce(caller, nonce+1, tracing.NonceChangeContractCreator)
}
@ -519,7 +509,7 @@ func (evm *EVM) create(caller common.Address, code []byte, gas GasBudget, value
statelessGas := evm.AccessEvents.ContractCreatePreCheckGas(address, gas.RegularGas)
prior, ok := gas.Charge(GasCosts{RegularGas: statelessGas})
if !ok {
return nil, common.Address{}, gas.ExitHalt(initialStateGas), ErrOutOfGas
return nil, common.Address{}, gas.ExitHalt(), ErrOutOfGas
}
if evm.Config.Tracer.HasGasHook() {
evm.Config.Tracer.EmitGasChange(prior.AsTracing(), gas.AsTracing(), tracing.GasChangeWitnessContractCollisionCheck)
@ -540,7 +530,7 @@ func (evm *EVM) create(caller common.Address, code []byte, gas GasBudget, value
if evm.StateDB.GetNonce(address) != 0 ||
(contractHash != (common.Hash{}) && contractHash != types.EmptyCodeHash) || // non-empty code
isEIP7610RejectedAccount(evm.ChainConfig().ChainID, address, evm.chainRules.IsEIP158) {
halt := gas.ExitHalt(initialStateGas)
halt := gas.ExitHalt()
if evm.Config.Tracer.HasGasHook() {
evm.Config.Tracer.EmitGasChange(gas.AsTracing(), halt.AsTracing(), tracing.GasChangeCallFailedExecution)
}
@ -568,7 +558,7 @@ func (evm *EVM) create(caller common.Address, code []byte, gas GasBudget, value
if evm.chainRules.IsEIP4762 {
consumed, wanted := evm.AccessEvents.ContractCreateInitGas(address, gas.RegularGas)
if consumed < wanted {
return nil, common.Address{}, gas.ExitHalt(initialStateGas), ErrOutOfGas
return nil, common.Address{}, gas.ExitHalt(), ErrOutOfGas
}
prior, _ := gas.Charge(GasCosts{RegularGas: consumed})
if evm.Config.Tracer.HasGasHook() {
@ -593,7 +583,7 @@ func (evm *EVM) create(caller common.Address, code []byte, gas GasBudget, value
if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) {
evm.StateDB.RevertToSnapshot(snapshot)
exit := contract.Gas.Exit(err, initialStateGas)
exit := contract.Gas.Exit(err)
if err != ErrExecutionReverted {
if evm.Config.Tracer.HasGasHook() {
evm.Config.Tracer.EmitGasChange(contract.Gas.AsTracing(), exit.AsTracing(), tracing.GasChangeCallFailedExecution)

View file

@ -251,13 +251,22 @@ func (g GasBudget) ExitRevert() GasBudget {
}
// ExitHalt produces the leftover form for an exceptional halt. Remaining
// regular gas is accounted as burned; the reservoir resets to initialStateGas
// (the value the caller held at the call site). UsedStateGas is zeroed
// because state-gas effects do not persist on halt.
func (g GasBudget) ExitHalt(initialStateGas uint64) GasBudget {
// regular gas is burned into UsedRegularGas; the state dimension follows the
// same revert-style formula as ExitRevert because the spec routes both halt
// and revert through incorporate_child_on_error:
//
// parent.state_gas_left = parent + child.state_gas_used + child.state_gas_left
//
// which in our model means returning `StateGas + UsedStateGas` to the parent
// and zeroing the per-frame counter.
func (g GasBudget) ExitHalt() GasBudget {
reservoir := int64(g.StateGas) + g.UsedStateGas
if reservoir < 0 {
reservoir = 0
}
return GasBudget{
RegularGas: 0,
StateGas: initialStateGas,
StateGas: uint64(reservoir),
UsedRegularGas: g.UsedRegularGas + g.RegularGas,
UsedStateGas: 0,
}
@ -272,14 +281,14 @@ func (g GasBudget) ExitHalt(initialStateGas uint64) GasBudget {
//
// Soft validation failures (occurring BEFORE evm.Run) should call Preserved
// directly instead of going through this dispatcher.
func (g GasBudget) Exit(err error, initialStateGas uint64) GasBudget {
func (g GasBudget) Exit(err error) GasBudget {
switch {
case err == nil:
return g.ExitSuccess()
case err == ErrExecutionReverted:
return g.ExitRevert()
default:
return g.ExitHalt(initialStateGas)
return g.ExitHalt()
}
}