mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-10 08:51:38 +00:00
core: do selfdestructs
This commit is contained in:
parent
87641c7265
commit
48d7bf08d7
5 changed files with 67 additions and 21 deletions
22
core/evm.go
22
core/evm.go
|
|
@ -18,7 +18,6 @@ package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/bits"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
|
|
@ -91,26 +90,7 @@ func CostPerStateByte(header *types.Header, config *params.ChainConfig) uint64 {
|
||||||
if !config.IsAmsterdam(header.Number, header.Time) {
|
if !config.IsAmsterdam(header.Number, header.Time) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
const (
|
return 1174
|
||||||
blocksPerYear uint64 = 2_628_000 // 7200 * 365
|
|
||||||
offset uint64 = 9578
|
|
||||||
significantBts uint64 = 5
|
|
||||||
)
|
|
||||||
numerator := header.GasLimit * blocksPerYear
|
|
||||||
denominator := uint64(2) * params.TargetStateGrowthPerYear
|
|
||||||
raw := (numerator + denominator - 1) / denominator
|
|
||||||
shifted := raw + offset
|
|
||||||
// bit length of shifted
|
|
||||||
bitLen := uint64(64 - bits.LeadingZeros64(shifted))
|
|
||||||
var shift uint64
|
|
||||||
if bitLen > significantBts {
|
|
||||||
shift = bitLen - significantBts
|
|
||||||
}
|
|
||||||
quantized := (shifted >> shift) << shift
|
|
||||||
if quantized > offset {
|
|
||||||
return quantized - offset
|
|
||||||
}
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEVMTxContext creates a new transaction context for a single transaction.
|
// NewEVMTxContext creates a new transaction context for a single transaction.
|
||||||
|
|
|
||||||
|
|
@ -779,6 +779,61 @@ func (s *StateDB) StateChangedBytes(revid int, excludeSubcalls bool) int64 {
|
||||||
return s.journal.stateChangedBytes(revid, s.stateObjects, excludeSubcalls)
|
return s.journal.stateChangedBytes(revid, s.stateObjects, excludeSubcalls)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SelfDestructRefundBytes computes the total state bytes to refund at tx-end
|
||||||
|
// for accounts that were both created and selfdestructed during this
|
||||||
|
// transaction.
|
||||||
|
func (s *StateDB) SelfDestructRefundBytes() int64 {
|
||||||
|
// Collect addresses created and selfdestructed in this tx.
|
||||||
|
targets := make(map[common.Address]*stateObject)
|
||||||
|
for addr, obj := range s.stateObjects {
|
||||||
|
if s.IsNewContract(addr) && s.HasSelfDestructed(addr) {
|
||||||
|
targets[addr] = obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(targets) == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
// Account creation + code deposit refunds.
|
||||||
|
var bytes int64
|
||||||
|
for _, obj := range targets {
|
||||||
|
bytes += CostPerAccount + int64(len(obj.code))
|
||||||
|
}
|
||||||
|
// For storage slots: walk journal storage entries to find the tx-entry
|
||||||
|
// value of each slot. Count slots where tx-entry was zero and the final
|
||||||
|
// dirty value is non-zero (i.e. the slot was charged as new and not
|
||||||
|
// subsequently cleared).
|
||||||
|
type slotKey struct {
|
||||||
|
addr common.Address
|
||||||
|
key common.Hash
|
||||||
|
}
|
||||||
|
originAtTxEntry := make(map[slotKey]common.Hash)
|
||||||
|
for _, e := range s.journal.entries {
|
||||||
|
sc, ok := e.(storageChange)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := targets[sc.account]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sk := slotKey{sc.account, sc.key}
|
||||||
|
if _, seen := originAtTxEntry[sk]; !seen {
|
||||||
|
originAtTxEntry[sk] = sc.origvalue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for sk, orig := range originAtTxEntry {
|
||||||
|
if orig != (common.Hash{}) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
obj := targets[sk.addr]
|
||||||
|
cur, dirty := obj.dirtyStorage[sk.key]
|
||||||
|
if !dirty || cur == (common.Hash{}) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
bytes += CostPerSlot
|
||||||
|
}
|
||||||
|
return bytes
|
||||||
|
}
|
||||||
|
|
||||||
type removedAccountWithBalance struct {
|
type removedAccountWithBalance struct {
|
||||||
address common.Address
|
address common.Address
|
||||||
balance *uint256.Int
|
balance *uint256.Int
|
||||||
|
|
|
||||||
|
|
@ -296,3 +296,7 @@ func (s *hookedStateDB) Finalise(deleteEmptyObjects bool) *bal.StateAccessList {
|
||||||
func (s *hookedStateDB) StateChangedBytes(revid int, excludeSubcalls bool) int64 {
|
func (s *hookedStateDB) StateChangedBytes(revid int, excludeSubcalls bool) int64 {
|
||||||
return s.inner.StateChangedBytes(revid, excludeSubcalls)
|
return s.inner.StateChangedBytes(revid, excludeSubcalls)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) SelfDestructRefundBytes() int64 {
|
||||||
|
return s.inner.SelfDestructRefundBytes()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -634,6 +634,8 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
||||||
if rules.IsAmsterdam {
|
if rules.IsAmsterdam {
|
||||||
if vmerr == nil {
|
if vmerr == nil {
|
||||||
outerBytes := st.state.StateChangedBytes(outerSnapshot, false)
|
outerBytes := st.state.StateChangedBytes(outerSnapshot, false)
|
||||||
|
// Refund state gas for selfdestructed accounts.
|
||||||
|
outerBytes -= st.state.SelfDestructRefundBytes()
|
||||||
st.gasRemaining.Charge(vm.GasCosts{StateGas: outerBytes * int64(st.evm.Context.CostPerStateByte)})
|
st.gasRemaining.Charge(vm.GasCosts{StateGas: outerBytes * int64(st.evm.Context.CostPerStateByte)})
|
||||||
} else {
|
} else {
|
||||||
if execGasUsed.StateGas > 0 {
|
if execGasUsed.StateGas > 0 {
|
||||||
|
|
|
||||||
|
|
@ -111,4 +111,9 @@ type StateDB interface {
|
||||||
// is true, cached subcall costs are not added to the total. Used by
|
// is true, cached subcall costs are not added to the total. Used by
|
||||||
// EIP-8037 for state gas metering.
|
// EIP-8037 for state gas metering.
|
||||||
StateChangedBytes(revid int, excludeSubcalls bool) int64
|
StateChangedBytes(revid int, excludeSubcalls bool) int64
|
||||||
|
|
||||||
|
// SelfDestructRefundBytes returns the total state bytes to refund at
|
||||||
|
// tx-end for accounts that were both created and selfdestructed during
|
||||||
|
// this transaction (per EIP-6780).
|
||||||
|
SelfDestructRefundBytes() int64
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue