mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-08 07:58:40 +00:00
core/vm: introduce eip-8037 gas metering for SSTORE
This commit is contained in:
parent
01036bed83
commit
93ffef90cc
4 changed files with 62 additions and 9 deletions
|
|
@ -43,6 +43,7 @@ var activators = map[int]func(*JumpTable){
|
||||||
7939: enable7939,
|
7939: enable7939,
|
||||||
8024: enable8024,
|
8024: enable8024,
|
||||||
7843: enable7843,
|
7843: enable7843,
|
||||||
|
8037: enable8037,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnableEIP enables the given EIP on the config.
|
// EnableEIP enables the given EIP on the config.
|
||||||
|
|
@ -590,3 +591,9 @@ func enable7843(jt *JumpTable) {
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// enable8037 applies EIP-8037: State Creation Gas Cost Increase
|
||||||
|
func enable8037(jt *JumpTable) {
|
||||||
|
jt[SLOAD].constantGas = params.SloadGasEIP2200
|
||||||
|
jt[SSTORE].dynamicGas = gasSStoreEIP8037
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -226,6 +226,52 @@ func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m
|
||||||
return GasCosts{RegularGas: params.SloadGasEIP2200}, nil // dirty update (2.2)
|
return GasCosts{RegularGas: params.SloadGasEIP2200}, nil // dirty update (2.2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EIP-8037 constants. EIP-8037 only diverges from EIP-2200 on slots whose
|
||||||
|
// tx-original is zero AND on writes that cross the zero/non-zero boundary
|
||||||
|
// (i.e. a state creation or its in-tx undo). Everything else stays on the
|
||||||
|
// EIP-2200 schedule.
|
||||||
|
const (
|
||||||
|
stateBytesPerSlotEIP8037 = 64 // bytes attributed to one slot's state
|
||||||
|
costPerStateByteEIP8037 = 1157 // gas per state-creation byte
|
||||||
|
sstoreBaseGasEIP8037 = 2900 // regular gas baseline for the EIP-8037 transitions
|
||||||
|
stateGasEIP8037 = stateBytesPerSlotEIP8037 * costPerStateByteEIP8037
|
||||||
|
)
|
||||||
|
|
||||||
|
// gasSStoreEIP8037 prices SSTORE under EIP-8037.
|
||||||
|
//
|
||||||
|
// Two specific (original, current, value) shapes get the new pricing:
|
||||||
|
// - O == 0, C == 0, V != 0 — creating fresh state in this tx.
|
||||||
|
// Charge stateGasEIP8037 of state gas and sstoreBaseGasEIP8037 of regular gas.
|
||||||
|
// - O == 0, C != 0, V == 0 — undoing the in-tx creation.
|
||||||
|
// Refund stateGasEIP8037 of state gas (negative StateGas in the cost
|
||||||
|
// vector) and pay sstoreBaseGasEIP8037 of regular gas.
|
||||||
|
//
|
||||||
|
// Every other shape — including O != 0 of any kind, and O == 0 cases that
|
||||||
|
// don't cross zero — defers to gasSStoreEIP2200 unchanged.
|
||||||
|
func gasSStoreEIP8037(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (GasCosts, error) {
|
||||||
|
if evm.readOnly {
|
||||||
|
return GasCosts{}, ErrWriteProtection
|
||||||
|
}
|
||||||
|
if contract.Gas.RegularGas <= params.SstoreSentryGasEIP2200 {
|
||||||
|
return GasCosts{}, errors.New("not enough gas for reentrancy sentry")
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
zero = common.Hash{}
|
||||||
|
y, x = stack.back(1), stack.back(0)
|
||||||
|
current, original = evm.StateDB.GetStateAndCommittedState(contract.Address(), x.Bytes32())
|
||||||
|
value = common.Hash(y.Bytes32())
|
||||||
|
)
|
||||||
|
if original == zero {
|
||||||
|
switch {
|
||||||
|
case current == zero && value != zero: // creation
|
||||||
|
return GasCosts{RegularGas: sstoreBaseGasEIP8037, StateGas: stateGasEIP8037}, nil
|
||||||
|
case current != zero && value == zero: // undo creation
|
||||||
|
return GasCosts{RegularGas: sstoreBaseGasEIP8037, StateGas: -stateGasEIP8037}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return gasSStoreEIP2200(evm, contract, stack, mem, memorySize)
|
||||||
|
}
|
||||||
|
|
||||||
func makeGasLog(n uint64) gasFunc {
|
func makeGasLog(n uint64) gasFunc {
|
||||||
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (GasCosts, error) {
|
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (GasCosts, error) {
|
||||||
requestedSize, overflow := stack.back(1).Uint64WithOverflow()
|
requestedSize, overflow := stack.back(1).Uint64WithOverflow()
|
||||||
|
|
|
||||||
|
|
@ -18,17 +18,16 @@ package vm
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
// GasCosts denotes a vector of gas costs in the
|
// GasCosts denotes a vector of gas costs in the multidimensional metering
|
||||||
// multidimensional metering paradigm. It represents the cost
|
// paradigm. It represents the cost charged by an individual operation.
|
||||||
// charged by an individual operation.
|
//
|
||||||
|
// StateGas is signed so an operation can express a state-gas refund
|
||||||
|
// (negative cost) — e.g. an SSTORE that undoes an in-tx state creation.
|
||||||
|
// Such a refund flows back into the StateGas reservoir of the GasBudget,
|
||||||
|
// not into RegularGas.
|
||||||
type GasCosts struct {
|
type GasCosts struct {
|
||||||
RegularGas uint64
|
RegularGas uint64
|
||||||
StateGas uint64
|
StateGas int64
|
||||||
}
|
|
||||||
|
|
||||||
// Sum returns the total gas (regular + state).
|
|
||||||
func (g GasCosts) Sum() uint64 {
|
|
||||||
return g.RegularGas + g.StateGas
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a visual representation of the gas vector.
|
// String returns a visual representation of the gas vector.
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,7 @@ func newAmsterdamInstructionSet() JumpTable {
|
||||||
instructionSet := newOsakaInstructionSet()
|
instructionSet := newOsakaInstructionSet()
|
||||||
enable7843(&instructionSet) // EIP-7843 (SLOTNUM opcode)
|
enable7843(&instructionSet) // EIP-7843 (SLOTNUM opcode)
|
||||||
enable8024(&instructionSet) // EIP-8024 (Backward compatible SWAPN, DUPN, EXCHANGE)
|
enable8024(&instructionSet) // EIP-8024 (Backward compatible SWAPN, DUPN, EXCHANGE)
|
||||||
|
enable8037(&instructionSet) // EIP-8037 (State Creation Gas Cost Increase)
|
||||||
return validate(instructionSet)
|
return validate(instructionSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue