Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ cover.out

# CI/CD and development files
.github/
Makefile
docker-compose*.yml

# Test data
Expand Down
10 changes: 6 additions & 4 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ env:

on:
push:
branches:
- development
tags:
- v*

Expand Down Expand Up @@ -218,20 +220,20 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Generate token for infrastructure dispatch (main)
id: infra-dispatch-token-main
- name: Generate token for infrastructure dispatch (development)
id: infra-dispatch-token-dev
uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2
with:
app-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
owner: getoptimum
repositories: infrastructure

- name: Trigger Ansible deploy (main)
- name: Trigger Ansible deploy (development)
run: |
gh api repos/getoptimum/infrastructure/dispatches \
-f event_type=deploy_gateways \
-f "client_payload[tag]=dev-latest" \
-f "client_payload[digest]=${{ needs.docker.outputs.digest }}"
env:
GH_TOKEN: ${{ steps.infra-dispatch-token-main.outputs.token }}
GH_TOKEN: ${{ steps.infra-dispatch-token-dev.outputs.token }}
7 changes: 6 additions & 1 deletion .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ jobs:
go-version: ${{ env.go-version }}
- name: Install dependencies
run: go mod download
- name: Run rlnc-server
run: |
make run-rlnc-server &
timeout 120s bash -c 'until compgen -G "/dev/shm/go_shm_rlnc_semaphore_mump2p-protocol_lane*" >/dev/null; do
sleep 1; done'
- name: Run tests
run: CI_RUN="true" PROMETHEUS_VALIDATION_SCHEME=legacy make test
- name: Measure test coverage
Expand All @@ -92,4 +97,4 @@ jobs:
continue-on-error: true # first run requires the repo wiki to be initialized once
uses: ncruces/go-coverage-report@dfc237255099f2d25066babde51253992175e365 # v0.3.2
with:
coverage-file: cover.out
coverage-file: cover.out
2 changes: 1 addition & 1 deletion .github/workflows/security-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ jobs:
owner: getoptimum
# Scoped to this repo (push target) plus the private module deps that
# `go` must fetch to build the branch-tip SBOM, not the whole org.
repositories: optimum-gateway,optimum-common,optimum-p2p,rlnc
repositories: optimum-gateway,optimum-common,optimum-p2p,mump2p-protocol,rlnc,shm
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
ref: ${{ github.head_ref }}
Expand Down
26 changes: 16 additions & 10 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Project Overview

**Optimum Gateway** is a single-process gossipsub relay that bridges Ethereum Consensus Layer (CL) libp2p traffic with the mump2p mesh. It:
**Optimum Gateway** is a gossipsub relay that bridges Ethereum Consensus Layer (CL) libp2p traffic with the mump2p mesh. The gateway process uses a required local `rlnc-server` companion for RLNC coding over shared memory. It:

- Subscribes to Ethereum gossip topics (via local libp2p)
- Forwards messages to mump2p peers
Expand All @@ -19,6 +19,7 @@ cmd/main.go
├── gossipsub_gateway.Service (Main relay; runs two p2p loops)
│ ├── libp2p host + subscriptions (CL-side gossipsub)
│ ├── mum_p2p.Node (mump2p-side mesh; pkg/service/mum_p2p)
│ │ └── SHM client (local rlnc-server; 20 lanes named mump2p-protocol)
│ ├── aggregator.Service (Batch attestations into containers)
│ └── channels: clMessages, mumP2PMessages
├── telemetry service (Prometheus, Loki, Mimir pushers)
Expand All @@ -38,13 +39,17 @@ cmd/main.go

```bash
make build # Builds into ./bin/optimum-gateway
make build-rlnc-server # Builds the required ./bin/rlnc-server companion
make run-rlnc-server # Runs the RLNC shared-memory server
make run # go run cmd/main.go -config config/app_conf.yml
make test # Go test suite; coverage is reported here, threshold checked by make coverage
make lint # Installs/runs golangci-lint on ./... (see Makefile)
make proto # Regenerate Go from .proto files
make vulcheck # govulncheck with hardcoded exception list
```

Keep `make run-rlnc-server` running in a separate terminal before `make run` or `make test`. The run target builds the RLNC server on first use.

### Proto & Code Generation

Proto files define gRPC and aggregation messages:
Expand Down Expand Up @@ -124,14 +129,15 @@ Gateway calls `filterAndBuildEthTopics()` to expand shorts into fulls using fork
## Integration Points & Dependencies


| Dependency | Purpose | Notes |
| ------------------------------------ | ---------------------------------------------------- | ----------------------------------------------- |
| github.com/libp2p/go-libp2p | libp2p host & gossipsub | Local CL peering |
| github.com/getoptimum/optimum-p2p | mump2p gossipsub (RLNC) | Used by `pkg/service/mum_p2p` |
| github.com/getoptimum/optimum-common | Shared types, logger, config | Utilities, auth claims |
| github.com/libp2p/go-libp2p-kad-dht | mump2p peer discovery | Used by `pkg/service/mum_p2p/dhtdiscovery` |
| github.com/prometheus/client_golang | Metrics export | Local Prometheus scrape |
| github.com/gofiber/fiber/v3 | HTTP API | `/`, `/api/v1/self_info`, `/metrics`, `/health` |
| Dependency | Purpose | Notes |
| --------------------------------------- | ---------------------------------------- | -------------------------------------------------------- |
| github.com/libp2p/go-libp2p | libp2p host & gossipsub | Local CL peering |
| github.com/getoptimum/mump2p-protocol | RLNC-enabled mump2p pubsub and SHM client | Used by `pkg/service/mum_p2p` |
| github.com/getoptimum/rlnc | RLNC shared-memory server | Built by `make build-rlnc-server` |
| github.com/getoptimum/optimum-common | Shared types, logger, config | Utilities, auth claims |
| github.com/libp2p/go-libp2p-kad-dht | mump2p peer discovery | Used by `pkg/service/mum_p2p/dhtdiscovery` |
| github.com/prometheus/client_golang | Metrics export | Local Prometheus scrape |
| github.com/gofiber/fiber/v3 | HTTP API | `/`, `/api/v1/self_info`, `/metrics`, `/health` |


## Security Trust Model
Expand Down Expand Up @@ -382,4 +388,4 @@ Your implementation must make the codebase better in the narrowest way needed to
Write less.
Change less.
Break less.
Explain exactly what changed.
Explain exactly what changed.
10 changes: 8 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ FROM --platform=$BUILDPLATFORM golang:1.26.6-alpine AS builder
ARG TARGETPLATFORM
ARG BUILDPLATFORM

RUN apk add --no-cache build-base git clang lld openssh-client
RUN apk add --no-cache build-base git clang lld openssh-client bash

COPY --from=xx / /

Expand Down Expand Up @@ -46,6 +46,8 @@ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \
go build -o /gateway/optimum-gateway ./cmd

RUN make RLNC_SERVER_OUTPUT=/gateway/bin/rlnc-server build-rlnc-server

FROM alpine:3.22

RUN apk upgrade --no-cache && \
Expand All @@ -61,12 +63,16 @@ WORKDIR /gateway
RUN mkdir -p /gateway/logs

COPY --from=builder /gateway/optimum-gateway /optimum-gateway
COPY --from=builder /gateway/bin/rlnc-server /rlnc-server
COPY --from=builder /optimum-gateway/docker-entrypoint.sh /docker-entrypoint.sh

# License, patent marking and third-party attribution shipped with the binary.
COPY --from=builder /optimum-gateway/LICENSE /optimum-gateway/NOTICE /optimum-gateway/PATENTS /optimum-gateway/THIRD-PARTY-NOTICES.md /usr/share/doc/optimum-gateway/

# USER gateway
#RUN /rlnc-server --lanes 20 --name mump2p-protocol &

EXPOSE 33212 33213 48123

ENTRYPOINT ["/optimum-gateway"]
RUN chmod +x /docker-entrypoint.sh
ENTRYPOINT ["/docker-entrypoint.sh"]
26 changes: 22 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ COVERAGE_PASS_THRESHOLD := $(shell echo "$(COVERAGE_TOTAL) $(COVERAGE_THRESHOLD)
# (#955/#951) so the impact is bounded. Rationale in govulncheck.yaml and #924.
VULN_EXCEPTION_NAMES := ["GO-2024-3218"]

RLNC_VERSION ?= v0.10.0
RLNC_REPOSITORY ?= https://github.com/getoptimum/rlnc.git
RLNC_SERVER_OUTPUT ?= ./bin/rlnc-server

GO_LICENSES_RUN := go run github.com/google/go-licenses@v1.6.0
CYCLONEDX_RUN := go run github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod@v1.10.0

help: ## Show help
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

Expand Down Expand Up @@ -66,8 +73,19 @@ build: ## Builds binary
@echo "-- building binary"
go build -o ./bin/optimum-gateway ./cmd

GO_LICENSES_RUN := go run github.com/google/go-licenses@v1.6.0
CYCLONEDX_RUN := go run github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod@v1.10.0
build-rlnc-server:
rm -rf /tmp/rlnc
git clone --depth 1 --branch "$(RLNC_VERSION)" "$(RLNC_REPOSITORY)" /tmp/rlnc
echo "⚙️ Building RLNC server binary...";
(cd "/tmp/rlnc" && CGO_ENABLED=1 go build -ldflags "-linkmode=external" -o "$(abspath $(RLNC_SERVER_OUTPUT))" ./cmd/rlnc-server);
echo "✅ RLNC server built at $(abspath $(RLNC_SERVER_OUTPUT))"

run-rlnc-server: ## Run RLNC server. if binary not exist it will build it first
@echo "-- running rlnc-server"
@if [ ! -f "./bin/rlnc-server" ]; then \
$(MAKE) build-rlnc-server; \
fi
./bin/rlnc-server --lanes 20 --name mump2p-protocol

license-check: ## Check shipped binary (./cmd) deps for strong copyleft (strict)
@echo "Running license check (shipped binary)..."
Expand Down Expand Up @@ -131,6 +149,6 @@ fastssz-generate: ## Vendor fastssz spectests SSZ types into pkg/protocol/fastss
@rm -f pkg/protocol/fastssz_codegen/*_test.go pkg/protocol/fastssz_codegen/cmp.go
@echo "fastssz code vendored at pkg/protocol/fastssz_codegen/"

.PHONY: fastssz-generate
.PHONY: help test lint coverage vulcheck build deps proto run run_cl build_hermes_image run_gateway_with_sidecar license-check license-check-test notices sbom sbom-binary sbom-full
.PHONY: help test lint coverage vulcheck build deps proto run run_cl build_hermes_image run_gateway_with_sidecar
.PHONY: license-check license-check-test notices sbom sbom-binary sbom-full build-rlnc-server fastssz-generate run-rlnc-server
.DEFAULT_GOAL := help
31 changes: 22 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,19 @@ flowchart LR
LP <--> CORE <--> MP
end

RLNC["Local rlnc-server<br/>20 shared-memory lanes"]
MESH["Other gateways<br/>mump2p mesh"]

CL <-->|"gossip (ssz_snappy)"| LP
MP <-->|"shared memory"| RLNC
MP <-->|"RLNC mump2p"| MESH

classDef ext fill:#eef,stroke:#88a,color:#225;
class CL,BS,RLNC,MESH,OBS ext;
class CL,RLNC,MESH ext;
```

The gateway uses `mump2p-protocol` for RLNC-enabled pubsub and delegates RLNC coding to the required local `rlnc-server` process over shared memory.

### Message flow

#### Ethereum CL → mump2p mesh
Expand Down Expand Up @@ -105,14 +109,19 @@ docker run --name optimum-gateway --rm \

### Run from source

Requires **Go 1.26+**.
Requires **Go 1.26+**, Git, and a working CGO/C toolchain.

```sh
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.yml
make build # builds ./bin/optimum-gateway

# terminal 1; builds ./bin/rlnc-server on first use
make run-rlnc-server

# terminal 2
make run # go run cmd/main.go -config config/app_conf.yml
```

### Connect your CL client
Expand Down Expand Up @@ -195,13 +204,17 @@ For debugging Prysm from source, patch the flags noted in [`guide.md`](guide.md)
## Make targets

```sh
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)
make help # list all targets
make build # build the gateway binary
make build-rlnc-server # build ./bin/rlnc-server from getoptimum/rlnc
make run-rlnc-server # run the required local RLNC shared-memory server
make test # unit + integration tests with coverage
make lint # golangci-lint
make vulcheck # govulncheck (with documented exception list)
```

Keep `make run-rlnc-server` running in a separate terminal before `make run` or `make test`.

## Documentation

- [Integration guide for validators](guide.md)
Expand Down
Loading
Loading