|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +# --------------------------------------------------------------- |
| 4 | +# Entrypoint script for voting-node container |
| 5 | +# --------------------------------------------------------------- |
| 6 | +# |
| 7 | +# This script serves as the entrypoint for the jormungandr node. |
| 8 | +# |
| 9 | +# It expects the following environment variables to be set except where noted: |
| 10 | +# |
| 11 | +# STORAGE_PATH - The path where the node's data will be stored |
| 12 | +# NODE_CONFIG_PATH - The path to the node's configuration file |
| 13 | +# ENV (optional) - The target environment. Used for fetching the node's configuration and archives from S3. |
| 14 | +# GENESIS_PATH (optional) - The path to the genesis block |
| 15 | +# GENESIS_BUCKET (optional) - The S3 bucket where the genesis block is stored. |
| 16 | +# GENESIS_FUND (optional) - The fund name. Used for fetching the genesis block from S3. |
| 17 | +# GENESIS_SKIP_OVERRIDE (optional) - If set, the node will not override the genesis block if it already exists in the storage path. |
| 18 | +# GENESIS_VERSION (optional) - The genesis version. Used for fetching the genesis block from S3. If not set, the "default" version will be used. |
| 19 | +# ARCHIVE_BUCKET (optional) - The S3 bucket where archives are stored. |
| 20 | +# ARCHIVE_ID (optional) - If present, the node will attempt to fetch the archive with the specified ID from S3 and restore it. |
| 21 | +# BFT_PATH (optional) - The path to the BFT file. Only used by leader nodes. |
| 22 | +# LEADER (optional) - If set, the node will be configured as a leader node. |
| 23 | +# DEBUG_SLEEP (optional) - If set, the script will sleep for the specified number of seconds before starting the node. |
| 24 | +# --------------------------------------------------------------- |
| 25 | + |
| 26 | +# Enable strict mode |
| 27 | +set +x |
| 28 | +set -o errexit |
| 29 | +set -o pipefail |
| 30 | +set -o nounset |
| 31 | +set -o functrace |
| 32 | +set -o errtrace |
| 33 | +set -o monitor |
| 34 | +set -o posix |
| 35 | +shopt -s dotglob |
| 36 | + |
| 37 | +check_env_vars() { |
| 38 | + local env_vars=("$@") |
| 39 | + |
| 40 | + # Iterate over the array and check if each variable is set |
| 41 | + for var in "${env_vars[@]}"; do |
| 42 | + echo "Checking $var" |
| 43 | + if [ -z "${!var+x}" ]; then |
| 44 | + echo ">>> Error: $var is required and not set." |
| 45 | + exit 1 |
| 46 | + fi |
| 47 | + done |
| 48 | +} |
| 49 | + |
| 50 | +debug_sleep() { |
| 51 | + if [ -n "${DEBUG_SLEEP:-}" ]; then |
| 52 | + echo "DEBUG_SLEEP is set. Sleeping for ${DEBUG_SLEEP} seconds..." |
| 53 | + sleep "${DEBUG_SLEEP}" |
| 54 | + fi |
| 55 | +} |
| 56 | + |
| 57 | +fetch_archive() { |
| 58 | + local bucket=$1 |
| 59 | + local env=$2 |
| 60 | + local id=$3 |
| 61 | + local archive_path=$4 |
| 62 | + |
| 63 | + echo ">>> Fetching archive from S3 using the following parameters..." |
| 64 | + echo "Bucket: $bucket" |
| 65 | + echo "Environment: $env" |
| 66 | + echo "Archive ID: $id" |
| 67 | + |
| 68 | + fetcher --bucket "$bucket" archive -e "$env" -i "$id" "$archive_path" |
| 69 | + |
| 70 | + echo ">>> Clearing storage path..." |
| 71 | + rm -rf "${STORAGE_PATH:?}/*" |
| 72 | + |
| 73 | + echo ">>> Extracting archive..." |
| 74 | + zstd -cd "$archive_path" | tar xf - -C "$STORAGE_PATH" |
| 75 | + rm "$archive_path" |
| 76 | + |
| 77 | + echo ">>> Setting last restored archive to $ARCHIVE_ID" |
| 78 | + echo "$id" >"$STORAGE_PATH/last_restored_archive" |
| 79 | +} |
| 80 | + |
| 81 | +fetch_genesis() { |
| 82 | + local bucket=$1 |
| 83 | + local env=$2 |
| 84 | + local fund=$3 |
| 85 | + local version=$4 |
| 86 | + local path=$5 |
| 87 | + |
| 88 | + echo ">>> Fetching genesis block from S3 using the following parameters..." |
| 89 | + echo "Bucket: $bucket" |
| 90 | + echo "Environment: $env" |
| 91 | + echo "Fund: $fund" |
| 92 | + echo "Version: ${version}" |
| 93 | + |
| 94 | + mkdir -p "$(dirname "$GENESIS_PATH")" |
| 95 | + fetcher --bucket "$bucket" artifact -e "$env" -f "$fund" -t "genesis" -v "${version}" "$path" |
| 96 | +} |
| 97 | + |
| 98 | +echo ">>> Starting entrypoint script..." |
| 99 | + |
| 100 | +REQUIRED_ENV=( |
| 101 | + "STORAGE_PATH" |
| 102 | + "NODE_CONFIG_PATH" |
| 103 | +) |
| 104 | +echo ">>> Checking required env vars..." |
| 105 | +check_env_vars "${REQUIRED_ENV[@]}" |
| 106 | + |
| 107 | +# Verify the storage path exists |
| 108 | +if [[ ! -d "$STORAGE_PATH" ]]; then |
| 109 | + echo "ERROR: storage path does not exist at: $STORAGE_PATH" |
| 110 | + echo ">>> Aborting..." |
| 111 | + exit 1 |
| 112 | +fi |
| 113 | + |
| 114 | +# Verify config is present |
| 115 | +if [[ ! -f "$NODE_CONFIG_PATH" ]]; then |
| 116 | + echo "ERROR: node configuration is absent at: $NODE_CONFIG_PATH" |
| 117 | + echo ">>> Aborting..." |
| 118 | + exit 1 |
| 119 | +fi |
| 120 | + |
| 121 | +# The name of the file that indicates that fetching should be disabled |
| 122 | +DISABLE_FETCHING_FILE="$STORAGE_PATH/disable_fetching" |
| 123 | + |
| 124 | +# The path to the genesis block on the storage volume |
| 125 | +GENESIS_STORAGE_PATH="$STORAGE_PATH/artifacts/block0.bin" |
| 126 | + |
| 127 | +if [[ -f "$DISABLE_FETCHING_FILE" ]]; then |
| 128 | + echo ">>> $DISABLE_FETCHING_FILE file exists. Skipping fetching genesis file and/or archive..." |
| 129 | + |
| 130 | + if [[ -z "${GENESIS_PATH:=}" || ! -f "$GENESIS_PATH" ]]; then |
| 131 | + if [[ ! -f "$GENESIS_STORAGE_PATH" ]]; then |
| 132 | + echo ">>> ERROR: No genesis block provided and genesis block is absent at: $GENESIS_STORAGE_PATH" |
| 133 | + echo ">>> ERROR: Cannot continue without a genesis block. Aborting..." |
| 134 | + exit 1 |
| 135 | + fi |
| 136 | + fi |
| 137 | +else |
| 138 | + # Verify genesis block is present or attempt to fetch from S3 |
| 139 | + if [[ -z "${GENESIS_PATH:=}" || ! -f "$GENESIS_PATH" ]]; then |
| 140 | + echo ">>> No genesis block provided. Attempting to fetch from S3..." |
| 141 | + |
| 142 | + REQUIRED_ENV=( |
| 143 | + "ENV" |
| 144 | + "GENESIS_BUCKET" |
| 145 | + "GENESIS_FUND" |
| 146 | + ) |
| 147 | + echo ">>> Checking required env vars for fetching from S3..." |
| 148 | + check_env_vars "${REQUIRED_ENV[@]}" |
| 149 | + |
| 150 | + # Check if genesis block already exists in the storage path |
| 151 | + GENESIS_PATH="$GENESIS_STORAGE_PATH" |
| 152 | + if [[ -f "$GENESIS_PATH" ]]; then |
| 153 | + echo ">>> Genesis block already exists at $GENESIS_PATH." |
| 154 | + |
| 155 | + if [[ -n "${GENESIS_SKIP_OVERRIDE:=}" ]]; then |
| 156 | + echo ">>> GENESIS_SKIP_OVERRIDE is set. Skipping overriding the genesis block..." |
| 157 | + else |
| 158 | + echo ">>> Downloading newer version from S3..." |
| 159 | + TMP_GENESIS_PATH="/tmp/block0.bin" |
| 160 | + fetch_genesis "$GENESIS_BUCKET" "$ENV" "$GENESIS_FUND" "${GENESIS_VERSION:=}" "$TMP_GENESIS_PATH" |
| 161 | + |
| 162 | + if cmp -s "$GENESIS_PATH" "$TMP_GENESIS_PATH"; then |
| 163 | + echo ">>> The genesis blocks are the same. Skipping..." |
| 164 | + rm "$TMP_GENESIS_PATH" |
| 165 | + else |
| 166 | + echo ">>> The genesis blocks are different." |
| 167 | + echo ">>> Clearing storage path..." |
| 168 | + rm -rf "${STORAGE_PATH:?}/*" |
| 169 | + |
| 170 | + echo ">>> Replacing genesis block..." |
| 171 | + mkdir -p "$(dirname "$GENESIS_PATH")" |
| 172 | + mv "$TMP_GENESIS_PATH" "$GENESIS_PATH" |
| 173 | + fi |
| 174 | + fi |
| 175 | + else |
| 176 | + fetch_genesis "$GENESIS_BUCKET" "$ENV" "$GENESIS_FUND" "${GENESIS_VERSION:=}" "$GENESIS_PATH" |
| 177 | + fi |
| 178 | + fi |
| 179 | + |
| 180 | + # Check if we need to pull an archive from S3 |
| 181 | + if [[ -n "${ARCHIVE_ID:=}" ]]; then |
| 182 | + echo ">>> Archive ID provided. Attempting to fetch from S3..." |
| 183 | + ARCHIVE_PATH="/tmp/archive.tar.zstd" |
| 184 | + |
| 185 | + REQUIRED_ENV=( |
| 186 | + "ENV" |
| 187 | + "ARCHIVE_BUCKET" |
| 188 | + "ARCHIVE_ID" |
| 189 | + ) |
| 190 | + echo ">>> Checking required env vars for fetching the archive from S3..." |
| 191 | + check_env_vars "${REQUIRED_ENV[@]}" |
| 192 | + |
| 193 | + echo ">>> Checking if the archive has already been restored..." |
| 194 | + if [[ -f "$STORAGE_PATH/last_restored_archive" ]]; then |
| 195 | + |
| 196 | + LAST_RESTORED_ARCHIVE=$(cat "$STORAGE_PATH/last_restored_archive") |
| 197 | + |
| 198 | + if [[ "$LAST_RESTORED_ARCHIVE" == "$ARCHIVE_ID" ]]; then |
| 199 | + echo ">>> Archive $ARCHIVE_ID has already been restored. Skipping..." |
| 200 | + else |
| 201 | + fetch_archive "$ARCHIVE_BUCKET" "$ENV" "$ARCHIVE_ID" "$ARCHIVE_PATH" |
| 202 | + fi |
| 203 | + else |
| 204 | + fetch_archive "$ARCHIVE_BUCKET" "$ENV" "$ARCHIVE_ID" "$ARCHIVE_PATH" |
| 205 | + fi |
| 206 | + fi |
| 207 | +fi |
| 208 | +echo ">>> Running the node with the following parameters:" |
| 209 | +echo "Storage path: $STORAGE_PATH" |
| 210 | +echo "Node config: $NODE_CONFIG_PATH" |
| 211 | +echo "Genesis block: $GENESIS_PATH" |
| 212 | +echo "Genesis block hash (SHA256): $(sha256sum "$GENESIS_PATH" | awk '{ print $1 }')" |
| 213 | + |
| 214 | +args+=() |
| 215 | +args+=("--storage" "$STORAGE_PATH") |
| 216 | +args+=("--config" "$NODE_CONFIG_PATH") |
| 217 | +args+=("--genesis-block" "$GENESIS_PATH") |
| 218 | + |
| 219 | +if [[ -n "${LEADER:=}" ]]; then |
| 220 | + echo ">>> Configuring node as leader..." |
| 221 | + |
| 222 | + # shellcheck disable=SC2153 |
| 223 | + if [[ ! -f "$BFT_PATH" ]]; then |
| 224 | + echo "ERROR: BFT is absent at: $BFT_PATH" |
| 225 | + echo ">>> Aborting..." |
| 226 | + exit 1 |
| 227 | + fi |
| 228 | + |
| 229 | + echo ">>> Using BFT at: $BFT_PATH" |
| 230 | + args+=("--secret" "$BFT_PATH") |
| 231 | +fi |
| 232 | + |
| 233 | +# Sleep if DEBUG_SLEEP is set |
| 234 | +debug_sleep |
| 235 | + |
| 236 | +echo "Starting node..." |
| 237 | +exec "/app/jormungandr" "${args[@]}" |
0 commit comments