mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-08 07:58:40 +00:00
core: last fixes
This commit is contained in:
parent
48d7bf08d7
commit
f71f4da77a
7 changed files with 110 additions and 7 deletions
|
|
@ -241,6 +241,19 @@ func ApplyTransaction(evm *vm.EVM, gp *GasPool, statedb *state.StateDB, header *
|
|||
return ApplyTransactionWithEVM(msg, gp, statedb, header.Number, header.Hash(), header.Time, tx, evm)
|
||||
}
|
||||
|
||||
// systemCallGasBudget returns the gas budget for system calls. Pre-Amsterdam
|
||||
// the budget is 30M regular gas. Post-Amsterdam (EIP-8037), an additional
|
||||
// state-gas reservoir of `STATE_BYTES_PER_STORAGE_SET × CPSB × SYSTEM_MAX_SSTORES_PER_CALL`
|
||||
// is provided to cover the expected new SSTOREs in system contracts.
|
||||
func systemCallGasBudget(evm *vm.EVM) vm.GasBudget {
|
||||
const regular = 30_000_000
|
||||
if evm.ChainConfig().IsAmsterdam(evm.Context.BlockNumber, evm.Context.Time) {
|
||||
stateGas := params.StorageCreationSize * evm.Context.CostPerStateByte * params.SystemMaxSstoresPerCall
|
||||
return vm.NewGasBudget(regular, stateGas)
|
||||
}
|
||||
return vm.NewGasBudgetReg(regular)
|
||||
}
|
||||
|
||||
// ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root
|
||||
// contract. This method is exported to be used in tests.
|
||||
func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM) {
|
||||
|
|
@ -261,7 +274,7 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM) {
|
|||
}
|
||||
evm.SetTxContext(NewEVMTxContext(msg))
|
||||
evm.StateDB.AddAddressToAccessList(params.BeaconRootsAddress)
|
||||
_, _, _ = evm.Call(msg.From, *msg.To, msg.Data, vm.NewGasBudgetReg(30_000_000), common.U2560)
|
||||
_, _, _ = evm.Call(msg.From, *msg.To, msg.Data, systemCallGasBudget(evm), common.U2560)
|
||||
if evm.StateDB.AccessEvents() != nil {
|
||||
evm.StateDB.AccessEvents().Merge(evm.AccessEvents)
|
||||
}
|
||||
|
|
@ -288,7 +301,7 @@ func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM) {
|
|||
}
|
||||
evm.SetTxContext(NewEVMTxContext(msg))
|
||||
evm.StateDB.AddAddressToAccessList(params.HistoryStorageAddress)
|
||||
_, _, err := evm.Call(msg.From, *msg.To, msg.Data, vm.NewGasBudgetReg(30_000_000), common.U2560)
|
||||
_, _, err := evm.Call(msg.From, *msg.To, msg.Data, systemCallGasBudget(evm), common.U2560)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
@ -327,7 +340,7 @@ func processRequestsSystemCall(requests *[][]byte, evm *vm.EVM, requestType byte
|
|||
}
|
||||
evm.SetTxContext(NewEVMTxContext(msg))
|
||||
evm.StateDB.AddAddressToAccessList(addr)
|
||||
ret, _, err := evm.Call(msg.From, *msg.To, msg.Data, vm.NewGasBudgetReg(30_000_000), common.U2560)
|
||||
ret, _, err := evm.Call(msg.From, *msg.To, msg.Data, systemCallGasBudget(evm), common.U2560)
|
||||
if evm.StateDB.AccessEvents() != nil {
|
||||
evm.StateDB.AccessEvents().Merge(evm.AccessEvents)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -769,10 +769,10 @@ func (st *stateTransition) applyAuthorization(rules params.Rules, auth *types.Se
|
|||
return 0, err
|
||||
}
|
||||
|
||||
// If the account already exists in state, refund the new account cost
|
||||
// charged in the intrinsic calculation.
|
||||
// If the account is not empty (per EIP-161: non-zero nonce, balance, or
|
||||
// code) refund the new account cost charged in the intrinsic calculation.
|
||||
var refund uint64
|
||||
if st.state.Exist(authority) {
|
||||
if !st.state.Empty(authority) {
|
||||
if rules.IsAmsterdam {
|
||||
// EIP-8037: refund account creation state gas to the reservoir
|
||||
refund = params.AccountCreationSize * st.evm.Context.CostPerStateByte
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ var activators = map[int]func(*JumpTable){
|
|||
7939: enable7939,
|
||||
8024: enable8024,
|
||||
7843: enable7843,
|
||||
8037: enable8037,
|
||||
}
|
||||
|
||||
// EnableEIP enables the given EIP on the config.
|
||||
|
|
@ -169,6 +170,13 @@ func enable3529(jt *JumpTable) {
|
|||
jt[SELFDESTRUCT].dynamicGas = gasSelfdestructEIP3529
|
||||
}
|
||||
|
||||
// enable8037 enables EIP-8037 SSTORE repricing: the regular-gas portion of
|
||||
// new slot creation and same-tx 0→X→0 reset is reduced; the state-gas
|
||||
// portion is charged/refunded at frame-end via the journal.
|
||||
func enable8037(jt *JumpTable) {
|
||||
jt[SSTORE].dynamicGas = gasSStoreEIP8037
|
||||
}
|
||||
|
||||
// enable3198 applies EIP-3198 (BASEFEE Opcode)
|
||||
// - Adds an opcode that returns the current block's base fee.
|
||||
func enable3198(jt *JumpTable) {
|
||||
|
|
|
|||
|
|
@ -660,7 +660,15 @@ func (evm *EVM) initNewContract(contract *Contract, address common.Address) ([]b
|
|||
}
|
||||
|
||||
if !evm.chainRules.IsEIP4762 {
|
||||
createDataGas := uint64(len(ret)) * params.CreateDataGas
|
||||
var createDataGas uint64
|
||||
if evm.chainRules.IsAmsterdam {
|
||||
// EIP-8037: regular gas portion is the keccak hashing cost
|
||||
// (6 × ⌈L/32⌉). The state-gas portion (L × CPSB) is charged
|
||||
// at frame end via the journal's codeChange walker.
|
||||
createDataGas = ((uint64(len(ret)) + 31) / 32) * params.Keccak256WordGas
|
||||
} else {
|
||||
createDataGas = uint64(len(ret)) * params.CreateDataGas
|
||||
}
|
||||
if !contract.UseGas(GasCosts{RegularGas: createDataGas}, evm.Config.Tracer, tracing.GasChangeCallCodeStorage) {
|
||||
return ret, ErrCodeStoreOutOfGas
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ func newAmsterdamInstructionSet() JumpTable {
|
|||
instructionSet := newOsakaInstructionSet()
|
||||
enable7843(&instructionSet) // EIP-7843 (SLOTNUM opcode)
|
||||
enable8024(&instructionSet) // EIP-8024 (Backward compatible SWAPN, DUPN, EXCHANGE)
|
||||
enable8037(&instructionSet) // EIP-8037 SSTORE repricing
|
||||
return validate(instructionSet)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -222,8 +222,80 @@ var (
|
|||
// gasSStoreEIP3529 implements gas cost for SSTORE according to EIP-3529
|
||||
// Replace `SSTORE_CLEARS_SCHEDULE` with `SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST` (4,800)
|
||||
gasSStoreEIP3529 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP3529)
|
||||
|
||||
// gasSStoreEIP8037 implements gas cost for SSTORE under EIP-8037.
|
||||
// New slot creation (orig=0, current=0, value!=0) is repriced from
|
||||
// SstoreSetGas (20,000) to SstoreUpdateGas - ColdSloadCost (2,900); the
|
||||
// state-gas portion (32 × CPSB) is charged at frame-end via the journal.
|
||||
// Likewise the same-tx 0→X→0 reset refund is reduced from 19,900 to
|
||||
// SstoreUpdateGas - ColdSloadCost - WarmStorageReadCost (2,800); the
|
||||
// state-gas refund is also handled at frame-end.
|
||||
gasSStoreEIP8037 = makeGasSStoreFuncAmsterdam(params.SstoreClearsScheduleRefundEIP3529)
|
||||
)
|
||||
|
||||
// makeGasSStoreFuncAmsterdam returns the EIP-8037 SSTORE gas function. It is
|
||||
// identical to makeGasSStoreFunc except that the regular-gas portion of new
|
||||
// slot creation and same-tx 0→X→0 reset is reduced (the state-gas portion is
|
||||
// charged/refunded at frame-end via the journal).
|
||||
func makeGasSStoreFuncAmsterdam(clearingRefund uint64) gasFunc {
|
||||
return func(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 (
|
||||
y, x = stack.Back(1), stack.peek()
|
||||
slot = common.Hash(x.Bytes32())
|
||||
current, original = evm.StateDB.GetStateAndCommittedState(contract.Address(), slot)
|
||||
cost = uint64(0)
|
||||
)
|
||||
if _, slotPresent := evm.StateDB.SlotInAccessList(contract.Address(), slot); !slotPresent {
|
||||
cost = params.ColdSloadCostEIP2929
|
||||
evm.StateDB.AddSlotToAccessList(contract.Address(), slot)
|
||||
}
|
||||
value := common.Hash(y.Bytes32())
|
||||
|
||||
// EIP-8037: regular-gas portion of new slot creation is the storage
|
||||
// update cost minus cold sload (2,900). State-gas portion is at
|
||||
// frame-end.
|
||||
sstoreNewSlotRegularGas := params.SstoreResetGasEIP2200 - params.ColdSloadCostEIP2929
|
||||
|
||||
if current == value { // noop
|
||||
return GasCosts{RegularGas: cost + params.WarmStorageReadCostEIP2929}, nil
|
||||
}
|
||||
if original == current {
|
||||
if original == (common.Hash{}) { // create slot (2.1.1)
|
||||
return GasCosts{RegularGas: cost + sstoreNewSlotRegularGas}, nil
|
||||
}
|
||||
if value == (common.Hash{}) { // delete pre-existing slot
|
||||
evm.StateDB.AddRefund(clearingRefund)
|
||||
}
|
||||
return GasCosts{RegularGas: cost + (params.SstoreResetGasEIP2200 - params.ColdSloadCostEIP2929)}, nil
|
||||
}
|
||||
if original != (common.Hash{}) {
|
||||
if current == (common.Hash{}) { // recreate slot (2.2.1.1)
|
||||
evm.StateDB.SubRefund(clearingRefund)
|
||||
} else if value == (common.Hash{}) { // delete dirty (2.2.1.2)
|
||||
evm.StateDB.AddRefund(clearingRefund)
|
||||
}
|
||||
}
|
||||
if original == value {
|
||||
if original == (common.Hash{}) { // 0→X→0: reset to original-zero
|
||||
// EIP-8037: regular-gas refund is reduced because the
|
||||
// original SET cost was already reduced to
|
||||
// sstoreNewSlotRegularGas. State-gas refund (32 × CPSB)
|
||||
// is applied at frame-end.
|
||||
evm.StateDB.AddRefund(sstoreNewSlotRegularGas - params.WarmStorageReadCostEIP2929)
|
||||
} else { // reset to original existing slot
|
||||
evm.StateDB.AddRefund((params.SstoreResetGasEIP2200 - params.ColdSloadCostEIP2929) - params.WarmStorageReadCostEIP2929)
|
||||
}
|
||||
}
|
||||
return GasCosts{RegularGas: cost + params.WarmStorageReadCostEIP2929}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// makeSelfdestructGasFn can create the selfdestruct dynamic gas function for EIP-2929 and EIP-3529
|
||||
func makeSelfdestructGasFn(refundsEnabled bool) gasFunc {
|
||||
gasFunc := func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (GasCosts, error) {
|
||||
|
|
|
|||
|
|
@ -193,6 +193,7 @@ const (
|
|||
AccountCreationSize = 112
|
||||
StorageCreationSize = 32
|
||||
AuthorizationCreationSize = 23
|
||||
SystemMaxSstoresPerCall = 16 // EIP-8037: upper bound on new SSTOREs per system call
|
||||
|
||||
GasBlockAccessListItem = 2000 // EIP-7928: gas cost per BAL item for gas limit check
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue