From f16313e9e05a9d291bb40dc261e1ca744e909076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=BDiga=20Kokelj?= Date: Wed, 31 Jul 2024 17:25:46 +0200 Subject: [PATCH 1/6] disable rate limiting for local network --- testnet/launcher/docker.go | 1 + testnet/launcher/gateway/config.go | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/testnet/launcher/docker.go b/testnet/launcher/docker.go index b92936caea..61c9d60603 100644 --- a/testnet/launcher/docker.go +++ b/testnet/launcher/docker.go @@ -191,6 +191,7 @@ func (t *Testnet) Start() error { gateway.WithTenNodeHTTPPort(13010), gateway.WithTenNodeWSPort(13011), gateway.WithTenNodeHost("validator-host"), + gateway.WithRateLimitUserComputeTime(0), // disable rate limiting for local network gateway.WithDockerImage("testnetobscuronet.azurecr.io/obscuronet/obscuro_gateway:latest"), ), ) diff --git a/testnet/launcher/gateway/config.go b/testnet/launcher/gateway/config.go index 507d5e6a19..bd72fc318b 100644 --- a/testnet/launcher/gateway/config.go +++ b/testnet/launcher/gateway/config.go @@ -1,16 +1,19 @@ package gateway +import "time" + // Option is a function that applies configs to a Config Object type Option = func(c *Config) // Config holds the properties that configure the package type Config struct { - tenNodeHost string - tenNodeHTTPPort int - tenNodeWSPort int - gatewayHTTPPort int - gatewayWSPort int - dockerImage string + tenNodeHost string + tenNodeHTTPPort int + tenNodeWSPort int + gatewayHTTPPort int + gatewayWSPort int + rateLimitUserComputeTime time.Duration + dockerImage string } func NewGatewayConfig(opts ...Option) *Config { @@ -58,3 +61,9 @@ func WithGatewayWSPort(i int) Option { c.gatewayWSPort = i } } + +func WithRateLimitUserComputeTime(d time.Duration) Option { + return func(c *Config) { + c.rateLimitUserComputeTime = d + } +} From 2154819d27d3aca76e8baa941bee8fd720bd0696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=BDiga=20Kokelj?= Date: Thu, 1 Aug 2024 12:04:15 +0200 Subject: [PATCH 2/6] pass the parameters from config to the gateway --- testnet/launcher/gateway/docker.go | 1 + 1 file changed, 1 insertion(+) diff --git a/testnet/launcher/gateway/docker.go b/testnet/launcher/gateway/docker.go index 7be1786b72..cdae1a564a 100644 --- a/testnet/launcher/gateway/docker.go +++ b/testnet/launcher/gateway/docker.go @@ -33,6 +33,7 @@ func (n *DockerGateway) Start() error { "--nodeHost", n.cfg.tenNodeHost, "--dbType", "sqlite", "--logPath", "sys_out", + "--rateLimitUserComputeTime", fmt.Sprintf("%d", n.cfg.rateLimitUserComputeTime), } _, err := docker.StartNewContainer("gateway", n.cfg.dockerImage, cmds, []int{n.cfg.gatewayHTTPPort, n.cfg.gatewayWSPort}, nil, nil, nil) From 05a6fdce2476055341b04152c61c37c3cbadf594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=BDiga=20Kokelj?= Date: Fri, 2 Aug 2024 12:59:33 +0200 Subject: [PATCH 3/6] skip adding and deleting requests if rate limiting is disabled --- .../ratelimiter/rate_limiter.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tools/walletextension/ratelimiter/rate_limiter.go b/tools/walletextension/ratelimiter/rate_limiter.go index f2be19ac41..b403725ae3 100644 --- a/tools/walletextension/ratelimiter/rate_limiter.go +++ b/tools/walletextension/ratelimiter/rate_limiter.go @@ -28,6 +28,10 @@ var zeroUUID uuid.UUID // AddRequest adds a new request interval to a user's current requests and returns the UUID. func (rl *RateLimiter) AddRequest(userID common.Address, interval RequestInterval) uuid.UUID { + // If the userComputeTime is 0, do nothing (rate limiting is disabled) + if rl.GetUserComputeTime() == 0 { + return zeroUUID + } rl.mu.Lock() defer rl.mu.Unlock() @@ -45,6 +49,11 @@ func (rl *RateLimiter) AddRequest(userID common.Address, interval RequestInterva // SetRequestEnd updates the end time of a request interval given its UUID. func (rl *RateLimiter) SetRequestEnd(userID common.Address, id uuid.UUID) { + // If the userComputeTime is 0, do nothing (rate limiting is disabled) + if rl.GetUserComputeTime() == 0 { + return + } + if user, userExists := rl.users[userID]; userExists { if request, requestExists := user.CurrentRequests[id]; requestExists { rl.mu.Lock() @@ -205,6 +214,11 @@ func (rl *RateLimiter) PruneRequests() { // periodically prunes the requests that have ended before the rate limiter's window every 10 * window milliseconds func (rl *RateLimiter) periodicPrune() { + // If the userComputeTime is 0, do nothing (rate limiting is disabled) + if rl.GetUserComputeTime() == 0 { + return + } + for { time.Sleep(rl.window * 10) rl.PruneRequests() @@ -212,6 +226,11 @@ func (rl *RateLimiter) periodicPrune() { } func (rl *RateLimiter) logRateLimitedStats() { + // If the userComputeTime is 0, do nothing (rate limiting is disabled) + if rl.GetUserComputeTime() == 0 { + return + } + for { time.Sleep(30 * time.Minute) rl.mu.Lock() From 87d80ee44897e0f6d350730b3c03d2330a7cce3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=BDiga=20Kokelj?= Date: Mon, 5 Aug 2024 17:44:51 +0200 Subject: [PATCH 4/6] prune requests twice per window duration --- tools/walletextension/ratelimiter/rate_limiter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/walletextension/ratelimiter/rate_limiter.go b/tools/walletextension/ratelimiter/rate_limiter.go index b403725ae3..3a633fd11b 100644 --- a/tools/walletextension/ratelimiter/rate_limiter.go +++ b/tools/walletextension/ratelimiter/rate_limiter.go @@ -220,7 +220,7 @@ func (rl *RateLimiter) periodicPrune() { } for { - time.Sleep(rl.window * 10) + time.Sleep(rl.window / 2) rl.PruneRequests() } } From 16deaf7024a590927926f0209a61d8cb27aa4746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=BDiga=20Kokelj?= Date: Tue, 6 Aug 2024 10:34:44 +0200 Subject: [PATCH 5/6] use RWMutex and don't start prunning and logging if rate limiting is disabled --- .../ratelimiter/rate_limiter.go | 33 ++++++++----------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/tools/walletextension/ratelimiter/rate_limiter.go b/tools/walletextension/ratelimiter/rate_limiter.go index 3a633fd11b..6418f0e5e1 100644 --- a/tools/walletextension/ratelimiter/rate_limiter.go +++ b/tools/walletextension/ratelimiter/rate_limiter.go @@ -71,8 +71,8 @@ func (rl *RateLimiter) SetRequestEnd(userID common.Address, id uuid.UUID) { // CountOpenRequests counts the number of requests without an End time set. func (rl *RateLimiter) CountOpenRequests(userID common.Address) int { - rl.mu.Lock() - defer rl.mu.Unlock() + rl.mu.RLock() + defer rl.mu.RUnlock() var count int if user, exists := rl.users[userID]; exists { @@ -109,7 +109,7 @@ func (rl *RateLimiter) SumComputeTime(userID common.Address) time.Duration { } type RateLimiter struct { - mu sync.Mutex + mu sync.RWMutex users map[common.Address]*RateLimitUser userComputeTime time.Duration window time.Duration @@ -135,15 +135,15 @@ func (rl *RateLimiter) IncrementRateLimitedRequests() { // GetMaxConcurrentRequest returns the maximum number of concurrent requests allowed. func (rl *RateLimiter) GetMaxConcurrentRequest() uint32 { - rl.mu.Lock() - defer rl.mu.Unlock() + rl.mu.RLock() + defer rl.mu.RUnlock() return rl.maxConcurrentRequests } // GetUserComputeTime returns the user compute time func (rl *RateLimiter) GetUserComputeTime() time.Duration { - rl.mu.Lock() - defer rl.mu.Unlock() + rl.mu.RLock() + defer rl.mu.RUnlock() return rl.userComputeTime } @@ -155,8 +155,13 @@ func NewRateLimiter(rateLimitUserComputeTime time.Duration, rateLimitWindow time maxConcurrentRequests: concurrentRequestsLimit, logger: logger, } - go rl.logRateLimitedStats() - go rl.periodicPrune() + + // If the userComputeTime is 0 (rate limiting is disabled) we don't need to prune and log rate limited stats + if rl.GetUserComputeTime() != 0 { + go rl.logRateLimitedStats() + go rl.periodicPrune() + } + return rl } @@ -214,11 +219,6 @@ func (rl *RateLimiter) PruneRequests() { // periodically prunes the requests that have ended before the rate limiter's window every 10 * window milliseconds func (rl *RateLimiter) periodicPrune() { - // If the userComputeTime is 0, do nothing (rate limiting is disabled) - if rl.GetUserComputeTime() == 0 { - return - } - for { time.Sleep(rl.window / 2) rl.PruneRequests() @@ -226,11 +226,6 @@ func (rl *RateLimiter) periodicPrune() { } func (rl *RateLimiter) logRateLimitedStats() { - // If the userComputeTime is 0, do nothing (rate limiting is disabled) - if rl.GetUserComputeTime() == 0 { - return - } - for { time.Sleep(30 * time.Minute) rl.mu.Lock() From 7ada3c6a3ae98447be79d2245adc8f652e1a2bc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=BDiga=20Kokelj?= Date: Tue, 6 Aug 2024 12:03:20 +0200 Subject: [PATCH 6/6] fix comment --- tools/walletextension/ratelimiter/rate_limiter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/walletextension/ratelimiter/rate_limiter.go b/tools/walletextension/ratelimiter/rate_limiter.go index 6418f0e5e1..05103b46f6 100644 --- a/tools/walletextension/ratelimiter/rate_limiter.go +++ b/tools/walletextension/ratelimiter/rate_limiter.go @@ -217,7 +217,7 @@ func (rl *RateLimiter) PruneRequests() { } } -// periodically prunes the requests that have ended before the rate limiter's window every 10 * window milliseconds +// periodically prunes the requests that have ended before the rate limiter's window milliseconds func (rl *RateLimiter) periodicPrune() { for { time.Sleep(rl.window / 2)