diff --git a/README.md b/README.md index c2c2e37..fc6caeb 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,108 @@ Electric Eel (`eleel`) ==== -This is a multiplexer for Ethereum execution clients. It allows multiple consensus -clients to connect to a single execution client endpoint. +Eleel is a multiplexer for Ethereum execution clients. It allows multiple consensus +clients to connect to a single execution client. -There are several limitations: +It is suitable for monitoring and analytics but **should not** be used to run +validators and **will** cause you to miss block proposals if you attempt this. -- Implementation is WIP. -- One consensus node must be nominated as the controlling node. -- No payload building -- `eleel` will never send payload attributes to the EL: use a builder. +Eleel is written in Rust and makes use of components from [Lighthouse][]. -`eleel` is API-compatible with [`openexecution`][openexecution], rewritten in -Rust to take advantage of the stronger type-system and to reuse components from -[Lighthouse][]. +## Build from source -[openexecution]: https://github.com/TennisBowling/openexecution -[Lighthouse]: https://github.com/sigp/lighthouse +``` +cargo install --release --locked +``` + +A binary will be installed to `~/.cargo/bin/eleel`. + +## Getting started + +Eleel needs to connect to a _real_ execution node, e.g. Geth/Nethermind/Besu. You +should set up an execution node and take note of the JWT secret it uses. We'll provide it to +Eleel's `--ee-jwt-secret` flag. + +Eleel also needs a _controlling consensus node_ (e.g. Lighthouse) which is responsible for driving +the execution node. The controlling node is _in charge_, and its messages will be sent +directly to the execution node. The controller connects to Eleel using the `/canonical` path. There +is a second JWT secret for authenticating the controller to Eleel, which is set using the +`--controller-jwt-secret` flag. + +You can generate a new JWT secret using this command: + +``` +openssl rand -hex 32 | tr -d "\n" +``` + +In addition to the single controller node, Eleel also supports _multiple_ consensus clients, +which can be authenticated using any of a collection of JWT secrets specified in a TOML config +file. There are a lot of JWT secrets! An example TOML file can be seen below: + +```toml +[secrets] +node1 = "c259fb249f7fa1882b1d4150ace73c1023aba4f6267b29a871ad5c9adc7a543a" +node2 = "fb6073f77160f9a7ce11190d3612e841daea2e7319a59e1d82a8804e9fa193ee" +``` + +The identifiers `node1` and `node2` are _key IDs_ which are used by Eleel to decide which secret +to use when authenticating a request. It does this by examining the `key` field of the claim +(distinct from the standard JWT key-id). If the `key` is not set by the client then Eleel +tries all of the keys in a random order looking for a match (slow). + +Putting this all together, here's an example of Eleel sharing a Geth node between two Lighthouse +nodes: + +Eleel, connected to Geth on port 8551 and serving the consensus nodes on port 8552: + +``` +eleel \ + --ee-jwt-secret /tmp/execution.jwt \ + --ee-url "http://localhost:8551" \ + --controller-jwt-secret /tmp/controller.jwt \ + --client-jwt-secrets /tmp/client-secrets.toml \ + --listen-port 8552 +``` + +Geth, using the same JWT secret that Eleel uses to connect to it: + +``` +geth --authrpc.jwtsecret /tmp/execution.jwt --authrpc.port 8551 +``` + +Lighthouse running as the controller and connected to Eleel's `/canonical` endpoint: + +``` +lighthouse bn \ + --execution-endpoint "http://localhost:8552/canonical" \ + --execution-jwt "/tmp/controller.jwt" +``` + +Lighthouse running as a client connected to Eleel's `/` endpoint: + +``` +lighthouse bn \ + --execution-endpoint "http://localhost:8552" \ + --execution-jwt "/tmp/node1.jwt" \ + --execution-jwt-id "node1" +``` + +### CLI reference + +For full CLI options see [`./docs/cli-reference.md`](./docs/cli-reference.md), or run +`eleel --help`. + +## Block Building + +Eleel does not build valid execution blocks, but will build _invalid_ dummy execution +payloads. This is designed for use with [blockdreamer][blockdreamer] only and +**will cause you to propose invalid blocks** if used by a validator client. ## License Copyright Sigma Prime 2023 and contributors. Licensed under the terms of the Apache 2.0 license. + +[Lighthouse]: https://github.com/sigp/lighthouse +[blockdreamer]: https://github.com/blockprint-collective/blockdreamer diff --git a/docs/cli-reference.md b/docs/cli-reference.md new file mode 100644 index 0000000..bfba2ec --- /dev/null +++ b/docs/cli-reference.md @@ -0,0 +1,106 @@ +``` +Ethereum execution engine multiplexer + +Usage: eleel [OPTIONS] --ee-jwt-secret --controller-jwt-secret --client-jwt-secrets + +Options: + --listen-address + Listening address for the HTTP server + + [default: 127.0.0.1] + + --listen-port + Listening port for the HTTP server + + [default: 8552] + + --ee-url + Primary execution engine to be shared by connected consensus nodes + + [default: http://localhost:8551] + + --ee-jwt-secret + Path to the JWT secret for the primary execution engine + + --controller-jwt-secret + Path to the JWT secret for the controlling consensus client + + --client-jwt-secrets + Path to TOML file of JWT secrets for the non-controlling consensus clients. + + See docs for TOML file format. + + --new-payload-cache-size + Number of recent newPayload messages to cache in memory + + [default: 64] + + --fcu-cache-size + Number of recent forkchoiceUpdated messages to cache in memory + + [default: 64] + + --payload-builder-cache-size + Number of payload attributes and past payloads to cache in memory + + [default: 8] + + --payload-builder-extra-data + Extra data to include in produced blocks + + [default: Eleel] + + --justified-block-cache-size + Number of justified block hashes to cache in memory + + [default: 4] + + --finalized-block-cache-size + Number of finalized block hashes to cache in memory + + [default: 4] + + --fcu-matching + Choose the type of matching to use before returning a VALID fcU message to a client + + [default: loose] + + Possible values: + - exact: match head/safe/finalized from controller exactly + - loose: match head and sanity check safe/finalized + - head-only: match head and ignore safe/finalized (dangerous) + + --network + Network that the consensus and execution nodes are operating on + + [default: mainnet] + + --new-payload-wait-millis + Maximum time that a consensus node should wait for a newPayload response from the cache. + + We expect that the controlling consensus node and primary execution node will take some time to process requests, and that requests from consensus nodes could arrive while this processing is on-going. Using a timeout of 0 will often result in a SYNCING response, which will put the consensus node into optimistic sync. Using a longer timeout will allow the definitive (VALID) response from the execution engine to be returned, more closely matching the behaviour of a full execution engine. + + [default: 2000] + + --new-payload-wait-cutoff + Maximum age of a payload that will trigger a wait on `newPayload` + + Payloads older than this age receive an instant SYNCING response. See docs for `--new-payload-wait-millis` for the purpose of this wait. + + [default: 64] + + --fcu-wait-millis + Maximum time that a consensus node should wait for a forkchoiceUpdated response from the cache. + + See the docs for `--new-payload-wait-millis` for the purpose of this timeout. + + [default: 1000] + + --body-limit-mb + Maximum size of JSON-RPC message to accept from any connected consensus node + + [default: 128] + + -h, --help + Print help (see a summary with '-h') +```