diff --git a/.dockerignore b/.dockerignore index 5628ed55..927362b5 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1,3 @@ geth-data/ reth-data/ +nethermind-data/ diff --git a/.env.mainnet b/.env.mainnet index c1148691..4b64eaf8 100644 --- a/.env.mainnet +++ b/.env.mainnet @@ -4,6 +4,9 @@ OP_GETH_SEQUENCER_HTTP=https://mainnet-sequencer.base.org # [optional] used to enable geth stats: # OP_GETH_ETH_STATS=nodename:secret@host:port +# OP_NETHERMIND_ETHSTATS_ENABLED=true +# OP_NETHERMIND_ETHSTATS_NODE_NAME=NethermindNode +# OP_NETHERMIND_ETHSTATS_ENDPOINT=ethstats_endpoint # [required] replace with your preferred L1 (Ethereum, not Base) node RPC URL: OP_NODE_L1_ETH_RPC=https://1rpc.io/eth diff --git a/.env.sepolia b/.env.sepolia index 00e53513..c864cb11 100644 --- a/.env.sepolia +++ b/.env.sepolia @@ -4,6 +4,9 @@ OP_GETH_SEQUENCER_HTTP=https://sepolia-sequencer.base.org # [optional] used to enable geth stats: # OP_GETH_ETH_STATS=nodename:secret@host:port +# OP_NETHERMIND_ETHSTATS_ENABLED=true +# OP_NETHERMIND_ETHSTATS_NODE_NAME=NethermindNode +# OP_NETHERMIND_ETHSTATS_ENDPOINT=ethstats_endpoint # [required] replace with your preferred L1 (Ethereum, not Base) node RPC URL: OP_NODE_L1_ETH_RPC=https://rpc.sepolia.org diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index d7d4bf5d..3cb22cae 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -13,6 +13,7 @@ env: GETH_DEPRECATED_IMAGE_NAME: node GETH_IMAGE_NAME: node-geth RETH_IMAGE_NAME: node-reth + NETHERMIND_IMAGE_NAME: node-nethermind jobs: geth: @@ -87,3 +88,35 @@ jobs: build-args: | FEATURES=${{ matrix.features }} platforms: ${{ matrix.arch }} + nethermind: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Log into the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata for the Docker image + id: meta + uses: docker/metadata-action@v4 + with: + images: | + ${{ env.NAMESPACE }}/${{ env.NETHERMIND_IMAGE_NAME }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push the Docker image + uses: docker/build-push-action@v4 + with: + context: . + file: nethermind/Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + platforms: linux/amd64,linux/arm64 diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 3b2fc9fc..0cc659a8 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -48,3 +48,23 @@ jobs: build-args: | FEATURES=${{ matrix.features }} platforms: ${{ matrix.arch }} + nethermind: + runs-on: ubuntu-latest + strategy: + matrix: + arch: [ linux/amd64, linux/arm64 ] + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Build the Docker image + uses: docker/build-push-action@v4 + with: + context: . + file: nethermind/Dockerfile + push: false + platforms: ${{ matrix.arch }} + diff --git a/.gitignore b/.gitignore index b2f231e6..27ac158c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /.idea/ /geth-data/ /reth-data/ +/nethermind-data/ .DS_Store diff --git a/nethermind/Dockerfile b/nethermind/Dockerfile new file mode 100644 index 00000000..e4fbd297 --- /dev/null +++ b/nethermind/Dockerfile @@ -0,0 +1,46 @@ +FROM golang:1.21 AS op + +WORKDIR /app + +ENV REPO=https://github.com/ethereum-optimism/optimism.git +ENV VERSION=v1.9.1 +ENV COMMIT=4797ddb70e05d4952685bad53e608cb5606284e6 +RUN git clone $REPO --branch op-node/$VERSION --single-branch . && \ + git switch -c branch-$VERSION && \ + bash -c '[ "$(git rev-parse HEAD)" = "$COMMIT" ]' + +RUN cd op-node && \ + make VERSION=$VERSION op-node + +FROM mcr.microsoft.com/dotnet/sdk:8.0-noble AS build + +ARG BUILD_CONFIG=release +ARG TARGETARCH + +WORKDIR /app + +ENV REPO=https://github.com/nethermindeth/nethermind +ENV VERSION=1.28.0 +RUN git clone $REPO . && git checkout $VERSION + +RUN arch=$([ "$TARGETARCH" = "amd64" ] && echo "x64" || echo "$TARGETARCH") && \ + dotnet publish src/Nethermind/Nethermind.Runner -c $BUILD_CONFIG -a $arch -o /publish --sc false + + +FROM mcr.microsoft.com/dotnet/aspnet:8.0-noble + +RUN apt-get update && \ + apt-get install -y jq curl supervisor && \ + rm -rf /var/lib/apt/lists + +RUN mkdir -p /var/log/supervisor + +WORKDIR /app + +COPY --from=build /publish ./ +COPY --from=op /app/op-node/bin/op-node ./ +COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf +COPY nethermind/nethermind-entrypoint ./execution-entrypoint +COPY op-node-entrypoint . + +CMD ["/usr/bin/supervisord"] \ No newline at end of file diff --git a/nethermind/nethermind-entrypoint b/nethermind/nethermind-entrypoint new file mode 100644 index 00000000..b226c959 --- /dev/null +++ b/nethermind/nethermind-entrypoint @@ -0,0 +1,58 @@ +#!/bin/bash +set -eu + +# Default configurations +NETHERMIND_DATA_DIR=${NETHERMIND_DATA_DIR:-/data} +NETHERMIND_LOG_LEVEL=${NETHERMIND_LOG_LEVEL:-Info} +NETWORK=${NETWORK:-mainnet} + +RPC_PORT="${RPC_PORT:-8545}" +WS_PORT="${WS_PORT:-8546}" +AUTHRPC_PORT="${AUTHRPC_PORT:-8551}" +METRICS_PORT="${METRICS_PORT:-6060}" +DISCOVERY_PORT="${DISCOVERY_PORT:-30303}" + +JWT_SECRET_FILE=${JWT_SECRET_FILE:-/tmp/jwt/jwtsecret} +ADDITIONAL_ARGS="" + +# Check if required variables are set +if [[ -z "$NETWORK" ]]; then + echo "Expected NETWORK to be set" 1>&2 + exit 1 +fi + +# Create necessary directories +mkdir -p "$NETHERMIND_DATA_DIR" + +# Write the JWT secret +if [[ -z "${OP_NODE_L2_ENGINE_AUTH_RAW:-}" ]]; then + echo "Expected OP_NODE_L2_ENGINE_AUTH_RAW to be set" 1>&2 + exit 1 +fi +echo "$OP_NODE_L2_ENGINE_AUTH_RAW" > "$OP_NODE_L2_ENGINE_AUTH" + +# Additional arguments based on environment variables +if [[ -n "${OP_NETHERMIND_ETHSTATS_ENABLED:-}" ]]; then + ADDITIONAL_ARGS="$ADDITIONAL_ARGS --EthStats.Enabled=$OP_NETHERMIND_ETHSTATS_ENABLED" +fi + +if [[ -n "${OP_NETHERMIND_ETHSTATS_ENDPOINT:-}" ]]; then + ADDITIONAL_ARGS="$ADDITIONAL_ARGS --EthStats.NodeName=${OP_NETHERMIND_ETHSTATS_NODE_NAME:-NethermindNode} --EthStats.Endpoint=$OP_NETHERMIND_ETHSTATS_ENDPOINT" +fi + +# Execute Nethermind +exec ./nethermind \ + --config="$OP_NODE_NETWORK" \ + --datadir="$NETHERMIND_DATA_DIR" \ + --log="$NETHERMIND_LOG_LEVEL" \ + --JsonRpc.Enabled=true \ + --JsonRpc.Host=0.0.0.0 \ + --JsonRpc.WebSocketsPort="$WS_PORT" \ + --JsonRpc.Port="$RPC_PORT" \ + --JsonRpc.JwtSecretFile="$OP_NODE_L2_ENGINE_AUTH" \ + --JsonRpc.EngineHost=0.0.0.0 \ + --JsonRpc.EnginePort="$AUTHRPC_PORT" \ + --HealthChecks.Enabled=true \ + --Metrics.Enabled=true \ + --Metrics.ExposePort="$METRICS_PORT" \ + $ADDITIONAL_ARGS