Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

api: remove computationcost limit at call/estimate apis #2086

Merged
merged 5 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions api/api_ethereum.go
Original file line number Diff line number Diff line change
Expand Up @@ -1436,7 +1436,7 @@ func EthDoCall(ctx context.Context, b Backend, args EthTransactionArgs, blockNrO
if msg.Gas() < intrinsicGas {
return nil, fmt.Errorf("%w: msg.gas %d, want %d", blockchain.ErrIntrinsicGas, msg.Gas(), intrinsicGas)
}
evm, vmError, err := b.GetEVM(ctx, msg, state, header, vm.Config{})
evm, vmError, err := b.GetEVM(ctx, msg, state, header, vm.Config{ComputationCostLimit: params.OpcodeComputationCostLimitInfinite})
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1491,7 +1491,7 @@ func EthDoEstimateGas(ctx context.Context, b Backend, args EthTransactionArgs, b

executable := func(gas uint64) (bool, *blockchain.ExecutionResult, error) {
args.Gas = (*hexutil.Uint64)(&gas)
result, err := EthDoCall(ctx, b, args, rpc.NewBlockNumberOrHashWithNumber(rpc.LatestBlockNumber), nil, 0, gasCap)
result, err := EthDoCall(ctx, b, args, rpc.NewBlockNumberOrHashWithNumber(rpc.LatestBlockNumber), nil, b.RPCEVMTimeout(), gasCap)
if err != nil {
if errors.Is(err, blockchain.ErrIntrinsicGas) {
return true, nil, nil // Special case, raise gas limit
Expand Down
12 changes: 6 additions & 6 deletions api/api_ethereum_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,7 @@ import (
"math/big"
"reflect"
"testing"

"github.com/stretchr/testify/require"

"github.com/klaytn/klaytn/consensus"
"github.com/klaytn/klaytn/crypto"
"github.com/klaytn/klaytn/governance"
"time"

"github.com/golang/mock/gomock"
"github.com/klaytn/klaytn/accounts"
Expand All @@ -27,13 +22,17 @@ import (
"github.com/klaytn/klaytn/blockchain/vm"
"github.com/klaytn/klaytn/common"
"github.com/klaytn/klaytn/common/hexutil"
"github.com/klaytn/klaytn/consensus"
"github.com/klaytn/klaytn/consensus/gxhash"
"github.com/klaytn/klaytn/consensus/mocks"
"github.com/klaytn/klaytn/crypto"
"github.com/klaytn/klaytn/governance"
"github.com/klaytn/klaytn/networks/rpc"
"github.com/klaytn/klaytn/params"
"github.com/klaytn/klaytn/rlp"
"github.com/klaytn/klaytn/storage/database"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

var dummyChainConfigForEthereumAPITest = &params.ChainConfig{
Expand Down Expand Up @@ -2489,6 +2488,7 @@ func testEstimateGas(t *testing.T, mockBackend *mock_api.MockBackend, fnEstimate
}
mockBackend.EXPECT().ChainConfig().Return(chainConfig).AnyTimes()
mockBackend.EXPECT().RPCGasCap().Return(common.Big0).AnyTimes()
mockBackend.EXPECT().RPCEVMTimeout().Return(5 * time.Second).AnyTimes()
mockBackend.EXPECT().StateAndHeaderByNumber(any, any).DoAndReturn(getStateAndHeader).AnyTimes()
mockBackend.EXPECT().StateAndHeaderByNumberOrHash(any, any).DoAndReturn(getStateAndHeader).AnyTimes()
mockBackend.EXPECT().GetEVM(any, any, any, any, any).DoAndReturn(getEVM).AnyTimes()
Expand Down
6 changes: 3 additions & 3 deletions api/api_public_blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNrOr
if rpcGasCap := s.b.RPCGasCap(); rpcGasCap != nil {
gasCap = rpcGasCap
}
result, _, err := DoCall(ctx, s.b, args, blockNrOrHash, vm.Config{}, s.b.RPCEVMTimeout(), gasCap)
result, _, err := DoCall(ctx, s.b, args, blockNrOrHash, vm.Config{ComputationCostLimit: params.OpcodeComputationCostLimitInfinite}, s.b.RPCEVMTimeout(), gasCap)
if err != nil {
return nil, err
}
Expand All @@ -398,7 +398,7 @@ func (s *PublicBlockChainAPI) EstimateComputationCost(ctx context.Context, args
if rpcGasCap := s.b.RPCGasCap(); rpcGasCap != nil {
gasCap = rpcGasCap
}
_, computationCost, err := DoCall(ctx, s.b, args, blockNrOrHash, vm.Config{}, s.b.RPCEVMTimeout(), gasCap)
_, computationCost, err := DoCall(ctx, s.b, args, blockNrOrHash, vm.Config{ComputationCostLimit: params.OpcodeComputationCostLimitInfinite}, s.b.RPCEVMTimeout(), gasCap)
return (hexutil.Uint64)(computationCost), err
}

Expand Down Expand Up @@ -428,7 +428,7 @@ func (s *PublicBlockChainAPI) DoEstimateGas(ctx context.Context, b Backend, args
// Create a helper to check if a gas allowance results in an executable transaction
executable := func(gas uint64) (bool, *blockchain.ExecutionResult, error) {
args.Gas = hexutil.Uint64(gas)
result, _, err := DoCall(ctx, b, args, rpc.NewBlockNumberOrHashWithNumber(rpc.LatestBlockNumber), vm.Config{}, 0, gasCap)
result, _, err := DoCall(ctx, b, args, rpc.NewBlockNumberOrHashWithNumber(rpc.LatestBlockNumber), vm.Config{ComputationCostLimit: params.OpcodeComputationCostLimitInfinite}, s.b.RPCEVMTimeout(), gasCap)
if err != nil {
if errors.Is(err, blockchain.ErrIntrinsicGas) {
return true, nil, nil // Special case, raise gas limit
Expand Down
6 changes: 3 additions & 3 deletions api/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ type Backend interface {
ChainDB() database.DBManager
EventMux() *event.TypeMux
AccountManager() accounts.AccountManager
RPCEVMTimeout() time.Duration // global timeout for klay_call
RPCGasCap() *big.Int // global gas cap for klay_call over rpc: DoS protection
RPCTxFeeCap() float64 // global tx fee cap for all transaction related APIs
RPCEVMTimeout() time.Duration // global timeout for eth/klay_call/estimateGas/estimateComputationCost
RPCGasCap() *big.Int // global gas cap for eth/klay_call/estimateGas/estimateComputationCost
RPCTxFeeCap() float64 // global tx fee cap in eth_signTransaction
Engine() consensus.Engine
FeeHistory(ctx context.Context, blockCount int, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error)

Expand Down
37 changes: 18 additions & 19 deletions blockchain/vm/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,25 +123,26 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter {
cfg.JumpTable = jt
}

// Enable the opcode computation cost limit
if cfg.ComputationCostLimit == 0 {
switch {
case evm.chainRules.IsCancun:
cfg.ComputationCostLimit = uint64(params.OpcodeComputationCostLimitCancun)
default:
cfg.ComputationCostLimit = uint64(params.OpcodeComputationCostLimit)
}
// When setting computation cost limit value, priority is given to the original value, override experimental value,
// and then the limit value specified for each hard fork. If the original value is not infinite or
// there is no override value, the next priority value is used.
// Cautious, the infinite value is only applicable for specific API calls. (e.g. call/estimateGas/estimateComputationGas)
if cfg.ComputationCostLimit == params.OpcodeComputationCostLimitInfinite {
return &EVMInterpreter{evm: evm, cfg: cfg}
}

// It is an experimental feature.
// Override the computation cost with an experiment value
if params.OpcodeComputationCostLimitOverride != 0 {
cfg.ComputationCostLimit = params.OpcodeComputationCostLimitOverride
return &EVMInterpreter{evm: evm, cfg: cfg}
}

return &EVMInterpreter{
evm: evm,
cfg: cfg,
// Set the opcode computation cost limit by the default value
switch {
case evm.chainRules.IsCancun:
cfg.ComputationCostLimit = uint64(params.OpcodeComputationCostLimitCancun)
default:
cfg.ComputationCostLimit = uint64(params.OpcodeComputationCostLimit)
}
return &EVMInterpreter{evm: evm, cfg: cfg}
}

// count values and execution time of the opcodes are collected until the node is turned off.
Expand Down Expand Up @@ -242,11 +243,9 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte) (ret []byte, err
}

// We limit tx's execution time using the sum of computation cost of opcodes.
if in.evm.Config.ComputationCostLimit != 0 {
in.evm.opcodeComputationCostSum += operation.computationCost
if in.evm.opcodeComputationCostSum > in.evm.Config.ComputationCostLimit {
return nil, ErrOpcodeComputationCostLimitReached
}
in.evm.opcodeComputationCostSum += operation.computationCost
if in.evm.opcodeComputationCostSum > in.evm.Config.ComputationCostLimit {
return nil, ErrOpcodeComputationCostLimitReached
}
var memorySize uint64
var extraSize uint64
Expand Down
6 changes: 3 additions & 3 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -830,21 +830,21 @@ var (
}
RPCGlobalGasCap = &cli.Uint64Flag{
Name: "rpc.gascap",
Usage: "Sets a cap on gas that can be used in klay_call/estimateGas",
Usage: "Sets a cap on gas in {eth,klay}_{call,estimateGas,estimateComputationCost} (0 = no cap)",
Aliases: []string{"http-rpc.gascap"},
EnvVars: []string{"KLAYTN_RPC_GASCAP"},
Category: "API AND CONSOLE",
}
RPCGlobalEVMTimeoutFlag = &cli.DurationFlag{
Name: "rpc.evmtimeout",
Usage: "Sets a timeout used for eth_call (0=infinite)",
Usage: "Sets a timeout in {eth,klay}_{call,estimateGas,estimateComputationCost}. (0 = apply http-rpc.execution.timeout)",
yoomee1313 marked this conversation as resolved.
Show resolved Hide resolved
Aliases: []string{"http-rpc.evmtimeout"},
EnvVars: []string{"KLAYTN_RPC_EVMTIMEOUT"},
Category: "API AND CONSOLE",
}
RPCGlobalEthTxFeeCapFlag = &cli.Float64Flag{
Name: "rpc.ethtxfeecap",
Usage: "Sets a cap on transaction fee (in klay) that can be sent via the eth namespace RPC APIs (0 = no cap)",
Usage: "Sets a cap on transaction fee (=gasLimit*gasPrice) (in klay) in eth_signTransaction (0 = no cap)",
Aliases: []string{"http-rpc.eth-tx-feecap"},
EnvVars: []string{"KLAYTN_RPC_ETHTXFEECAP"},
Category: "API AND CONSOLE",
Expand Down