diff --git a/.changeset/khaki-bottles-matter.md b/.changeset/khaki-bottles-matter.md new file mode 100644 index 000000000000..c117f06510c8 --- /dev/null +++ b/.changeset/khaki-bottles-matter.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/l2geth': patch +--- + +add --rpc.evmtimeout flag to configure timeout for eth_call diff --git a/l2geth/cmd/geth/main.go b/l2geth/cmd/geth/main.go index 57af9c98d4b7..bdc6a84a07ff 100644 --- a/l2geth/cmd/geth/main.go +++ b/l2geth/cmd/geth/main.go @@ -188,6 +188,7 @@ var ( utils.IPCPathFlag, utils.InsecureUnlockAllowedFlag, utils.RPCGlobalGasCap, + utils.RPCGlobalEVMTimeoutFlag, } whisperFlags = []cli.Flag{ diff --git a/l2geth/cmd/geth/usage.go b/l2geth/cmd/geth/usage.go index 8a8a55bce483..5e91377c8a14 100644 --- a/l2geth/cmd/geth/usage.go +++ b/l2geth/cmd/geth/usage.go @@ -178,6 +178,7 @@ var AppHelpFlagGroups = []flagGroup{ utils.RPCPortFlag, utils.RPCApiFlag, utils.RPCGlobalGasCap, + utils.RPCGlobalEVMTimeoutFlag, utils.RPCCORSDomainFlag, utils.RPCVirtualHostsFlag, utils.WSEnabledFlag, diff --git a/l2geth/cmd/utils/flags.go b/l2geth/cmd/utils/flags.go index 2747673fc0fc..27c838fa0267 100644 --- a/l2geth/cmd/utils/flags.go +++ b/l2geth/cmd/utils/flags.go @@ -518,6 +518,11 @@ var ( Name: "rpc.gascap", Usage: "Sets a cap on gas that can be used in eth_call/estimateGas", } + RPCGlobalEVMTimeoutFlag = &cli.DurationFlag{ + Name: "rpc.evmtimeout", + Usage: "Sets a timeout used for eth_call (0=infinite)", + Value: eth.DefaultConfig.RPCEVMTimeout, + } // Logging and debug settings EthStatsURLFlag = cli.StringFlag{ Name: "ethstats", @@ -1660,6 +1665,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { if ctx.GlobalIsSet(RPCGlobalGasCap.Name) { cfg.RPCGasCap = new(big.Int).SetUint64(ctx.GlobalUint64(RPCGlobalGasCap.Name)) } + if ctx.GlobalIsSet(RPCGlobalEVMTimeoutFlag.Name) { + cfg.RPCEVMTimeout = ctx.Duration(RPCGlobalEVMTimeoutFlag.Name) + } // Override any default configs for hard coded networks. switch { diff --git a/l2geth/eth/api_backend.go b/l2geth/eth/api_backend.go index 35de825c9757..247ef73bd384 100644 --- a/l2geth/eth/api_backend.go +++ b/l2geth/eth/api_backend.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "math/big" + "time" "github.com/ethereum-optimism/optimism/l2geth/accounts" "github.com/ethereum-optimism/optimism/l2geth/common" @@ -400,6 +401,10 @@ func (b *EthAPIBackend) RPCGasCap() *big.Int { return b.eth.config.RPCGasCap } +func (b *EthAPIBackend) RPCEVMTimeout() time.Duration { + return b.eth.config.RPCEVMTimeout +} + func (b *EthAPIBackend) BloomStatus() (uint64, uint64) { sections, _, _ := b.eth.bloomIndexer.Sections() return params.BloomBitsBlocks, sections diff --git a/l2geth/eth/config.go b/l2geth/eth/config.go index a1f84bf2f71a..9f0c85380017 100644 --- a/l2geth/eth/config.go +++ b/l2geth/eth/config.go @@ -57,7 +57,8 @@ var DefaultConfig = Config{ GasPrice: big.NewInt(params.GWei), Recommit: 3 * time.Second, }, - TxPool: core.DefaultTxPoolConfig, + TxPool: core.DefaultTxPoolConfig, + RPCEVMTimeout: 5 * time.Second, GPO: gasprice.Config{ Blocks: 20, Percentile: 60, @@ -169,6 +170,9 @@ type Config struct { // RPCGasCap is the global gas cap for eth-call variants. RPCGasCap *big.Int `toml:",omitempty"` + // RPCEVMTimeout is the global timeout for eth-call. (0=infinite) + RPCEVMTimeout time.Duration + // Checkpoint is a hardcoded checkpoint which can be nil. Checkpoint *params.TrustedCheckpoint `toml:",omitempty"` diff --git a/l2geth/graphql/graphql.go b/l2geth/graphql/graphql.go index 730a0a5ef008..b3039f5e08c7 100644 --- a/l2geth/graphql/graphql.go +++ b/l2geth/graphql/graphql.go @@ -20,7 +20,6 @@ package graphql import ( "context" "errors" - "time" ethereum "github.com/ethereum-optimism/optimism/l2geth" "github.com/ethereum-optimism/optimism/l2geth/common" @@ -776,7 +775,7 @@ func (b *Block) Call(ctx context.Context, args struct { return nil, err } } - result, gas, failed, err := ethapi.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, &vm.Config{}, 5*time.Second, b.backend.RPCGasCap()) + result, gas, failed, err := ethapi.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, &vm.Config{}, b.backend.RPCEVMTimeout(), b.backend.RPCGasCap()) status := hexutil.Uint64(1) if failed { status = 0 @@ -842,7 +841,7 @@ func (p *Pending) Call(ctx context.Context, args struct { Data ethapi.CallArgs }) (*CallResult, error) { pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) - result, gas, failed, err := ethapi.DoCall(ctx, p.backend, args.Data, pendingBlockNr, nil, &vm.Config{}, 5*time.Second, p.backend.RPCGasCap()) + result, gas, failed, err := ethapi.DoCall(ctx, p.backend, args.Data, pendingBlockNr, nil, &vm.Config{}, p.backend.RPCEVMTimeout(), p.backend.RPCGasCap()) status := hexutil.Uint64(1) if failed { status = 0 diff --git a/l2geth/internal/ethapi/api.go b/l2geth/internal/ethapi/api.go index c009509c2c9c..64b736b008b7 100644 --- a/l2geth/internal/ethapi/api.go +++ b/l2geth/internal/ethapi/api.go @@ -963,7 +963,7 @@ func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNrOr if overrides != nil { accounts = *overrides } - result, _, failed, err := DoCall(ctx, s.b, args, blockNrOrHash, accounts, &vm.Config{}, 5*time.Second, s.b.RPCGasCap()) + result, _, failed, err := DoCall(ctx, s.b, args, blockNrOrHash, accounts, &vm.Config{}, s.b.RPCEVMTimeout(), s.b.RPCGasCap()) if err != nil { return nil, err } diff --git a/l2geth/internal/ethapi/backend.go b/l2geth/internal/ethapi/backend.go index ca2f40098dbf..d2a8d33c3021 100644 --- a/l2geth/internal/ethapi/backend.go +++ b/l2geth/internal/ethapi/backend.go @@ -20,6 +20,7 @@ package ethapi import ( "context" "math/big" + "time" "github.com/ethereum-optimism/optimism/l2geth/accounts" "github.com/ethereum-optimism/optimism/l2geth/common" @@ -45,7 +46,8 @@ type Backend interface { ChainDb() ethdb.Database AccountManager() *accounts.Manager ExtRPCEnabled() bool - RPCGasCap() *big.Int // global gas cap for eth_call over rpc: DoS protection + RPCGasCap() *big.Int // global gas cap for eth_call over rpc: DoS protection + RPCEVMTimeout() time.Duration // global timeout (0=infinite) for eth_call over rpc: DoS protection // Blockchain API SetHead(number uint64) diff --git a/l2geth/les/api_backend.go b/l2geth/les/api_backend.go index 98e2360be364..13e899ecce10 100644 --- a/l2geth/les/api_backend.go +++ b/l2geth/les/api_backend.go @@ -20,6 +20,7 @@ import ( "context" "errors" "math/big" + "time" "github.com/ethereum-optimism/optimism/l2geth/accounts" "github.com/ethereum-optimism/optimism/l2geth/common" @@ -316,6 +317,10 @@ func (b *LesApiBackend) RPCGasCap() *big.Int { return b.eth.config.RPCGasCap } +func (b *LesApiBackend) RPCEVMTimeout() time.Duration { + return b.eth.config.RPCEVMTimeout +} + func (b *LesApiBackend) BloomStatus() (uint64, uint64) { if b.eth.bloomIndexer == nil { return 0, 0