mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-24 08:49:29 +00:00
core/vm: change exit halt
This commit is contained in:
parent
ce25997091
commit
bf69a15de6
2 changed files with 25 additions and 26 deletions
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue