#!/bin/sh set -e # Exit on failure if [ $# -lt 1 ]; then echo "Error: No argument provided. Please specify '0gchaind' or 'geth' as the first argument." exit 1 fi MODE="$1" shift case "$MODE" in 0gchaind) # Continue with 0gchaind-specific logic (rest of script) ;; geth) GETH_DATA_DIR="/root/.ethereum/" if [ -z "$(ls -A "$GETH_DATA_DIR")" ]; then if [ -f /0g/genesis.json ]; then /0g/bin/geth init --datadir $GETH_DATA_DIR /0g/genesis.json elif [ -f /0g/geth-genesis.json ]; then /0g/bin/geth init --datadir $GETH_DATA_DIR /0g/geth-genesis.json else echo "No genesis file found at /0g/genesis.json or /0g/geth-genesis.json" >&2 exit 1 fi else echo "Datadir not empty, continuing!" >&2 fi exec /0g/bin/geth $@ exit 0 ;; *) echo "Error: Unknown argument '$MODE'. Please specify '0gchaind' or 'geth'." exit 1 ;; esac echo "MONIKER: $MONIKER" AUTH_RPC=${AUTH_RPC:-http://0g-$CHAIN_NAME:8551} # just as example HOME_DIR="/root/.0g" mkdir -p $HOME_DIR CONFIG_DIR="$HOME_DIR/config" DATA_DIR="$HOME_DIR/data" mkdir -p $CONFIG_DIR mkdir -p $DATA_DIR if [ "$CHAIN_NAME" = "galileo" ]; then CHAIN_SPEC=testnet else CHAIN_SPEC=mainnet fi env # seems to be the same for all the 0g chains # $DATA_DIR and $CONFIG_DIR are SEPARATE docker volumes (_zerog and _config), # so the presence of a file in one says nothing about the other. Guard on everything # 0gchaind actually needs to boot, and write the copies so the LAST file written is the # one that would make a re-run skip. # # The previous version guarded solely on $DATA_DIR/priv_validator_state.json and copied it # BEFORE the two key files. An init interrupted between those copies therefore left the # data volume with the guard file and the config volume without the keys, so every later # start took the "Already initialized" branch, copied nothing, and 0gchaind panicked: # # panic: error calling provider ProvideBlsSigner (node-core/components/signer.go:46): # key file does not exist at path: /root/.0g/config/priv_validator_key.json # # That state is unrecoverable by restarting - the node wedges permanently. Hit on # aristotle @ rpc-de-32 on 2026-08-12 after repeated build failures interrupted its init. if [ ! -f "$CONFIG_DIR/priv_validator_key.json" ] || \ [ ! -f "$CONFIG_DIR/node_key.json" ] || \ [ ! -f "$DATA_DIR/priv_validator_state.json" ]; then echo "0g: node identity incomplete (config keys and/or priv_validator_state.json). Initializing..." TMP_DIR=$(mktemp -d) # You can add any additional initialization logic here if needed if /0g/bin/0gchaind init ${MONIKER} --chaincfg.chain-spec ${CHAIN_SPEC} --home $TMP_DIR; then cp -r /0g/0g-home/0gchaind-home/config/* $CONFIG_DIR # Keys first, guard file last: if this is interrupted the next start re-runs # initialization instead of latching into the wedged state described above. cp $TMP_DIR/config/node_key.json $CONFIG_DIR cp $TMP_DIR/config/priv_validator_key.json $CONFIG_DIR cp $TMP_DIR/data/priv_validator_state.json $DATA_DIR else echo "Already initialized, continuing!" >&2 fi rm -rf $TMP_DIR # delete tmp dir else echo "0g: node identity complete (config keys + priv_validator_state.json). Continuing!" >&2 fi exec /0g/bin/0gchaind $@