This tool implements proxyd, an RPC request router and proxy for BSC Builder. It is based on the ethereum-optimism/infra proxyd service and has been modified to integrate with bsc-builder's mev-guard functionality.
This repository is a fork of the proxyd service from the ethereum-optimism/infra repository. The original service has been enhanced to support BSC Builder's MEV protection mechanisms.
This proxy does the following things:
- Whitelists RPC methods.
- Routes RPC methods to groups of backend services.
- Automatically retries failed backend requests.
- Track backend consensus (
latest,safe,finalizedblocks), peer count and sync state. - Re-write requests and responses to enforce consensus.
- Load balance requests across backend services.
- Cache immutable responses from backends.
- Provides metrics to measure request latency, error rates, and the like.
- Override eth_call responses for MEV guard verification (BSC Builder enhancement).
This version of proxyd includes a special feature for MEV guard verification that allows overriding eth_call responses based on specific address and data combinations.
To configure eth_call overrides, add the following section to your configuration file:
[eth_call_override]
[[eth_call_override.rules]]
address = "0x1234567890123456789012345678901234567890"
value = "0x0"
result = "\"0x0000000000000000000000000000000000000000000000000000000000000001\""
[[eth_call_override.rules]]
address = "0x0987654321098765432109876543210987654321"
value = "0x1000000000000000000"
result = "\"0x0000000000000000000000000000000000000000000000000000000000000000\""When an eth_call request is received:
- The proxy checks if the request's
toaddress andvaluefields match any configured rules - If a match is found, the predefined
resultis returned immediately without forwarding to backends - If no match is found, the request is processed normally through the backend services
The matching is case-insensitive for both address and value fields. If no value is specified in the request, it defaults to "0x0".
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.
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
latestblock, i.e. if a backend is experiencing a fork, the fork won't be visible to the clients - the lowest
safeblock - the lowest
finalizedblock - 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
latestblock 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.
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_getLogseth_newFiltereth_getBalanceeth_getCodeeth_getTransactionCounteth_calleth_getStorageAteth_getBlockTransactionCountByNumbereth_getUncleCountByBlockNumbereth_getBlockByNumbereth_getTransactionByBlockNumberAndIndexeth_getUncleByBlockNumberAndIndexdebug_getRawReceipts
And eth_blockNumber response is overridden with current block consensus.
Cache use Redis and can be enabled for the following immutable methods:
eth_chainIdnet_versioneth_getBlockTransactionCountByHasheth_getUncleCountByBlockHasheth_getBlockByHasheth_getTransactionByBlockHashAndIndexeth_getUncleByBlockHashAndIndexdebug_getRawReceipts(block hash only)
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.
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.