diff --git a/chain/ev-node.genesis.json b/chain/ev-node.genesis.json index 597f7f0..3760e9f 100644 --- a/chain/ev-node.genesis.json +++ b/chain/ev-node.genesis.json @@ -3,5 +3,6 @@ "start_time": "2025-09-09T10:50:02.349087636Z", "initial_height": 1, "proposer_address": "N89c6gm4fP8oW7OxEtHft7b7PFu8BRzrqkPRzVH04dA=", - "da_start_height": 7970386 + "da_start_height": 7970386, + "da_epoch_forced_inclusion": 50 } diff --git a/deployment/README.md b/deployment/README.md index 0bb27c0..23418bf 100644 --- a/deployment/README.md +++ b/deployment/README.md @@ -101,3 +101,14 @@ docker compose logs -f docker compose logs -f ev-node docker compose logs -f ev-reth ``` + +## Second Full Node + ev-reth + +The `ev-node-2` service runs as a full node with its own `ev-reth-2` instance and syncs from `ev-node` over P2P. Note: full nodes still require a working DA endpoint. + +1) Start the stack and follow logs (the peer address is discovered via `evm net-info` on startup): + +```bash +docker compose up -d ev-node-2 +docker compose logs -f ev-node-2 +``` diff --git a/deployment/docker-compose/.env b/deployment/docker-compose/.env index 8fd16e7..e0cae49 100644 --- a/deployment/docker-compose/.env +++ b/deployment/docker-compose/.env @@ -17,4 +17,12 @@ EV_RETH_WS_PORT="8546" EV_NODE_P2P_PORT="7676" EV_NODE_PROMETHEUS_PORT="26660" EV_NODE_RPC_PORT="7331" -DA_ADDRESS="" \ No newline at end of file +DA_ADDRESS="" +EV_RETH_2_PROMETHEUS_PORT="9002" +EV_RETH_2_ENGINE_PORT="8552" +EV_RETH_2_DISCOVERY_PORT="30304" +EV_RETH_2_RPC_PORT="8547" +EV_RETH_2_WS_PORT="8548" +EV_NODE_2_P2P_PORT="7677" +EV_NODE_2_PROMETHEUS_PORT="26661" +EV_NODE_2_RPC_PORT="7332" diff --git a/deployment/docker-compose/.gitignore b/deployment/docker-compose/.gitignore new file mode 100644 index 0000000..b28a2ad --- /dev/null +++ b/deployment/docker-compose/.gitignore @@ -0,0 +1,3 @@ +data/ +/data +/snapshots diff --git a/deployment/docker-compose/compose.yaml b/deployment/docker-compose/compose.yaml index 9d81e3b..a26fc5c 100644 --- a/deployment/docker-compose/compose.yaml +++ b/deployment/docker-compose/compose.yaml @@ -22,7 +22,8 @@ services: volumes: - ./ev-reth.genesis.json:/root/genesis.json:ro - jwttoken:/root/jwt:ro - - ev-reth-data:/root/reth + - ./data/ev-reth:/root/reth + - ./snapshots:/snapshots - ./init-1-ev-reth-snapshot.sh:/init-1-ev-reth-snapshot.sh entrypoint: [/bin/sh, /init-1-ev-reth-snapshot.sh] restart: "no" @@ -34,7 +35,7 @@ services: image: &image ghcr.io/evstack/ev-node-evm-single:v1.0.0-beta.11 env_file: .env volumes: - - ev-node-data:/root/.evm + - ./data/ev-node:/root/.evm - ./ev-node.genesis.json:/volumes/sequencer_export/genesis.json:ro - ./ev-reth.genesis.json:/root/genesis.json:ro - jwttoken:/root/jwt:ro @@ -46,10 +47,11 @@ services: image: *alpine env_file: .env volumes: - - ev-node-data:/root/.evm + - ./data/ev-node:/root/.evm - ./ev-node.genesis.json:/volumes/sequencer_export/genesis.json:ro - ./ev-reth.genesis.json:/root/genesis.json:ro - jwttoken:/root/jwt:ro + - ./snapshots:/snapshots - ./init-2-ev-node-snapshot.sh:/init-2-ev-node-snapshot.sh entrypoint: [/bin/bash, /init-2-ev-node-snapshot.sh] restart: "no" @@ -70,7 +72,7 @@ services: volumes: - ./ev-reth.genesis.json:/root/genesis.json:ro - jwttoken:/root/jwt:ro - - ev-reth-data:/root/reth + - ./data/ev-reth:/root/reth entrypoint: /bin/sh -c command: - | @@ -116,8 +118,67 @@ services: retries: 3 start_period: 30s +# ev-reth-2: +# image: ghcr.io/evstack/ev-reth:v0.2.1 +# depends_on: +# jwt-init: +# condition: service_completed_successfully +# init-1-snapshot-ev-reth: +# condition: service_completed_successfully +# env_file: .env +# network_mode: host +# restart: always +# volumes: +# - ./ev-reth.genesis.json:/root/genesis.json:ro +# - jwttoken:/root/jwt:ro +# - ./data/ev-reth-2:/root/reth +# entrypoint: /bin/sh -c +# command: +# - | +# ev-reth node \ +# --engine.persistence-threshold 0 \ +# --engine.memory-block-buffer-target 0 \ +# --engine.always-process-payload-attributes-on-canonical-head \ +# --chain /root/genesis.json \ +# --metrics 0.0.0.0:${EV_RETH_2_PROMETHEUS_PORT} \ +# --log.file.directory /root/logs \ +# --authrpc.addr 0.0.0.0 \ +# --authrpc.port ${EV_RETH_2_ENGINE_PORT} \ +# --authrpc.jwtsecret /root/jwt/jwt.hex \ +# --http --http.addr 0.0.0.0 --http.port ${EV_RETH_2_RPC_PORT} \ +# --http.api "eth,net,web3,txpool" \ +# --ws --ws.addr 0.0.0.0 --ws.port ${EV_RETH_2_WS_PORT} \ +# --port ${EV_RETH_2_DISCOVERY_PORT} \ +# --disable-discovery \ +# --trusted-peers enode://e3e0025a64440eff4879b216766550d7237291cb94b79bb641b1e25933b08c9a3aada6583e25b320aebe84b643b85e14be934a8725eb6aacb74d6f65abfbeb74@fullnode-1-eden-testnet.binarybuilders.services:30313,enode://477544b9c4bc4136b9d25759b38be971c29dcf669105e02e8630f1e0407f58dc740137d3f21d02451d5f7b08bbbf31909cbd876af99818a34e64892e73498906@fullnode-2-eden-testnet.binarybuilders.services:30313 \ +# --txpool.pending-max-count 200000 \ +# --txpool.pending-max-size 200 \ +# --txpool.queued-max-count 200000 \ +# --txpool.queued-max-size 200 \ +# --txpool.max-account-slots 2048 \ +# --txpool.max-new-txns 2048 \ +# --txpool.additional-validation-tasks 16 \ +# --datadir /root/reth +# healthcheck: +# test: +# [ +# CMD, +# curl, +# -X, +# POST, +# -H, +# "Content-Type: application/json", +# --data, +# '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":1}', +# "http://localhost:${EV_RETH_2_RPC_PORT}", +# ] +# interval: 5s +# timeout: 5s +# retries: 3 +# start_period: 30s + ev-node: - image: *image + image: ghcr.io/evstack/ev-node-evm:v1.0.0-rc.1 env_file: .env network_mode: host restart: always @@ -127,11 +188,11 @@ services: init-2-snapshot-ev-node: condition: service_completed_successfully volumes: - - ev-node-data:/root/.evm + - ./data/ev-node:/root/.evm - ./ev-node.genesis.json:/volumes/sequencer_export/genesis.json:ro - ./ev-reth.genesis.json:/root/genesis.json:ro - jwttoken:/root/jwt:ro - - ./entrypoint.fullnode.sh:/usr/bin/entrypoint.sh + - ./entrypoint.fullnode_main.sh:/usr/bin/entrypoint.sh command: - start - --evnode.rpc.address=0.0.0.0:${EV_NODE_RPC_PORT} @@ -139,7 +200,9 @@ services: - --evnode.instrumentation.prometheus_listen_addr=:${EV_NODE_PROMETHEUS_PORT} - --evnode.p2p.listen_address=/ip4/0.0.0.0/tcp/7676 - --evnode.p2p.peers=/ip4/157.180.53.133/tcp/7686/p2p/12D3KooWMCfKiRXrd3o1m8TBDknmjZFqnmgFpP6gfjhBBVwnuCXK/p2p/12D3KooWMCfKiRXrd3o1m8TBDknmjZFqnmgFpP6gfjhBBVwnuCXK,/ip4/157.180.53.70/tcp/7686/p2p/12D3KooWEpRjbVZuQVZNxaifZDZ3dGLV6Dj7fT5Eox95PQhgWsJ7/p2p/12D3KooWEpRjbVZuQVZNxaifZDZ3dGLV6Dj7fT5Eox95PQhgWsJ7 - # - --evnode.log.level=debug +# - --evnode.node.stop_height=62038057 + - --evm.jwt-secret-file=/root/jwt/jwt.hex + - --evnode.log.level=debug environment: - DA_HEADER_NAMESPACE=${DA_HEADER_NAMESPACE} - DA_DATA_NAMESPACE=${DA_DATA_NAMESPACE} @@ -153,10 +216,46 @@ services: retries: 3 start_period: 30s +# ev-node-2: +# image: *image +# env_file: .env +# network_mode: host +# restart: always +# depends_on: +# ev-node: +# condition: service_started +# ev-reth-2: +# condition: service_started +# init-2-snapshot-ev-node: +# condition: service_completed_successfully +# volumes: +# - ./data/ev-node-2:/root/.evm +# - ./ev-node.genesis.json:/volumes/sequencer_export/genesis.json:ro +# - ./ev-reth.genesis.json:/root/genesis.json:ro +# - jwttoken:/root/jwt:ro +# - ./entrypoint.fullnode.sh:/usr/bin/entrypoint.sh +# command: +# - start +# - --evnode.rpc.address=0.0.0.0:${EV_NODE_2_RPC_PORT} +# - --evnode.instrumentation.prometheus +# - --evnode.instrumentation.prometheus_listen_addr=:${EV_NODE_2_PROMETHEUS_PORT} +# - --evnode.p2p.listen_address=/ip4/0.0.0.0/tcp/${EV_NODE_2_P2P_PORT} +# # - --evnode.log.level=debug +# environment: +# - DA_HEADER_NAMESPACE= +# - DA_DATA_NAMESPACE= +# - DA_ADDRESS= +# - EV_NODE_P2P_SOURCE_RPC=localhost:${EV_NODE_RPC_PORT} +# - EVM_ENGINE_URL=http://localhost:${EV_RETH_2_ENGINE_PORT} +# - EVM_ETH_URL=http://localhost:${EV_RETH_2_RPC_PORT} +# - EVM_JWT_SECRET_FILE=/root/jwt/jwt.hex +# healthcheck: +# test: [CMD, curl, "localhost:${EV_NODE_2_RPC_PORT}/health/live"] +# interval: 5s +# timeout: 5s +# retries: 3 +# start_period: 30s + volumes: - ev-node-data: - driver: local - ev-reth-data: - driver: local jwttoken: driver: local diff --git a/deployment/docker-compose/entrypoint.fullnode.sh b/deployment/docker-compose/entrypoint.fullnode.sh index 9eea5ed..2b9e7c8 100755 --- a/deployment/docker-compose/entrypoint.fullnode.sh +++ b/deployment/docker-compose/entrypoint.fullnode.sh @@ -166,6 +166,31 @@ if [ -n "${DA_HEADER_NAMESPACE-}" ]; then log "DEBUG" "Added DA header namespace flag: ${DA_HEADER_NAMESPACE}" fi +# Auto-discover sequencer p2p address when not provided +if [ -z "${SEQUENCER_P2P_INFO-}" ] && [ -n "${EV_NODE_P2P_SOURCE_RPC-}" ]; then + log "INFO" "SEQUENCER_P2P_INFO not set, attempting discovery via evm net-info" + net_info="" + retry_count=0 + max_retries=5 + while [ "${retry_count}" -lt "${max_retries}" ] && [ -z "${net_info}" ]; do + net_info=$(evm-single net-info --evnode.rpc.address=${EV_NODE_P2P_SOURCE_RPC} 2>/dev/null || true) + if [ -n "${net_info}" ]; then + break + fi + retry_count=$((retry_count + 1)) + sleep 2 + done + p2p_addr=$(printf "%s\n" "${net_info}" | sed -n 's/.*\(\/ip4\/[^ ]*\/p2p\/[A-Za-z0-9]*\).*/\1/p' | head -n 1) + + if [ -n "${p2p_addr}" ]; then + SEQUENCER_P2P_INFO="${p2p_addr}" + default_flags="${default_flags} --evnode.p2p.peers ${SEQUENCER_P2P_INFO}" + log "SUCCESS" "Discovered sequencer p2p address: ${SEQUENCER_P2P_INFO}" + else + log "WARNING" "Failed to discover sequencer p2p address from evm net-info" + fi +fi + default_flags="${default_flags} --home=${CONFIG_HOME}" log "SUCCESS" "Configuration flags prepared successfully" diff --git a/deployment/docker-compose/entrypoint.fullnode_main.sh b/deployment/docker-compose/entrypoint.fullnode_main.sh new file mode 100755 index 0000000..e1ea5d6 --- /dev/null +++ b/deployment/docker-compose/entrypoint.fullnode_main.sh @@ -0,0 +1,214 @@ +#!/bin/sh +# Fail on any error +set -e + +# Fail when using undeclared variables +set -u + +# Source shared logging utility +log() { + level="$1" + message="$2" + timestamp=$(date '+%Y-%m-%d %H:%M:%S') + + echo "📝 [${timestamp}] ${level}: ${message}" +} + +log "INIT" "Starting EVM Fullnode initialization" +sleep 5 + +# Function to extract --home value from arguments +get_home_dir() { + home_dir="${HOME}/.evm" + + # Parse arguments to find --home + while [ $# -gt 0 ]; do + case "$1" in + --home) + if [ -n "$2" ]; then + home_dir="$2" + break + fi + ;; + --home=*) + home_dir="${1#--home=}" + break + ;; + esac + shift + done + + echo "${home_dir}" +} + +# Get the home directory (either from --home flag or default) +CONFIG_HOME=$(get_home_dir "$@") +log "INFO" "Using config home directory: ${CONFIG_HOME}" + +if [ ! -f "${CONFIG_HOME}/config/node_key.json" ]; then + log "INFO" "Node key not found. Initializing new fullnode configuration" + + # Build init flags array + init_flags="--home=${CONFIG_HOME}" + + INIT_COMMAND="evm init ${init_flags}" + log "INIT" "Initializing fullnode with command: ${INIT_COMMAND}" + ${INIT_COMMAND} + log "SUCCESS" "Fullnode initialization completed" +else + log "INFO" "Node key already exists. Skipping initialization" +fi + +# Importing genesis +cp -pr /volumes/sequencer_export/genesis.json "${CONFIG_HOME}/config/genesis.json" +log "SUCCESS" "genesis.json copied to: ${CONFIG_HOME}/config/genesis.json" + +# Auto-retrieve genesis hash if not provided +log "INFO" "Checking genesis hash configuration" +if [ -z "${EVM_GENESIS_HASH-}" ] && [ -n "${EVM_ETH_URL-}" ]; then + log "INFO" "EVM_GENESIS_HASH not provided, attempting to retrieve from ev-reth at: ${EVM_ETH_URL}" + + # Wait for ev-reth to be ready (max 60 seconds) + retry_count=0 + max_retries=12 + while [ "${retry_count}" -lt "${max_retries}" ]; do + if curl -s --connect-timeout 5 "${EVM_ETH_URL}" >/dev/null 2>&1; then + log "SUCCESS" "ev-reth is ready, retrieving genesis hash..." + break + fi + log "INFO" "Waiting for ev-reth to be ready... (attempt $((retry_count + 1))/${max_retries})" + sleep 5 + retry_count=$((retry_count + 1)) + done + + if [ "${retry_count}" -eq "${max_retries}" ]; then + log "WARNING" "Could not connect to ev-reth at ${EVM_ETH_URL} after ${max_retries} attempts" + log "WARNING" "Proceeding without auto-retrieved genesis hash..." + else + # Retrieve genesis block hash using curl and shell parsing + log "NETWORK" "Fetching genesis block from ev-reth..." + genesis_response=$(curl -s -X POST -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0", false],"id":1}' \ + "${EVM_ETH_URL}" 2>/dev/null) + + if [ $? -eq 0 ] && [ -n "${genesis_response}" ]; then + # Extract hash using shell parameter expansion and sed + # Look for "hash":"0x..." pattern and extract the hash value + genesis_hash=$(echo "${genesis_response}" | sed -n 's/.*"hash":"\([^"]*\)".*/\1/p') + + if [ -n "${genesis_hash}" ] && [ "${genesis_hash#0x}" != "${genesis_hash}" ]; then + EVM_GENESIS_HASH="${genesis_hash}" + log "SUCCESS" "Successfully retrieved genesis hash: ${EVM_GENESIS_HASH}" + else + log "WARNING" "Could not parse genesis hash from response" + log "DEBUG" "Response: ${genesis_response}" + fi + else + log "WARNING" "Failed to retrieve genesis block from ev-reth" + fi + fi +elif [ -n "${EVM_GENESIS_HASH-}" ]; then + log "INFO" "Using provided genesis hash: ${EVM_GENESIS_HASH}" +else + log "INFO" "No genesis hash configuration provided" +fi + +# Build start flags array +log "INFO" "Building startup configuration flags" +default_flags="" + +# Add required flags if environment variables are set +if [ -n "${EVM_JWT_SECRET_FILE-}" ]; then + default_flags="${default_flags} --evm.jwt-secret-file ${EVM_JWT_SECRET_FILE}" + log "DEBUG" "Added JWT secret file flag" +fi + +if [ -n "${EVM_GENESIS_HASH-}" ]; then + default_flags="${default_flags} --evm.genesis-hash ${EVM_GENESIS_HASH}" + log "DEBUG" "Added genesis hash flag" +fi + +if [ -n "${EVM_ENGINE_URL-}" ]; then + default_flags="${default_flags} --evm.engine-url ${EVM_ENGINE_URL}" + log "DEBUG" "Added engine URL flag: ${EVM_ENGINE_URL}" +fi + +if [ -n "${EVM_ETH_URL-}" ]; then + default_flags="${default_flags} --evm.eth-url ${EVM_ETH_URL}" + log "DEBUG" "Added ETH URL flag: ${EVM_ETH_URL}" +fi + +log "INFO" "Configuring Data Availability (DA) settings" +if [ -n "${SEQUENCER_P2P_INFO-}" ]; then + default_flags="${default_flags} --evnode.p2p.peers ${SEQUENCER_P2P_INFO}" + log "DEBUG" "Added p2p peer flag: ${SEQUENCER_P2P_INFO}" +fi + +# Conditionally add DA-related flags +log "INFO" "Configuring Data Availability (DA) settings" +if [ -n "${DA_ADDRESS-}" ]; then + default_flags="${default_flags} --evnode.da.address ${DA_ADDRESS}" + log "DEBUG" "Added DA address flag: ${DA_ADDRESS}" +fi + +if [ -n "${DA_AUTH_TOKEN-}" ]; then + default_flags="${default_flags} --evnode.da.auth_token ${DA_AUTH_TOKEN}" + log "DEBUG" "Added DA auth token flag" +fi + +if [ -n "${DA_DATA_NAMESPACE-}" ]; then + default_flags="${default_flags} --evnode.da.data_namespace ${DA_DATA_NAMESPACE}" + log "DEBUG" "Added DA data namespace flag: ${DA_DATA_NAMESPACE}" +fi + +if [ -n "${DA_HEADER_NAMESPACE-}" ]; then + default_flags="${default_flags} --evnode.da.namespace ${DA_HEADER_NAMESPACE}" + log "DEBUG" "Added DA header namespace flag: ${DA_HEADER_NAMESPACE}" +fi + +# Auto-discover sequencer p2p address when not provided +if [ -z "${SEQUENCER_P2P_INFO-}" ] && [ -n "${EV_NODE_P2P_SOURCE_RPC-}" ]; then + log "INFO" "SEQUENCER_P2P_INFO not set, attempting discovery via evm net-info" + net_info="" + retry_count=0 + max_retries=5 + while [ "${retry_count}" -lt "${max_retries}" ] && [ -z "${net_info}" ]; do + net_info=$(evm net-info --evnode.rpc.address=${EV_NODE_P2P_SOURCE_RPC} 2>/dev/null || true) + if [ -n "${net_info}" ]; then + break + fi + retry_count=$((retry_count + 1)) + sleep 2 + done + p2p_addr=$(printf "%s\n" "${net_info}" | sed -n 's/.*\(\/ip4\/[^ ]*\/p2p\/[A-Za-z0-9]*\).*/\1/p' | head -n 1) + + if [ -n "${p2p_addr}" ]; then + SEQUENCER_P2P_INFO="${p2p_addr}" + default_flags="${default_flags} --evnode.p2p.peers ${SEQUENCER_P2P_INFO}" + log "SUCCESS" "Discovered sequencer p2p address: ${SEQUENCER_P2P_INFO}" + else + log "WARNING" "Failed to discover sequencer p2p address from evm net-info" + fi +fi + +default_flags="${default_flags} --home=${CONFIG_HOME}" + +log "SUCCESS" "Configuration flags prepared successfully" + +# If no arguments passed, show help +if [ $# -eq 0 ]; then + log "INFO" "No arguments provided, showing help" + exec evm +fi + +# If first argument is "start", apply default flags +if [ "$1" = "start" ]; then + shift + log "INIT" "Starting EVM fullnode with command: evm start ${default_flags} $*" + log "INFO" "Fullnode is now starting up..." + eval "exec evm start ${default_flags} \"\$@\"" +else + # For any other command/subcommand, pass through directly + log "INFO" "Executing command: evm $*" + exec evm "$@" +fi diff --git a/deployment/docker-compose/ev-node.genesis.json b/deployment/docker-compose/ev-node.genesis.json index 597f7f0..3760e9f 100644 --- a/deployment/docker-compose/ev-node.genesis.json +++ b/deployment/docker-compose/ev-node.genesis.json @@ -3,5 +3,6 @@ "start_time": "2025-09-09T10:50:02.349087636Z", "initial_height": 1, "proposer_address": "N89c6gm4fP8oW7OxEtHft7b7PFu8BRzrqkPRzVH04dA=", - "da_start_height": 7970386 + "da_start_height": 7970386, + "da_epoch_forced_inclusion": 50 } diff --git a/deployment/docker-compose/init-1-ev-reth-snapshot.sh b/deployment/docker-compose/init-1-ev-reth-snapshot.sh index 088a1e6..a15ba30 100755 --- a/deployment/docker-compose/init-1-ev-reth-snapshot.sh +++ b/deployment/docker-compose/init-1-ev-reth-snapshot.sh @@ -18,13 +18,28 @@ log() { } EV_RETH_DATA_PATH=/root/reth +SNAPSHOT_CACHE_DIR=/snapshots BASE_URL=https://fsn1.your-objectstorage.com/6774130f-22e6-9d15-1103-96c8ec9b555b/private/testnet +download_snapshot() { + url="$1" + dest="$2" + + if command -v aria2c >/dev/null 2>&1; then + aria2c -x 8 -s 8 -k 1M -c -o "$(basename "${dest}")" -d "$(dirname "${dest}")" "${url}" + else + curl -fL --progress-bar -o "${dest}" "${url}" + fi +} + if [[ ! -f ${EV_RETH_DATA_PATH}/_created_by_init_script ]]; then - apk add --no-cache lz4 + apk add --no-cache lz4 aria2 log "INIT" "Starting ev-reth snapshot download and configuration (Init Container 2)" + # Create snapshot cache directory if it doesn't exist + mkdir -p "${SNAPSHOT_CACHE_DIR}" + log "INFO" "Fetching snapshot information" snapshot_metadata="${BASE_URL}/index.html" log "DOWNLOAD" "Fetching snapshot metadata from: ${snapshot_metadata}" @@ -49,28 +64,33 @@ if [[ ! -f ${EV_RETH_DATA_PATH}/_created_by_init_script ]]; then log "SUCCESS" "Found snapshot: ${snapshot_name}" - # Download snapshot using curl - log "DOWNLOAD" "Downloading snapshot from: ${BASE_URL}/${snapshot_name}" - log "INFO" "This may take several minutes depending on your connection speed..." - - if ! curl -fL --progress-bar -o /tmp/ev-reth-snap.tar.lz4 "${BASE_URL}/${snapshot_name}"; then - log "ERROR" "Failed to download snapshot from ${BASE_URL}/${snapshot_name}" - exit 1 + # Check if snapshot exists in cache + cached_snapshot="${SNAPSHOT_CACHE_DIR}/${snapshot_name}" + if [[ -f "${cached_snapshot}" ]]; then + log "INFO" "Found cached snapshot: ${cached_snapshot}" + log "INFO" "Skipping download, using cached file" + snapshot_file="${cached_snapshot}" + else + # Download snapshot using curl + log "DOWNLOAD" "Downloading snapshot from: ${BASE_URL}/${snapshot_name}" + log "INFO" "This may take several minutes depending on your connection speed..." + + if ! download_snapshot "${BASE_URL}/${snapshot_name}" "${cached_snapshot}"; then + log "ERROR" "Failed to download snapshot from ${BASE_URL}/${snapshot_name}" + exit 1 + fi + log "SUCCESS" "Snapshot downloaded successfully to ${cached_snapshot}" + snapshot_file="${cached_snapshot}" fi - log "SUCCESS" "Snapshot downloaded successfully to /tmp/ev-reth-snap.tar.lz4" log "INFO" "Extracting snapshot archive" # Use lz4 to decompress and pipe to tar (BusyBox compatible) - if ! lz4 -dc /tmp/ev-reth-snap.tar.lz4 | tar -xvf - --strip-components=1 -C "${EV_RETH_DATA_PATH}"; then + if ! lz4 -dc "${snapshot_file}" | tar -xvf - --strip-components=1 -C "${EV_RETH_DATA_PATH}"; then log "ERROR" "Failed to extract snapshot archive" exit 1 fi log "SUCCESS" "Snapshot extracted successfully" - log "INFO" "Cleaning up temporary files" - rm /tmp/ev-reth-snap.tar.lz4 - log "SUCCESS" "Temporary files cleaned up" - log "SUCCESS" "Init container 2 completed" touch "${EV_RETH_DATA_PATH}/_created_by_init_script" diff --git a/deployment/docker-compose/init-2-ev-node-snapshot.sh b/deployment/docker-compose/init-2-ev-node-snapshot.sh index 492eaf5..efc9296 100755 --- a/deployment/docker-compose/init-2-ev-node-snapshot.sh +++ b/deployment/docker-compose/init-2-ev-node-snapshot.sh @@ -18,13 +18,28 @@ log() { } EV_NODE_DATA_PATH=/root/.evm +SNAPSHOT_CACHE_DIR=/snapshots BASE_URL=https://fsn1.your-objectstorage.com/6774130f-22e6-9d15-1103-96c8ec9b555b/private/testnet +download_snapshot() { + url="$1" + dest="$2" + + if command -v aria2c >/dev/null 2>&1; then + aria2c -x 8 -s 8 -k 1M -c -o "$(basename "${dest}")" -d "$(dirname "${dest}")" "${url}" + else + curl -fL --progress-bar -o "${dest}" "${url}" + fi +} + if [[ ! -f ${EV_NODE_DATA_PATH}/_created_by_init_script ]]; then - apk add --no-cache lz4 + apk add --no-cache lz4 aria2 log "INIT" "Starting ev-node snapshot download and configuration (Init Container 2)" + # Create snapshot cache directory if it doesn't exist + mkdir -p "${SNAPSHOT_CACHE_DIR}" + log "INFO" "Fetching snapshot information" snapshot_metadata="${BASE_URL}/index.html" log "DOWNLOAD" "Fetching snapshot metadata from: ${snapshot_metadata}" @@ -49,28 +64,33 @@ if [[ ! -f ${EV_NODE_DATA_PATH}/_created_by_init_script ]]; then log "SUCCESS" "Found snapshot: ${snapshot_name}" - # Download snapshot using curl - log "DOWNLOAD" "Downloading snapshot from: ${BASE_URL}/${snapshot_name}" - log "INFO" "This may take several minutes depending on your connection speed..." - - if ! curl -fL --progress-bar -o /tmp/ev-node-snap.tar.lz4 "${BASE_URL}/${snapshot_name}"; then - log "ERROR" "Failed to download snapshot from ${BASE_URL}/${snapshot_name}" - exit 1 + # Check if snapshot exists in cache + cached_snapshot="${SNAPSHOT_CACHE_DIR}/${snapshot_name}" + if [[ -f "${cached_snapshot}" ]]; then + log "INFO" "Found cached snapshot: ${cached_snapshot}" + log "INFO" "Skipping download, using cached file" + snapshot_file="${cached_snapshot}" + else + # Download snapshot using curl + log "DOWNLOAD" "Downloading snapshot from: ${BASE_URL}/${snapshot_name}" + log "INFO" "This may take several minutes depending on your connection speed..." + + if ! download_snapshot "${BASE_URL}/${snapshot_name}" "${cached_snapshot}"; then + log "ERROR" "Failed to download snapshot from ${BASE_URL}/${snapshot_name}" + exit 1 + fi + log "SUCCESS" "Snapshot downloaded successfully to ${cached_snapshot}" + snapshot_file="${cached_snapshot}" fi - log "SUCCESS" "Snapshot downloaded successfully to /tmp/ev-node-snap.tar.lz4" log "INFO" "Extracting snapshot archive" # Use lz4 to decompress and pipe to tar (BusyBox compatible) - if ! lz4 -dc /tmp/ev-node-snap.tar.lz4 | tar -xvf - --strip-components=1 -C "${EV_NODE_DATA_PATH}"; then + if ! lz4 -dc "${snapshot_file}" | tar -xvf - --strip-components=1 -C "${EV_NODE_DATA_PATH}"; then log "ERROR" "Failed to extract snapshot archive" exit 1 fi log "SUCCESS" "Snapshot extracted successfully" - log "INFO" "Cleaning up temporary files" - rm /tmp/ev-node-snap.tar.lz4 - log "SUCCESS" "Temporary files cleaned up" - log "SUCCESS" "Init container 2 completed" touch "${EV_NODE_DATA_PATH}/_created_by_init_script" diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 1246f9d..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,91 +0,0 @@ -name: "Evolve EVM" - -services: - ev-reth: - container_name: ev-reth - restart: unless-stopped - image: ghcr.io/evstack/ev-reth:latest - ports: - - "9001:9001" # metrics - - "30303:30303" # eth/66 peering - - "8545:8545" # rpc - - "8551:8551" # engine - - "8546:8546" # ws - volumes: - - ./chain:/root/chain:ro - - ./jwttoken:/root/jwt:ro - - reth:/home/reth/eth-home - entrypoint: /bin/sh -c - command: - - | - ev-reth node \ - --chain /root/chain/genesis.json \ - --datadir /home/reth/eth-home \ - --metrics 0.0.0.0:9001 \ - --authrpc.addr 0.0.0.0 \ - --authrpc.port 8551 \ - --authrpc.jwtsecret /root/jwt/jwt.hex \ - --http --http.addr 0.0.0.0 --http.port 8545 \ - --http.api eth,net,web3,txpool \ - --ws --ws.addr 0.0.0.0 --ws.port 8546 \ - --ws.api eth,net,web3 \ - --engine.persistence-threshold 0 \ - --engine.memory-block-buffer-target 0 \ - --disable-discovery \ - --txpool.pending-max-count 200000 \ - --txpool.pending-max-size 200 \ - --txpool.queued-max-count 200000 \ - --txpool.queued-max-size 200 \ - --txpool.max-account-slots 2048 \ - --txpool.max-new-txns 2048 \ - --txpool.additional-validation-tasks 16 \ - --ev-reth.enable - networks: - - evolve-network - - local-da: - image: ghcr.io/evstack/local-da:v0.1.0 - ports: - - "7980:7980" - command: ["-listen-all"] - networks: - - evolve-network - - ev-node-eden-testnet: - image: ghcr.io/01builders/eden-testnet:main - depends_on: - ev-reth: - condition: service_started - local-da: - condition: service_started - ports: - - "7676:7676" # p2p - - "7331:7331" # rpc - volumes: - - eden-testnet-data:/root/.eden-testnet/ - restart: always - entrypoint: /usr/bin/entrypoint.sh - command: start - environment: - - EVM_ENGINE_URL=http://ev-reth:8551 - - EVM_ETH_URL=http://ev-reth:8545 - - EVM_JWT_SECRET=f747494bb0fb338a0d71f5f9fe5b5034c17cc988c229b59fd71e005ee692e9bf - - EVM_GENESIS_HASH=0x2b8bbb1ea1e04f9c9809b4b278a8687806edc061a356c7dbc491930d8e922503 - - EVM_BLOCK_TIME=1s - - EVM_SIGNER_PASSPHRASE=secret - - DA_ADDRESS=http://local-da:7980 # http://localhost:26658 (Use if not using local-da) - # - DA_AUTH_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBbGxvdyI6WyJwdWJsaWMiLCJyZWFkIiwid3JpdGUiXSwiTm9uY2UiOiJQcEswTmhyWi9IY05NWkVtUG9sSXNpRTRDcUpMdE9mbWtBMW0zMWFUaEswPSIsIkV4cGlyZXNBdCI6IjAwMDEtMDEtMDFUMDA6MDA6MDBaIn0.gaWh6tS6Rel1XFYclDkapNnZlaZVjrikCRNBxSDkCGk - # - DA_NAMESPACE=00000000000000000000000000000000000000000008e5f679bf7116c1 - networks: - - evolve-network - -volumes: - eden-testnet-data: - reth: - -networks: - evolve-network: - driver: bridge - ipam: - config: - - subnet: 172.16.0.0/24