Announcing multi-client support for rbuilder

I’m happy to announce that this PR brings support for different EL clients to rbuilder.

The benefit of this effort is increasing client diversity in BuilderNet

The solution is quite simple; it assumes there is an external EL client to which rbuilder connects via IPC (by external, I mean external to the rbuilder process).

Implementation details

This solution leverages IPC-RPC calls to provide the state to rbuilder, which is then used during transaction execution. Final state root calculation is currently not done by the rbuilder but by the external node.

The benefits of this approach are that it’s quite generic, and any client implementation can now leverage rbuilder for block building.

The biggest downside is the overhead the IPC brings, as every time EVM needs some state data, it makes an IPC call. And even though IPC by itself isn’t that expensive, when coupled with JSON serialization/deserialization and the sheer amount of requests, it adds up.

That being said, we are already investigating ways to improve performance. An example of this is our custom IPC library implementation, as the one provided by alloy-rs was not well suited for this solution.

Node requirements

There are a couple of custom RPC calls EL clients must implement in order for this solution to work.

These are:

  1. rbuilder_calculateStateRoot for state root calculation
  2. rbuilder_getCodeByHash given Bytecode hash, returns Bytecode
  3. rbuilder_getBlockHash gets the block hash given block number (similar to eth_getBlockByNumber, but just returns block hash)
  4. rbuilder_getAccount gets account info (similar to eth_getProof, but w/o proof stuff)

Please follow this link to see the expected arguments and responses for each of the calls mentioned above.

I’m proud to say that the Nethermind client already supports all of the RPC methods defined above, and we have tested this solution heavily using the Nethermind client.

How to run rbuilder with Nethermind Client (NMC)

Nethermind config

  1. Build the latest main branch. Here is a guide on how to build from the source
  2. Follow this guide on how to run NMC. Importantly pass the following flags when starting the NMC:
    1. --jsonrpc-enabledmodules [rbuilder, Eth, Subscribe, TxPool, Rpc] to enable all necessary JSON-RPC modules
    2. --jsonrpc-ipcunixdomainsocketpath ~/execution-data/nm.ipc to enable IPC communcation
    3. --jsonrpc-websocketsport 8546 to enable Webscokets
    4. --JsonRpc.IpcProcessingConcurrency 16 --JsonRpc.WebSocketsProcessingConcurrency 2
      For better IPC and WebSokcet perf.

Full command example:

./nethermind -c mainnet  --data-dir ~/execution-data --jsonrpc-jwtsecretfile ~/jwt.hex  --healthchecks-enabled true --jsonrpc-enabledmodules [Eth,Subscribe,Trace,TxPool,Web3,Personal,Proof,Net,Parity,Health,Rpc,rbuilder,admin] --JsonRpc.Host 0.0.0.0 --jsonrpc-ipcunixdomainsocketpath ~/execution-data/nm.ipc --sync-nonvalidatornode true --jsonrpc-websocketsport 8546 --Sync.DownloadReceiptsInFastSync false  --JsonRpc.IpcProcessingConcurrency 16 --JsonRpc.WebSocketsProcessingConcurrency 2 --TxPool.BlobsSupport InMemory

rbuilder config

  1. Download latest rbuilder version (as of time of writing it’s v1.0.0 ) or build from the soruce
  2. start rbuilder like you usually would, e.g. rbuilder run config.toml
  3. Make sure config.toml has following
[ipc_provider]
ipc_path = "<path_to_ipc>"
mempool_server_url = "ws://localhost:8546"
request_timeout_ms = 100 # after how long IPC request will timeout in ms

Example of full config.toml

log_level = "info,rbuilder=info"
redacted_telemetry_server_port = 6061
redacted_telemetry_server_ip = "0.0.0.0"
full_telemetry_server_port = 6060
full_telemetry_server_ip = "0.0.0.0"

chain = "mainnet"

coinbase_secret_key = "<secret_key>"
relay_secret_key = "<secret_key>"

cl_node_url = "http://localhost:5052"
jsonrpc_server_port = 8645
jsonrpc_server_ip = "0.0.0.0"

ignore_cancellable_orders = true

watchdog_timeout_sec = 600
simulation_threads = 4

sbundle_mergeable_signers = []
live_builders = [ "mgp-ordering", "mp-ordering"]

[ipc_provider]
ipc_path = "/root/execution-data/nm.ipc"
mempool_server_url = "ws://localhost:8546"
request_timeout_ms = 100

[[relays]]
name = "flashbots"
url = "http://localhost:80"
priority = 0

[[builders]]
name = "mgp-ordering"
algo = "ordering-builder"
discard_txs = true
sorting = "mev-gas-price"
failed_order_retries = 1
drop_failed_orders = true

[[builders]]
name = "mp-ordering"
algo = "ordering-builder"
discard_txs = true
sorting = "max-profit"
failed_order_retries = 1
drop_failed_orders = true

Final thoughts

Feedback and comments are appreciated, please reach out!

Made possible with :heart: by the Nethermind and Flashbots teams.

3 Likes