EV-reth is a specialized integration layer that enables Reth to work seamlessly with Evolve, providing a custom payload builder that supports transaction submission via the Engine API.
This project provides a modified version of Reth that includes:
- Custom Payload Builder: A specialized payload builder that accepts transactions through Engine API payload attributes
- Evolve-Compatible Engine API: Modified Engine API validation to work with Evolve's block production model
- Transaction Support: Full support for including transactions in blocks via the Engine API
engine_forkchoiceUpdatedV3
method - Custom Consensus: Modified consensus layer that allows multiple blocks to have the same timestamp
- Txpool RPC Extension: Custom
txpoolExt_getTxs
RPC method for efficient transaction retrieval with configurable size limits
Unlike standard Reth, ev-reth accepts transactions directly through the Engine API payload attributes. This allows Evolve to submit transactions when requesting new payload creation.
The RollkitPayloadBuilder
handles:
- Transaction decoding from Engine API attributes
- Block construction with proper gas limits
- State execution and validation
Modified Engine API validator that:
- Bypasses block hash validation for Evolve blocks
- Supports custom gas limits per payload
- Maintains compatibility with standard Ethereum validation where possible
ev-reth includes a custom consensus implementation (RollkitConsensus
) that:
- Allows multiple blocks to have the same timestamp
- Wraps the standard Ethereum beacon consensus for most validation
- Only modifies timestamp validation to accept
header.timestamp >= parent.timestamp
instead of requiring strictly greater timestamps - Essential for Evolve's operation where multiple blocks may be produced with the same timestamp
Custom RPC namespace txpoolExt
that provides:
txpoolExt_getTxs
: Retrieves pending transactions from the pool as RLP-encoded bytes- Configurable byte limit for transaction retrieval (default: 1.98 MB)
- Efficient iteration that stops when reaching the byte limit
- Rust 1.82 or higher
- Git
# Clone the repository
git clone https://github.com/evstack/ev-reth.git
cd ev-reth
# Build the project
make build
# Run tests
make test
Basic usage:
./target/release/ev-reth node
With custom configuration:
./target/release/ev-reth node \
--chain <CHAIN_SPEC> \
--datadir <DATA_DIR> \
--http \
--http.api all \
--ws \
--ws.api all
When using the Engine API, you can include transactions in the payload attributes:
{
"method": "engine_forkchoiceUpdatedV3",
"params": [
{
"headBlockHash": "0x...",
"safeBlockHash": "0x...",
"finalizedBlockHash": "0x..."
},
{
"timestamp": "0x...",
"prevRandao": "0x...",
"suggestedFeeRecipient": "0x...",
"withdrawals": [],
"parentBeaconBlockRoot": "0x...",
"transactions": ["0x...", "0x..."], // RLP-encoded transactions
"gasLimit": "0x1c9c380" // Optional; defaults to parent header gas limit
}
]
}
To retrieve pending transactions from the txpool:
# Using curl
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "txpoolExt_getTxs",
"params": [],
"id": 1
}'
# Response format
{
"jsonrpc": "2.0",
"result": [
"0xf86d...", // RLP-encoded transaction bytes 1
"0xf86e...", // RLP-encoded transaction bytes 2
// ... more transactions up to the byte limit
],
"id": 1
}
Ev-reth follows a modular architecture similar to Odyssey, with clear separation of concerns:
bin/ev-reth
: The main executable binarycrates/common
: Shared utilities and constants used across all cratescrates/node
: Core node implementation including the payload buildercrates/evolve
: Evolve-specific types, RPC extensions, and integration logiccrates/tests
: Comprehensive test suite including unit and integration tests
This modular design allows for:
- Better code organization and maintainability
- Easier testing of individual components
- Clear separation between Evolve-specific and general node logic
- Reusable components for other projects
-
RollkitPayloadBuilder (
crates/node/src/builder.rs
)- Handles payload construction with transactions from Engine API
- Manages state execution and block assembly
-
RollkitEngineTypes (
bin/ev-reth/src/main.rs
)- Custom Engine API types supporting transaction attributes
- Payload validation and attribute processing
-
RollkitEngineValidator (
bin/ev-reth/src/main.rs
)- Modified validator for Rollkit-specific requirements
- Bypasses certain validations while maintaining security
-
Payload Builder Missing Payload Handling (
bin/ev-reth/src/builder.rs
)- Implements
on_missing_payload
to await in-progress payload builds - Prevents race conditions when multiple requests are made for the same payload
- Ensures deterministic payload generation without redundant builds
- Implements
-
RollkitConsensus (
crates/rollkit/src/consensus.rs
)- Custom consensus implementation for Rollkit
- Allows blocks with equal timestamps (parent.timestamp <= header.timestamp)
- Wraps standard Ethereum beacon consensus for other validations
-
Rollkit Types (
crates/rollkit/src/types.rs
)- Rollkit-specific payload attributes and types
- Transaction encoding/decoding utilities
-
Rollkit Txpool RPC (
crates/rollkit/src/rpc/txpool.rs
)- Custom RPC implementation for transaction pool queries
- Efficient transaction retrieval with size-based limits
- Returns RLP-encoded transaction bytes for Rollkit consumption
- Evolve submits transactions via Engine API payload attributes
RollkitEnginePayloadAttributes
decodes and validates transactionsRollkitPayloadBuilder
executes transactions and builds block- Block is returned via standard Engine API response
The payload builder can be configured with:
max_transactions
: Maximum transactions per block (default: 1000)min_gas_price
: Minimum gas price requirement (default: 1 Gwei)
The txpool RPC extension can be configured with:
max_txpool_bytes
: Maximum bytes of transactions to return (default: 1.85 MB)max_txpool_gas
: Maximum cumulative gas for transactions to return (default: 30,000,000)
Notes:
- Both limits apply together. Selection stops when either cap is reached.
- Set a limit to
0
to disable that constraint.
CLI/env overrides:
- None for txpool gas. The RPC follows the current block gas automatically.
- Block gas limit (per-block): Can be passed via Engine API payload attributes
gasLimit
. If omitted, ev-reth now defaults to the parent header’s gas limit (which is the genesis gas limit for the first block). The payload builder enforces this during execution and requires it to be > 0. - Txpool gas cap (RPC selection):
txpoolExt_getTxs
follows the current block gas limit automatically. There is no CLI/env override; this keeps txpool selection aligned with execution gas by default. - Relationship: These limits are aligned by default. Overriding the txpool cap makes them independent again; exact packing still depends on real execution.
Changing limits on a running chain:
- Per-block gas: Set
gasLimit
in Engine API payload attributes to change the block’s gas limit for that payload. Subsequent payloads will default to that new parent header gas limit unless overridden again. - Txpool gas cap: Follows the head block’s gas limit automatically. There is no fixed-cap override; change your block gas and the RPC alignment follows.
All standard Reth configuration options are supported. Key options for Rollkit integration:
--http
: Enable HTTP-RPC server--ws
: Enable WebSocket-RPC server--authrpc.port
: Engine API port (default: 8551)--authrpc.jwtsecret
: Path to JWT secret for Engine API authentication
ev-reth/
├── bin/
│ └── ev-reth/ # Main binary
│ ├── Cargo.toml
│ └── src/
│ └── main.rs # Binary with Engine API integration
├── crates/
│ ├── common/ # Shared utilities and constants
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs
│ │ └── constants.rs
│ ├── node/ # Core node implementation
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs
│ │ ├── builder.rs # Payload builder implementation
│ │ └── config.rs # Configuration types
│ ├── evolve/ # Evolve-specific types
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs
│ │ ├── config.rs # Evolve configuration
│ │ ├── consensus.rs # Custom consensus implementation
│ │ ├── types.rs # Evolve payload attributes
│ │ └── rpc/
│ │ ├── mod.rs
│ │ └── txpool.rs # Txpool RPC implementation
│ └── tests/ # Comprehensive test suite
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs
│ └── *.rs # Test files
├── etc/ # Configuration files
│ └── ev-reth-genesis.json # Genesis configuration
├── Cargo.toml # Workspace configuration
├── Makefile # Build automation
└── README.md # This file
# Run all tests
make test
# Run with verbose output
make test-verbose
# Run specific test
cargo test test_name
# Debug build
make build-dev
# Run with debug logs
make run-dev
-
Transaction Decoding Errors
- Ensure transactions are properly RLP-encoded
- Check that transaction format matches network requirements
-
Block Production Failures
- Verify gas limits are reasonable
- Check state availability for parent block
-
Engine API Connection Issues
- Ensure JWT secret is properly configured
- Verify Engine API port is accessible
Enable detailed logging:
RUST_LOG=debug,ev-reth=trace ./target/release/ev-reth node
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Submit a pull request
This project is dual-licensed under:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
This project builds upon the excellent work of: