init.sh

Overview

`init.sh` is a shell script designed to initialize and run an Ethereum-compatible blockchain node using the `geth` client. It automates the setup of the node's data directory, handles optional snapshot restoration for faster synchronization, configures essential runtime parameters, and manages the lifecycle of the `geth` process including graceful shutdown on termination signals.

Key functionalities include:

This script is typically used in containerized or automated environments where rapid node startup and proper signal handling are critical.


Detailed Explanation

Environment Variables and Constants


Main Script Flow

  1. Error Handling and Debugging

    set -e
    [ "$DEBUG" == "true" ] && set -x
    
    • set -e: Immediately exits the script if any command returns a non-zero status.

    • If DEBUG is enabled, prints each command before execution.

  2. Snapshot Restoration

    if [[ -n $SNAPSHOT && ! -d "$CHAINDATA_DIR" ]]; then
      ...
    fi
    
    • Checks if SNAPSHOT is set and the chaindata directory does not exist.

    • Installs necessary tools (wget, plus lz4 or zstd depending on snapshot format).

    • Removes any existing geth data directory.

    • Downloads and extracts the snapshot directly into the data directory.

    • Supports two snapshot compression formats:

      • .tar.lz4: Uses lz4 CLI for decompression.

      • .tar.zst: Uses zstd CLI for decompression.

  3. Genesis Initialization

    if [[ ! -d "$CHAINDATA_DIR" ]]; then
      geth init --datadir $DATA_DIR genesis.json
    fi
    
    • If the chaindata directory still does not exist after snapshot restoration, initializes the blockchain using a genesis.json file.

  4. Configuration Adjustment

    if ! grep -q 'StateScheme = "path"' config.toml; then
      sed -i '/^\[Eth\]/a StateScheme = "path"' config.toml
    fi
    
    • Checks if the StateScheme is set to "path" in the config.toml file.

    • If not present, inserts the line immediately after the [Eth] section header.

    • This setting influences how the Ethereum state is stored on disk.


Functions

start()

Starts the `geth` node with specified options.

start() {
  geth \
    --config config.toml \
    --datadir $DATA_DIR \
    --syncmode full \
    --db.engine pebble \
    --http \
    --http.addr 0.0.0.0 \
    --http.port 8545 \
    --http.api eth,net,web3,debug,txpool \
    --http.vhosts '*' \
    --http.corsdomain '*' \
    --ws \
    --ws.addr 0.0.0.0 \
    --ws.port 8546 \
    --ws.api eth,net,web3,debug,txpool \
    --ws.origins '*' \
    --state.scheme path \
    --rpc.allow-unprotected-txs \
    --history.transactions 0 \
    --nat none &
  PID="$!"
}

**Parameters:** None

**Returns:** None (runs `geth` in the background and stores its PID in `PID`)

**Details:**

**Usage Example:**

start

Starts the `geth` node in the background and captures its process ID.


stop()

Gracefully stops the running `geth` process.

stop() {
  echo "Catching signal and sending to PID: $PID" && kill $PID
  while $(kill -0 $PID 2>/dev/null); do sleep 1; done
}

**Parameters:** None

**Returns:** None

**Details:**

**Usage Example:**

stop

Stops the running `geth` node gracefully.


Signal Handling

trap 'stop' TERM INT

Process Control

start
wait $PID

Implementation Details and Algorithms


Interaction with Other System Components

This script is typically part of a containerized deployment, such as a Docker container, where it serves as the entrypoint or startup script.


Visual Diagram

flowchart TD
    StartScript["Start init.sh script"]
    CheckDebug["Check DEBUG env"]
    SetErrorExit["set -e"]
    CheckSnapshot["Is SNAPSHOT set and chaindata dir missing?"]
    InstallWget["Install wget"]
    RemoveOldData["Remove old geth data"]
    CheckLZ4["Is snapshot .tar.lz4?"]
    InstallLZ4["Install lz4"]
    DownloadLZ4["Download & extract snapshot (lz4)"]
    CheckZST["Is snapshot .tar.zst?"]
    InstallZST["Install zstd"]
    DownloadZST["Download & extract snapshot (zstd)"]
    CheckChainData["Does chaindata dir exist?"]
    InitGenesis["Run geth init with genesis.json"]
    CheckConfig["Check 'StateScheme = \"path\"' in config.toml"]
    UpdateConfig["Insert StateScheme = \"path\" if missing"]
    DefineStartFunc["Define start() function"]
    DefineStopFunc["Define stop() function"]
    SetupTrap["Setup trap for TERM and INT signals"]
    StartGeth["Call start()"]
    WaitPID["wait for geth process"]

    StartScript --> SetErrorExit
    SetErrorExit --> CheckDebug
    CheckDebug --> CheckSnapshot
    CheckSnapshot -->|Yes| InstallWget
    CheckSnapshot -->|No| CheckChainData
    InstallWget --> RemoveOldData
    RemoveOldData --> CheckLZ4
    CheckLZ4 -->|Yes| InstallLZ4
    CheckLZ4 -->|No| CheckZST
    InstallLZ4 --> DownloadLZ4
    DownloadLZ4 --> CheckChainData
    CheckZST -->|Yes| InstallZST
    CheckZST -->|No| CheckChainData
    InstallZST --> DownloadZST
    DownloadZST --> CheckChainData
    CheckChainData -->|No| InitGenesis
    CheckChainData -->|Yes| CheckConfig
    InitGenesis --> CheckConfig
    CheckConfig -->|No| UpdateConfig
    CheckConfig -->|Yes| DefineStartFunc
    UpdateConfig --> DefineStartFunc
    DefineStartFunc --> DefineStopFunc
    DefineStopFunc --> SetupTrap
    SetupTrap --> StartGeth
    StartGeth --> WaitPID

Summary

`init.sh` is a robust initialization and startup script for a `geth` Ethereum node, optimized for containerized deployments. It supports fast snapshot-based restoration, configuration management, and graceful shutdown handling. The script ensures the node is properly configured and started with a comprehensive RPC API surface, facilitating blockchain interaction via HTTP and WebSocket protocols.

By automating these setup steps, the script reduces manual intervention and accelerates deployment times for blockchain nodes in development, testing, or production environments.