infra/proxyd/proxyd
felipe 08b38db217 fix(proxyd): log initialization (#9785)
* fix(proxyd): log initialization

* update integration test as well
2024-03-08 00:29:59 +00:00
..
cmd/proxyd fix(proxyd): log initialization (#9785) 2024-03-08 00:29:59 +00:00
integration_tests fix(proxyd): log initialization (#9785) 2024-03-08 00:29:59 +00:00
pkg/avg-sliding-window sliding window thread safe 2023-04-26 13:07:01 -07:00
tools/mockserver feat(proxyd): avoid caching debug_getRawReceipts responses with 0 receipts 2023-10-19 11:29:24 -07:00
.gitignore maint: Move Go packages into root of repo, adopt go.work (#2524) 2022-05-04 21:51:24 +00:00
backend_test.go Weighted shuffle list 2023-11-08 20:23:49 -06:00
backend.go feat(proxyd): impl proxyd_healthz method (#8658) 2023-12-18 18:58:18 +00:00
cache_test.go fix: typo on cache_test eth_call (#9462) 2024-02-09 18:11:30 +00:00
cache.go feat(proxyd): change default cache ttl to 2 hours and make it configurable (#9645) 2024-02-23 21:58:00 +00:00
CHANGELOG.md Version Packages 2023-02-23 01:53:04 +00:00
config.go feat(proxyd): change default cache ttl to 2 hours and make it configurable (#9645) 2024-02-23 21:58:00 +00:00
consensus_poller.go proxyd: avoid banning a backend that is a forced candidate (#7275) 2023-09-25 21:12:55 -07:00
consensus_tracker.go feat(proxyd): improved consensus HA error reporting (#9647) 2024-02-23 21:17:07 +00:00
Dockerfile fix(proxyd): alpine version should be 3.18 (#7781) 2023-10-21 14:33:42 -07:00
Dockerfile.ignore ops: buildx bake and fix ci docker publish/release 2023-10-25 16:00:26 +02:00
entrypoint.sh maint: Move Go packages into root of repo, adopt go.work (#2524) 2022-05-04 21:51:24 +00:00
errors.go Last unwrapped errors 2022-09-09 04:56:59 -07:00
example.config.toml proxyd: add example block range regulation params (#8039) 2023-11-11 01:54:25 -08:00
frontend_rate_limiter_test.go feat(proxyd): high availability 2023-09-14 12:36:24 -07:00
frontend_rate_limiter.go feat(proxyd): high availability 2023-09-14 12:36:24 -07:00
go.mod Update op-geth dependency to upstream geth v1.13.8 and migrate to slog (#8917) 2024-02-06 21:02:02 +00:00
go.sum Update op-geth dependency to upstream geth v1.13.8 and migrate to slog (#8917) 2024-02-06 21:02:02 +00:00
Makefile chore(proxyd): remove -race from make tests (#7573) 2023-10-05 14:42:40 -07:00
methods.go feat(proxyd): avoid caching debug_getRawReceipts responses with 0 receipts 2023-10-19 11:29:24 -07:00
metrics.go feat(proxyd): improved consensus HA error reporting (#9647) 2024-02-23 21:17:07 +00:00
proxyd.go feat(proxyd): change default cache ttl to 2 hours and make it configurable (#9645) 2024-02-23 21:58:00 +00:00
reader_test.go proxyd: Handle oversize requests/backend responses 2023-10-21 15:18:53 -06:00
reader.go proxyd: Handle oversize requests/backend responses 2023-10-21 15:18:53 -06:00
README.md Aggregate typo fixes 2023-12-13 09:50:18 -08:00
redis.go feat(proxyd): high availability 2023-09-14 12:36:24 -07:00
rewriter_test.go feat(proxyd): support eip-1898 in tag rewritting 2023-10-27 15:38:20 -07:00
rewriter.go feat(proxyd): support eip-1898 in tag rewritting 2023-10-27 15:38:20 -07:00
rpc_test.go fix(proxyd): Fix compliance with JSON-RPC 2.0 spec by adding optional RPCError.Data (#3683) 2022-10-11 08:51:02 -06:00
rpc.go fix: unmarshaling -> unmarshalling on other files 2023-12-11 23:06:56 +07:00
server.go feat(proxyd): change default cache ttl to 2 hours and make it configurable (#9645) 2024-02-23 21:58:00 +00:00
string_set.go maint: Move Go packages into root of repo, adopt go.work (#2524) 2022-05-04 21:51:24 +00:00
tls.go style(batch-submitter,bss-core,proxyd): Fix lint Go (#3328) 2022-08-26 19:39:30 -06:00

rpc-proxy

This tool implements proxyd, an RPC request router and proxy. It does the following things:

  1. Whitelists RPC methods.
  2. Routes RPC methods to groups of backend services.
  3. Automatically retries failed backend requests.
  4. Track backend consensus (latest, safe, finalized blocks), peer count and sync state.
  5. Re-write requests and responses to enforce consensus.
  6. Load balance requests across backend services.
  7. Cache immutable responses from backends.
  8. Provides metrics to measure request latency, error rates, and the like.

Usage

Run make proxyd to build the binary. No additional dependencies are necessary.

To configure proxyd for use, you'll need to create a configuration file to define your proxy backends and routing rules. Check out example.config.toml for how to do this alongside a full list of all options with commentary.

Once you have a config file, start the daemon via proxyd <path-to-config>.toml.

Consensus awareness

Starting on v4.0.0, proxyd is aware of the consensus state of its backends. This helps minimize chain reorgs experienced by clients.

To enable this behavior, you must set consensus_aware value to true in the backend group.

When consensus awareness is enabled, proxyd will poll the backends for their states and resolve a consensus group based on:

  • the common ancestor latest block, i.e. if a backend is experiencing a fork, the fork won't be visible to the clients
  • the lowest safe block
  • the lowest finalized block
  • peer count
  • sync state

The backend group then acts as a round-robin load balancer distributing traffic equally across healthy backends in the consensus group, increasing the availability of the proxy.

A backend is considered healthy if it meets the following criteria:

  • not banned
  • avg 1-min moving window error rate ≤ configurable threshold
  • avg 1-min moving window latency ≤ configurable threshold
  • peer count ≥ configurable threshold
  • latest block lag ≤ configurable threshold
  • last state update ≤ configurable threshold
  • not currently syncing

When a backend is experiencing inconsistent consensus, high error rates or high latency, the backend will be banned for a configurable amount of time (default 5 minutes) and won't receive any traffic during this period.

Tag rewrite

When consensus awareness is enabled, proxyd will enforce the consensus state transparently for all the clients.

For example, if a client requests the eth_getBlockByNumber method with the latest tag, proxyd will rewrite the request to use the resolved latest block from the consensus group and forward it to the backend.

The following request methods are rewritten:

  • eth_getLogs
  • eth_newFilter
  • eth_getBalance
  • eth_getCode
  • eth_getTransactionCount
  • eth_call
  • eth_getStorageAt
  • eth_getBlockTransactionCountByNumber
  • eth_getUncleCountByBlockNumber
  • eth_getBlockByNumber
  • eth_getTransactionByBlockNumberAndIndex
  • eth_getUncleByBlockNumberAndIndex
  • debug_getRawReceipts

And eth_blockNumber response is overridden with current block consensus.

Cacheable methods

Cache use Redis and can be enabled for the following immutable methods:

  • eth_chainId
  • net_version
  • eth_getBlockTransactionCountByHash
  • eth_getUncleCountByBlockHash
  • eth_getBlockByHash
  • eth_getTransactionByBlockHashAndIndex
  • eth_getUncleByBlockHashAndIndex
  • debug_getRawReceipts (block hash only)

Meta method consensus_getReceipts

To support backends with different specifications in the same backend group, proxyd exposes a convenient method to fetch receipts abstracting away what specific backend will serve the request.

Each backend specifies their preferred method to fetch receipts with consensus_receipts_target config, which will be translated from consensus_getReceipts.

This method takes a blockNumberOrHash (i.e. tag|qty|hash) and returns the receipts for all transactions in the block.

Request example

{
  "jsonrpc":"2.0",
  "id": 1,
  "params": ["0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b"]
}

It currently supports translation to the following targets:

  • debug_getRawReceipts(blockOrHash) (default)
  • alchemy_getTransactionReceipts(blockOrHash)
  • parity_getBlockReceipts(blockOrHash)
  • eth_getBlockReceipts(blockOrHash)

The selected target is returned in the response, in a wrapped result.

Response example

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "method": "debug_getRawReceipts",
    "result": {
      // the actual raw result from backend
    }
  }
}

See op-node receipt fetcher.

Metrics

See metrics.go for a list of all available metrics.

The metrics port is configurable via the metrics.port and metrics.host keys in the config.

Adding Backend SSL Certificates in Docker

The Docker image runs on Alpine Linux. If you get SSL errors when connecting to a backend within Docker, you may need to add additional certificates to Alpine's certificate store. To do this, bind mount the certificate bundle into a file in /usr/local/share/ca-certificates. The entrypoint.sh script will then update the store with whatever is in the ca-certificates directory prior to starting proxyd.