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) evm.captureEnd(evm.depth, startGas, result, ret, err)
}(gas) }(gas)
} }
initialStateGas := gas.StateGas
// Fail if we're trying to execute above the call depth limit // Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) { if evm.depth > int(params.CallCreateDepth) {
return nil, gas.Preserved(), ErrDepth 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) wgas := evm.AccessEvents.CodeHashGas(addr, true, gas.RegularGas, false)
if _, ok := gas.ChargeRegular(wgas); !ok { if _, ok := gas.ChargeRegular(wgas); !ok {
evm.StateDB.RevertToSnapshot(snapshot) 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 // Calculate the remaining gas at the end of frame
exitGas := gas.Exit(err, initialStateGas) exitGas := gas.Exit(err)
if err != nil { if err != nil {
evm.StateDB.RevertToSnapshot(snapshot) 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) evm.captureEnd(evm.depth, startGas, result, ret, err)
}(gas) }(gas)
} }
initialStateGas := gas.StateGas
// Fail if we're trying to execute above the call depth limit // Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) { if evm.depth > int(params.CallCreateDepth) {
return nil, gas.Preserved(), ErrDepth 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 // Calculate the remaining gas at the end of frame
exitGas := gas.Exit(err, initialStateGas) exitGas := gas.Exit(err)
if err != nil { if err != nil {
evm.StateDB.RevertToSnapshot(snapshot) 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) evm.captureEnd(evm.depth, startGas, result, ret, err)
}(gas) }(gas)
} }
initialStateGas := gas.StateGas
// Fail if we're trying to execute above the call depth limit // Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) { if evm.depth > int(params.CallCreateDepth) {
return nil, gas.Preserved(), ErrDepth 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 // Calculate the remaining gas at the end of frame
exitGas := gas.Exit(err, initialStateGas) exitGas := gas.Exit(err)
if err != nil { if err != nil {
evm.StateDB.RevertToSnapshot(snapshot) 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) evm.captureEnd(evm.depth, startGas, result, ret, err)
}(gas) }(gas)
} }
initialStateGas := gas.StateGas
// Fail if we're trying to execute above the call depth limit // Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) { if evm.depth > int(params.CallCreateDepth) {
return nil, gas.Preserved(), ErrDepth 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 // Calculate the remaining gas at the end of frame
exitGas := gas.Exit(err, initialStateGas) exitGas := gas.Exit(err)
if err != nil { if err != nil {
evm.StateDB.RevertToSnapshot(snapshot) evm.StateDB.RevertToSnapshot(snapshot)
if err != ErrExecutionReverted { if err != ErrExecutionReverted {
@ -499,8 +491,6 @@ func (evm *EVM) create(caller common.Address, code []byte, gas GasBudget, value
err = ErrNonceUintOverflow err = ErrNonceUintOverflow
} }
} }
initialStateGas := gas.StateGas
if err == nil { if err == nil {
evm.StateDB.SetNonce(caller, nonce+1, tracing.NonceChangeContractCreator) 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) statelessGas := evm.AccessEvents.ContractCreatePreCheckGas(address, gas.RegularGas)
prior, ok := gas.Charge(GasCosts{RegularGas: statelessGas}) prior, ok := gas.Charge(GasCosts{RegularGas: statelessGas})
if !ok { if !ok {
return nil, common.Address{}, gas.ExitHalt(initialStateGas), ErrOutOfGas return nil, common.Address{}, gas.ExitHalt(), ErrOutOfGas
} }
if evm.Config.Tracer.HasGasHook() { if evm.Config.Tracer.HasGasHook() {
evm.Config.Tracer.EmitGasChange(prior.AsTracing(), gas.AsTracing(), tracing.GasChangeWitnessContractCollisionCheck) 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 || if evm.StateDB.GetNonce(address) != 0 ||
(contractHash != (common.Hash{}) && contractHash != types.EmptyCodeHash) || // non-empty code (contractHash != (common.Hash{}) && contractHash != types.EmptyCodeHash) || // non-empty code
isEIP7610RejectedAccount(evm.ChainConfig().ChainID, address, evm.chainRules.IsEIP158) { isEIP7610RejectedAccount(evm.ChainConfig().ChainID, address, evm.chainRules.IsEIP158) {
halt := gas.ExitHalt(initialStateGas) halt := gas.ExitHalt()
if evm.Config.Tracer.HasGasHook() { if evm.Config.Tracer.HasGasHook() {
evm.Config.Tracer.EmitGasChange(gas.AsTracing(), halt.AsTracing(), tracing.GasChangeCallFailedExecution) 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 { if evm.chainRules.IsEIP4762 {
consumed, wanted := evm.AccessEvents.ContractCreateInitGas(address, gas.RegularGas) consumed, wanted := evm.AccessEvents.ContractCreateInitGas(address, gas.RegularGas)
if consumed < wanted { if consumed < wanted {
return nil, common.Address{}, gas.ExitHalt(initialStateGas), ErrOutOfGas return nil, common.Address{}, gas.ExitHalt(), ErrOutOfGas
} }
prior, _ := gas.Charge(GasCosts{RegularGas: consumed}) prior, _ := gas.Charge(GasCosts{RegularGas: consumed})
if evm.Config.Tracer.HasGasHook() { 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) { if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) {
evm.StateDB.RevertToSnapshot(snapshot) evm.StateDB.RevertToSnapshot(snapshot)
exit := contract.Gas.Exit(err, initialStateGas) exit := contract.Gas.Exit(err)
if err != ErrExecutionReverted { if err != ErrExecutionReverted {
if evm.Config.Tracer.HasGasHook() { if evm.Config.Tracer.HasGasHook() {
evm.Config.Tracer.EmitGasChange(contract.Gas.AsTracing(), exit.AsTracing(), tracing.GasChangeCallFailedExecution) 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 // ExitHalt produces the leftover form for an exceptional halt. Remaining
// regular gas is accounted as burned; the reservoir resets to initialStateGas // regular gas is burned into UsedRegularGas; the state dimension follows the
// (the value the caller held at the call site). UsedStateGas is zeroed // same revert-style formula as ExitRevert because the spec routes both halt
// because state-gas effects do not persist on halt. // and revert through incorporate_child_on_error:
func (g GasBudget) ExitHalt(initialStateGas uint64) GasBudget { //
// 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{ return GasBudget{
RegularGas: 0, RegularGas: 0,
StateGas: initialStateGas, StateGas: uint64(reservoir),
UsedRegularGas: g.UsedRegularGas + g.RegularGas, UsedRegularGas: g.UsedRegularGas + g.RegularGas,
UsedStateGas: 0, UsedStateGas: 0,
} }
@ -272,14 +281,14 @@ func (g GasBudget) ExitHalt(initialStateGas uint64) GasBudget {
// //
// Soft validation failures (occurring BEFORE evm.Run) should call Preserved // Soft validation failures (occurring BEFORE evm.Run) should call Preserved
// directly instead of going through this dispatcher. // directly instead of going through this dispatcher.
func (g GasBudget) Exit(err error, initialStateGas uint64) GasBudget { func (g GasBudget) Exit(err error) GasBudget {
switch { switch {
case err == nil: case err == nil:
return g.ExitSuccess() return g.ExitSuccess()
case err == ErrExecutionReverted: case err == ErrExecutionReverted:
return g.ExitRevert() return g.ExitRevert()
default: default:
return g.ExitHalt(initialStateGas) return g.ExitHalt()
} }
} }