more review feedback

This commit is contained in:
Guillaume Ballet 2024-05-02 16:51:10 +02:00
parent d5699fbb2e
commit 04a4fe14d9
3 changed files with 246 additions and 67 deletions

View file

@ -57,44 +57,44 @@ func NewAccessEvents(pointCache *utils.PointCache) *AccessEvents {
// Merge is used to merge the access events that were generated during the // Merge is used to merge the access events that were generated during the
// execution of a tx, with the accumulation of all access events that were // execution of a tx, with the accumulation of all access events that were
// generated during the execution of all txs preceding this one in a block. // generated during the execution of all txs preceding this one in a block.
func (aw *AccessEvents) Merge(other *AccessEvents) { func (ae *AccessEvents) Merge(other *AccessEvents) {
for k := range other.branches { for k := range other.branches {
aw.branches[k] |= other.branches[k] ae.branches[k] |= other.branches[k]
} }
for k, chunk := range other.chunks { for k, chunk := range other.chunks {
aw.chunks[k] |= chunk ae.chunks[k] |= chunk
} }
} }
// Key returns, predictably, the list of keys that were touched during the // Key returns, predictably, the list of keys that were touched during the
// buildup of the access witness. // buildup of the access witness.
func (aw *AccessEvents) Keys() [][]byte { func (ae *AccessEvents) Keys() [][]byte {
// TODO: consider if parallelizing this is worth it, probably depending on len(aw.chunks). // TODO: consider if parallelizing this is worth it, probably depending on len(ae.chunks).
keys := make([][]byte, 0, len(aw.chunks)) keys := make([][]byte, 0, len(ae.chunks))
for chunk := range aw.chunks { for chunk := range ae.chunks {
basePoint := aw.pointCache.Get(chunk.addr[:]) basePoint := ae.pointCache.Get(chunk.addr[:])
key := utils.GetTreeKeyWithEvaluatedAddress(basePoint, &chunk.treeIndex, chunk.leafKey) key := utils.GetTreeKeyWithEvaluatedAddress(basePoint, &chunk.treeIndex, chunk.leafKey)
keys = append(keys, key) keys = append(keys, key)
} }
return keys return keys
} }
func (aw *AccessEvents) Copy() *AccessEvents { func (ae *AccessEvents) Copy() *AccessEvents {
naw := &AccessEvents{ cpy := &AccessEvents{
branches: make(map[branchAccessKey]mode), branches: make(map[branchAccessKey]mode),
chunks: make(map[chunkAccessKey]mode), chunks: make(map[chunkAccessKey]mode),
pointCache: aw.pointCache, pointCache: ae.pointCache,
} }
naw.Merge(aw) cpy.Merge(ae)
return naw return cpy
} }
// AddAccount returns the gas to be charged for each of the currently cold // AddAccount returns the gas to be charged for each of the currently cold
// member fields of an account. // member fields of an account.
func (aw *AccessEvents) AddAccount(addr []byte, isWrite bool) uint64 { func (ae *AccessEvents) AddAccount(addr []byte, isWrite bool) uint64 {
var gas uint64 var gas uint64
for i := utils.VersionLeafKey; i <= utils.CodeSizeLeafKey; i++ { for i := utils.VersionLeafKey; i <= utils.CodeSizeLeafKey; i++ {
gas += aw.touchAddressAndChargeGas(addr, zeroTreeIndex, byte(i), isWrite) gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, byte(i), isWrite)
} }
return gas return gas
} }
@ -102,60 +102,60 @@ func (aw *AccessEvents) AddAccount(addr []byte, isWrite bool) uint64 {
// MessageCallGas returns the gas to be charged for each of the currently // MessageCallGas returns the gas to be charged for each of the currently
// cold member fields of an account, that need to be touched when making a message // cold member fields of an account, that need to be touched when making a message
// call to that account. // call to that account.
func (aw *AccessEvents) MessageCallGas(destination []byte) uint64 { func (ae *AccessEvents) MessageCallGas(destination []byte) uint64 {
var gas uint64 var gas uint64
gas += aw.touchAddressAndChargeGas(destination, zeroTreeIndex, utils.VersionLeafKey, false) gas += ae.touchAddressAndChargeGas(destination, zeroTreeIndex, utils.VersionLeafKey, false)
gas += aw.touchAddressAndChargeGas(destination, zeroTreeIndex, utils.CodeSizeLeafKey, false) gas += ae.touchAddressAndChargeGas(destination, zeroTreeIndex, utils.CodeSizeLeafKey, false)
return gas return gas
} }
// ValueTransferGas returns the gas to be charged for each of the currently // ValueTransferGas returns the gas to be charged for each of the currently
// cold balance member fields of the caller and the callee accounts. // cold balance member fields of the caller and the callee accounts.
func (aw *AccessEvents) ValueTransferGas(callerAddr, targetAddr []byte) uint64 { func (ae *AccessEvents) ValueTransferGas(callerAddr, targetAddr []byte) uint64 {
var gas uint64 var gas uint64
gas += aw.touchAddressAndChargeGas(callerAddr, zeroTreeIndex, utils.BalanceLeafKey, true) gas += ae.touchAddressAndChargeGas(callerAddr, zeroTreeIndex, utils.BalanceLeafKey, true)
gas += aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BalanceLeafKey, true) gas += ae.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BalanceLeafKey, true)
return gas return gas
} }
// ContractCreateInitGas returns the access gas costs for the initialization of // ContractCreateInitGas returns the access gas costs for the initialization of
// a contract creation. // a contract creation.
func (aw *AccessEvents) ContractCreateInitGas(addr []byte, createSendsValue bool) uint64 { func (ae *AccessEvents) ContractCreateInitGas(addr []byte, createSendsValue bool) uint64 {
var gas uint64 var gas uint64
gas += aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.VersionLeafKey, true) gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.VersionLeafKey, true)
gas += aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.NonceLeafKey, true) gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.NonceLeafKey, true)
if createSendsValue { if createSendsValue {
gas += aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BalanceLeafKey, true) gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BalanceLeafKey, true)
} }
return gas return gas
} }
// AddTxOrigin adds the member fields of the sender account to the witness, // AddTxOrigin adds the member fields of the sender account to the witness,
// so that cold accesses are not charged, since they are covered by the 21000 gas. // so that cold accesses are not charged, since they are covered by the 21000 gas.
func (aw *AccessEvents) AddTxOrigin(originAddr []byte) { func (ae *AccessEvents) AddTxOrigin(originAddr []byte) {
for i := utils.VersionLeafKey; i <= utils.CodeSizeLeafKey; i++ { for i := utils.VersionLeafKey; i <= utils.CodeSizeLeafKey; i++ {
aw.touchAddressAndChargeGas(originAddr, zeroTreeIndex, byte(i), i == utils.BalanceLeafKey || i == utils.NonceLeafKey) ae.touchAddressAndChargeGas(originAddr, zeroTreeIndex, byte(i), i == utils.BalanceLeafKey || i == utils.NonceLeafKey)
} }
} }
// AddTxDestination adds the member fields of the sender account to the witness, // AddTxDestination adds the member fields of the sender account to the witness,
// so that cold accesses are not charged, since they are covered by the 21000 gas. // so that cold accesses are not charged, since they are covered by the 21000 gas.
func (aw *AccessEvents) AddTxDestination(targetAddr []byte, sendsValue bool) { func (ae *AccessEvents) AddTxDestination(targetAddr []byte, sendsValue bool) {
for i := utils.VersionLeafKey; i <= utils.CodeSizeLeafKey; i++ { for i := utils.VersionLeafKey; i <= utils.CodeSizeLeafKey; i++ {
aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, byte(i), i == utils.VersionLeafKey && sendsValue) ae.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, byte(i), i == utils.VersionLeafKey && sendsValue)
} }
} }
// SlotGas returns the amount of gas to be charged for a cold storage access. // SlotGas returns the amount of gas to be charged for a cold storage access.
func (aw *AccessEvents) SlotGas(addr []byte, slot common.Hash, isWrite bool) uint64 { func (ae *AccessEvents) SlotGas(addr []byte, slot common.Hash, isWrite bool) uint64 {
treeIndex, subIndex := utils.StorageIndex(slot.Bytes()) treeIndex, subIndex := utils.StorageIndex(slot.Bytes())
return aw.touchAddressAndChargeGas(addr, *treeIndex, subIndex, isWrite) return ae.touchAddressAndChargeGas(addr, *treeIndex, subIndex, isWrite)
} }
// touchAddressAndChargeGas adds any missing access event to the witness, and returns the cold // touchAddressAndChargeGas adds any missing access event to the witness, and returns the cold
// access cost to be charged, if need be. // access cost to be charged, if need be.
func (aw *AccessEvents) touchAddressAndChargeGas(addr []byte, treeIndex uint256.Int, subIndex byte, isWrite bool) uint64 { func (ae *AccessEvents) touchAddressAndChargeGas(addr []byte, treeIndex uint256.Int, subIndex byte, isWrite bool) uint64 {
stemRead, selectorRead, stemWrite, selectorWrite, selectorFill := aw.touchAddress(addr, treeIndex, subIndex, isWrite) stemRead, selectorRead, stemWrite, selectorWrite, selectorFill := ae.touchAddress(addr, treeIndex, subIndex, isWrite)
var gas uint64 var gas uint64
if stemRead { if stemRead {
@ -178,33 +178,33 @@ func (aw *AccessEvents) touchAddressAndChargeGas(addr []byte, treeIndex uint256.
} }
// touchAddress adds any missing access event to the witness. // touchAddress adds any missing access event to the witness.
func (aw *AccessEvents) touchAddress(addr []byte, treeIndex uint256.Int, subIndex byte, isWrite bool) (bool, bool, bool, bool, bool) { func (ae *AccessEvents) touchAddress(addr []byte, treeIndex uint256.Int, subIndex byte, isWrite bool) (bool, bool, bool, bool, bool) {
branchKey := newBranchAccessKey(addr, treeIndex) branchKey := newBranchAccessKey(addr, treeIndex)
chunkKey := newChunkAccessKey(branchKey, subIndex) chunkKey := newChunkAccessKey(branchKey, subIndex)
// Read access. // Read access.
var branchRead, chunkRead bool var branchRead, chunkRead bool
if _, hasStem := aw.branches[branchKey]; !hasStem { if _, hasStem := ae.branches[branchKey]; !hasStem {
branchRead = true branchRead = true
aw.branches[branchKey] = AccessWitnessReadFlag ae.branches[branchKey] = AccessWitnessReadFlag
} }
if _, hasSelector := aw.chunks[chunkKey]; !hasSelector { if _, hasSelector := ae.chunks[chunkKey]; !hasSelector {
chunkRead = true chunkRead = true
aw.chunks[chunkKey] = AccessWitnessReadFlag ae.chunks[chunkKey] = AccessWitnessReadFlag
} }
// Write access. // Write access.
var branchWrite, chunkWrite, chunkFill bool var branchWrite, chunkWrite, chunkFill bool
if isWrite { if isWrite {
if (aw.branches[branchKey] & AccessWitnessWriteFlag) == 0 { if (ae.branches[branchKey] & AccessWitnessWriteFlag) == 0 {
branchWrite = true branchWrite = true
aw.branches[branchKey] |= AccessWitnessWriteFlag ae.branches[branchKey] |= AccessWitnessWriteFlag
} }
chunkValue := aw.chunks[chunkKey] chunkValue := ae.chunks[chunkKey]
if (chunkValue & AccessWitnessWriteFlag) == 0 { if (chunkValue & AccessWitnessWriteFlag) == 0 {
chunkWrite = true chunkWrite = true
aw.chunks[chunkKey] |= AccessWitnessWriteFlag ae.chunks[chunkKey] |= AccessWitnessWriteFlag
} }
// TODO: charge chunk filling costs if the leaf was previously empty in the state // TODO: charge chunk filling costs if the leaf was previously empty in the state
@ -238,7 +238,7 @@ func newChunkAccessKey(branchKey branchAccessKey, leafKey byte) chunkAccessKey {
} }
// CodeChunksRangeGas is a helper function to touch every chunk in a code range and charge witness gas costs // CodeChunksRangeGas is a helper function to touch every chunk in a code range and charge witness gas costs
func (aw *AccessEvents) CodeChunksRangeGas(contractAddr []byte, startPC, size uint64, codeLen uint64, isWrite bool) uint64 { func (ae *AccessEvents) CodeChunksRangeGas(contractAddr []byte, startPC, size uint64, codeLen uint64, isWrite bool) uint64 {
// note that in the case where the copied code is outside the range of the // note that in the case where the copied code is outside the range of the
// contract code but touches the last leaf with contract code in it, // contract code but touches the last leaf with contract code in it,
// we don't include the last leaf of code in the AccessWitness. The // we don't include the last leaf of code in the AccessWitness. The
@ -261,7 +261,7 @@ func (aw *AccessEvents) CodeChunksRangeGas(contractAddr []byte, startPC, size ui
for chunkNumber := startPC / 31; chunkNumber <= endPC/31; chunkNumber++ { for chunkNumber := startPC / 31; chunkNumber <= endPC/31; chunkNumber++ {
treeIndex := *uint256.NewInt((chunkNumber + 128) / 256) treeIndex := *uint256.NewInt((chunkNumber + 128) / 256)
subIndex := byte((chunkNumber + 128) % 256) subIndex := byte((chunkNumber + 128) % 256)
gas := aw.touchAddressAndChargeGas(contractAddr, treeIndex, subIndex, isWrite) gas := ae.touchAddressAndChargeGas(contractAddr, treeIndex, subIndex, isWrite)
var overflow bool var overflow bool
statelessGasCharged, overflow = math.SafeAdd(statelessGasCharged, gas) statelessGasCharged, overflow = math.SafeAdd(statelessGasCharged, gas)
if overflow { if overflow {
@ -272,22 +272,47 @@ func (aw *AccessEvents) CodeChunksRangeGas(contractAddr []byte, startPC, size ui
return statelessGasCharged return statelessGasCharged
} }
func (aw *AccessEvents) VersionGas(addr []byte, isWrite bool) uint64 { // VersionGas returns the amount of gas to be charged if the account's version hasn't been
return aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.VersionLeafKey, isWrite) // touched in the proper mode. If `isWrite` is `true` then the charged gas is for an access
// in write mode. If false, the charged gas corresponds to an access in read mode.
// Note that an access in write mode implies an access in read mode, whereas an access in
// read mode does not imply an access in write mode.
func (ae *AccessEvents) VersionGas(addr []byte, isWrite bool) uint64 {
return ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.VersionLeafKey, isWrite)
} }
func (aw *AccessEvents) BalanceGas(addr []byte, isWrite bool) uint64 { // BalanceGas returns the amount of gas to be charged if the account's balance hasn't been
return aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BalanceLeafKey, isWrite) // touched in the proper mode. If `isWrite` is `true` then the charged gas is for an access
// in write mode. If false, the charged gas corresponds to an access in read mode.
// Note that an access in write mode implies an access in read mode, whereas an access in
// read mode does not imply an access in write mode.
func (ae *AccessEvents) BalanceGas(addr []byte, isWrite bool) uint64 {
return ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BalanceLeafKey, isWrite)
} }
func (aw *AccessEvents) NonceGas(addr []byte, isWrite bool) uint64 { // NonceGas returns the amount of gas to be charged if the account's nonce hasn't been
return aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.NonceLeafKey, isWrite) // touched in the proper mode. If `isWrite` is `true` then the charged gas is for an access
// in write mode. If false, the charged gas corresponds to an access in read mode.
// Note that an access in write mode implies an access in read mode, whereas an access in
// read mode does not imply an access in write mode.
func (ae *AccessEvents) NonceGas(addr []byte, isWrite bool) uint64 {
return ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.NonceLeafKey, isWrite)
} }
func (aw *AccessEvents) CodeSizeGas(addr []byte, isWrite bool) uint64 { // CodeSizeGas returns the amount of gas to be charged if the account's code size hasn't been
return aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeSizeLeafKey, isWrite) // touched in the proper mode. If `isWrite` is `true` then the charged gas is for an access
// in write mode. If false, the charged gas corresponds to an access in read mode.
// Note that an access in write mode implies an access in read mode, whereas an access in
// read mode does not imply an access in write mode.
func (ae *AccessEvents) CodeSizeGas(addr []byte, isWrite bool) uint64 {
return ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeSizeLeafKey, isWrite)
} }
func (aw *AccessEvents) CodeHashGas(addr []byte, isWrite bool) uint64 { // CodeHashGas returns the amount of gas to be charged if the account's code hash hasn't been
return aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeKeccakLeafKey, isWrite) // touched in the proper mode. If `isWrite` is `true` then the charged gas is for an access
// in write mode. If false, the charged gas corresponds to an access in read mode.
// Note that an access in write mode implies an access in read mode, whereas an access in
// read mode does not imply an access in write mode.
func (ae *AccessEvents) CodeHashGas(addr []byte, isWrite bool) uint64 {
return ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeKeccakLeafKey, isWrite)
} }

View file

@ -0,0 +1,154 @@
// Copyright 2021 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package state
import (
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie/utils"
)
var (
testAddr [20]byte
testAddr2 [20]byte
)
func init() {
for i := byte(0); i < 20; i++ {
testAddr[i] = i
testAddr[2] = 2 * i
}
}
func TestAccountHeaderGas(t *testing.T) {
ae := NewAccessEvents(utils.NewPointCache(1024))
// Check cold read cost
gas := ae.VersionGas(testAddr[:], false)
if gas != params.WitnessBranchReadCost+params.WitnessChunkReadCost {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessBranchReadCost+params.WitnessChunkReadCost)
}
// Check warm read cost
gas = ae.VersionGas(testAddr[:], false)
if gas != 0 {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
}
// Check cold read costs in the same group no longer incur the branch read cost
gas = ae.BalanceGas(testAddr[:], false)
if gas != params.WitnessChunkReadCost {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessChunkReadCost)
}
gas = ae.NonceGas(testAddr[:], false)
if gas != params.WitnessChunkReadCost {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessChunkReadCost)
}
gas = ae.CodeSizeGas(testAddr[:], false)
if gas != params.WitnessChunkReadCost {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessChunkReadCost)
}
gas = ae.CodeHashGas(testAddr[:], false)
if gas != params.WitnessChunkReadCost {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessChunkReadCost)
}
// Check cold write cost
gas = ae.VersionGas(testAddr[:], true)
if gas != params.WitnessBranchWriteCost+params.WitnessChunkWriteCost {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessBranchReadCost+params.WitnessBranchWriteCost)
}
// Check warm write cost
gas = ae.VersionGas(testAddr[:], true)
if gas != 0 {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
}
// Check a write without a read charges both read and write costs
gas = ae.BalanceGas(testAddr2[:], true)
if gas != params.WitnessBranchReadCost+params.WitnessBranchWriteCost+params.WitnessChunkWriteCost+params.WitnessChunkReadCost {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessBranchReadCost+params.WitnessBranchWriteCost+params.WitnessChunkWriteCost+params.WitnessChunkReadCost)
}
// Check that a write followed by a read charges nothing
gas = ae.BalanceGas(testAddr2[:], false)
if gas != 0 {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
}
// Check that reading a slot from the account header only charges the
// chunk read cost.
gas = ae.SlotGas(testAddr[:], common.Hash{}, false)
if gas != params.WitnessChunkReadCost {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessChunkReadCost)
}
}
// TestContractCreateInitGas checks that the gas cost of contract creation is correctly
// calculated.
func TestContractCreateInitGas(t *testing.T) {
ae := NewAccessEvents(utils.NewPointCache(1024))
var testAddr [20]byte
for i := byte(0); i < 20; i++ {
testAddr[i] = i
}
// Check cold read cost, without a value
gas := ae.ContractCreateInitGas(testAddr[:], false)
if gas != params.WitnessBranchWriteCost+params.WitnessBranchReadCost+params.WitnessChunkWriteCost*2+params.WitnessChunkReadCost*2 {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessBranchWriteCost+params.WitnessBranchReadCost+params.WitnessChunkWriteCost*3)
}
// Check warm read cost
gas = ae.ContractCreateInitGas(testAddr[:], false)
if gas != 0 {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
}
}
// TestMessageCallGas checks that the gas cost of message calls is correctly
// calculated.
func TestMessageCallGas(t *testing.T) {
ae := NewAccessEvents(utils.NewPointCache(1024))
// Check cold read cost, without a value
gas := ae.MessageCallGas(testAddr[:])
if gas != params.WitnessBranchReadCost+params.WitnessChunkReadCost*2 {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessBranchReadCost+params.WitnessChunkReadCost*2)
}
// Check that reading the version and code size of the same account does not incur the branch read cost
gas = ae.VersionGas(testAddr[:], false)
if gas != 0 {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
}
gas = ae.CodeSizeGas(testAddr[:], false)
if gas != 0 {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
}
// Check warm read cost
gas = ae.MessageCallGas(testAddr[:])
if gas != 0 {
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
}
}

View file

@ -52,12 +52,12 @@ func gasExtCodeSize4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory,
if _, isPrecompile := evm.precompile(address); isPrecompile { if _, isPrecompile := evm.precompile(address); isPrecompile {
return 0, nil return 0, nil
} }
wgas := evm.AccessEvents.VersionGas(address[:], false) gas := evm.AccessEvents.VersionGas(address[:], false)
wgas += evm.AccessEvents.CodeSizeGas(address[:], false) gas += evm.AccessEvents.CodeSizeGas(address[:], false)
if wgas == 0 { if gas == 0 {
wgas = params.WarmStorageReadCostEIP2929 gas = params.WarmStorageReadCostEIP2929
} }
return wgas, nil return gas, nil
} }
func gasExtCodeHash4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { func gasExtCodeHash4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
@ -65,11 +65,11 @@ func gasExtCodeHash4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory,
if _, isPrecompile := evm.precompile(address); isPrecompile { if _, isPrecompile := evm.precompile(address); isPrecompile {
return 0, nil return 0, nil
} }
codehashgas := evm.AccessEvents.CodeHashGas(address[:], false) gas := evm.AccessEvents.CodeHashGas(address[:], false)
if codehashgas == 0 { if gas == 0 {
codehashgas = params.WarmStorageReadCostEIP2929 gas = params.WarmStorageReadCostEIP2929
} }
return codehashgas, nil return gas, nil
} }
func makeCallVariantGasEIP4762(oldCalculator gasFunc) gasFunc { func makeCallVariantGasEIP4762(oldCalculator gasFunc) gasFunc {
@ -81,11 +81,11 @@ func makeCallVariantGasEIP4762(oldCalculator gasFunc) gasFunc {
if _, isPrecompile := evm.precompile(contract.Address()); isPrecompile { if _, isPrecompile := evm.precompile(contract.Address()); isPrecompile {
return gas, nil return gas, nil
} }
wgas := evm.AccessEvents.MessageCallGas(contract.Address().Bytes()) witnessGas := evm.AccessEvents.MessageCallGas(contract.Address().Bytes())
if wgas == 0 { if witnessGas == 0 {
wgas = params.WarmStorageReadCostEIP2929 witnessGas = params.WarmStorageReadCostEIP2929
} }
return wgas + gas, nil return witnessGas + gas, nil
} }
} }