ethrex: an Ethereum client designed around proving, not retrofitting it
Minimalist, stable, modular, fast, and ZK native implementation of the Ethereum protocol in Rust. L1 and L2 execution client.
At a glance
- What is it?
- ethrex is a Rust implementation of the Ethereum protocol that LambdaClass built with zero knowledge proving in mind, running either as a regular L1 execution client or as a multi-prover ZK-Rollup. The judgement is that the interesting engineering is in the shared execution layer and the build hygiene around it, and that the licensing and release cadence are unusually easy for a client to adopt.
- Who is it for?
- ethrex is a good fit for a team that wants an Ethereum execution client small enough to read, wants proving support built into the same codebase rather than bolted on, and needs a rollup stack that can point at SP1, RISC Zero or a TEE, and for a team that wants a Docker deployment with a beacon node wired up already.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Proving shaped the architecture from the first commit
The README is emphatic on one point, and it is the point that separates this client from others. ethrex was built from the ground up with zero knowledge proving in mind, and the text says explicitly that this is not a feature bolted onto an existing client, but a core design principle that shapes how execution, state management and the whole architecture are structured. The audience splits cleanly in two. For L1 node operators the value is integration with several zkVMs, SP1, RISC Zero, ZisK and OpenVM, so block execution can be proven, plus ZK optimised data structures that reduce proving overhead, plus a small codebase that is less complex to run next to a prover. For L2 builders the value is a multi-prover ZK-Rollup architecture supporting SP1, RISC Zero and TEEs out of the box, proof aggregation through an Aligned Layer integration, and one execution client for both layers, which the README argues gives consistent behaviour and easier debugging. Support for based sequencing is described as in the works.
The same execution client in two roles
The client runs in two modes, and the naming is the documentation for the difference. In L1 mode ethrex behaves as a regular Ethereum execution client. In L2 mode it acts as a multi-prover ZK-Rollup, in which block execution is proven and the proof is sent to an L1 network for verification, so the rollup inherits the L1 security. TEEs sit alongside the two zkVMs as a third proving option, which is a different trust story from a zkVM and is worth understanding before you choose a backend. The structural claim is the interesting one for a reader deciding whether to try it: the L1 and L2 paths share one execution implementation rather than running the same protocol twice in two codebases. The cost of that choice is scope, since the same code has to satisfy both a validator operator and a rollup team, and the README is candid that the client follows a philosophy of minimal code rather than feature parity with long established clients.
The crate layout is the architecture document
Cargo.toml defines a workspace with a long member list, and reading it tells you more than the prose does. The entry point is cmd/ethrex, and the default-members setting points at it, so a plain cargo build in the root produces the client. Around it sit crates/blockchain, crates/common with subcrates for rlp, trie and crypto, crates/storage, crates/networking with p2p and rpc subcrates, and a crates/vm tree with a levm subcrate and a runner. The rollup side lives under crates/l2, split into common, prover, sdk, storage and networking/rpc, alongside a top level crates/prover and a crates/guest-program, which is the piece a proving backend executes. Tooling holds a history_validator and a repl. Two members are excluded from the root workspace, and the comments explain why: the zkevm_bench workspace hard-depends on zisk, which is x86 only and cannot build on arm or macOS, and keeping it out preserves portable default builds, lint and Docker images. That is a small but revealing detail about how the project treats build portability.
Docker Compose wires ethrex to a beacon node
The compose file is the fastest way to understand the operational shape, and it is more concrete than the documentation index. Three services are defined. A setup_jwt service uses an alpine image and generates a 32 byte hex secret with openssl into a shared secrets volume, and both other services wait for it to complete. The lighthouse service runs sigp/lighthouse with the beacon role, an HTTP address, the execution endpoint pointed at the ethrex container over http://ethrex:8551, the shared JWT secret for the authenticated engine connection, and a checkpoint sync URL parameterised by the network, with a 600 second timeout. The ethrex service pulls ghcr.io/lambdaclass/ethrex:main with pull_policy always, exposes port 8545 on the loopback interface only, mounts a data volume, and runs with --syncmode snap, --datadir /data, and separate --http.addr and --authrpc.addr arguments:
command: >
--http.addr 0.0.0.0
--network ${ETHREX_NETWORK:-mainnet}
--authrpc.addr 0.0.0.0
--authrpc.jwtsecret /secrets/jwt.hex
--syncmode snap
--datadir /dataThe network is selected with the ETHREX_NETWORK variable, defaulting to mainnet. A nofile limit of 1000000 is set for the client, which is the kind of detail that matters for a node with many peers and open files.
The container build shows the dependency weight
The Dockerfile starts from rust:1.93-slim-bookworm and installs the system libraries needed to compile native crates, naming rocksdb, openssl-sys and bindgen as the reasons for build-essential, libclang-dev, libssl-dev, pkg-config, ca-certificates, curl and git. The build uses a chef and planner stage pattern with cargo-chef so the dependency recipe is computed once and invalidated only when sources change, and cargo-chef is installed from a prebuilt cargo-binstall binary with a pinned version for reproducibility. Two comments in the file are worth reading as engineering notes rather than trivia. One explains that cargo is forced to fetch git dependencies through the git CLI instead of libgit2 because the bundled libgit2 hangs on some hosts and networks inside containers. The other explains that the cargo-chef download must use uname -m rather than the target architecture, because cargo-chef is a build platform tool. Elsewhere in the tree you can see the same attention: rust-toolchain.toml, .tool-versions, clippy.toml, book.toml for the documentation build, lychee.toml for link checking, an audits directory, a metrics directory and a fixtures directory.
Release profiles chosen for build time as much as runtime
The Cargo profiles reveal what the team optimises for. The release profile uses opt-level 3, thin LTO and codegen-units equal to 1, which is close to the usual recipe for a release binary that should run fast:
[profile.release]
opt-level = 3
lto = "thin"
codegen-units = 1The test profile is the interesting one, and the comment explains it in detail. It keeps the release grade opt-level for the hot EVM, trie and RLP paths, but drops thin LTO, raises codegen-units and uses line-tables-only debug info, so that cargo test rebuilds finish in a fraction of the time of a release-with-debug build. It also keeps the debug_assert and overflow checks that the release profile switches off, so tests still exercise those paths. A second profile inherits release and adds debug assertions for the same reason. The design principles listed in the README match this behaviour, with vertical integration and a minimal dependency count, a simple type system without generics spreading everywhere, few abstractions on the grounds that repeating code two or three times is fine, readability over premature optimisation, and concurrency used only where strictly necessary.
Licensing, releases and how to follow the project
The licence situation is one of the friendlier ones in this space. The repository carries both LICENSE-APACHE and LICENSE-MIT, and the workspace package metadata declares the licence as MIT OR Apache-2.0, so a downstream project can pick either. The version field in the workspace is 30.0.0, matching the release cadence, with v30.0.0 tagged on 2026-10-16 after the v30.0.0-rc.1 and rc.2 candidates on 2026-10-14 and 2026-10-15. The last push was on 2026-10-19 and the repository is not archived. For day to day work the documentation lives in the docs directory and is published at docs.ethrex.xyz, split into L1 and L2 sections, with a separate ROADMAP.md for planned work. Security issues have a stated route, either the GitHub private vulnerability reporting feature or an email to [email protected], with the policy in .github/SECURITY.md. One caveat on the README's own evidence: the lines of code comparison chart is labelled as data taken from the main branch of each project at 2025/10/08, so it is a snapshot rather than a live measure.
Editorial conclusion
ethrex is a good fit for a team that wants an Ethereum execution client small enough to read, wants proving support built into the same codebase rather than bolted on, and needs a rollup stack that can point at SP1, RISC Zero or a TEE, and for a team that wants a Docker deployment with a beacon node wired up already. It is a poor fit if you depend on long tail consensus client features, if you need a proven zkVM, since the rollup is explicitly in development, or if your build environment is arm based, because one benchmark workspace is excluded precisely because it cannot compile there. Before you deploy it, read the getting started section of the documentation and the v30.0.0 release notes, confirm the execution endpoint on port 8551 is reachable from your beacon node over the shared JWT secret, and check the ROADMAP.md for the features you are assuming are finished.
Frequently asked questions
What is the difference between running ethrex as L1 and as L2?
In L1 mode ethrex is a regular Ethereum execution client. In L2 mode it is a multi-prover ZK-Rollup where block execution is proven and the proof is sent to an L1 network for verification, so the rollup inherits the L1 security. Support for based sequencing is described as in the works.
How do I run ethrex alongside a consensus client?
The docker-compose file in the repository sets this up with a setup_jwt service that generates a hex secret, a lighthouse service whose execution endpoint points at http://ethrex:8551, and the ethrex service itself running with --authrpc.jwtsecret, --syncmode snap and --datadir /data. The network is chosen with the ETHREX_NETWORK variable, which defaults to mainnet.
Which proving backends does ethrex support?
The README lists integrations with SP1, RISC Zero, ZisK and OpenVM for proving Ethereum block execution, and the L2 mode is described as a multi-prover ZK-Rollup supporting SP1, RISC Zero and TEEs out of the box, with proof aggregation through an Aligned Layer integration.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/lambdaclass-ethrex)Was this useful?