mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 14:46:42 +00:00
core/vm: implement stack.Address
This commit is contained in:
parent
dd232413c5
commit
83c0624999
4 changed files with 43 additions and 49 deletions
|
|
@ -381,9 +381,9 @@ func gasExpEIP158(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memor
|
||||||
func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
var (
|
var (
|
||||||
gas uint64
|
gas uint64
|
||||||
value, addr = stack.Back(2), stack.Back(1)
|
value = stack.Back(2)
|
||||||
transfersValue = !value.IsZero()
|
transfersValue = !value.IsZero()
|
||||||
address = common.Address(addr.Bytes20())
|
address = stack.Address(1)
|
||||||
)
|
)
|
||||||
if evm.chainRules.IsEIP158 {
|
if evm.chainRules.IsEIP158 {
|
||||||
if transfersValue && evm.StateDB.Empty(address) {
|
if transfersValue && evm.StateDB.Empty(address) {
|
||||||
|
|
@ -430,7 +430,7 @@ func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memory
|
||||||
var (
|
var (
|
||||||
gas uint64
|
gas uint64
|
||||||
overflow bool
|
overflow bool
|
||||||
value, addr = stack.Back(2), stack.Back(1)
|
value = stack.Back(2)
|
||||||
)
|
)
|
||||||
if value.Sign() != 0 && !evm.chainRules.IsEIP4762 {
|
if value.Sign() != 0 && !evm.chainRules.IsEIP4762 {
|
||||||
gas += params.CallValueTransferGas
|
gas += params.CallValueTransferGas
|
||||||
|
|
@ -439,7 +439,7 @@ func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memory
|
||||||
return 0, ErrGasUintOverflow
|
return 0, ErrGasUintOverflow
|
||||||
}
|
}
|
||||||
if evm.chainRules.IsEIP4762 && !contract.IsSystemCall {
|
if evm.chainRules.IsEIP4762 && !contract.IsSystemCall {
|
||||||
address := common.Address(addr.Bytes20())
|
address := stack.Address(1)
|
||||||
transfersValue := !value.IsZero()
|
transfersValue := !value.IsZero()
|
||||||
if transfersValue {
|
if transfersValue {
|
||||||
gas, overflow = math.SafeAdd(gas, evm.AccessEvents.ValueTransferGas(contract.Address(), address))
|
gas, overflow = math.SafeAdd(gas, evm.AccessEvents.ValueTransferGas(contract.Address(), address))
|
||||||
|
|
@ -495,8 +495,7 @@ func gasSelfdestruct(evm *EVM, contract *Contract, stack *Stack, mem *Memory, me
|
||||||
// EIP150 homestead gas reprice fork:
|
// EIP150 homestead gas reprice fork:
|
||||||
if evm.chainRules.IsEIP150 {
|
if evm.chainRules.IsEIP150 {
|
||||||
gas = params.SelfdestructGasEIP150
|
gas = params.SelfdestructGasEIP150
|
||||||
addr := stack.Back(0)
|
var address = stack.Address(0)
|
||||||
var address = common.Address(addr.Bytes20())
|
|
||||||
|
|
||||||
if evm.chainRules.IsEIP158 {
|
if evm.chainRules.IsEIP158 {
|
||||||
// if empty and transfers value
|
// if empty and transfers value
|
||||||
|
|
|
||||||
|
|
@ -120,11 +120,10 @@ func gasExtCodeCopyEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memo
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
addr := stack.Back(0)
|
addr := stack.Address(0)
|
||||||
address := common.Address(addr.Bytes20())
|
|
||||||
// Check slot presence in the access list
|
// Check slot presence in the access list
|
||||||
if !evm.StateDB.AddressInAccessList(address) {
|
if !evm.StateDB.AddressInAccessList(addr) {
|
||||||
evm.StateDB.AddAddressToAccessList(address)
|
evm.StateDB.AddAddressToAccessList(addr)
|
||||||
var overflow bool
|
var overflow bool
|
||||||
// We charge (cold-warm), since 'warm' is already charged as constantGas
|
// We charge (cold-warm), since 'warm' is already charged as constantGas
|
||||||
if gas, overflow = math.SafeAdd(gas, params.ColdAccountAccessCostEIP2929-params.WarmStorageReadCostEIP2929); overflow {
|
if gas, overflow = math.SafeAdd(gas, params.ColdAccountAccessCostEIP2929-params.WarmStorageReadCostEIP2929); overflow {
|
||||||
|
|
@ -143,12 +142,11 @@ func gasExtCodeCopyEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memo
|
||||||
// - extcodesize,
|
// - extcodesize,
|
||||||
// - (ext) balance
|
// - (ext) balance
|
||||||
func gasEip2929AccountCheck(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
func gasEip2929AccountCheck(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
addr := stack.Back(0)
|
addr := stack.Address(0)
|
||||||
address := common.Address(addr.Bytes20())
|
|
||||||
// Check slot presence in the access list
|
// Check slot presence in the access list
|
||||||
if !evm.StateDB.AddressInAccessList(address) {
|
if !evm.StateDB.AddressInAccessList(addr) {
|
||||||
// If the caller cannot afford the cost, this change will be rolled back
|
// If the caller cannot afford the cost, this change will be rolled back
|
||||||
evm.StateDB.AddAddressToAccessList(address)
|
evm.StateDB.AddAddressToAccessList(addr)
|
||||||
// The warm storage read cost is already charged as constantGas
|
// The warm storage read cost is already charged as constantGas
|
||||||
return params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929, nil
|
return params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929, nil
|
||||||
}
|
}
|
||||||
|
|
@ -157,15 +155,14 @@ func gasEip2929AccountCheck(evm *EVM, contract *Contract, stack *Stack, mem *Mem
|
||||||
|
|
||||||
func makeCallVariantGasCallEIP2929(oldCalculator gasFunc, addressPosition int) gasFunc {
|
func makeCallVariantGasCallEIP2929(oldCalculator gasFunc, addressPosition int) gasFunc {
|
||||||
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
addr := stack.Back(addressPosition)
|
addr := stack.Address(addressPosition)
|
||||||
address := common.Address(addr.Bytes20())
|
|
||||||
// Check slot presence in the access list
|
// Check slot presence in the access list
|
||||||
warmAccess := evm.StateDB.AddressInAccessList(address)
|
warmAccess := evm.StateDB.AddressInAccessList(addr)
|
||||||
// The WarmStorageReadCostEIP2929 (100) is already deducted in the form of a constant cost, so
|
// The WarmStorageReadCostEIP2929 (100) is already deducted in the form of a constant cost, so
|
||||||
// the cost to charge for cold access, if any, is Cold - Warm
|
// the cost to charge for cold access, if any, is Cold - Warm
|
||||||
coldCost := params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929
|
coldCost := params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929
|
||||||
if !warmAccess {
|
if !warmAccess {
|
||||||
evm.StateDB.AddAddressToAccessList(address)
|
evm.StateDB.AddAddressToAccessList(addr)
|
||||||
// Charge the remaining difference here already, to correctly calculate available
|
// Charge the remaining difference here already, to correctly calculate available
|
||||||
// gas for call
|
// gas for call
|
||||||
if !contract.UseGas(coldCost, evm.Config.Tracer, tracing.GasChangeCallStorageColdAccess) {
|
if !contract.UseGas(coldCost, evm.Config.Tracer, tracing.GasChangeCallStorageColdAccess) {
|
||||||
|
|
@ -228,16 +225,15 @@ func makeSelfdestructGasFn(refundsEnabled bool) gasFunc {
|
||||||
gasFunc := func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
gasFunc := func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
var (
|
var (
|
||||||
gas uint64
|
gas uint64
|
||||||
addr = stack.Back(0)
|
addr = stack.Address(0)
|
||||||
address = common.Address(addr.Bytes20())
|
|
||||||
)
|
)
|
||||||
if !evm.StateDB.AddressInAccessList(address) {
|
if !evm.StateDB.AddressInAccessList(addr) {
|
||||||
// If the caller cannot afford the cost, this change will be rolled back
|
// If the caller cannot afford the cost, this change will be rolled back
|
||||||
evm.StateDB.AddAddressToAccessList(address)
|
evm.StateDB.AddAddressToAccessList(addr)
|
||||||
gas = params.ColdAccountAccessCostEIP2929
|
gas = params.ColdAccountAccessCostEIP2929
|
||||||
}
|
}
|
||||||
// if empty and transfers value
|
// if empty and transfers value
|
||||||
if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
|
if evm.StateDB.Empty(addr) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
|
||||||
gas += params.CreateBySelfdestructGas
|
gas += params.CreateBySelfdestructGas
|
||||||
}
|
}
|
||||||
if refundsEnabled && !evm.StateDB.HasSelfDestructed(contract.Address()) {
|
if refundsEnabled && !evm.StateDB.HasSelfDestructed(contract.Address()) {
|
||||||
|
|
@ -259,13 +255,12 @@ func makeCallVariantGasCallEIP7702(oldCalculator gasFunc) gasFunc {
|
||||||
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
var (
|
var (
|
||||||
total uint64 // total dynamic gas used
|
total uint64 // total dynamic gas used
|
||||||
addr = stack.Back(1)
|
addr = stack.Address(1)
|
||||||
address = common.Address(addr.Bytes20())
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Check slot presence in the access list
|
// Check slot presence in the access list
|
||||||
if !evm.StateDB.AddressInAccessList(address) {
|
if !evm.StateDB.AddressInAccessList(addr) {
|
||||||
evm.StateDB.AddAddressToAccessList(address)
|
evm.StateDB.AddAddressToAccessList(addr)
|
||||||
// The WarmStorageReadCostEIP2929 (100) is already deducted in the form of a constant cost, so
|
// The WarmStorageReadCostEIP2929 (100) is already deducted in the form of a constant cost, so
|
||||||
// the cost to charge for cold access, if any, is Cold - Warm
|
// the cost to charge for cold access, if any, is Cold - Warm
|
||||||
coldCost := params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929
|
coldCost := params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929
|
||||||
|
|
@ -278,7 +273,7 @@ func makeCallVariantGasCallEIP7702(oldCalculator gasFunc) gasFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if code is a delegation and if so, charge for resolution.
|
// Check if code is a delegation and if so, charge for resolution.
|
||||||
if target, ok := types.ParseDelegation(evm.StateDB.GetCode(address)); ok {
|
if target, ok := types.ParseDelegation(evm.StateDB.GetCode(addr)); ok {
|
||||||
var cost uint64
|
var cost uint64
|
||||||
if evm.StateDB.AddressInAccessList(target) {
|
if evm.StateDB.AddressInAccessList(target) {
|
||||||
cost = params.WarmStorageReadCostEIP2929
|
cost = params.WarmStorageReadCostEIP2929
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ package vm
|
||||||
import (
|
import (
|
||||||
gomath "math"
|
gomath "math"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
@ -46,9 +45,8 @@ func gasBalance4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, mem
|
||||||
if contract.IsSystemCall {
|
if contract.IsSystemCall {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
addr := stack.Back(0)
|
addr := stack.Address(0)
|
||||||
address := addr.Bytes20()
|
gas := evm.AccessEvents.BasicDataGas(addr, false)
|
||||||
gas := evm.AccessEvents.BasicDataGas(address, false)
|
|
||||||
if gas == 0 {
|
if gas == 0 {
|
||||||
gas = params.WarmStorageReadCostEIP2929
|
gas = params.WarmStorageReadCostEIP2929
|
||||||
}
|
}
|
||||||
|
|
@ -56,15 +54,14 @@ func gasBalance4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, mem
|
||||||
}
|
}
|
||||||
|
|
||||||
func gasExtCodeSize4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
func gasExtCodeSize4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
addr := stack.Back(0)
|
addr := stack.Address(0)
|
||||||
address := addr.Bytes20()
|
if _, isPrecompile := evm.precompile(addr); isPrecompile {
|
||||||
if _, isPrecompile := evm.precompile(address); isPrecompile {
|
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
if contract.IsSystemCall {
|
if contract.IsSystemCall {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
gas := evm.AccessEvents.BasicDataGas(address, false)
|
gas := evm.AccessEvents.BasicDataGas(addr, false)
|
||||||
if gas == 0 {
|
if gas == 0 {
|
||||||
gas = params.WarmStorageReadCostEIP2929
|
gas = params.WarmStorageReadCostEIP2929
|
||||||
}
|
}
|
||||||
|
|
@ -75,12 +72,11 @@ func gasExtCodeHash4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory,
|
||||||
if contract.IsSystemCall {
|
if contract.IsSystemCall {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
addr := stack.Back(0)
|
addr := stack.Address(0)
|
||||||
address := addr.Bytes20()
|
if _, isPrecompile := evm.precompile(addr); isPrecompile {
|
||||||
if _, isPrecompile := evm.precompile(address); isPrecompile {
|
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
gas := evm.AccessEvents.CodeHashGas(address, false)
|
gas := evm.AccessEvents.CodeHashGas(addr, false)
|
||||||
if gas == 0 {
|
if gas == 0 {
|
||||||
gas = params.WarmStorageReadCostEIP2929
|
gas = params.WarmStorageReadCostEIP2929
|
||||||
}
|
}
|
||||||
|
|
@ -115,8 +111,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func gasSelfdestructEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
func gasSelfdestructEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
addr := stack.Back(0)
|
beneficiaryAddr := stack.Address(0)
|
||||||
beneficiaryAddr := common.Address(addr.Bytes20())
|
|
||||||
if _, isPrecompile := evm.precompile(beneficiaryAddr); isPrecompile {
|
if _, isPrecompile := evm.precompile(beneficiaryAddr); isPrecompile {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
@ -167,9 +162,8 @@ func gasExtCodeCopyEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Memo
|
||||||
if contract.IsSystemCall {
|
if contract.IsSystemCall {
|
||||||
return gas, nil
|
return gas, nil
|
||||||
}
|
}
|
||||||
addr := stack.Back(0)
|
addr := stack.Address(0)
|
||||||
address := common.Address(addr.Bytes20())
|
wgas := evm.AccessEvents.BasicDataGas(addr, false)
|
||||||
wgas := evm.AccessEvents.BasicDataGas(address, false)
|
|
||||||
if wgas == 0 {
|
if wgas == 0 {
|
||||||
wgas = params.WarmStorageReadCostEIP2929
|
wgas = params.WarmStorageReadCostEIP2929
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package vm
|
||||||
import (
|
import (
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -185,3 +186,8 @@ func (s *Stack) dup(n int) {
|
||||||
func (s *Stack) Back(n int) uint256.Int {
|
func (s *Stack) Back(n int) uint256.Int {
|
||||||
return s.inner.data[s.bottom+s.size-n-1]
|
return s.inner.data[s.bottom+s.size-n-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Address returns the n'th item in stack turned into an address
|
||||||
|
func (s *Stack) Address(n int) common.Address {
|
||||||
|
return common.Address(s.inner.data[s.bottom+s.size-n-1].Bytes20())
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue