Bridging Ethereum Consensus Layer gossip with the RLNC-enhanced mump2p mesh — for faster block & attestation propagation.
Security: see
SECURITY.mdfor the trust model, the listener inventory with default binds and auth gates, and how to report vulnerabilities.
The Optimum Gateway (OG) connects an Ethereum Consensus Layer (CL) client to the
mump2p mesh — a libp2p network running the RLNC-enhanced mump2p protocol.
It acts as:
- a subscriber to Ethereum libp2p gossip topics (
/eth2/<fork_digest>/.../ssz_snappy); - a publisher/forwarder of that traffic into the mump2p mesh; and
- a receiver of
mump2pmessages, re-encoding and re-injecting them into the local CL libp2p network.
The result is reduced propagation delay, improved validator rewards, and cross-network latency telemetry — with no changes required to the CL client (it just peers with the gateway).
flowchart LR
CL["Ethereum CL client<br/>(Prysm / Grandine)"]
subgraph GW["Optimum Gateway"]
direction TB
LP["libp2p host<br/>:33212 (CL-facing)"]
CORE["dedup TTL cache<br/>+ SSZ re-encode"]
MP["mump2p host<br/>:33213 (mesh)"]
LP <--> CORE <--> MP
end
MESH["Other gateways<br/>mump2p mesh"]
CL <-->|"gossip (ssz_snappy)"| LP
MP <-->|"RLNC mump2p"| MESH
classDef ext fill:#eef,stroke:#88a,color:#225;
class CL,BS,RLNC,MESH,OBS ext;
- The gateway subscribes to the configured CL gossip topics via its local libp2p host.
- Each message is fingerprinted (fast XXHash) and stored in a short TTL cache (≈1 min) for dedup.
- The message is forwarded to connected mump2p peers (with optional aggregation batching for non-block topics).
- A
mump2pmessage arrives from a local or remote mump2p peer. - If its hash is already in the TTL cache, it is ignored; otherwise it is SSZ-decoded.
- It is re-encoded and published to the local libp2p network for CL propagation, and telemetry is recorded.
The simplest path is the bundled Compose file, which starts both:
docker compose -f docker-compose-local.yml upTo run the gateway image directly:
docker run --name optimum-gateway --rm \
-p 33212:33212/tcp \
-p 33213:33213/tcp \
-p 48123:48123/tcp \
-v $(pwd)/config:/app/config \
-v $(pwd)/data/libp2p:/tmp/libp2p \
-v $(pwd)/data/mump2p:/tmp/mump2p \
getoptimum/gateway:v1.1.1 \
-config=/app/config/app_conf.ymlagent_mump2p_port (default 33213) must be reachable by other gateways in the mesh.
Requires Go 1.26+.
git clone https://github.com/getoptimum/optimum-gateway
cd optimum-gateway
cp config/sample.app_conf.yml config/app_conf.yml
make build # builds ./bin/optimum-gateway
make run # go run cmd/main.go -config config/app_conf.ymlFetch the gateway peer info and point your beacon node at it:
curl -s http://localhost:48123/api/v1/self_info | jq '{peer_id, multiaddrs: .libp2p.multiaddrs}'# Example Prysm flag
--peer=/ip4/<YOUR_GATEWAY_IP>/tcp/33212/p2p/<YOUR_GATEWAY_PEER_ID>See config/sample.app_conf.yml for the full reference.
The gateway is configured via a YAML file (config/app_conf.yml) or environment
variables; env vars override YAML. A minimal config:
api_key: ogw_live_**** # given by optimum team
gateway_cluster_id: **** # given by optimum team
log_level: info
chain: hoodi # or: mainnet
identity_libp2p_dir: /tmp/libp2p
identity_mump2p_dir: /tmp/mump2p
agent_lib_p2p_port: 33212 # CL-facing libp2p
agent_mump2p_port: 33213 # mump2p mesh (gateway-to-gateway)
telemetry_enable: true
telemetry_port: 48123
See config/sample.app_conf.yml and guide.md for the full reference.
The gateway exposes an HTTP server on telemetry_port (default 48123):
| Endpoint | Description |
|---|---|
GET /health |
Structured health check (CL peers, mesh peers, subscribed topics, last block age) — returns 200/503 for load balancers. |
GET /api/v1/self_info |
Peer info: peer_id, multiaddrs, fork digest, chain, peer counts, version/commit. |
GET /metrics |
Prometheus metrics (only when telemetry_enable: true). |
GET / |
Liveness root. |
curl -s http://localhost:48123/health | jq
curl -s http://localhost:48123/api/v1/self_info | jq '.mump2p.total_peers'Generate an identity and run a CL client locally against the gateway:
go run cmd/generate_identity/main.go
curl https://raw.githubusercontent.com/OffchainLabs/prysm/master/prysm.sh --output prysm.sh && chmod +x prysm.sh && ./prysm.sh beacon-chain generate-auth-secret
mv jwt.hex /home/<USER>/local_cl/local_eth/jwt
make run_cl # brings up the CL dependency via docker composeRun Prysm as a binary against Hoodi (sync from a checkpoint):
cd prysm
go run ./cmd/beacon-chain/ \
--execution-endpoint=http://0.0.0.0:8551 --hoodi \
--jwt-secret=/home/<USER>/local_cl/local_eth/jwt/jwt.hex \
--checkpoint-sync-url=https://hoodi.beaconstate.info \
--genesis-beacon-api-url=https://hoodi.beaconstate.info \
--peer=<GATEWAY_MULTIADDRESS> --accept-terms-of-useFor debugging Prysm from source, patch the flags noted in guide.md and run the TestGatewayReal integration test.
make help # list all targets
make build # build the binary
make test # unit + integration tests with coverage
make lint # golangci-lint
make vulcheck # govulncheck (with documented exception list)See docs/contributing.md. Please run make lint and
make test before opening a PR, and report security issues privately per
SECURITY.md rather than via public issues.
Source is provided under the MIT License: see LICENSE.
The MIT License grants copyright permissions only and grants no rights under any
patent. PATENTS lists patents and patent applications licensed to
Spice Solutions Inc. by CodeOn; operating this software may involve practicing
patented technology, and any patent rights you require must be obtained from the
relevant patent holder directly. Third-party dependencies are inventoried in
THIRD-PARTY-NOTICES.md with attributions in
NOTICE.
