From 26452f451f579d1c8ed073b0935869e7ee5bc8df Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Fri, 11 Oct 2024 10:58:41 -0300 Subject: [PATCH] CALL witness charge ordering change Signed-off-by: Ignacio Hagopian --- core/vm/eips.go | 8 +++--- core/vm/gas_table.go | 4 +++ core/vm/instructions.go | 59 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 63 insertions(+), 8 deletions(-) diff --git a/core/vm/eips.go b/core/vm/eips.go index 73fbf703c0b7..99d884e0ae37 100644 --- a/core/vm/eips.go +++ b/core/vm/eips.go @@ -322,11 +322,11 @@ func enable4762(jt *JumpTable) { jt[CREATE].constantGas = params.CreateNGasEip4762 jt[CREATE2].constantGas = params.CreateNGasEip4762 jt[CALL].constantGas = 0 - jt[CALL].dynamicGas = gasCall + jt[CALL].dynamicGas = gasZero jt[CALLCODE].constantGas = 0 - jt[CALLCODE].dynamicGas = gasCallCode + jt[CALLCODE].dynamicGas = gasZero jt[STATICCALL].constantGas = 0 - jt[STATICCALL].dynamicGas = gasStaticCall + jt[STATICCALL].dynamicGas = gasZero jt[DELEGATECALL].constantGas = 0 - jt[DELEGATECALL].dynamicGas = gasDelegateCall + jt[DELEGATECALL].dynamicGas = gasZero } diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go index 672b7d02b542..6fbc6e7dd299 100644 --- a/core/vm/gas_table.go +++ b/core/vm/gas_table.go @@ -425,6 +425,10 @@ func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memory return gas, nil } +func gasZero(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + return 0, nil +} + func gasDelegateCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { gas, err := memoryGasCost(mem, memorySize) if err != nil { diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 67aa303b5f23..0d442fe96bf0 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -20,6 +20,7 @@ import ( "encoding/binary" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" @@ -778,6 +779,27 @@ func chargeCallVariantEIP4762(evm *EVM, scope *ScopeContext) bool { } +func getMemSize(operation *operation, stack *Stack) (uint64, error) { + // All ops with a dynamic memory usage also has a dynamic gas cost. + var memorySize uint64 + // calculate the new memory size and expand the memory to fit + // the operation + // Memory check needs to be done prior to evaluating the dynamic gas portion, + // to detect calculation overflows + if operation.memorySize != nil { + memSize, overflow := operation.memorySize(stack) + if overflow { + return 0, ErrGasUintOverflow + } + // memory is expanded in words of 32 bytes. Gas + // is also calculated in words. + if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow { + return 0, ErrGasUintOverflow + } + } + return memorySize, nil +} + func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { if interpreter.evm.chainRules.IsEIP4762 { address := common.Address(scope.Stack.Back(1).Bytes20()) @@ -795,8 +817,15 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt if interpreter.evm.chainRules.IsEIP4762 && !chargeCallVariantEIP4762(interpreter.evm, scope) { return nil, ErrOutOfGas } + memSize, err := getMemSize(interpreter.table[CALL], scope.Stack) + if err != nil { + return nil, err + } + dynamicCost, err := gasCall(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memSize) + if err != nil || !scope.Contract.UseGas(dynamicCost) { + return nil, ErrOutOfGas + } - var err error interpreter.evm.callGasTemp, err = callGas(interpreter.evm.chainRules.IsEIP150, scope.Contract.Gas, 0, scope.Stack.Back(0)) if err != nil { return nil, err @@ -849,7 +878,14 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([ if interpreter.evm.chainRules.IsEIP4762 && !chargeCallVariantEIP4762(interpreter.evm, scope) { return nil, ErrOutOfGas } - var err error + memSize, err := getMemSize(interpreter.table[CALLCODE], scope.Stack) + if err != nil { + return nil, err + } + dynamicCost, err := gasCallCode(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memSize) + if err != nil || !scope.Contract.UseGas(dynamicCost) { + return nil, ErrOutOfGas + } interpreter.evm.callGasTemp, err = callGas(interpreter.evm.chainRules.IsEIP150, scope.Contract.Gas, 0, scope.Stack.Back(0)) if err != nil { return nil, err @@ -896,7 +932,14 @@ func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext if interpreter.evm.chainRules.IsEIP4762 && !chargeCallVariantEIP4762(interpreter.evm, scope) { return nil, ErrOutOfGas } - var err error + memSize, err := getMemSize(interpreter.table[DELEGATECALL], scope.Stack) + if err != nil { + return nil, err + } + dynamicCost, err := gasDelegateCall(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memSize) + if err != nil || !scope.Contract.UseGas(dynamicCost) { + return nil, ErrOutOfGas + } interpreter.evm.callGasTemp, err = callGas(interpreter.evm.chainRules.IsEIP150, scope.Contract.Gas, 0, scope.Stack.Back(0)) if err != nil { return nil, err @@ -936,7 +979,15 @@ func opStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) if interpreter.evm.chainRules.IsEIP4762 && !chargeCallVariantEIP4762(interpreter.evm, scope) { return nil, ErrOutOfGas } - var err error + + memSize, err := getMemSize(interpreter.table[STATICCALL], scope.Stack) + if err != nil { + return nil, err + } + dynamicCost, err := gasCall(interpreter.evm, scope.Contract, scope.Stack, scope.Memory, memSize) + if err != nil || !scope.Contract.UseGas(dynamicCost) { + return nil, ErrOutOfGas + } interpreter.evm.callGasTemp, err = callGas(interpreter.evm.chainRules.IsEIP150, scope.Contract.Gas, 0, scope.Stack.Back(0)) if err != nil { return nil, err