Skip to content
This repository has been archived by the owner on Oct 11, 2024. It is now read-only.

Implement ETH JSON-RPC Rate Limiting #484

Merged
merged 57 commits into from
Nov 3, 2019

Conversation

fabioberger
Copy link
Contributor

@fabioberger fabioberger commented Oct 30, 2019

Currently, the number of Ethereum JSON-RPC requests a node makes scales with the number of orders being discovered. Instead, we want there to be a max cap, and if it is reached, have the node wait for more orders to accumulate before making the next RPC request.

There are two distinct caps, a per 24hr UTC time window cap, and a max per second cap. Both default to the Infura free-tier settings and are configurable by node operators.

Remaining TODOs:

  • Expose number of ETH JSON-RPC queries sent in stats response
  • Make sure we are rate-limiting order validation retry logic requests
  • Final review

@fabioberger fabioberger force-pushed the feature/ethRateLimiting branch from 332903d to 7653fdb Compare October 30, 2019 07:28
@fabioberger fabioberger changed the title WIP: Implement ETH JSON-RPC Rate Limiting Implement ETH JSON-RPC Rate Limiting Oct 30, 2019
@fabioberger fabioberger requested a review from albrow October 30, 2019 21:16
@fabioberger fabioberger added this to the Hardening Mesh milestone Oct 30, 2019
@@ -1,4 +1,4 @@
package ethereum
package signer
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to move this into it's own sub-package in order to break a circular import error.

Copy link
Contributor

@albrow albrow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fabio I still need to take a closer look at some parts of this PR (including the tests), but in the interest of time I am submitting my thoughts so far.

core/core.go Outdated Show resolved Hide resolved
core/core.go Outdated Show resolved Hide resolved
core/core.go Outdated Show resolved Hide resolved
core/core.go Outdated Show resolved Hide resolved
core/core.go Outdated Show resolved Hide resolved
ratelimit/rate_limiter.go Outdated Show resolved Hide resolved
ratelimit/rate_limiter.go Outdated Show resolved Hide resolved
ethereum/blockwatch/client.go Outdated Show resolved Hide resolved
ratelimit/rate_limiter.go Outdated Show resolved Hide resolved
ratelimit/rate_limiter.go Outdated Show resolved Hide resolved
ethereum/ethrpcclient/eth_rpc_client.go Show resolved Hide resolved
ethereum/ethwatch/eth_watcher_test.go Outdated Show resolved Hide resolved
// many from the bucket so that it starts empty for the next 24hr period
r.mu.Lock()
accruedGrants := r.maxRequestsPer24Hrs - r.grantedInLast24hrsUTC
if err := r.twentyFourHourLimiter.WaitN(ctx, accruedGrants); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we use AllowN instead of WaitN here? There's no reason to block; I think we just want to take accruedGrants out of the bucket.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation does not specify whether callingAllowN will deduct however many tokens have accrued before returning false. I dug into the code and if there aren't N tokens that have accrued, the request is rejected and the bucket is not emptied. We must use WaitN.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm.. that's really annoying. @fabioberger are we confident that there is no situation where this could block?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I am confident this should never block. When we instantiate the rate limiter, we drain the bucket so that the number of accrued grants is theoreticalGrantsAccrued - grantedInLast24hrsUTC (where the theoretical grants accrued is calculated from the time elapsed since the start of the UTC day interval). Therefore the grants accrued left to be drained will be maxRequestsPer24Hrs - grantedInLast24hrsUTC.

ethereum/ratelimit/rate_limiter.go Show resolved Hide resolved
ethereum/ratelimit/fake_rate_limiter.go Outdated Show resolved Hide resolved
ethereum/ethwatch/eth_watcher_test.go Outdated Show resolved Hide resolved
ethereum/ratelimit/rate_limiter_test.go Show resolved Hide resolved
ethereum/ratelimit/rate_limiter_test.go Outdated Show resolved Hide resolved
ethereum/ratelimit/rate_limiter_test.go Outdated Show resolved Hide resolved
zeroex/orderwatch/order_watcher_test.go Outdated Show resolved Hide resolved
@fabioberger fabioberger force-pushed the feature/ethRateLimiting branch from 84d98ea to afe35fa Compare November 1, 2019 17:15
@albrow albrow self-requested a review November 1, 2019 18:01
Copy link
Contributor

@albrow albrow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few outstanding comments.

Copy link
Contributor

@albrow albrow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved after CI passes

@fabioberger fabioberger merged commit 6b232ff into development Nov 3, 2019
@fabioberger fabioberger deleted the feature/ethRateLimiting branch November 3, 2019 16:46
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants