diff --git a/cmd/harmony/config_migrations.go b/cmd/harmony/config_migrations.go index 7c9420a0be..b3da9ec2ba 100644 --- a/cmd/harmony/config_migrations.go +++ b/cmd/harmony/config_migrations.go @@ -340,6 +340,23 @@ func init() { return confTree } + migrations["2.5.12"] = func(confTree *toml.Tree) *toml.Tree { + if confTree.Get("HTTP.ReadTimeout") == nil { + confTree.Set("HTTP.ReadTimeout", defaultConfig.HTTP.ReadTimeout) + } + if confTree.Get("HTTP.WriteTimeout") == nil { + confTree.Set("HTTP.WriteTimeout", defaultConfig.HTTP.WriteTimeout) + } + if confTree.Get("HTTP.IdleTimeout") == nil { + confTree.Set("HTTP.IdleTimeout", defaultConfig.HTTP.IdleTimeout) + } + if confTree.Get("RPCOpt.EvmCallTimeout") == nil { + confTree.Set("RPCOpt.EvmCallTimeout", defaultConfig.RPCOpt.EvmCallTimeout) + } + confTree.Set("Version", "2.5.13") + return confTree + } + // check that the latest version here is the same as in default.go largestKey := getNextVersion(migrations) if largestKey != tomlConfigVersion { diff --git a/cmd/harmony/default.go b/cmd/harmony/default.go index 3835c49210..95e05b29cc 100644 --- a/cmd/harmony/default.go +++ b/cmd/harmony/default.go @@ -5,7 +5,7 @@ import ( nodeconfig "github.com/harmony-one/harmony/internal/configs/node" ) -const tomlConfigVersion = "2.5.12" +const tomlConfigVersion = "2.5.13" const ( defNetworkType = nodeconfig.Mainnet @@ -44,6 +44,9 @@ var defaultConfig = harmonyconfig.HarmonyConfig{ Port: nodeconfig.DefaultRPCPort, AuthPort: nodeconfig.DefaultAuthRPCPort, RosettaPort: nodeconfig.DefaultRosettaPort, + ReadTimeout: nodeconfig.DefaultHTTPTimeoutRead, + WriteTimeout: nodeconfig.DefaultHTTPTimeoutWrite, + IdleTimeout: nodeconfig.DefaultHTTPTimeoutIdle, }, WS: harmonyconfig.WsConfig{ Enabled: true, @@ -59,6 +62,7 @@ var defaultConfig = harmonyconfig.HarmonyConfig{ RpcFilterFile: "./.hmy/rpc_filter.txt", RateLimterEnabled: true, RequestsPerSecond: nodeconfig.DefaultRPCRateLimit, + EvmCallTimeout: nodeconfig.DefaultEvmCallTimeout, }, BLSKeys: harmonyconfig.BlsConfig{ KeyDir: "./.hmy/blskeys", diff --git a/cmd/harmony/flags.go b/cmd/harmony/flags.go index 2ffceb6e5b..8a2799ce28 100644 --- a/cmd/harmony/flags.go +++ b/cmd/harmony/flags.go @@ -75,6 +75,9 @@ var ( httpPortFlag, httpAuthPortFlag, httpRosettaPortFlag, + httpReadTimeoutFlag, + httpWriteTimeoutFlag, + httpIdleTimeoutFlag, } wsFlags = []cli.Flag{ @@ -92,6 +95,7 @@ var ( rpcFilterFileFlag, rpcRateLimiterEnabledFlag, rpcRateLimitFlag, + rpcEvmCallTimeoutFlag, } blsFlags = append(newBLSFlags, legacyBLSFlags...) @@ -695,6 +699,21 @@ var ( Usage: "rosetta port to listen for HTTP requests", DefValue: defaultConfig.HTTP.RosettaPort, } + httpReadTimeoutFlag = cli.StringFlag{ + Name: "http.timeout.read", + Usage: "maximum duration to read the entire request, including the body", + DefValue: defaultConfig.HTTP.ReadTimeout, + } + httpWriteTimeoutFlag = cli.StringFlag{ + Name: "http.timeout.write", + Usage: "maximum duration before timing out writes of the response", + DefValue: defaultConfig.HTTP.WriteTimeout, + } + httpIdleTimeoutFlag = cli.StringFlag{ + Name: "http.timeout.idle", + Usage: "maximum amount of time to wait for the next request when keep-alives are enabled", + DefValue: defaultConfig.HTTP.IdleTimeout, + } ) func applyHTTPFlags(cmd *cobra.Command, config *harmonyconfig.HarmonyConfig) { @@ -732,6 +751,16 @@ func applyHTTPFlags(cmd *cobra.Command, config *harmonyconfig.HarmonyConfig) { config.HTTP.Enabled = true } + if cli.IsFlagChanged(cmd, httpReadTimeoutFlag) { + config.HTTP.ReadTimeout = cli.GetStringFlagValue(cmd, httpReadTimeoutFlag) + } + if cli.IsFlagChanged(cmd, httpWriteTimeoutFlag) { + config.HTTP.WriteTimeout = cli.GetStringFlagValue(cmd, httpWriteTimeoutFlag) + } + if cli.IsFlagChanged(cmd, httpIdleTimeoutFlag) { + config.HTTP.IdleTimeout = cli.GetStringFlagValue(cmd, httpIdleTimeoutFlag) + } + } // ws flags @@ -821,6 +850,12 @@ var ( Usage: "the number of requests per second for RPCs", DefValue: defaultConfig.RPCOpt.RequestsPerSecond, } + + rpcEvmCallTimeoutFlag = cli.StringFlag{ + Name: "rpc.evm-call-timeout", + Usage: "timeout for evm execution (eth_call); 0 means infinite timeout", + DefValue: defaultConfig.RPCOpt.EvmCallTimeout, + } ) func applyRPCOptFlags(cmd *cobra.Command, config *harmonyconfig.HarmonyConfig) { @@ -845,7 +880,9 @@ func applyRPCOptFlags(cmd *cobra.Command, config *harmonyconfig.HarmonyConfig) { if cli.IsFlagChanged(cmd, rpcRateLimitFlag) { config.RPCOpt.RequestsPerSecond = cli.GetIntFlagValue(cmd, rpcRateLimitFlag) } - + if cli.IsFlagChanged(cmd, rpcEvmCallTimeoutFlag) { + config.RPCOpt.EvmCallTimeout = cli.GetStringFlagValue(cmd, rpcEvmCallTimeoutFlag) + } } // bls flags diff --git a/cmd/harmony/flags_test.go b/cmd/harmony/flags_test.go index 15ba9aaf08..2015188ed4 100644 --- a/cmd/harmony/flags_test.go +++ b/cmd/harmony/flags_test.go @@ -77,6 +77,9 @@ func TestHarmonyFlags(t *testing.T) { AuthPort: 9501, RosettaEnabled: false, RosettaPort: 9700, + ReadTimeout: defaultConfig.HTTP.ReadTimeout, + WriteTimeout: defaultConfig.HTTP.WriteTimeout, + IdleTimeout: defaultConfig.HTTP.IdleTimeout, }, RPCOpt: harmonyconfig.RpcOptConfig{ DebugEnabled: false, @@ -86,6 +89,7 @@ func TestHarmonyFlags(t *testing.T) { RpcFilterFile: "./.hmy/rpc_filter.txt", RateLimterEnabled: true, RequestsPerSecond: 1000, + EvmCallTimeout: defaultConfig.RPCOpt.EvmCallTimeout, }, WS: harmonyconfig.WsConfig{ Enabled: true, @@ -531,6 +535,9 @@ func TestRPCFlags(t *testing.T) { Port: defaultConfig.HTTP.Port, AuthPort: defaultConfig.HTTP.AuthPort, RosettaPort: defaultConfig.HTTP.RosettaPort, + ReadTimeout: defaultConfig.HTTP.ReadTimeout, + WriteTimeout: defaultConfig.HTTP.WriteTimeout, + IdleTimeout: defaultConfig.HTTP.IdleTimeout, }, }, { @@ -542,6 +549,9 @@ func TestRPCFlags(t *testing.T) { Port: 9001, AuthPort: defaultConfig.HTTP.AuthPort, RosettaPort: defaultConfig.HTTP.RosettaPort, + ReadTimeout: defaultConfig.HTTP.ReadTimeout, + WriteTimeout: defaultConfig.HTTP.WriteTimeout, + IdleTimeout: defaultConfig.HTTP.IdleTimeout, }, }, { @@ -553,6 +563,9 @@ func TestRPCFlags(t *testing.T) { Port: defaultConfig.HTTP.Port, AuthPort: 9001, RosettaPort: defaultConfig.HTTP.RosettaPort, + ReadTimeout: defaultConfig.HTTP.ReadTimeout, + WriteTimeout: defaultConfig.HTTP.WriteTimeout, + IdleTimeout: defaultConfig.HTTP.IdleTimeout, }, }, { @@ -564,6 +577,9 @@ func TestRPCFlags(t *testing.T) { Port: 9001, AuthPort: defaultConfig.HTTP.AuthPort, RosettaPort: 10001, + ReadTimeout: defaultConfig.HTTP.ReadTimeout, + WriteTimeout: defaultConfig.HTTP.WriteTimeout, + IdleTimeout: defaultConfig.HTTP.IdleTimeout, }, }, { @@ -575,6 +591,9 @@ func TestRPCFlags(t *testing.T) { Port: defaultConfig.HTTP.Port, AuthPort: defaultConfig.HTTP.AuthPort, RosettaPort: 10001, + ReadTimeout: defaultConfig.HTTP.ReadTimeout, + WriteTimeout: defaultConfig.HTTP.WriteTimeout, + IdleTimeout: defaultConfig.HTTP.IdleTimeout, }, }, { @@ -586,6 +605,23 @@ func TestRPCFlags(t *testing.T) { Port: 9501, AuthPort: 9502, RosettaPort: 9701, + ReadTimeout: defaultConfig.HTTP.ReadTimeout, + WriteTimeout: defaultConfig.HTTP.WriteTimeout, + IdleTimeout: defaultConfig.HTTP.IdleTimeout, + }, + }, + { + args: []string{"--http.timeout.read", "10s", "--http.timeout.write", "20s", "--http.timeout.idle", "30s"}, + expConfig: harmonyconfig.HttpConfig{ + Enabled: true, + RosettaEnabled: false, + IP: defaultConfig.HTTP.IP, + Port: defaultConfig.HTTP.Port, + AuthPort: defaultConfig.HTTP.AuthPort, + RosettaPort: defaultConfig.HTTP.RosettaPort, + ReadTimeout: "10s", + WriteTimeout: "20s", + IdleTimeout: "30s", }, }, } @@ -699,6 +735,7 @@ func TestRPCOptFlags(t *testing.T) { RpcFilterFile: "./.hmy/rpc_filter.txt", RateLimterEnabled: true, RequestsPerSecond: 1000, + EvmCallTimeout: defaultConfig.RPCOpt.EvmCallTimeout, }, }, @@ -712,6 +749,7 @@ func TestRPCOptFlags(t *testing.T) { RpcFilterFile: "./.hmy/rpc_filter.txt", RateLimterEnabled: true, RequestsPerSecond: 1000, + EvmCallTimeout: defaultConfig.RPCOpt.EvmCallTimeout, }, }, @@ -725,6 +763,7 @@ func TestRPCOptFlags(t *testing.T) { RpcFilterFile: "./.hmy/rpc_filter.txt", RateLimterEnabled: true, RequestsPerSecond: 1000, + EvmCallTimeout: defaultConfig.RPCOpt.EvmCallTimeout, }, }, @@ -738,6 +777,7 @@ func TestRPCOptFlags(t *testing.T) { RpcFilterFile: "./.hmy/rpc_filter.txt", RateLimterEnabled: true, RequestsPerSecond: 1000, + EvmCallTimeout: defaultConfig.RPCOpt.EvmCallTimeout, }, }, @@ -751,6 +791,7 @@ func TestRPCOptFlags(t *testing.T) { RpcFilterFile: "./rmf.toml", RateLimterEnabled: true, RequestsPerSecond: 1000, + EvmCallTimeout: defaultConfig.RPCOpt.EvmCallTimeout, }, }, @@ -764,6 +805,7 @@ func TestRPCOptFlags(t *testing.T) { RpcFilterFile: "./.hmy/rpc_filter.txt", RateLimterEnabled: true, RequestsPerSecond: 1000, + EvmCallTimeout: defaultConfig.RPCOpt.EvmCallTimeout, }, }, @@ -777,6 +819,7 @@ func TestRPCOptFlags(t *testing.T) { RpcFilterFile: "./.hmy/rpc_filter.txt", RateLimterEnabled: true, RequestsPerSecond: 2000, + EvmCallTimeout: defaultConfig.RPCOpt.EvmCallTimeout, }, }, @@ -790,6 +833,21 @@ func TestRPCOptFlags(t *testing.T) { RpcFilterFile: "./.hmy/rpc_filter.txt", RateLimterEnabled: false, RequestsPerSecond: 2000, + EvmCallTimeout: defaultConfig.RPCOpt.EvmCallTimeout, + }, + }, + + { + args: []string{"--rpc.evm-call-timeout", "10s"}, + expConfig: harmonyconfig.RpcOptConfig{ + DebugEnabled: false, + EthRPCsEnabled: true, + StakingRPCsEnabled: true, + LegacyRPCsEnabled: true, + RpcFilterFile: "./.hmy/rpc_filter.txt", + RateLimterEnabled: true, + RequestsPerSecond: 1000, + EvmCallTimeout: "10s", }, }, } diff --git a/cmd/harmony/main.go b/cmd/harmony/main.go index eacc392f10..f01cb758ed 100644 --- a/cmd/harmony/main.go +++ b/cmd/harmony/main.go @@ -334,23 +334,7 @@ func setupNodeAndRun(hc harmonyconfig.HarmonyConfig) { } // Parse RPC config - nodeConfig.RPCServer = nodeconfig.RPCServerConfig{ - HTTPEnabled: hc.HTTP.Enabled, - HTTPIp: hc.HTTP.IP, - HTTPPort: hc.HTTP.Port, - HTTPAuthPort: hc.HTTP.AuthPort, - WSEnabled: hc.WS.Enabled, - WSIp: hc.WS.IP, - WSPort: hc.WS.Port, - WSAuthPort: hc.WS.AuthPort, - DebugEnabled: hc.RPCOpt.DebugEnabled, - EthRPCsEnabled: hc.RPCOpt.EthRPCsEnabled, - StakingRPCsEnabled: hc.RPCOpt.StakingRPCsEnabled, - LegacyRPCsEnabled: hc.RPCOpt.LegacyRPCsEnabled, - RpcFilterFile: hc.RPCOpt.RpcFilterFile, - RateLimiterEnabled: hc.RPCOpt.RateLimterEnabled, - RequestsPerSecond: hc.RPCOpt.RequestsPerSecond, - } + nodeConfig.RPCServer = hc.ToRPCServerConfig() // Parse rosetta config nodeConfig.RosettaServer = nodeconfig.RosettaServerConfig{ diff --git a/internal/configs/harmony/harmony.go b/internal/configs/harmony/harmony.go index 67c29f820f..d4e8df4b00 100644 --- a/internal/configs/harmony/harmony.go +++ b/internal/configs/harmony/harmony.go @@ -3,6 +3,10 @@ package harmony import ( "reflect" "strings" + "time" + + nodeconfig "github.com/harmony-one/harmony/internal/configs/node" + "github.com/harmony-one/harmony/internal/utils" ) // HarmonyConfig contains all the configs user can set for running harmony binary. Served as the bridge @@ -32,6 +36,62 @@ type HarmonyConfig struct { ShardData ShardDataConfig } +func (hc HarmonyConfig) ToRPCServerConfig() nodeconfig.RPCServerConfig { + readTimeout, err := time.ParseDuration(hc.HTTP.ReadTimeout) + if err != nil { + readTimeout, _ = time.ParseDuration(nodeconfig.DefaultHTTPTimeoutRead) + utils.Logger().Warn(). + Str("provided", hc.HTTP.ReadTimeout). + Dur("updated", readTimeout). + Msg("Sanitizing invalid http read timeout") + } + writeTimeout, err := time.ParseDuration(hc.HTTP.WriteTimeout) + if err != nil { + writeTimeout, _ = time.ParseDuration(nodeconfig.DefaultHTTPTimeoutWrite) + utils.Logger().Warn(). + Str("provided", hc.HTTP.WriteTimeout). + Dur("updated", writeTimeout). + Msg("Sanitizing invalid http write timeout") + } + idleTimeout, err := time.ParseDuration(hc.HTTP.IdleTimeout) + if err != nil { + idleTimeout, _ = time.ParseDuration(nodeconfig.DefaultHTTPTimeoutIdle) + utils.Logger().Warn(). + Str("provided", hc.HTTP.IdleTimeout). + Dur("updated", idleTimeout). + Msg("Sanitizing invalid http idle timeout") + } + evmCallTimeout, err := time.ParseDuration(hc.RPCOpt.EvmCallTimeout) + if err != nil { + evmCallTimeout, _ = time.ParseDuration(nodeconfig.DefaultEvmCallTimeout) + utils.Logger().Warn(). + Str("provided", hc.RPCOpt.EvmCallTimeout). + Dur("updated", evmCallTimeout). + Msg("Sanitizing invalid evm_call timeout") + } + return nodeconfig.RPCServerConfig{ + HTTPEnabled: hc.HTTP.Enabled, + HTTPIp: hc.HTTP.IP, + HTTPPort: hc.HTTP.Port, + HTTPAuthPort: hc.HTTP.AuthPort, + HTTPTimeoutRead: readTimeout, + HTTPTimeoutWrite: writeTimeout, + HTTPTimeoutIdle: idleTimeout, + WSEnabled: hc.WS.Enabled, + WSIp: hc.WS.IP, + WSPort: hc.WS.Port, + WSAuthPort: hc.WS.AuthPort, + DebugEnabled: hc.RPCOpt.DebugEnabled, + EthRPCsEnabled: hc.RPCOpt.EthRPCsEnabled, + StakingRPCsEnabled: hc.RPCOpt.StakingRPCsEnabled, + LegacyRPCsEnabled: hc.RPCOpt.LegacyRPCsEnabled, + RpcFilterFile: hc.RPCOpt.RpcFilterFile, + RateLimiterEnabled: hc.RPCOpt.RateLimterEnabled, + RequestsPerSecond: hc.RPCOpt.RequestsPerSecond, + EvmCallTimeout: evmCallTimeout, + } +} + type DnsSync struct { Port int // replaces: Network.DNSSyncPort Zone string // replaces: Network.DNSZone @@ -180,6 +240,9 @@ type HttpConfig struct { AuthPort int RosettaEnabled bool RosettaPort int + ReadTimeout string + WriteTimeout string + IdleTimeout string } type WsConfig struct { @@ -197,6 +260,7 @@ type RpcOptConfig struct { RpcFilterFile string // Define filters to enable/disable RPC exposure RateLimterEnabled bool // Enable Rate limiter for RPC RequestsPerSecond int // for RPC rate limiter + EvmCallTimeout string // Timeout for eth_call } type DevnetConfig struct { diff --git a/internal/configs/harmony/harmony_test.go b/internal/configs/harmony/harmony_test.go new file mode 100644 index 0000000000..fef7cac9df --- /dev/null +++ b/internal/configs/harmony/harmony_test.go @@ -0,0 +1,81 @@ +package harmony + +import ( + "fmt" + "testing" + "time" + + nodeconfig "github.com/harmony-one/harmony/internal/configs/node" + "github.com/stretchr/testify/assert" +) + +func TestToRPCServerConfig(t *testing.T) { + tests := []struct { + input HarmonyConfig + output nodeconfig.RPCServerConfig + }{ + { + input: HarmonyConfig{ + HTTP: HttpConfig{ + Enabled: true, + RosettaEnabled: false, + IP: "127.0.0.1", + Port: nodeconfig.DefaultRPCPort, + AuthPort: nodeconfig.DefaultAuthRPCPort, + RosettaPort: nodeconfig.DefaultRosettaPort, + ReadTimeout: "-1", + WriteTimeout: "-2", + IdleTimeout: "-3", + }, + WS: WsConfig{ + Enabled: true, + IP: "127.0.0.1", + Port: nodeconfig.DefaultWSPort, + AuthPort: nodeconfig.DefaultAuthWSPort, + }, + RPCOpt: RpcOptConfig{ + DebugEnabled: false, + EthRPCsEnabled: true, + StakingRPCsEnabled: true, + LegacyRPCsEnabled: true, + RpcFilterFile: "./.hmy/rpc_filter.txt", + RateLimterEnabled: true, + RequestsPerSecond: nodeconfig.DefaultRPCRateLimit, + EvmCallTimeout: "-4", + }, + }, + output: nodeconfig.RPCServerConfig{ + HTTPEnabled: true, + HTTPIp: "127.0.0.1", + HTTPPort: nodeconfig.DefaultRPCPort, + HTTPAuthPort: nodeconfig.DefaultAuthRPCPort, + HTTPTimeoutRead: 30 * time.Second, + HTTPTimeoutWrite: 30 * time.Second, + HTTPTimeoutIdle: 120 * time.Second, + WSEnabled: true, + WSIp: "127.0.0.1", + WSPort: nodeconfig.DefaultWSPort, + WSAuthPort: nodeconfig.DefaultAuthWSPort, + DebugEnabled: false, + EthRPCsEnabled: true, + StakingRPCsEnabled: true, + LegacyRPCsEnabled: true, + RpcFilterFile: "./.hmy/rpc_filter.txt", + RateLimiterEnabled: true, + RequestsPerSecond: nodeconfig.DefaultRPCRateLimit, + EvmCallTimeout: 5 * time.Second, + }, + }, + } + for i, tt := range tests { + assertObject := assert.New(t) + name := fmt.Sprintf("TestToRPCServerConfig: #%d", i) + t.Run(name, func(t *testing.T) { + assertObject.Equal( + tt.input.ToRPCServerConfig(), + tt.output, + name, + ) + }) + } +} diff --git a/internal/configs/node/config.go b/internal/configs/node/config.go index 9a0e950ecc..9f681fca9f 100644 --- a/internal/configs/node/config.go +++ b/internal/configs/node/config.go @@ -8,6 +8,7 @@ import ( "math/big" "strings" "sync" + "time" bls_core "github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/harmony/crypto/bls" @@ -115,6 +116,10 @@ type RPCServerConfig struct { HTTPPort int HTTPAuthPort int + HTTPTimeoutRead time.Duration + HTTPTimeoutWrite time.Duration + HTTPTimeoutIdle time.Duration + WSEnabled bool WSIp string WSPort int @@ -130,6 +135,8 @@ type RPCServerConfig struct { RateLimiterEnabled bool RequestsPerSecond int + + EvmCallTimeout time.Duration } // RosettaServerConfig is the config for the rosetta server diff --git a/internal/configs/node/network.go b/internal/configs/node/network.go index 8b15d3359c..03f1472125 100644 --- a/internal/configs/node/network.go +++ b/internal/configs/node/network.go @@ -51,6 +51,12 @@ const ( DefaultAuthRPCPort = 9501 // DefaultRosettaPort is the default rosetta port. The actual port used is 9000+700 DefaultRosettaPort = 9700 + // DefaultHTTP timeouts - read, write, and idle + DefaultHTTPTimeoutRead = "30s" + DefaultHTTPTimeoutWrite = "30s" + DefaultHTTPTimeoutIdle = "120s" + // DefaultEvmCallTimeout is the default timeout for evm call + DefaultEvmCallTimeout = "5s" // DefaultWSPort is the default port for web socket endpoint. The actual port used is DefaultWSPort = 9800 // DefaultAuthWSPort is the default port for web socket auth endpoint. The actual port used is diff --git a/rosetta/infra/harmony-mainnet.conf b/rosetta/infra/harmony-mainnet.conf index a929eeeab1..8d51609cb1 100644 --- a/rosetta/infra/harmony-mainnet.conf +++ b/rosetta/infra/harmony-mainnet.conf @@ -1,4 +1,4 @@ -Version = "2.5.11" +Version = "2.5.13" [BLSKeys] KMSConfigFile = "" @@ -41,9 +41,12 @@ Version = "2.5.11" AuthPort = 9501 Enabled = true IP = "0.0.0.0" + IdleTimeout = "120s" Port = 9500 + ReadTimeout = "30s" RosettaEnabled = true RosettaPort = 9700 + WriteTimeout = "30s" [Log] Console = false @@ -62,6 +65,8 @@ Version = "2.5.11" NetworkType = "mainnet" [P2P] + ConnManagerHighWatermark = 192 + ConnManagerLowWatermark = 160 DisablePrivateIPScan = false DiscConcurrency = 0 IP = "0.0.0.0" @@ -69,8 +74,6 @@ Version = "2.5.11" MaxConnsPerIP = 10 MaxPeers = 0 Port = 9000 - ConnManagerLowWatermark = 160 - ConnManagerHighWatermark = 192 WaitForEachPeerToConnect = false [Pprof] @@ -84,6 +87,7 @@ Version = "2.5.11" [RPCOpt] DebugEnabled = false EthRPCsEnabled = true + EvmCallTimeout = "5s" LegacyRPCsEnabled = true RateLimterEnabled = true RequestsPerSecond = 1000 @@ -104,11 +108,23 @@ Version = "2.5.11" DiscHighCap = 128 DiscSoftLowCap = 8 Downloader = false - StagedSync = false Enabled = false InitStreams = 8 - MinPeers = 5 MaxAdvertiseWaitTime = 30 + MinPeers = 5 + StagedSync = false + + [Sync.StagedSyncCfg] + DoubleCheckBlockHashes = false + InsertChainBatchSize = 0 + LogProgress = false + MaxBackgroundBlocks = 0 + MaxBlocksPerSyncCycle = 0 + MaxMemSyncCycleSize = 0 + TurboMode = false + UseMemDB = false + VerifyAllSig = false + VerifyHeaderBatchSize = 0 [TxPool] AccountSlots = 16 diff --git a/rosetta/infra/harmony-pstn.conf b/rosetta/infra/harmony-pstn.conf index edb911f87a..1bb865c1a5 100644 --- a/rosetta/infra/harmony-pstn.conf +++ b/rosetta/infra/harmony-pstn.conf @@ -1,4 +1,4 @@ -Version = "2.5.11" +Version = "2.5.13" [BLSKeys] KMSConfigFile = "" @@ -41,9 +41,12 @@ Version = "2.5.11" AuthPort = 9501 Enabled = true IP = "0.0.0.0" + IdleTimeout = "120s" Port = 9500 + ReadTimeout = "30s" RosettaEnabled = true RosettaPort = 9700 + WriteTimeout = "30s" [Log] Console = false @@ -62,6 +65,8 @@ Version = "2.5.11" NetworkType = "partner" [P2P] + ConnManagerHighWatermark = 192 + ConnManagerLowWatermark = 160 DisablePrivateIPScan = false DiscConcurrency = 0 IP = "0.0.0.0" @@ -69,8 +74,6 @@ Version = "2.5.11" MaxConnsPerIP = 10 MaxPeers = 0 Port = 9000 - ConnManagerLowWatermark = 160 - ConnManagerHighWatermark = 192 WaitForEachPeerToConnect = false [Pprof] @@ -84,6 +87,7 @@ Version = "2.5.11" [RPCOpt] DebugEnabled = false EthRPCsEnabled = true + EvmCallTimeout = "5s" LegacyRPCsEnabled = true RateLimterEnabled = true RequestsPerSecond = 1000 @@ -104,11 +108,23 @@ Version = "2.5.11" DiscHighCap = 128 DiscSoftLowCap = 8 Downloader = false - StagedSync = false Enabled = false InitStreams = 8 - MinPeers = 2 MaxAdvertiseWaitTime = 30 + MinPeers = 2 + StagedSync = false + + [Sync.StagedSyncCfg] + DoubleCheckBlockHashes = false + InsertChainBatchSize = 0 + LogProgress = false + MaxBackgroundBlocks = 0 + MaxBlocksPerSyncCycle = 0 + MaxMemSyncCycleSize = 0 + TurboMode = false + UseMemDB = false + VerifyAllSig = false + VerifyHeaderBatchSize = 0 [TxPool] AccountSlots = 16 diff --git a/rosetta/rosetta.go b/rosetta/rosetta.go index 860c2d0d66..a056300573 100644 --- a/rosetta/rosetta.go +++ b/rosetta/rosetta.go @@ -84,7 +84,11 @@ func getRouter(asserter *asserter.Asserter, hmy *hmy.Harmony, limiterEnable bool server.NewMempoolAPIController(services.NewMempoolAPI(hmy), asserter), server.NewNetworkAPIController(services.NewNetworkAPI(hmy), asserter), server.NewConstructionAPIController(services.NewConstructionAPI(hmy), asserter), - server.NewCallAPIController(services.NewCallAPIService(hmy, limiterEnable, rateLimit), asserter), + server.NewCallAPIController( + services.NewCallAPIService(hmy, limiterEnable, rateLimit, + hmy.NodeAPI.GetConfig().NodeConfig.RPCServer.EvmCallTimeout), + asserter, + ), server.NewEventsAPIController(services.NewEventAPI(hmy), asserter), server.NewSearchAPIController(services.NewSearchAPI(hmy), asserter), ) diff --git a/rosetta/services/call_service.go b/rosetta/services/call_service.go index 46f528d7b9..9d26bab282 100644 --- a/rosetta/services/call_service.go +++ b/rosetta/services/call_service.go @@ -3,6 +3,7 @@ package services import ( "context" "encoding/json" + "time" "github.com/coinbase/rosetta-sdk-go/server" "github.com/coinbase/rosetta-sdk-go/types" @@ -82,10 +83,15 @@ func (c *CallAPIService) Call( } -func NewCallAPIService(hmy *hmy.Harmony, limiterEnable bool, rateLimit int) server.CallAPIServicer { +func NewCallAPIService( + hmy *hmy.Harmony, + limiterEnable bool, + rateLimit int, + evmCallTimeout time.Duration, +) server.CallAPIServicer { return &CallAPIService{ hmy: hmy, - publicContractAPI: rpc2.NewPublicContractAPI(hmy, rpc2.V2, limiterEnable, rateLimit), + publicContractAPI: rpc2.NewPublicContractAPI(hmy, rpc2.V2, limiterEnable, rateLimit, evmCallTimeout), publicStakingAPI: rpc2.NewPublicStakingAPI(hmy, rpc2.V2), publicBlockChainAPI: rpc2.NewPublicBlockchainAPI(hmy, rpc2.V2, limiterEnable, rateLimit), } diff --git a/rosetta/services/construction.go b/rosetta/services/construction.go index 3442d4c629..f2bd6e6c91 100644 --- a/rosetta/services/construction.go +++ b/rosetta/services/construction.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "math/big" + "time" "github.com/coinbase/rosetta-sdk-go/server" "github.com/coinbase/rosetta-sdk-go/types" @@ -24,17 +25,19 @@ const ( // ConstructAPI implements the server.ConstructAPIServicer interface. type ConstructAPI struct { - hmy *hmy.Harmony - signer hmyTypes.Signer - stakingSigner stakingTypes.Signer + hmy *hmy.Harmony + signer hmyTypes.Signer + stakingSigner stakingTypes.Signer + evmCallTimeout time.Duration } // NewConstructionAPI creates a new instance of a ConstructAPI. func NewConstructionAPI(hmy *hmy.Harmony) server.ConstructionAPIServicer { return &ConstructAPI{ - hmy: hmy, - signer: hmyTypes.NewEIP155Signer(new(big.Int).SetUint64(hmy.ChainID)), - stakingSigner: stakingTypes.NewEIP155Signer(new(big.Int).SetUint64(hmy.ChainID)), + hmy: hmy, + signer: hmyTypes.NewEIP155Signer(new(big.Int).SetUint64(hmy.ChainID)), + stakingSigner: stakingTypes.NewEIP155Signer(new(big.Int).SetUint64(hmy.ChainID)), + evmCallTimeout: hmy.NodeAPI.GetConfig().NodeConfig.RPCServer.EvmCallTimeout, } } diff --git a/rosetta/services/construction_check.go b/rosetta/services/construction_check.go index 1c3e1db699..c842770ab7 100644 --- a/rosetta/services/construction_check.go +++ b/rosetta/services/construction_check.go @@ -270,7 +270,7 @@ func (s *ConstructAPI) ConstructionMetadata( callArgs.To = &contractAddress } evmExe, err := rpc.DoEVMCall( - ctx, s.hmy, callArgs, latest, rpc.CallTimeout, + ctx, s.hmy, callArgs, latest, s.evmCallTimeout, ) if err != nil { return nil, common.NewError(common.CatchAllError, map[string]interface{}{ diff --git a/rpc/contract.go b/rpc/contract.go index 337bea7cde..abcb4f9418 100644 --- a/rpc/contract.go +++ b/rpc/contract.go @@ -31,11 +31,18 @@ type PublicContractService struct { hmy *hmy.Harmony version Version // TEMP SOLUTION to rpc node spamming issue - limiterCall *rate.Limiter + limiterCall *rate.Limiter + evmCallTimeout time.Duration } // NewPublicContractAPI creates a new API for the RPC interface -func NewPublicContractAPI(hmy *hmy.Harmony, version Version, limiterEnable bool, limit int) rpc.API { +func NewPublicContractAPI( + hmy *hmy.Harmony, + version Version, + limiterEnable bool, + limit int, + evmCallTimeout time.Duration, +) rpc.API { var limiter *rate.Limiter if limiterEnable { limiter = rate.NewLimiter(rate.Limit(limit), limit) @@ -44,8 +51,13 @@ func NewPublicContractAPI(hmy *hmy.Harmony, version Version, limiterEnable bool, return rpc.API{ Namespace: version.Namespace(), Version: APIVersion, - Service: &PublicContractService{hmy, version, limiter}, - Public: true, + Service: &PublicContractService{ + hmy: hmy, + version: version, + limiterCall: limiter, + evmCallTimeout: evmCallTimeout, + }, + Public: true, } } @@ -80,7 +92,7 @@ func (s *PublicContractService) Call( } // Execute call - result, err := DoEVMCall(ctx, s.hmy, args, blockNrOrHash, CallTimeout) + result, err := DoEVMCall(ctx, s.hmy, args, blockNrOrHash, s.evmCallTimeout) if err != nil { return nil, err } diff --git a/rpc/rpc.go b/rpc/rpc.go index 2c94f0a5e5..a8f1e121a9 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -4,7 +4,6 @@ import ( "fmt" "net" "strings" - "time" "github.com/harmony-one/harmony/eth/rpc" "github.com/harmony-one/harmony/hmy" @@ -28,8 +27,6 @@ const ( const ( // APIVersion used for DApp's, bumped after RPC refactor (7/2020) APIVersion = "1.1" - // CallTimeout is the timeout given to all contract calls - CallTimeout = 5 * time.Second // LogTag is the tag found in the log for all RPC logs LogTag = "[RPC]" // HTTPPortOffset .. @@ -58,7 +55,6 @@ var ( wsEndpoint = "" wsAuthEndpoint = "" httpVirtualHosts = []string{"*"} - httpTimeouts = rpc.DefaultHTTPTimeouts httpOrigins = []string{"*"} wsOrigins = []string{"*"} ) @@ -86,13 +82,18 @@ func StartServers(hmy *hmy.Harmony, apis []rpc.API, config nodeconfig.RPCServerC rmf.ExposeAll() } if config.HTTPEnabled { + timeouts := rpc.HTTPTimeouts{ + ReadTimeout: config.HTTPTimeoutRead, + WriteTimeout: config.HTTPTimeoutWrite, + IdleTimeout: config.HTTPTimeoutIdle, + } httpEndpoint = fmt.Sprintf("%v:%v", config.HTTPIp, config.HTTPPort) - if err := startHTTP(apis, &rmf); err != nil { + if err := startHTTP(apis, &rmf, timeouts); err != nil { return err } httpAuthEndpoint = fmt.Sprintf("%v:%v", config.HTTPIp, config.HTTPAuthPort) - if err := startAuthHTTP(authApis, &rmf); err != nil { + if err := startAuthHTTP(authApis, &rmf, timeouts); err != nil { return err } } @@ -158,8 +159,8 @@ func getAPIs(hmy *hmy.Harmony, config nodeconfig.RPCServerConfig) []rpc.API { NewPublicHarmonyAPI(hmy, V2), NewPublicBlockchainAPI(hmy, V1, config.RateLimiterEnabled, config.RequestsPerSecond), NewPublicBlockchainAPI(hmy, V2, config.RateLimiterEnabled, config.RequestsPerSecond), - NewPublicContractAPI(hmy, V1, config.RateLimiterEnabled, config.RequestsPerSecond), - NewPublicContractAPI(hmy, V2, config.RateLimiterEnabled, config.RequestsPerSecond), + NewPublicContractAPI(hmy, V1, config.RateLimiterEnabled, config.RequestsPerSecond, config.EvmCallTimeout), + NewPublicContractAPI(hmy, V2, config.RateLimiterEnabled, config.RequestsPerSecond, config.EvmCallTimeout), NewPublicTransactionAPI(hmy, V1), NewPublicTransactionAPI(hmy, V2), NewPublicPoolAPI(hmy, V1, config.RateLimiterEnabled, config.RequestsPerSecond), @@ -185,7 +186,7 @@ func getAPIs(hmy *hmy.Harmony, config nodeconfig.RPCServerConfig) []rpc.API { publicAPIs = append(publicAPIs, NewPublicHarmonyAPI(hmy, Eth), NewPublicBlockchainAPI(hmy, Eth, config.RateLimiterEnabled, config.RequestsPerSecond), - NewPublicContractAPI(hmy, Eth, config.RateLimiterEnabled, config.RequestsPerSecond), + NewPublicContractAPI(hmy, Eth, config.RateLimiterEnabled, config.RequestsPerSecond, config.EvmCallTimeout), NewPublicTransactionAPI(hmy, Eth), NewPublicPoolAPI(hmy, Eth, config.RateLimiterEnabled, config.RequestsPerSecond), eth.NewPublicEthService(hmy, "eth"), @@ -210,7 +211,7 @@ func getAPIs(hmy *hmy.Harmony, config nodeconfig.RPCServerConfig) []rpc.API { return publicAPIs } -func startHTTP(apis []rpc.API, rmf *rpc.RpcMethodFilter) (err error) { +func startHTTP(apis []rpc.API, rmf *rpc.RpcMethodFilter, httpTimeouts rpc.HTTPTimeouts) (err error) { httpListener, httpHandler, err = rpc.StartHTTPEndpoint( httpEndpoint, apis, HTTPModules, rmf, httpOrigins, httpVirtualHosts, httpTimeouts, ) @@ -227,7 +228,7 @@ func startHTTP(apis []rpc.API, rmf *rpc.RpcMethodFilter) (err error) { return nil } -func startAuthHTTP(apis []rpc.API, rmf *rpc.RpcMethodFilter) (err error) { +func startAuthHTTP(apis []rpc.API, rmf *rpc.RpcMethodFilter, httpTimeouts rpc.HTTPTimeouts) (err error) { httpListener, httpHandler, err = rpc.StartHTTPEndpoint( httpAuthEndpoint, apis, HTTPModules, rmf, httpOrigins, httpVirtualHosts, httpTimeouts, )