From f6d095d39fc0b88587115c9b72914eac234dc4d7 Mon Sep 17 00:00:00 2001 From: Daniil Ankushin Date: Mon, 21 Apr 2025 10:39:40 +0400 Subject: [PATCH 1/5] feat(execution): add Nethermind as alternative client (#1) Add support for using Nethermind as an alternative execution client alongside op-geth --- .env.example | 12 ++++ README.md | 36 ++++++++++- docker-compose.yml | 32 ++++++++++ docker/dockerfiles/Dockerfile.nethermind | 11 ++++ envs/op-sepolia/nethermind.env | 12 ++++ scripts/start-op-nethermind.sh | 76 ++++++++++++++++++++++++ scripts/start-op-node.sh | 2 +- start.sh | 17 ++++++ 8 files changed, 195 insertions(+), 3 deletions(-) create mode 100644 docker/dockerfiles/Dockerfile.nethermind create mode 100644 envs/op-sepolia/nethermind.env create mode 100755 scripts/start-op-nethermind.sh create mode 100755 start.sh diff --git a/.env.example b/.env.example index 75bdf78..c7e9f3f 100644 --- a/.env.example +++ b/.env.example @@ -8,6 +8,18 @@ NETWORK_NAME=op-mainnet # Type of node to run ("full" or "archive"), note that "archive" is 10x bigger NODE_TYPE=full +# Execution client to use ("nethermind" or "op-geth") +EXECUTION_CLIENT=op-geth + +# Nethermind specific settings +NETHERMIND_DATA_DIR=/nethermind +NETHERMIND_LOG_LEVEL=Info +PORT__OP_NETHERMIND_HTTP=9995 +PORT__OP_NETHERMIND_WS=9996 +PORT__OP_NETHERMIND_AUTHRPC=8551 +PORT__OP_NETHERMIND_METRICS=6060 +PORT__OP_NETHERMIND_DISCOVERY=30303 + ############################################################################### # ↓ REQUIRED (BEDROCK) ↓ # ############################################################################### diff --git a/README.md b/README.md index 71971e7..5579817 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,11 @@ Open `.env` with your editor of choice * **NODE_TYPE** - Choose the type of node you want to run: * `full` (Full node) - A Full node contains a few recent blocks without historical states. * `archive` (Archive node) - An Archive node stores the complete history of the blockchain, including historical states. +* **EXECUTION_CLIENT** - Choose which execution client to use: + * `op-geth` - The original execution client for OP Stack (default) + * `nethermind` - Alternative high-performance execution client written in C# + + You can set this in your `.env` file or use it as an environment variable when running the `start.sh` script. * **OP_NODE__RPC_ENDPOINT** - Specify the endpoint for the RPC of Layer 1 (e.g., Ethereum mainnet). For instance, you can use the free plan of Alchemy for the Ethereum mainnet. * **OP_NODE__L1_BEACON** - Specify the beacon endpoint of Layer 1. You can use [QuickNode for the beacon endpoint](https://www.quicknode.com). For example: https://xxx-xxx-xxx.quiknode.pro/db55a3908ba7e4e5756319ffd71ec270b09a7dce * **OP_NODE__RPC_TYPE** - Specify the service provider for the RPC endpoint you've chosen in the previous step. The available options are: @@ -119,15 +124,42 @@ Open `.env` with your editor of choice * **IMAGE_TAG__[...]** - Use custom docker image for specified components. * **PORT__[...]** - Use custom port for specified components. +### Nethermind Configuration +When using Nethermind as the execution client, you can configure the following additional settings: + +* **NETHERMIND_DATA_DIR** - Directory where Nethermind stores its data (default: /nethermind) +* **NETHERMIND_LOG_LEVEL** - Logging level for Nethermind (default: Info) +* **PORT__OP_NETHERMIND_HTTP** - HTTP RPC port (default: 9995) +* **PORT__OP_NETHERMIND_WS** - WebSocket RPC port (default: 9996) +* **PORT__OP_NETHERMIND_AUTHRPC** - Engine API port (default: 8551) +* **PORT__OP_NETHERMIND_METRICS** - Metrics port (default: 6060) +* **PORT__OP_NETHERMIND_DISCOVERY** - P2P discovery port (default: 30303) + ## Operating the Node ### Start +You can start the node using the provided `start.sh` script: + ```sh -docker compose up -d --build +# Start with op-geth (default) +./start.sh + +# Start with Nethermind +EXECUTION_CLIENT=nethermind ./start.sh +``` + +Or using docker compose directly: + +```sh +# For op-geth +docker compose --profile op-geth up -d --build + +# For Nethermind +docker compose --profile nethermind up -d --build ``` -Will start the node in a detached shell (`-d`), meaning the node will continue to run in the background. We recommended to add `--build` to make sure that latest changes are being applied. +This will start the node in a detached shell (`-d`), meaning the node will continue to run in the background. We recommend adding `--build` to make sure that latest changes are being applied. ### View logs diff --git a/docker-compose.yml b/docker-compose.yml index 346bf3d..4111e50 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -32,6 +32,9 @@ services: restart: unless-stopped stop_grace_period: 5m entrypoint: /scripts/start-op-geth.sh + profiles: + - op-geth + - !nethermind env_file: - ./envs/${NETWORK_NAME}/op-geth.env - .env @@ -49,6 +52,34 @@ services: extra_hosts: - "host.docker.internal:host-gateway" + op-nethermind: + build: + context: . + dockerfile: docker/dockerfiles/Dockerfile.nethermind + restart: unless-stopped + stop_grace_period: 5m + profiles: + - nethermind + - !op-geth + env_file: + - ./envs/${NETWORK_NAME}/nethermind.env + - .env + volumes: + - ./scripts:/scripts:ro + - op_nethermind:/nethermind + - shared:/shared + - torrent_downloads:/downloads + - ./.upgrade-pectra:/upgrade-pectra + ports: + - ${PORT__OP_NETHERMIND_HTTP:-9995}:9995 + - ${PORT__OP_NETHERMIND_WS:-9996}:9996 + - ${PORT__OP_NETHERMIND_AUTHRPC:-8551}:8551 + - ${PORT__OP_NETHERMIND_METRICS:-6062}:6060 + - ${PORT__OP_NETHERMIND_DISCOVERY:-30303}:30303/udp + - ${PORT__OP_NETHERMIND_DISCOVERY:-30303}:30303/tcp + extra_hosts: + - "host.docker.internal:host-gateway" + op-node: image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-node:v1.13.0 restart: unless-stopped @@ -126,4 +157,5 @@ volumes: influxdb_data: shared: op_geth: + op_nethermind: torrent_downloads: diff --git a/docker/dockerfiles/Dockerfile.nethermind b/docker/dockerfiles/Dockerfile.nethermind new file mode 100644 index 0000000..a72b055 --- /dev/null +++ b/docker/dockerfiles/Dockerfile.nethermind @@ -0,0 +1,11 @@ +FROM nethermind/nethermind:1.31.6 + +# Install bash +RUN apt-get update && apt-get install -y bash + +# Copy and set up the startup script +COPY scripts/start-op-nethermind.sh /scripts/ +RUN chmod +x /scripts/start-op-nethermind.sh + +# Set the entrypoint to use bash +ENTRYPOINT ["/bin/bash", "/scripts/start-op-nethermind.sh"] \ No newline at end of file diff --git a/envs/op-sepolia/nethermind.env b/envs/op-sepolia/nethermind.env new file mode 100644 index 0000000..2ab5d37 --- /dev/null +++ b/envs/op-sepolia/nethermind.env @@ -0,0 +1,12 @@ +NETWORK_NAME=op-sepolia +BEDROCK_SEQUENCER_HTTP=https://sepolia-sequencer.optimism.io +NETHERMIND_LOG_LEVEL=Info +NODE_TYPE=full + +# Optional EthStats configuration +# OP_NETHERMIND_ETHSTATS_ENABLED=true +# OP_NETHERMIND_ETHSTATS_NODE_NAME=MyNethermindNode +# OP_NETHERMIND_ETHSTATS_ENDPOINT=ws://stats.optimism.io:3000 + +# Optional bootnode configuration +# OP_NETHERMIND_BOOTNODES=enode://... diff --git a/scripts/start-op-nethermind.sh b/scripts/start-op-nethermind.sh new file mode 100755 index 0000000..98bf2fa --- /dev/null +++ b/scripts/start-op-nethermind.sh @@ -0,0 +1,76 @@ +#!/bin/bash +set -e + +# Add debug information +echo "Debug: Checking Nethermind executable..." +ls -l /nethermind/Nethermind.Runner || echo "Nethermind.Runner not found in /nethermind/" +echo "Debug: Checking entire /nethermind directory..." +ls -la /nethermind/ || echo "/nethermind directory not found or empty" + +# Wait for the Bedrock flag for this network to be set. +echo "Waiting for Bedrock node to initialize..." +while [ ! -f /shared/initialized.txt ]; do + sleep 1 +done + +if [ ! -f /upgrade-pectra/upgraded ]; then + echo "Please upgrade to Pectra with upgrade-pectra.sh" + exit 1 +fi + +# Default configurations +NETHERMIND_DATA_DIR=${NETHERMIND_DATA_DIR:-/nethermind} +NETHERMIND_LOG_LEVEL=${NETHERMIND_LOG_LEVEL:-Info} + +# Use environment variables from .env +RPC_PORT="${PORT__OP_NETHERMIND_HTTP:-8545}" +WS_PORT="${PORT__OP_NETHERMIND_WS:-8546}" +AUTHRPC_PORT="${PORT__OP_NETHERMIND_AUTHRPC:-8551}" +METRICS_PORT="${PORT__OP_NETHERMIND_METRICS:-6060}" +DISCOVERY_PORT="${PORT__OP_NETHERMIND_DISCOVERY:-30303}" + +# Create necessary directories +mkdir -p "$NETHERMIND_DATA_DIR" + +# Additional arguments based on environment variables +ADDITIONAL_ARGS="" + +if [ -n "${OP_NETHERMIND_BOOTNODES:-}" ]; then + ADDITIONAL_ARGS="$ADDITIONAL_ARGS --Network.Bootnodes=$OP_NETHERMIND_BOOTNODES" +fi + +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 + +# Determine syncmode based on NODE_TYPE +if [ "$NODE_TYPE" = "full" ]; then + ADDITIONAL_ARGS="$ADDITIONAL_ARGS --Sync.FastSync=true" +else + ADDITIONAL_ARGS="$ADDITIONAL_ARGS --Sync.FastSync=false" +fi + +# Execute Nethermind with properly formatted arguments +exec /nethermind/Nethermind.Runner \ + --config "$NETWORK_NAME" \ + --datadir "$NETHERMIND_DATA_DIR" \ + --Optimism.SequencerUrl "$BEDROCK_SEQUENCER_HTTP" \ + --log "$NETHERMIND_LOG_LEVEL" \ + --JsonRpc.Enabled true \ + --JsonRpc.Host 0.0.0.0 \ + --JsonRpc.WebSocketsPort "$WS_PORT" \ + --JsonRpc.Port "$RPC_PORT" \ + --JsonRpc.JwtSecretFile /shared/jwt.txt \ + --JsonRpc.EngineHost 0.0.0.0 \ + --JsonRpc.EnginePort "$AUTHRPC_PORT" \ + --JsonRpc.EnabledModules "Web3,Eth,Subscribe,Net,Engine" \ + --Network.DiscoveryPort "$DISCOVERY_PORT" \ + --Network.P2PPort "$DISCOVERY_PORT" \ + --HealthChecks.Enabled true \ + --Metrics.Enabled true \ + --Metrics.ExposePort "$METRICS_PORT" \ + $ADDITIONAL_ARGS diff --git a/scripts/start-op-node.sh b/scripts/start-op-node.sh index c801b96..2c281fe 100755 --- a/scripts/start-op-node.sh +++ b/scripts/start-op-node.sh @@ -21,7 +21,7 @@ fi # Start op-node. exec op-node \ --l1=$OP_NODE__RPC_ENDPOINT \ - --l2=http://op-geth:8551 \ + --l2=http://${EXECUTION_CLIENT}:8551 \ --rpc.addr=0.0.0.0 \ --rpc.port=9545 \ --l2.jwt-secret=/shared/jwt.txt \ diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..7f76cec --- /dev/null +++ b/start.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# Get the execution client from env var or default to op-geth +CLIENT=${EXECUTION_CLIENT:-op-geth} + +# Map the client name to the correct profile +if [ "$CLIENT" = "nethermind" ]; then + PROFILE="nethermind" +else + PROFILE="op-geth" +fi + +# Stop any running containers and remove volumes +docker compose down -v + +# Start with the appropriate profile +docker compose --profile $PROFILE up -d --build From ac51a1e3f2d6cff4959d3df9a5df9280c26aa274 Mon Sep 17 00:00:00 2001 From: Daniil Ankushin Date: Wed, 23 Apr 2025 10:11:21 +0300 Subject: [PATCH 2/5] Update scripts/start-op-nethermind.sh Co-authored-by: Ruben Buniatyan --- scripts/start-op-nethermind.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/start-op-nethermind.sh b/scripts/start-op-nethermind.sh index 98bf2fa..fb34c1c 100755 --- a/scripts/start-op-nethermind.sh +++ b/scripts/start-op-nethermind.sh @@ -55,7 +55,7 @@ else fi # Execute Nethermind with properly formatted arguments -exec /nethermind/Nethermind.Runner \ +exec /nethermind/nethermind \ --config "$NETWORK_NAME" \ --datadir "$NETHERMIND_DATA_DIR" \ --Optimism.SequencerUrl "$BEDROCK_SEQUENCER_HTTP" \ From 996f64617bea5cb67976328c9764edb0397787f8 Mon Sep 17 00:00:00 2001 From: Daniil Ankushin Date: Wed, 23 Apr 2025 10:12:45 +0300 Subject: [PATCH 3/5] Update scripts/start-op-nethermind.sh Co-authored-by: Ruben Buniatyan --- scripts/start-op-nethermind.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/start-op-nethermind.sh b/scripts/start-op-nethermind.sh index fb34c1c..b0f80d7 100755 --- a/scripts/start-op-nethermind.sh +++ b/scripts/start-op-nethermind.sh @@ -3,7 +3,7 @@ set -e # Add debug information echo "Debug: Checking Nethermind executable..." -ls -l /nethermind/Nethermind.Runner || echo "Nethermind.Runner not found in /nethermind/" +ls -l /nethermind/nethermind || echo "nethermind not found in /nethermind/" echo "Debug: Checking entire /nethermind directory..." ls -la /nethermind/ || echo "/nethermind directory not found or empty" From 9d01ca01a188ba96079c6bc10be7a2bc3265f13f Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Mon, 28 Apr 2025 16:00:42 +0400 Subject: [PATCH 4/5] refactor(compose): simplify profile handling and cleanup scripts Removed `start.sh` script in favor of dynamic profile selection via `COMPOSE_PROFILES` environment variable. Updated `.env.example` and `docker-compose.yml` to reflect the new approach, reducing complexity and improving maintainability. --- .env.example | 1 + docker-compose.yml | 3 +-- start.sh | 17 ----------------- 3 files changed, 2 insertions(+), 19 deletions(-) delete mode 100755 start.sh diff --git a/.env.example b/.env.example index c7e9f3f..8f1ddb3 100644 --- a/.env.example +++ b/.env.example @@ -10,6 +10,7 @@ NODE_TYPE=full # Execution client to use ("nethermind" or "op-geth") EXECUTION_CLIENT=op-geth +COMPOSE_PROFILES=${EXECUTION_CLIENT:-default} # Nethermind specific settings NETHERMIND_DATA_DIR=/nethermind diff --git a/docker-compose.yml b/docker-compose.yml index 2f43fa3..fbd007b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -33,8 +33,8 @@ services: stop_grace_period: 5m entrypoint: /scripts/start-op-geth.sh profiles: + - default - op-geth - - !nethermind env_file: - ./envs/${NETWORK_NAME}/op-geth.env - .env @@ -60,7 +60,6 @@ services: stop_grace_period: 5m profiles: - nethermind - - !op-geth env_file: - ./envs/${NETWORK_NAME}/nethermind.env - .env diff --git a/start.sh b/start.sh deleted file mode 100755 index 7f76cec..0000000 --- a/start.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -# Get the execution client from env var or default to op-geth -CLIENT=${EXECUTION_CLIENT:-op-geth} - -# Map the client name to the correct profile -if [ "$CLIENT" = "nethermind" ]; then - PROFILE="nethermind" -else - PROFILE="op-geth" -fi - -# Stop any running containers and remove volumes -docker compose down -v - -# Start with the appropriate profile -docker compose --profile $PROFILE up -d --build From b75ba8053b7121f9c7024f375914f8b76d00176c Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Mon, 28 Apr 2025 16:15:03 +0400 Subject: [PATCH 5/5] Update README --- README.md | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/README.md b/README.md index 5579817..70c6be8 100644 --- a/README.md +++ b/README.md @@ -139,27 +139,8 @@ When using Nethermind as the execution client, you can configure the following a ### Start -You can start the node using the provided `start.sh` script: - -```sh -# Start with op-geth (default) -./start.sh - -# Start with Nethermind -EXECUTION_CLIENT=nethermind ./start.sh -``` - -Or using docker compose directly: - ```sh -# For op-geth -docker compose --profile op-geth up -d --build - -# For Nethermind -docker compose --profile nethermind up -d --build -``` - -This will start the node in a detached shell (`-d`), meaning the node will continue to run in the background. We recommend adding `--build` to make sure that latest changes are being applied. +docker compose up -d --build ### View logs