diff --git a/.env.sample b/.env.sample index f7a87cd5..2137f510 100644 --- a/.env.sample +++ b/.env.sample @@ -1,10 +1,11 @@ ############################### DEFAULT ##################################### # Chain ID CHAIN_ID=167000 +NETWORK=taiko-mainnet # Exposed ports PORT_L2_EXECUTION_ENGINE_HTTP=8547 -PORT_L2_EXECUTION_ENGINE_WS=8548 +PORT_L2_EXECUTION_ENGINE_WS=8546 PORT_L2_EXECUTION_ENGINE_METRICS=6060 PORT_L2_EXECUTION_ENGINE_P2P=30306 PORT_PROVER_SERVER=9876 @@ -21,6 +22,14 @@ TAIKO_L1_ADDRESS=0x06a9Ab27c7e2255df1815E6CC0168d7755Feb19a TAIKO_TOKEN_L1_ADDRESS=0x10dea67478c5F8C5E2D90e5E9B26dBe60c54d800 TAIKO_L2_ADDRESS=0x1670000000000000000000000000000000010001 +# L2 Execution Engine Configuration +JWT="/data/jwt/secret" +# Options: taiko-geth or nethermind +L2_EXECUTION_ENGINE=taiko-geth +# L2_EXECUTION_ENGINE=nethermind +L2_EXECUTION_ENGINE_IMAGE=us-docker.pkg.dev/evmchain/images/taiko-geth:v1.11.1 +# L2_EXECUTION_ENGINE_IMAGE=nethermind/nethermind:1.30.1 + # P2P DISABLE_P2P_SYNC=false P2P_SYNC_URL=https://rpc.mainnet.taiko.xyz diff --git a/.env.sample.hekla b/.env.sample.hekla index 3115e1e3..d6af63e5 100644 --- a/.env.sample.hekla +++ b/.env.sample.hekla @@ -1,10 +1,11 @@ ############################### DEFAULT ##################################### # Chain ID CHAIN_ID=167009 +NETWORK=taiko-hekla # Exposed ports PORT_L2_EXECUTION_ENGINE_HTTP=8547 -PORT_L2_EXECUTION_ENGINE_WS=8548 +PORT_L2_EXECUTION_ENGINE_WS=8546 PORT_L2_EXECUTION_ENGINE_METRICS=6060 PORT_L2_EXECUTION_ENGINE_P2P=30306 PORT_PROVER_SERVER=9876 @@ -21,6 +22,14 @@ TAIKO_L1_ADDRESS=0x79C9109b764609df928d16fC4a91e9081F7e87DB TAIKO_TOKEN_L1_ADDRESS=0x6490E12d480549D333499236fF2Ba6676C296011 TAIKO_L2_ADDRESS=0x1670090000000000000000000000000000010001 +# L2 Execution Engine Configuration +JWT="/data/jwt/secret" +# Options: taiko-geth or nethermind +L2_EXECUTION_ENGINE=taiko-geth +# L2_EXECUTION_ENGINE=nethermind +L2_EXECUTION_ENGINE_IMAGE=us-docker.pkg.dev/evmchain/images/taiko-geth:v1.11.1 +# L2_EXECUTION_ENGINE_IMAGE=nethermind/nethermind:1.30.1 + # P2P DISABLE_P2P_SYNC=false P2P_SYNC_URL=https://rpc.hekla.taiko.xyz @@ -30,6 +39,7 @@ P2P_SYNC_URL=https://rpc.hekla.taiko.xyz # If you are using a local Holesky L1 node, you can refer to it as "http://host.docker.internal:8545" and "ws://host.docker.internal:8546", which refer to the default ports in the .env for an eth-docker L1 node. # However, you may need to add this host to docker-compose.yml. If that does not work, you can try the private local ip address (e.g. http://192.168.1.15:8545). You can find that with `ip addr show` or a similar command. # In addition, you can use your public ip address followed by the specific ports for http and ws (e.g. http://82.168.1.15:8545). You can find that with `hostname -I | awk '{print $1}'`. +L1_ENDPOINT_HTTP= L1_ENDPOINT_WS= # HTTP RPC endpoint of a L1 beacon node. Everything behind the top-level domain is ignored. Make sure you don't need to work with subdirectories. The path will always be /eth/v1... # If you are using a local Holesky L1 node, you can refer to it as "http://host.docker.internal:5052", which refer to the default REST port in the .env for an eth-docker L1 node. diff --git a/README.md b/README.md index 2545f7c1..8084002e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,56 @@ # simple-taiko-node Get started with the [guide](https://docs.taiko.xyz/guides/node-operators/run-a-taiko-node-with-docker/). + +## Setup Instructions + +1. Copy the appropriate .env sample file: + ```bash + # For regular setup + cp .env.sample .env + + # For Hekla testnet + cp .env.sample.hekla .env + ``` + +2. Configure the required L1 endpoints in your `.env` file: + ```env + # L1 endpoints (required) + L1_ENDPOINT_HTTP= # Your L1 HTTP endpoint + L1_ENDPOINT_WS= # Your L1 WebSocket endpoint + L1_BEACON_HTTP= # Your L1 Beacon node HTTP endpoint + ``` + + For the L1 Beacon endpoint: + - Local node example: `http://host.docker.internal:5052` + - Remote node example: `http://82.168.1.15:5052` + +3. Choose your L2 execution engine in the `.env` file: + + **Taiko-Geth** + ```env + L2_EXECUTION_ENGINE=taiko-geth + L2_EXECUTION_ENGINE_IMAGE=us-docker.pkg.dev/evmchain/images/taiko-geth:v1.11.1 + ``` + + **Nethermind** + ```env + L2_EXECUTION_ENGINE=nethermind + L2_EXECUTION_ENGINE_IMAGE=nethermind/nethermind:1.30.1 + ``` + +4. Start the node with docker-compose: + ```bash + # For regular setup + docker compose up + + # For Hekla testnet + docker compose -f docker-compose-hekla.yml up + ``` + +## Important Notes + +- The docker-compose configuration is unified for both execution engines +- The JWT secret for the execution engine is automatically managed by a dedicated initialization service +- The L1 beacon node endpoint should be configured with the correct protocol (http/https) and port +- All required endpoints must be properly configured in the `.env` file before starting the node diff --git a/docker-compose-hekla.yml b/docker-compose-hekla.yml index b64b65e1..69232b2b 100644 --- a/docker-compose-hekla.yml +++ b/docker-compose-hekla.yml @@ -5,44 +5,41 @@ x-logging: &logging max-file: "3" services: + jwt_init: + image: alpine + volumes: + - jwt_secret:/data/jwt + command: > + sh -c "mkdir -p /data/jwt && + if [ ! -f /data/jwt/secret ]; then + head -c 32 /dev/urandom | xxd -p -c 32 > /data/jwt/secret; + fi" + profiles: + - l2_execution_engine + l2_execution_engine: - image: us-docker.pkg.dev/evmchain/images/taiko-geth:v1.11.1 + image: ${L2_EXECUTION_ENGINE_IMAGE} restart: unless-stopped pull_policy: always + depends_on: + - jwt_init + env_file: + - .env stop_grace_period: 3m volumes: - - l2_execution_engine_data:/data/taiko-geth + - l2_execution_engine_data:/data + - ./script:/script + - jwt_secret:/data/jwt ports: - "${PORT_L2_EXECUTION_ENGINE_METRICS}:6060" - "${PORT_L2_EXECUTION_ENGINE_HTTP}:8545" - "${PORT_L2_EXECUTION_ENGINE_WS}:8546" - "${PORT_L2_EXECUTION_ENGINE_P2P}:${PORT_L2_EXECUTION_ENGINE_P2P}" - "${PORT_L2_EXECUTION_ENGINE_P2P}:${PORT_L2_EXECUTION_ENGINE_P2P}/udp" - command: | - --taiko - --networkid "${CHAIN_ID}" - --gcmode archive - --datadir /data/taiko-geth - --metrics - --metrics.expensive - --metrics.addr "0.0.0.0" - --bootnodes ${BOOT_NODES} - --authrpc.addr "0.0.0.0" - --authrpc.vhosts "*" - --http - --http.api debug,eth,net,web3,txpool,taiko - --http.addr "0.0.0.0" - --http.vhosts "*" - --ws - --ws.api debug,eth,net,web3,txpool,taiko - --ws.addr "0.0.0.0" - --ws.origins "*" - --gpo.ignoreprice "100000000" - --port ${PORT_L2_EXECUTION_ENGINE_P2P} - --discovery.port ${PORT_L2_EXECUTION_ENGINE_P2P} - --maxpeers ${MAXPEERS:-50} - --maxpendpeers ${MAXPENDPEERS:-0} - ${GETH_ADDITIONAL_ARGS:-} + entrypoint: + - /bin/sh + - -c + - "/script/start-l2-execution-engine.sh" <<: *logging profiles: - l2_execution_engine @@ -58,8 +55,9 @@ services: env_file: - .env volumes: - - l2_execution_engine_data:/data/taiko-geth + - l2_execution_engine_data:/data - ./script:/script + - jwt_secret:/data/jwt entrypoint: - /bin/sh - -c @@ -83,6 +81,7 @@ services: - .env volumes: - ./script:/script + - jwt_secret:/data/jwt entrypoint: - /bin/sh - -c @@ -101,8 +100,9 @@ services: env_file: - .env volumes: - - l2_execution_engine_data:/data/taiko-geth + - l2_execution_engine_data:/data - ./script:/script + - jwt_secret:/data/jwt entrypoint: - /bin/sh - -c @@ -158,3 +158,4 @@ volumes: l2_execution_engine_data: prometheus_data: grafana_data: + jwt_secret: diff --git a/docker-compose.yml b/docker-compose.yml index 6a977beb..3fcc8bbb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,50 +5,44 @@ x-logging: &logging max-file: "3" services: + jwt_init: + image: alpine + volumes: + - jwt_secret:/data/jwt + command: > + sh -c "mkdir -p /data/jwt && + if [ ! -f /data/jwt/secret ]; then + head -c 32 /dev/urandom | xxd -p -c 32 > /data/jwt/secret; + fi" + profiles: + - l2_execution_engine + l2_execution_engine: - image: us-docker.pkg.dev/evmchain/images/taiko-geth:v1.11.1 + image: ${L2_EXECUTION_ENGINE_IMAGE} restart: unless-stopped pull_policy: always + depends_on: + - jwt_init env_file: - .env stop_grace_period: 3m volumes: - - l2_execution_engine_data:/data/taiko-geth + - l2_execution_engine_data:/data + - ./script:/script + - jwt_secret:/data/jwt ports: - "${PORT_L2_EXECUTION_ENGINE_METRICS}:6060" - "${PORT_L2_EXECUTION_ENGINE_HTTP}:8545" - "${PORT_L2_EXECUTION_ENGINE_WS}:8546" - "${PORT_L2_EXECUTION_ENGINE_P2P}:${PORT_L2_EXECUTION_ENGINE_P2P}" - "${PORT_L2_EXECUTION_ENGINE_P2P}:${PORT_L2_EXECUTION_ENGINE_P2P}/udp" - command: | - --taiko - --networkid "${CHAIN_ID}" - --gcmode archive - --datadir /data/taiko-geth - --metrics - --metrics.addr "0.0.0.0" - --bootnodes ${BOOT_NODES} - --authrpc.addr "0.0.0.0" - --authrpc.vhosts "*" - --http - --http.api debug,eth,net,web3,txpool,taiko - --http.addr "0.0.0.0" - --http.vhosts "*" - --ws - --ws.api debug,eth,net,web3,txpool,taiko - --ws.addr "0.0.0.0" - --ws.origins "*" - --gpo.defaultprice "10000000" - --port ${PORT_L2_EXECUTION_ENGINE_P2P} - --discovery.port ${PORT_L2_EXECUTION_ENGINE_P2P} - --maxpeers ${MAXPEERS:-50} - --maxpendpeers ${MAXPENDPEERS:-0} - ${GETH_ADDITIONAL_ARGS:-} + entrypoint: + - /bin/sh + - -c + - "/script/start-l2-execution-engine.sh" <<: *logging profiles: - l2_execution_engine - - prover - - proposer taiko_client_driver: image: us-docker.pkg.dev/evmchain/images/taiko-client:taiko-client-v0.39.2 @@ -59,8 +53,9 @@ services: env_file: - .env volumes: - - l2_execution_engine_data:/data/taiko-geth + - l2_execution_engine_data:/data - ./script:/script + - jwt_secret:/data/jwt entrypoint: - /bin/sh - -c @@ -84,6 +79,7 @@ services: - .env volumes: - ./script:/script + - jwt_secret:/data/jwt entrypoint: - /bin/sh - -c @@ -102,8 +98,9 @@ services: env_file: - .env volumes: - - l2_execution_engine_data:/data/taiko-geth + - l2_execution_engine_data:/data - ./script:/script + - jwt_secret:/data/jwt entrypoint: - /bin/sh - -c @@ -159,3 +156,4 @@ volumes: l2_execution_engine_data: prometheus_data: grafana_data: + jwt_secret: \ No newline at end of file diff --git a/script/start-driver.sh b/script/start-driver.sh index 8ac2492e..28778650 100755 --- a/script/start-driver.sh +++ b/script/start-driver.sh @@ -10,7 +10,7 @@ if [ "$DISABLE_P2P_SYNC" = "false" ]; then --l2.auth http://l2_execution_engine:8551 \ --taikoL1 "${TAIKO_L1_ADDRESS}" \ --taikoL2 "${TAIKO_L2_ADDRESS}" \ - --jwtSecret /data/taiko-geth/geth/jwtsecret \ + --jwtSecret ${JWT} \ --p2p.sync \ --p2p.checkPointSyncUrl "${P2P_SYNC_URL}" else @@ -21,5 +21,5 @@ else --l2.auth http://l2_execution_engine:8551 \ --taikoL1 "${TAIKO_L1_ADDRESS}" \ --taikoL2 "${TAIKO_L2_ADDRESS}" \ - --jwtSecret /data/taiko-geth/geth/jwtsecret + --jwtSecret ${JWT} fi diff --git a/script/start-l2-execution-engine.sh b/script/start-l2-execution-engine.sh new file mode 100755 index 00000000..eaebe748 --- /dev/null +++ b/script/start-l2-execution-engine.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +if [ "$L2_EXECUTION_ENGINE" = "nethermind" ]; then + exec /nethermind/nethermind \ + --config ${NETWORK} \ + --datadir /data/nethermind \ + --JsonRpc.Enabled true \ + --JsonRpc.EnabledModules "Eth, Net, Parity, Personal, Proof, Rpc, Subscribe, Trace, TxPool, Web3, Taiko" \ + --Init.WebSocketsEnabled true \ + --JsonRpc.WebSocketsPort ${PORT_L2_EXECUTION_ENGINE_WS} \ + --JsonRpc.Host 0.0.0.0 \ + --JsonRpc.Port 8545 \ + --Network.DiscoveryPort "${PORT_L2_EXECUTION_ENGINE_P2P}" \ + --Network.P2PPort "${PORT_L2_EXECUTION_ENGINE_P2P}" \ + --JsonRpc.EngineHost 0.0.0.0 \ + --JsonRpc.EnginePort 8551 \ + --Network.MaxActivePeers "${MAXPEERS:-50}" \ + --Metrics.Enabled true \ + --Metrics.ExposePort 6060 \ + --JsonRpc.JwtSecretFile /data/jwt/secret +else + exec geth \ + --taiko \ + --networkid "${CHAIN_ID}" \ + --gcmode archive \ + --datadir /data/taiko-geth \ + --metrics \ + --metrics.addr "0.0.0.0" \ + --bootnodes ${BOOT_NODES} \ + --authrpc.addr "0.0.0.0" \ + --authrpc.vhosts "*" \ + --authrpc.jwtsecret /data/jwt/secret \ + --http \ + --http.api debug,eth,net,web3,txpool,taiko \ + --http.addr "0.0.0.0" \ + --http.vhosts "*" \ + --ws \ + --ws.api debug,eth,net,web3,txpool,taiko \ + --ws.addr "0.0.0.0" \ + --ws.port ${PORT_L2_EXECUTION_ENGINE_WS} \ + --ws.origins "*" \ + --gpo.defaultprice "10000000" \ + --port ${PORT_L2_EXECUTION_ENGINE_P2P} \ + --discovery.port ${PORT_L2_EXECUTION_ENGINE_P2P} \ + --maxpeers ${MAXPEERS:-50} \ + --maxpendpeers ${MAXPENDPEERS:-0} \ + ${GETH_ADDITIONAL_ARGS:-} +fi diff --git a/script/start-proposer-hekla.sh b/script/start-proposer-hekla.sh index c2aed559..d16ae647 100755 --- a/script/start-proposer-hekla.sh +++ b/script/start-proposer-hekla.sh @@ -9,7 +9,7 @@ if [ "$ENABLE_PROPOSER" = "true" ]; then --taikoL1 ${TAIKO_L1_ADDRESS} --taikoL2 ${TAIKO_L2_ADDRESS} --taikoToken ${TAIKO_TOKEN_L1_ADDRESS} - --jwtSecret /data/taiko-geth/geth/jwtsecret + --jwtSecret ${JWT} --l1.proposerPrivKey ${L1_PROPOSER_PRIVATE_KEY} --l2.suggestedFeeRecipient ${L2_SUGGESTED_FEE_RECIPIENT}" diff --git a/script/start-proposer.sh b/script/start-proposer.sh index fc5f1fd0..1af47587 100755 --- a/script/start-proposer.sh +++ b/script/start-proposer.sh @@ -9,7 +9,7 @@ if [ "$ENABLE_PROPOSER" = "true" ]; then --taikoL1 ${TAIKO_L1_ADDRESS} --taikoL2 ${TAIKO_L2_ADDRESS} --taikoToken ${TAIKO_TOKEN_L1_ADDRESS} - --jwtSecret /data/taiko-geth/geth/jwtsecret + --jwtSecret ${JWT} --l1.proposerPrivKey ${L1_PROPOSER_PRIVATE_KEY} --l2.suggestedFeeRecipient ${L2_SUGGESTED_FEE_RECIPIENT}"