From 4c37b1dd7e0398fa3a08aadf686425770e31da46 Mon Sep 17 00:00:00 2001 From: illuminatus Date: Sun, 28 Apr 2024 11:28:06 -0700 Subject: [PATCH] Issue/1756 mithril script updates (#27) * syntactic bug in entrypoint.sh #1757 * Remove uneeded UPDATE_CHECK=N exports now that it is a default of the image ENV variables * export G_ACCOUNT so guild-deploy.sh inherits it during forked builds * Set defaults for G_ACCOUNT and GUILD_DEPLOY_BRANCH to simplify manual docker build commands * Fix bug where updating cncli.sh #1756 mithril-client binary command/subcommand changes replace snapshot with cardano-db #1759 * Add reference to MITHRIL_DOWNLOAD for snapshot sync in regular docs * export each line of mithril.env for the signer use tee for logging to not hide issues/errors * Fix for PARTY_ID used in verify_signer_request and verify_signer_signature * Move sanchonet to RELEASE=testing * Update configs and node version support for 8.9.x (#1743) ## Description - [x] Update topology formats - [x] Update baseline node version references - [x] Update node/cli dependency refs and pre-downloaded binaries - [x] Update document references - [x] Update dbsync version * SANCHONET/PREVIEW - adjustments to support sanchonet and preview versions of mithril for guild-deploy.sh downloading. * linting and indentation consistentcy for entrypoint.sh * Workflows to get updated pre/unstable release as well as rebase preview and sanchonet branches. Occurs on push to alpha, workflow dispatch, and scheduled intervals * Docker Image workflow determine cnversion to use based on the guild_deploy_branch name. - When branch preview/sanchonet use prerelease node version. - For any other branch use the original logic for latest (stable) node version. --------- Co-authored-by: RdLrT <3169068+rdlrt@users.noreply.github.com> --- .github/workflows/autoupdate-testing.yml | 204 +++++++++++++ .github/workflows/docker_bin.yml | 9 +- docs/Build/node-cli.md | 2 +- docs/Scripts/mithril-client.md | 41 ++- docs/Scripts/mithril-relay.md | 11 +- docs/Scripts/mithril-signer.md | 17 +- files/docker/node/addons/entrypoint.sh | 53 ++-- files/docker/node/dockerfile_bin | 10 +- scripts/cnode-helper-scripts/cnode.sh | 4 +- scripts/cnode-helper-scripts/guild-deploy.sh | 60 +++- .../cnode-helper-scripts/mithril-client.sh | 256 ++++++----------- scripts/cnode-helper-scripts/mithril-relay.sh | 179 +++++++----- .../cnode-helper-scripts/mithril-signer.sh | 272 ++++++++++-------- scripts/cnode-helper-scripts/mithril.library | 199 +++++++++++++ 14 files changed, 890 insertions(+), 427 deletions(-) create mode 100644 .github/workflows/autoupdate-testing.yml create mode 100644 scripts/cnode-helper-scripts/mithril.library diff --git a/.github/workflows/autoupdate-testing.yml b/.github/workflows/autoupdate-testing.yml new file mode 100644 index 000000000..0aa7ff416 --- /dev/null +++ b/.github/workflows/autoupdate-testing.yml @@ -0,0 +1,204 @@ +name: Autoupdate testing branches +on: + workflow_dispatch: + push: + branches: + - alpha + schedule: + - cron: '0 */12 * * *' + +jobs: + start-summary: + runs-on: ubuntu-latest + steps: + - name: Set summary details + run: | + echo "## Autoupdate Testing Branches Summary Details" >> $GITHUB_STEP_SUMMARY + echo "| Name | Value |" >> $GITHUB_STEP_SUMMARY + echo "| ------------ | ---------------------------------------- |" >> $GITHUB_STEP_SUMMARY + echo "| GitHub Actor | ${GITHUB_ACTOR} |" >> $GITHUB_STEP_SUMMARY + echo "| GitHub Email | ${GITHUB_ACTOR}@users.noreply.github.com |" >> $GITHUB_STEP_SUMMARY + get-node-prerelease: + needs: start-summary + runs-on: ubuntu-latest + strategy: + matrix: + branch: [preview, sanchonet] + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ matrix.branch }} + - name: Configure Git + run: | + git config --global user.name "${GITHUB_ACTOR}" + git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com" + - name: Get current SHA + id: set_sha + run: | + echo "COMMIT_SHA=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + - name: Fetch node pre-release version + run: | + curl -sL https://api.github.com/repos/IntersectMBO/cardano-node/releases | jq -r '.[] | select(.prerelease == true) | .tag_name' | head -1 > files/docker/node/release-versions/cardano-node-prerelease.txt + - name: Assigns pre-release version + run: | + echo "PRERELEASE_VERSION=$(cat files/docker/node/release-versions/cardano-node-prerelease.txt)" >> $GITHUB_ENV + - name: Check for changes + id: git-check + run: | + MODIFIED=$([ -z "`git status --porcelain`" ] && echo "false" || echo "true") + echo "MODIFIED=${MODIFIED}" >> "$GITHUB_OUTPUT" + - name: Set summary details + if: always() + run: | + echo "## Get Node Pre-Release ${{ matrix.branch }}" >> $GITHUB_STEP_SUMMARY + echo "| Name | Value |" >> $GITHUB_STEP_SUMMARY + echo "| -------------------- | ---------------------------------------------------------- |" >> $GITHUB_STEP_SUMMARY + echo "| Prerelease Version | ${PRERELEASE_VERSION} |" >> $GITHUB_STEP_SUMMARY + echo "| Repository Modified | ${{ steps.git-check.outputs.MODIFIED }} |" >> $GITHUB_STEP_SUMMARY + echo "| Modified files | $(git diff --name-only $(echo ${{ steps.set_sha.outputs.COMMIT_SHA }}) | tr '\n' ',') |" >> $GITHUB_STEP_SUMMARY + - name: Commit latest pre-release versions + if: steps.git-check.outputs.MODIFIED == 'true' + run: | + git add files/docker/node/release-versions/cardano-node-prerelease.txt + git commit -am "New mithril pre-release versions: pre-release ${PRERELEASE_VERSION}" + git push + get-mithril-prerelease: + needs: get-node-prerelease + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: preview + - name: Configure Git + run: | + git config --global user.name "${GITHUB_ACTOR}" + git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com" + - name: Get current SHA + id: set_sha + run: | + echo "COMMIT_SHA=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + - name: Fetch Mithril release and pre-release versions + run: | + mithril_release="$(curl -s https://api.github.com/repos/input-output-hk/mithril/releases/latest | jq -r '.tag_name')" + mithril_prerelease="$(curl -s https://api.github.com/repos/input-output-hk/mithril/releases | jq -r '.[] | select(.prerelease == true) | select(.tag_name | endswith("-pre")) | .tag_name' | head -n 1)" + if [[ "${mithril_release}-pre" == "${mithril_prerelease}" ]]; then + echo "${mithril_release}" > files/docker/node/release-versions/mithril-prerelease.txt + PRERELEASE_VERSION=${mithril_release} + echo "PRERELEASE_VERSION=${PRERELEASE_VERSION}" >> $GITHUB_ENV + echo "RELEASE_MATCH=True" >> $GITHUB_ENV + + else + echo "${mithril_prerelease}" > files/docker/node/release-versions/mithril-prerelease.txt + PRERELEASE_VERSION=${mithril_prerelease} + echo "PRERELEASE_VERSION=${PRERELEASE_VERSION}" >> $GITHUB_ENV + echo "RELEASE_MATCH=False" >> $GITHUB_ENV + fi + + - name: Check for changes + id: git-check + run: | + MODIFIED=$([ -z "`git status --porcelain`" ] && echo "false" || echo "true") + echo "MODIFIED=${MODIFIED}" >> "$GITHUB_OUTPUT" + - name: Set summary details + if: always() + run: | + echo "## Get Mithril Pre-Release" >> $GITHUB_STEP_SUMMARY + echo "| Name | Value |" >> $GITHUB_STEP_SUMMARY + echo "| ----------------------------- | -------------------------------------------------------- |" >> $GITHUB_STEP_SUMMARY + echo "| Pre-release version | ${PRERELEASE_VERSION} |" >> $GITHUB_STEP_SUMMARY + echo "| Pre-release matches Release | ${RELEASE_MATCH} |" >> $GITHUB_STEP_SUMMARY + echo "| Repository Modified | ${{ steps.git-check.outputs.MODIFIED }} |" >> $GITHUB_STEP_SUMMARY + echo "| Modified files | $(git diff --name-only $(echo ${{ steps.set_sha.outputs.COMMIT_SHA }}) | tr '\n' ',') |" >> $GITHUB_STEP_SUMMARY + - name: Commit latest pre-release versions + if: steps.git-check.outputs.MODIFIED == 'true' + run: | + git add files/docker/node/release-versions/mithril-prerelease.txt + git commit -am "New mithril pre-release versions: pre-release ${PRERELEASE_VERSION}" + git push + get-mithril-unstable: + needs: get-node-prerelease + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: sanchonet + - name: Configure Git + run: | + git config --global user.name "${GITHUB_ACTOR}" + git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com" + - name: Get current SHA + id: set_sha + run: | + echo "COMMIT_SHA=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + - name: Fetch Mithril unstable version + run: | + curl -sL https://api.github.com/repos/input-output-hk/mithril/releases | jq -r '.[] | select(.prerelease == true and .tag_name == "unstable") | .tag_name' | head -1 > files/docker/node/release-versions/mithril-unstable.txt + - name: Assign unstable version + run: | + UNSTABLE_VERSION=$(cat files/docker/node/release-versions/mithril-unstable.txt) + echo "UNSTABLE_VERSION=${UNSTABLE_VERSION}" >> $GITHUB_ENV + - name: Check for changes + id: git-check + run: | + MODIFIED=$([ -z "`git status --porcelain`" ] && echo "false" || echo "true") + echo "MODIFIED=${MODIFIED}" >> "$GITHUB_OUTPUT" + - name: Set summary details + if: always() + run: | + echo "## Get Mithril Unstable" >> $GITHUB_STEP_SUMMARY + echo "| Name | Value |" >> $GITHUB_STEP_SUMMARY + echo "| -------------------- | ----------------------------------------------------------------------- |" >> $GITHUB_STEP_SUMMARY + echo "| Unstable version | ${UNSTABLE_VERSION} |" >> $GITHUB_STEP_SUMMARY + echo "| Repository Modified | ${{ steps.git-check.outputs.MODIFIED }} |" >> $GITHUB_STEP_SUMMARY + echo "| Modified files | $(git diff --name-only $(echo ${{ steps.set_sha.outputs.COMMIT_SHA }}) | tr '\n' ',') |" >> $GITHUB_STEP_SUMMARY + - name: Commit latest unstable versions + if: steps.git-check.outputs.MODIFIED == 'true' + run: | + git add files/docker/node/release-versions/mithril-unstable.txt + git commit -am "New mithril unstable versions: unstable ${UNSTABLE_VERSION}" + git push + rebase-testing-branches: + needs: [get-node-prerelease, get-mithril-prerelease, get-mithril-unstable] + runs-on: ubuntu-latest + strategy: + matrix: + branch: [preview, sanchonet] + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + fetch-depth: 0 + - name: Configure Git + run: | + git config --global user.name "${GITHUB_ACTOR}" + git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com" + - name: Get current SHA + id: set_sha + run: | + echo "COMMIT_SHA=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + - name: Fetch alpha + run: | + git fetch origin alpha + - name: Rebase on alpha + run: | + git rebase origin/alpha + - name: Check for changes + id: git-check + run: | + MODIFIED=$([ "$(git rev-parse HEAD)" != "$(echo ${{ steps.set_sha.outputs.COMMIT_SHA }})" ] && echo "true" || echo "false") + echo "MODIFIED=${MODIFIED}" >> "$GITHUB_OUTPUT" + - name: Set summary details + if: always() + run: | + echo "## Rebase ${{ matrix.branch }}" >> $GITHUB_STEP_SUMMARY + echo "| Name | Value |" >> $GITHUB_STEP_SUMMARY + echo "| --------------------- | ----------------------------------------------------------------------- |" >> $GITHUB_STEP_SUMMARY + echo "| Repository Modified | ${{ steps.git-check.outputs.MODIFIED }} |" >> $GITHUB_STEP_SUMMARY + echo "| Modified Files | $(git diff --name-only $(echo ${{ steps.set_sha.outputs.COMMIT_SHA }}) | tr '\n' ',') |" >> $GITHUB_STEP_SUMMARY + - name: Push changes + if: steps.git-check.outputs.MODIFIED == 'true' + run: | + git push --force-with-lease diff --git a/.github/workflows/docker_bin.yml b/.github/workflows/docker_bin.yml index 4e260d064..d0dfd9e59 100644 --- a/.github/workflows/docker_bin.yml +++ b/.github/workflows/docker_bin.yml @@ -49,10 +49,14 @@ jobs: id: set_short_sha run: | echo "short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - - name: Get CNVERSION + - name: Set CNVersion id: set_cnversion run: | - echo "cnversion=$(cat files/docker/node/release-versions/cardano-node-latest.txt)" >> $GITHUB_OUTPUT + if [[ "${{ steps.set_guild_deploy_branch.outputs.guild_deploy_branch }}" == "sanchonet" ]]; then + echo "cnversion=$(cat files/docker/node/release-versions/cardano-node-prerelease.txt)" >> "$GITHUB_OUTPUT" + else + echo "cnversion=$(cat files/docker/node/release-versions/cardano-node-latest.txt)" >> "$GITHUB_OUTPUT" + fi build_production: needs: set_environment_vars if: needs.set_environment_vars.outputs.testing == 'false' && needs.set_environment_vars.outputs.guild_deploy_branch == 'master' @@ -137,6 +141,7 @@ jobs: build-args: | G_ACCOUNT=${{ needs.set_environment_vars.outputs.g_account }} GUILD_DEPLOY_BRANCH=${{ needs.set_environment_vars.outputs.guild_deploy_branch }} + CARDANO_NODE_VERSION=${{ needs.set_environment_vars.outputs.cnversion }} - name: Add summary details if: always() run: | diff --git a/docs/Build/node-cli.md b/docs/Build/node-cli.md index 8ec0f5718..c41075c4b 100644 --- a/docs/Build/node-cli.md +++ b/docs/Build/node-cli.md @@ -63,7 +63,7 @@ POOL_NAME="GUILD" #### Start the node -To test starting the node in interactive mode, we will make use of pre-built script `cnode.sh`. This script automatically determines whether to start the node as a relay or block producer (if the required pool keys are present in the `$CNODE_HOME/priv/pool/` as mentioned above). The script contains a user-defined variable `CPU_CORES` which determines the number of CPU cores the node will use upon start-up: +To test starting the node in interactive mode, we will make use of pre-built script `cnode.sh`. This script automatically determines whether to start the node as a relay or block producer (if the required pool keys are present in the `$CNODE_HOME/priv/pool/` as mentioned above). If the `` variable is set to 'Y' it will download the latest snapshot from a Mithril aggregator to speed up the blockchain synchronization. The script contains a user-defined variable `CPU_CORES` which determines the number of CPU cores the node will use upon start-up: ```bash ###################################### diff --git a/docs/Scripts/mithril-client.md b/docs/Scripts/mithril-client.md index 2e4b1f960..32beab383 100644 --- a/docs/Scripts/mithril-client.md +++ b/docs/Scripts/mithril-client.md @@ -1,10 +1,37 @@ `mithril-client.sh` is a script to manage the Mithril client, a tool used to set up the Mithril client environment and manage downloading Mithril snapshots and stake distributions. The main features include: - **environment** - Creates a new `mithril.env` file with all the necessary environment variables for the Mithril client. -- **snapshot** - Download, list all or show a specific available Mithril snapshot. +- **cardano-db** - Download, list all or show a specific available Mithril snapshot. - **stake-distribution** - Download or list available Mithril stake distributions. - **-u** - Skip script update check. +## Usage + +```bash +Usage: bash [-u] [] +A script to run Cardano Mithril Client + +-u Skip script update check overriding UPDATE_CHECK value in env (must be first argument to script) + +Commands: +environment Manage mithril environment file + setup Setup mithril environment file + override Override default variable in the mithril environment file + update Update mithril environment file +cardano-db Interact with Cardano DB + download Download Cardano DB from Mithril snapshot + snapshot Interact with Mithril snapshots + list List available Mithril snapshots + json List availble Mithril snapshots in JSON format + show Show details of a Mithril snapshot + json Show details of a Mithril snapshot in JSON format +stake-distribution Interact with Mithril stake distributions + download Download latest stake distribution + list List available stake distributions + json Output latest Mithril snapshot in JSON format + +``` + ## Preparing a Relay or Block Producer Node To prepare a relay or block producer node, you should follow these steps: @@ -18,7 +45,7 @@ To prepare a relay or block producer node, you should follow these steps: 2. **Download the latest Mithril snapshot:** Once the environment file is set up, you can download the latest Mithril snapshot by running the script with the `snapshot download` command. This snapshot contains the latest state of the Cardano blockchain db from a Mithril Aggregator. ```bash - ./mithril-client.sh snapshot download + ./mithril-client.sh cardano-db download ``` ## Investigating Available Snapshots @@ -28,16 +55,16 @@ You can investigate the available snapshots by using the `snapshot list` and `sn - **List all available Mithril snapshots:** You can list all available Mithril snapshots by running the script with the `snapshot list` command. Add `json` at the end to get the output in JSON format. ```bash - ./mithril-client.sh snapshot list - ./mithril-client.sh snapshot list json + ./mithril-client.sh cardano-dbsnapshot list + ./mithril-client.sh cardano-dbsnapshot list json ``` - **Show details of a specific Mithril snapshot:** You can show details of a specific Mithril snapshot by running the script with the `snapshot show ` command, where `` is the digest of the snapshot. Add `json` at the end to get the output in JSON format. ```bash - ./mithril-client.sh snapshot show - ./mithril-client.sh snapshot show json - ./mithril-client.sh snapshot show json + ./mithril-client.sh cardano-dbsnapshot show + ./mithril-client.sh cardano-dbsnapshot show json + ./mithril-client.sh cardano-dbsnapshot show json ``` ## Managing Stake Distributions diff --git a/docs/Scripts/mithril-relay.md b/docs/Scripts/mithril-relay.md index a7713274a..01454779f 100644 --- a/docs/Scripts/mithril-relay.md +++ b/docs/Scripts/mithril-relay.md @@ -7,12 +7,13 @@ loadbalancer. It provides functionalities such as: ## Usage ```bash -Usage: mithril-relay.sh [-d] [-l] +bash [-d] [-l] [-u] [-h] +A script to setup Cardano Mithril relays -Options: - -d Install squid and configure as a relay - -l Install nginx and configure as a load balancer - -h Show this help text +-d Install squid and configure as a relay +-l Install nginx and configure as a load balancer +-u Skip update check +-h Show this help text ``` # Description diff --git a/docs/Scripts/mithril-signer.md b/docs/Scripts/mithril-signer.md index 1c846d433..4e28d4e6c 100644 --- a/docs/Scripts/mithril-signer.md +++ b/docs/Scripts/mithril-signer.md @@ -5,12 +5,17 @@ environment file to contain variables specific to the Mithril Signer. ## Usage ```bash -Usage: mithril-signer.sh [-d] [-u] - -Options: - -d Deploy mithril-signer as a systemd service - -u Update mithril environment file - -h Show this help text +Usage: bash [-d] [-D] [-e] [-k] [-r] [-s] [-u] [-h] +A script to setup, run and verify Cardano Mithril Signer + +-d Deploy mithril-signer as a systemd service +-D Run mithril-signer as a daemon +-e Update mithril environment file +-k Stop signer using SIGINT +-r Verify signer registration +-s Verify signer signature +-u Skip update check +-h Show this help text ``` # Description diff --git a/files/docker/node/addons/entrypoint.sh b/files/docker/node/addons/entrypoint.sh index e338c0f0a..c50f4d929 100755 --- a/files/docker/node/addons/entrypoint.sh +++ b/files/docker/node/addons/entrypoint.sh @@ -4,8 +4,17 @@ trap 'killall -s SIGINT cardano-node' SIGINT SIGTERM # "docker run --init" to enable the docker init proxy # To manually test: docker kill -s SIGTERM container +declare -A release_map=( + ["mainnet"]="release" + ["preprod"]="release" + ["preview"]="pre-release" + ["guild"]="release" + ["sanchonet"]="testing" +) + head -n 8 ~/.scripts/banner.txt +# shellcheck disable=SC1090 . ~/.bashrc > /dev/null 2>&1 echo "NETWORK: $NETWORK $POOL_NAME $TOPOLOGY"; @@ -17,29 +26,29 @@ echo "NODE: $HOSTNAME - Port:$CNODE_PORT - $POOL_NAME"; cardano-node --version; if [[ "${ENABLE_BACKUP}" == "Y" ]] || [[ "${ENABLE_RESTORE}" == "Y" ]]; then - [[ ! -d "${CNODE_HOME}"/backup/$NETWORK-db ]] && mkdir -p $CNODE_HOME/backup/$NETWORK-db - dbsize=$(du -s $CNODE_HOME/db | awk '{print $1}') - bksizedb=$(du -s $CNODE_HOME/backup/$NETWORK-db 2>/dev/null | awk '{print $1}') - if [[ "${ENABLE_RESTORE}" == "Y" ]] && [[ "$dbsize" -lt "$bksizedb" ]]; then - echo "Backup Started" - cp -rf "${CNODE_HOME}"/backup/"${NETWORK}"-db/* "${CNODE_HOME}"/db 2>/dev/null - echo "Backup Finished" - fi - - if [[ "${ENABLE_BACKUP}" == "Y" ]] && [[ "$dbsize" -gt "$bksizedb" ]]; then - echo "Restore Started" - cp -rf "${CNODE_HOME}"/db/* "${CNODE_HOME}"/backup/"${NETWORK}"-db/ 2>/dev/null - echo "Restore Finished" - fi + [[ ! -d "${CNODE_HOME}"/backup/$NETWORK-db ]] && mkdir -p $CNODE_HOME/backup/$NETWORK-db + dbsize=$(du -s $CNODE_HOME/db | awk '{print $1}') + bksizedb=$(du -s $CNODE_HOME/backup/$NETWORK-db 2>/dev/null | awk '{print $1}') + if [[ "${ENABLE_RESTORE}" == "Y" ]] && [[ "$dbsize" -lt "$bksizedb" ]]; then + echo "Backup Started" + cp -rf "${CNODE_HOME}"/backup/"${NETWORK}"-db/* "${CNODE_HOME}"/db 2>/dev/null + echo "Backup Finished" + fi + + if [[ "${ENABLE_BACKUP}" == "Y" ]] && [[ "$dbsize" -gt "$bksizedb" ]]; then + echo "Restore Started" + cp -rf "${CNODE_HOME}"/db/* "${CNODE_HOME}"/backup/"${NETWORK}"-db/ 2>/dev/null + echo "Restore Finished" + fi fi # Customisation customise () { -find /opt/cardano/cnode/files -name "*config*.json" -print0 | xargs -0 sed -i 's/127.0.0.1/0.0.0.0/g' > /dev/null 2>&1 -grep -i ENABLE_CHATTR /opt/cardano/cnode/scripts/cntools.sh >/dev/null && sed -E -i 's/^#?ENABLE_CHATTR=(true|false)?/ENABLE_CHATTR=false/g' /opt/cardano/cnode/scripts/cntools.sh > /dev/null 2>&1 -grep -i ENABLE_DIALOG /opt/cardano/cnode/scripts/cntools.sh >/dev/null && sed -E -i 's/^#?ENABLE_DIALOG=(true|false)?/ENABLE_DIALOG=false/' /opt/cardano/cnode/scripts/cntools.sh >> /opt/cardano/cnode/scripts/cntools.sh -find /opt/cardano/cnode/files -name "*config*.json" -print0 | xargs -0 sed -i 's/\"hasEKG\": 12788,/\"hasEKG\": [\n \"0.0.0.0\",\n 12788\n],/g' > /dev/null 2>&1 -return 0 + find /opt/cardano/cnode/files -name "*config*.json" -print0 | xargs -0 sed -i 's/127.0.0.1/0.0.0.0/g' > /dev/null 2>&1 + grep -i ENABLE_CHATTR /opt/cardano/cnode/scripts/cntools.sh >/dev/null && sed -E -i 's/^#?ENABLE_CHATTR=(true|false)?/ENABLE_CHATTR=false/g' /opt/cardano/cnode/scripts/cntools.sh > /dev/null 2>&1 + grep -i ENABLE_DIALOG /opt/cardano/cnode/scripts/cntools.sh >/dev/null && sed -E -i 's/^#?ENABLE_DIALOG=(true|false)?/ENABLE_DIALOG=false/' /opt/cardano/cnode/scripts/cntools.sh > /dev/null 2>&1 + find /opt/cardano/cnode/files -name "*config*.json" -print0 | xargs -0 sed -i 's/\"hasEKG\": 12788,/\"hasEKG\": [\n \"0.0.0.0\",\n 12788\n],/g' > /dev/null 2>&1 + return 0 } load_configs () { @@ -52,8 +61,12 @@ if [[ -n "${NETWORK}" ]] ; then else load_configs fi + if [[ -v release_map[$NETWORK] ]] ; then + ln -sf "${HOME}/.local/bin/mithril/${release_map[$NETWORK]}/mithril-signer" "${HOME}"/.local/bin/mithril-signer + ln -sf "${HOME}/.local/bin/mithril/${release_map[$NETWORK]}/mithril-client" "${HOME}"/.local/bin/mithril-client + fi else - echo "Please set a NETWORK environment variable to one of: mainnet / preview / preprod / guild-mainnet / guild" + echo "Please set a NETWORK environment variable to one of: mainnet / preview / preprod / guild-mainnet / guild / sanchonet" echo "mount a '$CNODE_HOME/priv/files' volume containing: mainnet-config.json, mainnet-shelley-genesis.json, mainnet-byron-genesis.json, and mainnet-topology.json " echo "for active nodes set POOL_DIR environment variable where op.cert, hot.skey and vrf.skey files reside. (usually under '${CNODE_HOME}/priv/pool/$POOL_NAME' ) " echo "or just set POOL_NAME environment variable (for default path). " diff --git a/files/docker/node/dockerfile_bin b/files/docker/node/dockerfile_bin index a0e549747..7ecdcf952 100644 --- a/files/docker/node/dockerfile_bin +++ b/files/docker/node/dockerfile_bin @@ -5,8 +5,9 @@ STOPSIGNAL SIGINT LABEL desc="Cardano Node by Guild's Operators" ARG DEBIAN_FRONTEND=noninteractive -ARG G_ACCOUNT -ARG GUILD_DEPLOY_BRANCH +ARG G_ACCOUNT=cardano-community +ARG GUILD_DEPLOY_BRANCH=master +ARG CARDANO_NODE_VERSION USER root WORKDIR / @@ -45,8 +46,8 @@ RUN set -x && apt update \ && mkdir -p /root/.local/bin \ && wget https://raw.githubusercontent.com/${G_ACCOUNT}/guild-operators/${GUILD_DEPLOY_BRANCH}/scripts/cnode-helper-scripts/guild-deploy.sh \ && export SUDO='N' \ - && export UPDATE_CHECK='N' \ && export SKIP_DBSYNC_DOWNLOAD='Y' \ + && export G_ACCOUNT=${G_ACCOUNT} \ && chmod +x ./guild-deploy.sh && ./guild-deploy.sh -b ${GUILD_DEPLOY_BRANCH} -s p \ && ls /opt/ \ && mkdir -p $CNODE_HOME/priv/files \ @@ -58,8 +59,9 @@ RUN set -x && apt update \ RUN set -x && export SUDO='N' \ - && export UPDATE_CHECK='N' \ && export SKIP_DBSYNC_DOWNLOAD='Y' \ + && export G_ACCOUNT=${G_ACCOUNT} \ + && export CARDANO_NODE_VERSION=${CARDANO_NODE_VERSION} \ && ./guild-deploy.sh -b ${GUILD_DEPLOY_BRANCH} -s dcmowx \ && cd /usr/bin \ && wget http://www.vdberg.org/~richard/tcpping \ diff --git a/scripts/cnode-helper-scripts/cnode.sh b/scripts/cnode-helper-scripts/cnode.sh index 865bdb2b9..720f88ade 100755 --- a/scripts/cnode-helper-scripts/cnode.sh +++ b/scripts/cnode-helper-scripts/cnode.sh @@ -65,9 +65,9 @@ pre_startup_sanity() { mithril_snapshot_download() { [[ -z "${MITHRIL_CLIENT}" ]] && MITHRIL_CLIENT="${CNODE_HOME}"/scripts/mithril-client.sh if [[ ! -f "${MITHRIL_CLIENT}" ]] || [[ ! -e "${MITHRIL_CLIENT}" ]]; then - echo "ERROR: Could not locate mithril-client.sh script or script is not executable. Skipping mithril snapshot download!!" + echo "ERROR: Could not locate mithril-client.sh script or script is not executable. Skipping mithril cardano-db snapshot download!!" else - "${MITHRIL_CLIENT}" snapshot download + "${MITHRIL_CLIENT}" cardano-db download fi } diff --git a/scripts/cnode-helper-scripts/guild-deploy.sh b/scripts/cnode-helper-scripts/guild-deploy.sh index c7d149979..cb190b6b7 100755 --- a/scripts/cnode-helper-scripts/guild-deploy.sh +++ b/scripts/cnode-helper-scripts/guild-deploy.sh @@ -109,7 +109,7 @@ set_defaults() { [[ "${SUDO}" = 'Y' && $(id -u) -eq 0 ]] && err_exit "Please run as non-root user." CNODE_HOME="${CNODE_PATH}/${CNODE_NAME}" CNODE_VNAME=$(echo "$CNODE_NAME" | awk '{print toupper($0)}') - CARDANO_NODE_VERSION="8.9.2" + [[ -z ${CARDANO_NODE_VERSION} ]] && CARDANO_NODE_VERSION="8.9.2" REPO="https://github.com/${G_ACCOUNT}/guild-operators" REPO_RAW="https://raw.githubusercontent.com/${G_ACCOUNT}/guild-operators" URL_RAW="${REPO_RAW}/${BRANCH}" @@ -371,7 +371,7 @@ download_cnodebins() { pushd "${HOME}"/tmp >/dev/null || err_exit echo -e "\n Downloading Cardano Node archive created from GitHub.." rm -f cardano-node cardano-address - curl -m 200 -sfL https://github.com/intersectmbo/cardano-node/releases/download/${CARDANO_NODE_VERSION}/cardano-node-${CARDANO_NODE_VERSION}-linux.tar.gz -o cnode.tar.gz || err_exit " Could not download cardano-node release ${CARDANO_NODE_VERSION} from GitHub!" + curl -m 200 -sfL https://github.com/intersectmbo/cardano-node/releases/download/${CARDANO_NODE_VERSION}/cardano-node-${CARDANO_NODE_VERSION%-pre}-linux.tar.gz -o cnode.tar.gz || err_exit " Could not download cardano-node release ${CARDANO_NODE_VERSION} from GitHub!" tar zxf cnode.tar.gz --strip-components 2 ./bin/cardano-node ./bin/cardano-cli ./bin/cardano-submit-api ./bin/bech32 &>/dev/null rm -f cnode.tar.gz [[ -f cardano-node ]] || err_exit " cardano-node archive downloaded but binary (cardano-node) not found after extracting package!" @@ -537,19 +537,50 @@ download_cardanosigner() { } # Download pre-built mithril-signer binary +download_mithril_version() { + local version=$1 + local target_dir=$2 + + echo -e "\n Downloading Mithril Signer/Client ${version}..." + rm -f mithril-signer mithril-client + + if [[ "${version}" == "unstable" ]]; then + local download_url + download_url=$(curl -s https://api.github.com/repos/input-output-hk/mithril/releases | jq -r '.[] | select(.prerelease == true) | select(.tag_name == "unstable") | .assets[] | select(.name | test("mithril-unstable-.*-linux-x64.tar.gz")) | .browser_download_url' | head -n 1) + curl -m 200 -sfL "${download_url}" -o mithril.tar.gz || err_exit " Could not download mithril's ${version} archive from IO github!" + else + curl -m 200 -sfL https://github.com/input-output-hk/mithril/releases/download/${version}/mithril-${version}-linux-x64.tar.gz -o mithril.tar.gz || err_exit " Could not download mithril's ${version} archive from IO github!" + fi + + tar zxf mithril.tar.gz mithril-signer mithril-client &>/dev/null + rm -f mithril.tar.gz + [[ -f mithril-signer ]] || err_exit " mithril archive downloaded but binary (mithril-signer) not found after extracting package!" + [[ -f mithril-client ]] || err_exit " mithril archive downloaded but binary (mithril-client) not found after extracting package!" + mv -t "${target_dir}" mithril-signer mithril-client +} + download_mithril() { - echo -e "\nDownloading Mithril..." - pushd "${HOME}"/tmp >/dev/null || err_exit - mithril_release="$(curl -s https://api.github.com/repos/input-output-hk/mithril/releases/latest | jq -r '.tag_name')" - echo -e "\n Downloading Mithril Signer/Client ${mithril_release}..." - rm -f mithril-signer mithril-client - curl -m 200 -sfL https://github.com/input-output-hk/mithril/releases/download/${mithril_release}/mithril-${mithril_release}-linux-x64.tar.gz -o mithril.tar.gz || err_exit " Could not download mithril's latest release archive from IO github!" - tar zxf mithril.tar.gz mithril-signer mithril-client &>/dev/null - rm -f mithril.tar.gz - [[ -f mithril-signer ]] || err_exit " mithril archive downloaded but binary (mithril-signer) not found after extracting package!" - [[ -f mithril-client ]] || err_exit " mithril archive downloaded but binary (mithril-client) not found after extracting package!" - mv -t "${HOME}"/.local/bin mithril-signer mithril-client - chmod +x "${HOME}"/.local/bin/* + echo -e "\nDownloading Mithril..." + # Create a directory for storing the release, pre-release and testing (unstable) builds + mkdir -p "${HOME}"/.local/bin/mithril/{release,pre-release,testing} -p 2>/dev/null + pushd "${HOME}"/tmp >/dev/null || err_exit + mithril_release="$(curl -s https://api.github.com/repos/input-output-hk/mithril/releases/latest | jq -r '.tag_name')" + # RELEASE + download_mithril_version "${mithril_release}" "${HOME}"/.local/bin/mithril/release + # PRE-RELEASE + mithril_prerelease="$(curl -s https://api.github.com/repos/input-output-hk/mithril/releases | jq -r '.[] | select(.prerelease == true) | select(.tag_name | endswith("-pre")) | .tag_name' | head -n 1)" + + if [[ "${mithril_release}-pre" == "${mithril_prerelease}" ]]; then + echo -e "\nCopying Mithril Signer/Client release to pre-release..." + cp "${HOME}"/.local/bin/mithril/release/* "${HOME}"/.local/bin/mithril/pre-release/ + else + download_mithril_version "${mithril_prerelease}" "${HOME}"/.local/bin/mithril/pre-release + fi + # TESTING + mithril_testing="$(curl -s https://api.github.com/repos/input-output-hk/mithril/releases | jq -r '.[] | select(.prerelease == true) | select(.tag_name == "unstable") | .tag_name')" + download_mithril_version "${mithril_testing}" "${HOME}"/.local/bin/mithril/testing + # MAKE ALL BUILDS EXECUTABLE + chmod +x "${HOME}"/.local/bin/mithril/{release,pre-release,testing}/* } # Create folder structure and set up permissions/ownerships @@ -637,6 +668,7 @@ populate_cnode() { updateWithCustomConfig "mithril-client.sh" updateWithCustomConfig "mithril-relay.sh" updateWithCustomConfig "mithril-signer.sh" + updateWithCustomConfig "mithril.library" find "${CNODE_HOME}/scripts" -name '*.sh' -exec chmod 755 {} \; 2>/dev/null chmod -R 700 "${CNODE_HOME}"/priv 2>/dev/null diff --git a/scripts/cnode-helper-scripts/mithril-client.sh b/scripts/cnode-helper-scripts/mithril-client.sh index 54c9a140c..9c59716b0 100755 --- a/scripts/cnode-helper-scripts/mithril-client.sh +++ b/scripts/cnode-helper-scripts/mithril-client.sh @@ -2,7 +2,7 @@ # shellcheck disable=SC2086 #shellcheck source=/dev/null -. "$(dirname $0)"/env offline +. "$(dirname $0)"/mithril.library ###################################### # User Variables - Change as desired # @@ -15,9 +15,6 @@ # Do NOT modify code below # ###################################### -U_ID=$(id -u) -G_ID=$(id -g) - ##################### # Functions # ##################### @@ -25,8 +22,8 @@ G_ID=$(id -g) usage() { cat <<-EOF - Usage: $(basename "$0") - Script to run Cardano Mithril Client + Usage: $(basename "$0") [-u] [] + A script to run Cardano Mithril Client -u Skip script update check overriding UPDATE_CHECK value in env (must be first argument to script) @@ -35,12 +32,13 @@ usage() { setup Setup mithril environment file override Override default variable in the mithril environment file update Update mithril environment file - snapshot Interact with Mithril snapshots - download Download latest Mithril snapshot - list List available Mithril snapshots - json List availble Mithril snapshots in JSON format - show Show details of a Mithril snapshot - json Show details of a Mithril snapshot in JSON format + cardano-db Interact with Cardano DB + download Download Cardano DB from Mithril snapshot + snapshot Interact with Mithril snapshots + list List available Mithril snapshots + json List availble Mithril snapshots in JSON format + show Show details of a Mithril snapshot + json Show details of a Mithril snapshot in JSON format stake-distribution Interact with Mithril stake distributions download Download latest stake distribution list List available stake distributions @@ -50,62 +48,10 @@ EOF } SKIP_UPDATE=N -[[ $1 = "-u" ]] && SKIP_UPDATE=Y && shift +[[ $1 = "-u" ]] && export SKIP_UPDATE=Y && shift ## mithril environment subcommands -environment_setup() { - local env_file="${CNODE_HOME}/mithril/mithril.env" - - if [[ -f "$env_file" ]]; then - if [[ "$UPDATE_ENVIRONMENT" != "Y" ]]; then - echo "Error: $env_file already exists. To update it, set UPDATE_ENVIRONMENT to 'Y'." >&2 - return 1 - else - echo "Updating $env_file..." - fi - else - echo "Creating $env_file..." - fi - - if [[ ! -d "${CNODE_HOME}/mithril/data-stores" ]]; then - sudo mkdir -p "${CNODE_HOME}"/mithril/data-stores - sudo chown -R "$U_ID":"$G_ID" "${CNODE_HOME}"/mithril 2>/dev/null - fi - if [[ -n "${POOL_NAME}" ]] && [[ "${POOL_NAME}" != "CHANGE_ME" ]]; then - export ERA_READER_ADDRESS=https://raw.githubusercontent.com/input-output-hk/mithril/main/mithril-infra/configuration/${RELEASE}-${NETWORK_NAME,,}/era.addr - export ERA_READER_VKEY=https://raw.githubusercontent.com/input-output-hk/mithril/main/mithril-infra/configuration/${RELEASE}-${NETWORK_NAME,,}/era.vkey - bash -c "cat <<-'EOF' > ${CNODE_HOME}/mithril/mithril.env - KES_SECRET_KEY_PATH=${POOL_DIR}/${POOL_HOTKEY_SK_FILENAME} - OPERATIONAL_CERTIFICATE_PATH=${POOL_DIR}/${POOL_OPCERT_FILENAME} - NETWORK=${NETWORK_NAME,,} - RELEASE=${RELEASE} - AGGREGATOR_ENDPOINT=https://aggregator.${RELEASE}-${NETWORK_NAME,,}.api.mithril.network/aggregator - RUN_INTERVAL=60000 - DB_DIRECTORY=${CNODE_HOME}/db - CARDANO_NODE_SOCKET_PATH=${CARDANO_NODE_SOCKET_PATH} - CARDANO_CLI_PATH=${HOME}/.local/bin/cardano-cli - DATA_STORES_DIRECTORY=${CNODE_HOME}/mithril/data-stores - STORE_RETENTION_LIMITS=5 - ERA_READER_ADAPTER_TYPE=cardano-chain - ERA_READER_ADAPTER_PARAMS=$(jq -nc --arg address "$(wget -q -O - "${ERA_READER_ADDRESS}")" --arg verification_key "$(wget -q -O - "${ERA_READER_VKEY}")" '{"address": $address, "verification_key": $verification_key}') - GENESIS_VERIFICATION_KEY=$(wget -q -O - https://raw.githubusercontent.com/input-output-hk/mithril/main/mithril-infra/configuration/${RELEASE}-${NETWORK_NAME,,}/genesis.vkey) - PARTY_ID=$(cat ${POOL_DIR}/${POOL_ID_FILENAME}) - SNAPSHOT_DIGEST=latest - EOF" - else - bash -c "cat <<-'EOF' > ${CNODE_HOME}/mithril/mithril.env - NETWORK=${NETWORK_NAME,,} - RELEASE=${RELEASE} - AGGREGATOR_ENDPOINT=https://aggregator.${RELEASE}-${NETWORK_NAME,,}.api.mithril.network/aggregator - DB_DIRECTORY=${CNODE_HOME}/db - GENESIS_VERIFICATION_KEY=$(wget -q -O - https://raw.githubusercontent.com/input-output-hk/mithril/main/mithril-infra/configuration/${RELEASE}-${NETWORK_NAME,,}/genesis.vkey) - SNAPSHOT_DIGEST=latest - EOF" - fi - chown $USER:$USER "${CNODE_HOME}"/mithril/mithril.env -} - environment_override() { local var_to_override="$1" local new_value="$2" @@ -121,96 +67,36 @@ environment_override() { sed -i "s|^${var_to_override}=.*|${var_to_override}=${new_value}|" "$env_file" } -pre_startup_sanity() { - if [[ ${UPDATE_CHECK} = Y && ${SKIP_UPDATE} != Y ]]; then - - echo "Checking for script updates..." - - # Check availability of checkUpdate function - if [[ ! $(command -v checkUpdate) ]]; then - echo -e "\nCould not find checkUpdate function in env, make sure you're using official guild docos for installation!" - exit 1 - fi - - # check for env update - ENV_UPDATED=${BATCH_AUTO_UPDATE} - checkUpdate "${PARENT}"/env N N N - case $? in - 1) ENV_UPDATED=Y ;; - 2) exit 1 ;; - esac - - # check for cncli.sh update - checkUpdate "${PARENT}"/cncli.sh ${ENV_UPDATED} - case $? in - 1) $0 "-u" "$@"; exit 0 ;; # re-launch script with same args skipping update check - 2) exit 1 ;; - esac - fi - - REQUIRED_PARAMETERS="Y" - if [[ ! -f "${CNODE_HOME}"/mithril/mithril.env ]]; then - echo "INFO: Mithril environment file not found, creating environment file.." - environment_setup && echo "INFO: Mithril environment file created successfully!!" - elif [[ "${UPDATE_ENVIRONMENT}" == "Y" ]]; then - echo "INFO: Updating mithril environment file.." - environment_setup && echo "INFO: Mithril environment file updated successfully!!" - fi +mithril_init() { + [[ ! -f "${CNODE_HOME}"/mithril/mithril.env ]] && generate_environment_file . "${CNODE_HOME}"/mithril/mithril.env - [[ -z "${NETWORK}" ]] && echo "ERROR: The NETWORK must be set before calling mithril-client!!" && REQUIRED_PARAMETERS="N" - [[ -z "${RELEASE}" ]] && echo "ERROR: Failed to set RELEASE variable, please check NETWORK variable in env file!!" && REQUIRED_PARAMETERS="N" - [[ -z "${CNODE_HOME}" ]] && echo "ERROR: The CNODE_HOME must be set before calling mithril-client!!" && REQUIRED_PARAMETERS="N" - [[ ! -d "${CNODE_HOME}" ]] && echo "ERROR: The CNODE_HOME directory does not exist, please check CNODE_HOME variable in env file!!" && REQUIRED_PARAMETERS="N" - [[ -z "${AGGREGATOR_ENDPOINT}" ]] && echo "ERROR: The AGGREGATOR_ENDPOINT must be set before calling mithril-client!!" && REQUIRED_PARAMETERS="N" - [[ -z "${GENESIS_VERIFICATION_KEY}" ]] && echo "ERROR: The GENESIS_VERIFICATION_KEY must be set before calling mithril-client!!" && REQUIRED_PARAMETERS="N" - [[ ! -x "${MITHRILBIN}" ]] && echo "ERROR: The MITHRILBIN variable does not contain an executable file, please check MITHRILBIN variable in env file!!" && REQUIRED_PARAMETERS="N" - [[ "${REQUIRED_PARAMETERS}" != "Y" ]] && exit 1 - export GENESIS_VERIFICATION_KEY - DOWNLOAD_SNAPSHOT="N" - REMOVE_DB_DIR="N" } -set_defaults() { - [[ -z "${MITHRILBIN}" ]] && MITHRILBIN="${HOME}"/.local/bin/mithril-client - if [[ -z "${NETWORK_NAME}" ]]; then - echo "ERROR: The NETWORK_NAME must be set before mithril-client can download snapshots!!" - exit 1 - else - case "${NETWORK_NAME,,}" in - mainnet|preprod|guild) - RELEASE="release" - ;; - preview) - RELEASE="pre-release" - ;; - *) - echo "ERROR: The NETWORK_NAME must be set to Mainnet, PreProd, Preview, Guild before mithril-client can download snapshots!!" - exit 1 - esac - fi - pre_startup_sanity -} check_db_dir() { # If the DB directory does not exist then set DOWNLOAD_SNAPSHOT to Y if [[ ! -d "${DB_DIRECTORY}" ]]; then echo "INFO: The db directory does not exist.." DOWNLOAD_SNAPSHOT="Y" - # If the DB directory is empty then set DOWNLOAD_SNAPSHOT to Y and REMOVE_DB_DIR to Y + # If the DB directory is empty then set DOWNLOAD_SNAPSHOT to Y elif [[ -d "${DB_DIRECTORY}" ]] && [[ -z "$(ls -A "${DB_DIRECTORY}")" ]] && [[ $(du -cs "${DB_DIRECTORY}"/* 2>/dev/null | awk '/total$/ {print $1}') -eq 0 ]]; then echo "INFO: The db directory is empty.." - REMOVE_DB_DIR="Y" DOWNLOAD_SNAPSHOT="Y" else - echo "INFO: The db directory is not empty.." + echo "INFO: The db directory is not empty, skipping Cardano DB download.." fi } -remove_db_dir() { - # Mithril client errors if the db folder already exists, so remove it if it is empty - if [[ "${REMOVE_DB_DIR}" == "Y" ]]; then - echo "INFO: Removing empty db directory to prepare for snapshot download.." - rmdir "${DB_DIRECTORY}" +cleanup_db_directory() { + echo "WARNING: Download failure, cleaning up DB directory.." + # Safety check to prevent accidental deletion of system files + if [[ -z "${DB_DIRECTORY}" ]]; then + echo "ERROR: DB_DIRECTORY is unset or null." + elif [[ -n "${DB_DIRECTORY}" && "${DB_DIRECTORY}" != "/" && "${DB_DIRECTORY}" != "${CNODE_HOME}" ]]; then + # :? Safety check to prevent accidental deletion of system files, even though initial if block should already prevent this + rm -rf "${DB_DIRECTORY:?}/"* + else + echo "INFO: Skipping cleanup of DB directory: ${DB_DIRECTORY}." fi } @@ -219,18 +105,26 @@ remove_db_dir() { download_snapshot() { if [[ "${DOWNLOAD_SNAPSHOT}" == "Y" ]]; then echo "INFO: Downloading latest mithril snapshot.." - "${MITHRILBIN}" -v --aggregator-endpoint ${AGGREGATOR_ENDPOINT} snapshot download --download-dir ${CNODE_HOME} ${SNAPSHOT_DIGEST} + trap 'cleanup_db_directory' INT + if ! "${MITHRILBIN}" -v --aggregator-endpoint ${AGGREGATOR_ENDPOINT} cardano-db download --download-dir ${CNODE_HOME} --genesis-verification-key ${GENESIS_VERIFICATION_KEY} ${SNAPSHOT_DIGEST} ; then + cleanup_db_directory + exit 1 + fi else - echo "INFO: Skipping snapshot download.." + echo "INFO: Skipping Cardano DB download.." fi } list_snapshots() { - if [[ $1 == "json" ]]; then - "${MITHRILBIN}" -v --aggregator-endpoint ${AGGREGATOR_ENDPOINT} snapshot list --json - else - "${MITHRILBIN}" -v --aggregator-endpoint ${AGGREGATOR_ENDPOINT} snapshot list - fi + local json_flag="" + + for arg in "$@"; do + if [[ $arg == "json" ]]; then + json_flag="--json" + fi + done + + "${MITHRILBIN}" -v --aggregator-endpoint ${AGGREGATOR_ENDPOINT} cardano-db snapshot list $json_flag } show_snapshot() { @@ -250,7 +144,7 @@ show_snapshot() { exit 1 fi - "${MITHRILBIN}" -v --aggregator-endpoint ${AGGREGATOR_ENDPOINT} snapshot show $digest $json_flag + "${MITHRILBIN}" -v --aggregator-endpoint ${AGGREGATOR_ENDPOINT} cardano-db snapshot show $digest $json_flag } ## mithril-stake-distribution subcommands @@ -265,31 +159,39 @@ download_stake_distribution() { } list_stake_distributions() { - if [[ $1 == "json" ]]; then - "${MITHRILBIN}" -v --aggregator-endpoint ${AGGREGATOR_ENDPOINT} mithril-stake-distribution list --json - else - "${MITHRILBIN}" -v --aggregator-endpoint ${AGGREGATOR_ENDPOINT} mithril-stake-distribution list - fi + local json_flag="" + + for arg in "$@"; do + if [[ $arg == "json" ]]; then + json_flag="--json" + fi + done + + "${MITHRILBIN}" -v --aggregator-endpoint ${AGGREGATOR_ENDPOINT} mithril-stake-distribution list $json_flag + } ##################### -# Execution # +# Execution/Main # ##################### +update_check "$@" + +set_defaults + # Parse command line options case $1 in environment) - set_defaults case $2 in setup) - environment_setup + generate_environment_file ;; override) environment_override $3 $4 ;; update) - UPDATE_ENVIRONMENT="Y" - environment_setup + export UPDATE_ENVIRONMENT="Y" + generate_environment_file ;; *) echo "Invalid environment subcommand: $2" >&2 @@ -298,36 +200,38 @@ case $1 in ;; esac ;; - snapshot) - set_defaults + cardano-db) + mithril_init case $2 in download) check_db_dir - remove_db_dir download_snapshot ;; - list) - case $3 in - json) - list_snapshots json + snapshot) + case $3 in + list) + case $4 in + json) + list_snapshots json + ;; + *) + list_snapshots + ;; + esac + ;; + show) + show_snapshot $4 $5 ;; *) - list_snapshots + echo "Invalid snapshot subcommand: $3" >&2 + usage + exit 1 ;; esac - ;; - show) - show_snapshot $3 $4 - ;; - *) - echo "Invalid snapshot subcommand: $2" >&2 - usage - exit 1 - ;; esac ;; stake-distribution) - set_defaults + mithril_init case $2 in download) download_stake_distribution @@ -350,7 +254,7 @@ case $1 in esac ;; *) - echo "Invalid command: $1" >&2 + echo "Invalid $(basename "$0") command: $1" >&2 usage exit 1 ;; diff --git a/scripts/cnode-helper-scripts/mithril-relay.sh b/scripts/cnode-helper-scripts/mithril-relay.sh index 6c104fddf..0207856f4 100755 --- a/scripts/cnode-helper-scripts/mithril-relay.sh +++ b/scripts/cnode-helper-scripts/mithril-relay.sh @@ -1,4 +1,8 @@ #!/bin/bash +# shellcheck disable=SC2086 +#shellcheck source=/dev/null + +. "$(dirname $0)"/mithril.library ###################################### # User Variables - Change as desired # @@ -26,16 +30,18 @@ RELAY_LISTENING_IP=() usage() { cat <<-EOF - $(basename "$0") [-d] [-l] + $(basename "$0") [-d] [-l] [-u] [-h] + A script to setup Cardano Mithril relays - Cardano Mithril relay wrapper script!! -d Install squid and configure as a relay -l Install nginx and configure as a load balancer + -u Skip update check -h Show this help text EOF } + generate_nginx_conf() { sudo bash -c "cat > /etc/nginx/nginx.conf <<'EOF' worker_processes 1; @@ -123,76 +129,103 @@ generate_squid_conf() { EOF" } +deploy_nginx_load_balancer() { + # Install nginx and configure load balancing + echo -e "\nInstalling nginx load balancer" + sudo apt-get update + sudo apt-get install -y nginx + + # Read the listening IP addresses from user input + while true; do + read -r -p "Enter the IP address of a relay: " ip + RELAY_LISTENING_IP+=("${ip}") + read -r -p "Are there more relays? (y/n) " yn + case ${yn} in + [Nn]*) break ;; + *) continue ;; + esac + done + + # Read the listening IP for the load balancer + read -r -p "Enter the IP address of the load balancer (press Enter to use default 127.0.0.1): " SIDECAR_LISTENING_IP + SIDECAR_LISTENING_IP=${SIDECAR_LISTENING_IP:-127.0.0.1} + echo "Using IP address ${SIDECAR_LISTENING_IP} for the load balancer configuration." + + # Read the listening port from user input + read -r -p "Enter the relay's listening port (press Enter to use default 3132): " RELAY_LISTENING_PORT + RELAY_LISTENING_PORT=${RELAY_LISTENING_PORT:-3132} + echo "Using port ${RELAY_LISTENING_PORT} for relay's listening port." + + # Generate the nginx configuration file + generate_nginx_conf + # Restart nginx and check status + echo -e "\nStarting Mithril relay sidecar (nginx load balancer)" + sudo systemctl restart nginx + sudo systemctl status nginx + +} + +deploy_squid_proxy() { + # Install squid and make a backup of the config file + echo -e "\nInstalling squid proxy" + sudo apt-get update + sudo apt-get install -y squid + sudo cp /etc/squid/squid.conf /etc/squid/squid.conf.bak + + # Read the listening IP addresses from user input + while true; do + read -r -p "Enter the IP address of your Block Producer: " ip + BLOCK_PRODUCER_IP+=("${ip}") + read -r -p "Are there more block producers? (y/n) " yn + case ${yn} in + [Nn]*) break ;; + *) continue ;; + esac + done + + # Read the listening port from user input + read -r -p "Enter the relay's listening port (press Enter to use default 3132): " RELAY_LISTENING_PORT + RELAY_LISTENING_PORT=${RELAY_LISTENING_PORT:-3132} + echo "Using port ${RELAY_LISTENING_PORT} for relay's listening port." + generate_squid_conf + + # Restart squid and check status + echo -e "\nStarting Mithril relay (squid proxy)" + sudo systemctl restart squid + sudo systemctl status squid + + # Inform the user to create the appropriate firewall rule + for ip in "${RELAY_LISTENING_IP[@]}"; do + echo "Create the appropriate firewall rule: sudo ufw allow from ${ip} to any port ${RELAY_LISTENING_PORT} proto tcp" + done +} + +stop_relays() { + echo " Stopping squid proxy and nginx load balancers.." + sudo systemctl stop squid 2>/dev/null + sudo systemctl stop nginx 2>/dev/null + sleep 5 + exit 0 +} + +##################### +# Execution/Main # +##################### + # Parse command line arguments -while getopts :dlh opt; do +while getopts :dlsuh opt; do case ${opt} in d) - # Install squid and make a backup of the config file - echo -e "\nInstalling squid proxy" - sudo apt-get update - sudo apt-get install -y squid - sudo cp /etc/squid/squid.conf /etc/squid/squid.conf.bak - - # Read the listening IP addresses from user input - while true; do - read -r -p "Enter the IP address of your Block Producer: " ip - BLOCK_PRODUCER_IP+=("${ip}") - read -r -p "Are there more block producers? (y/n) " yn - case ${yn} in - [Nn]*) break ;; - *) continue ;; - esac - done - - # Read the listening port from user input - read -r -p "Enter the relay's listening port (press Enter to use default 3132): " RELAY_LISTENING_PORT - RELAY_LISTENING_PORT=${RELAY_LISTENING_PORT:-3132} - echo "Using port ${RELAY_LISTENING_PORT} for relay's listening port." - generate_squid_conf - - # Restart squid and check status - echo -e "\nStarting Mithril relay (squid proxy)" - sudo systemctl restart squid - sudo systemctl status squid - - # Inform the user to create the appropriate firewall rule - for ip in "${RELAY_LISTENING_IP[@]}"; do - echo "Create the appropriate firewall rule: sudo ufw allow from ${ip} to any port ${RELAY_LISTENING_PORT} proto tcp" - done + INSTALL_SQUID_PROXY=Y ;; l) - # Install nginx and configure load balancing - echo -e "\nInstalling nginx load balancer" - sudo apt-get update - sudo apt-get install -y nginx - - # Read the listening IP addresses from user input - while true; do - read -r -p "Enter the IP address of a relay: " ip - RELAY_LISTENING_IP+=("${ip}") - read -r -p "Are there more relays? (y/n) " yn - case ${yn} in - [Nn]*) break ;; - *) continue ;; - esac - done - - # Read the listening IP for the load balancer - read -r -p "Enter the IP address of the load balancer (press Enter to use default 127.0.0.1): " SIDECAR_LISTENING_IP - SIDECAR_LISTENING_IP=${SIDECAR_LISTENING_IP:-127.0.0.1} - echo "Using IP address ${SIDECAR_LISTENING_IP} for the load balancer configuration." - - # Read the listening port from user input - read -r -p "Enter the relay's listening port (press Enter to use default 3132): " RELAY_LISTENING_PORT - RELAY_LISTENING_PORT=${RELAY_LISTENING_PORT:-3132} - echo "Using port ${RELAY_LISTENING_PORT} for relay's listening port." - - # Generate the nginx configuration file - generate_nginx_conf - # Restart nginx and check status - echo -e "\nStarting Mithril relay sidecar (nginx load balancer)" - sudo systemctl restart nginx - sudo systemctl status nginx + INSTALL_NGINX_LOAD_BALANCER=Y + ;; + u) + export SKIP_UPDATE='Y' + ;; + s) + STOP_RELAYS=Y ;; h) usage @@ -220,3 +253,15 @@ if [[ ${OPTIND} -eq 1 ]]; then usage exit 1 fi + +[[ "${STOP_RELAYS}" == "Y" ]] && stop_relays + +update_check "$@" + +if [[ ${INSTALL_SQUID_PROXY} = Y ]]; then + deploy_squid_proxy +fi + +if [[ ${INSTALL_NGINX_LOAD_BALANCER} = Y ]]; then + deploy_nginx_load_balancer +fi diff --git a/scripts/cnode-helper-scripts/mithril-signer.sh b/scripts/cnode-helper-scripts/mithril-signer.sh index 9670460c3..82c0f27c0 100755 --- a/scripts/cnode-helper-scripts/mithril-signer.sh +++ b/scripts/cnode-helper-scripts/mithril-signer.sh @@ -2,7 +2,7 @@ # shellcheck disable=SC2086 #shellcheck source=/dev/null -. "$(dirname $0)"/env offline +. "$(dirname $0)"/mithril.library ###################################### # User Variables - Change as desired # @@ -16,9 +16,6 @@ # Do NOT modify code below # ###################################### -U_ID=$(id -u) -G_ID=$(id -g) - ##################### # Functions # ##################### @@ -26,102 +23,36 @@ G_ID=$(id -g) usage() { cat <<-EOF - Usage: $(basename "$0") [-d] [-u] + Usage: $(basename "$0") [-d] [-D] [-e] [-k] [-r] [-s] [-u] [-h] + A script to setup, run and verify Cardano Mithril Signer - Cardano Mithril signer wrapper script !! -d Deploy mithril-signer as a systemd service - -u Update mithril environment file + -D Run mithril-signer as a daemon + -e Update mithril environment file + -k Stop signer using SIGINT + -r Verify signer registration + -s Verify signer signature + -u Skip update check -h Show this help text EOF } -set_defaults() { - [[ -z "${MITHRILBIN}" ]] && MITHRILBIN="${HOME}"/.local/bin/mithril-signer - if [[ -z "${POOL_NAME}" ]] || [[ "${POOL_NAME}" == "CHANGE_ME" ]]; then - echo "ERROR: The POOL_NAME must be set before deploying mithril-signer as a systemd service!!" - exit 1 - else - case "${NETWORK_NAME,,}" in - mainnet|preprod|guild) - RELEASE="release" - ;; - preview) - RELEASE="pre-release" - ;; - *) - echo "ERROR: The NETWORK_NAME must be set to Mainnet, PreProd, Preview, or Guild before mithril-signer can be deployed!!" - exit 1 - esac - fi -} - -pre_startup_sanity() { - [[ ! -f "${MITHRILBIN}" ]] && MITHRILBIN="$(command -v mithril-signer)" - if [[ ! -S "${CARDANO_NODE_SOCKET_PATH}" ]]; then - echo "ERROR: Could not locate socket file at ${CARDANO_NODE_SOCKET_PATH}, the node may not have completed startup !!" - exit 1 - fi +mithril_init() { + [[ ! -f "${CNODE_HOME}"/mithril/mithril.env ]] && generate_environment_file + for line in $(cat "${CNODE_HOME}"/mithril/mithril.env); do + export "${line}" + done # Move logs to archive - [[ -f "${LOG_DIR}"/mithril-signer.log ]] && mv "${LOG_DIR}"/mithril-signer.log "${LOG_DIR}"/archive/ -} - -get_relay_endpoint() { - read -r -p "Enter the IP address of the relay endpoint: " RELAY_ENDPOINT_IP - read -r -p "Enter the port of the relay endpoint (press Enter to use default 3132): " RELAY_PORT - RELAY_PORT=${RELAY_PORT:-3132} - echo "Using RELAY_ENDPOINT=${RELAY_ENDPOINT_IP}:${RELAY_PORT} for the Mithril signer relay endpoint." -} - -generate_environment_file() { - if [[ ! -d "${CNODE_HOME}/mithril/data-stores" ]]; then - sudo mkdir -p "${CNODE_HOME}"/mithril/data-stores - sudo chown -R "$U_ID":"$G_ID" "${CNODE_HOME}"/mithril 2>/dev/null - fi - # Inquire about the relay endpoint - read -r -p "Are you using a relay endpoint? (y/n, press Enter to use default y): " ENABLE_RELAY_ENDPOINT - ENABLE_RELAY_ENDPOINT=${ENABLE_RELAY_ENDPOINT:-y} - if [[ "${ENABLE_RELAY_ENDPOINT}" == "y" ]]; then - get_relay_endpoint - else - echo "Using a naive Mithril configuration without a mithril relay." - fi - - # Generate the full set of environment variables required by Mithril signer use case - export ERA_READER_ADDRESS=https://raw.githubusercontent.com/input-output-hk/mithril/main/mithril-infra/configuration/${RELEASE}-${NETWORK_NAME,,}/era.addr - export ERA_READER_VKEY=https://raw.githubusercontent.com/input-output-hk/mithril/main/mithril-infra/configuration/${RELEASE}-${NETWORK_NAME,,}/era.vkey - sudo bash -c "cat <<-'EOF' > ${CNODE_HOME}/mithril/mithril.env - KES_SECRET_KEY_PATH=${POOL_DIR}/${POOL_HOTKEY_SK_FILENAME} - OPERATIONAL_CERTIFICATE_PATH=${POOL_DIR}/${POOL_OPCERT_FILENAME} - NETWORK=${NETWORK_NAME,,} - RELEASE=${RELEASE} - AGGREGATOR_ENDPOINT=https://aggregator.${RELEASE}-${NETWORK_NAME,,}.api.mithril.network/aggregator - RUN_INTERVAL=60000 - DB_DIRECTORY=${CNODE_HOME}/db - CARDANO_NODE_SOCKET_PATH=${CARDANO_NODE_SOCKET_PATH} - CARDANO_CLI_PATH=${HOME}/.local/bin/cardano-cli - DATA_STORES_DIRECTORY=${CNODE_HOME}/mithril/data-stores - STORE_RETENTION_LIMITS=5 - ERA_READER_ADAPTER_TYPE=cardano-chain - ERA_READER_ADAPTER_PARAMS=$(jq -nc --arg address "$(wget -q -O - "${ERA_READER_ADDRESS}")" --arg verification_key "$(wget -q -O - "${ERA_READER_VKEY}")" '{"address": $address, "verification_key": $verification_key}') - GENESIS_VERIFICATION_KEY=$(wget -q -O - https://raw.githubusercontent.com/input-output-hk/mithril/main/mithril-infra/configuration/${RELEASE}-${NETWORK_NAME,,}/genesis.vkey) - PARTY_ID=$(cat ${POOL_DIR}/${POOL_ID_FILENAME}) - SNAPSHOT_DIGEST=latest - EOF" && sudo chown $USER:$USER "${CNODE_HOME}"/mithril/mithril.env - - if [[ "${ENABLE_RELAY_ENDPOINT}" == "y" ]]; then - sudo bash -c "echo RELAY_ENDPOINT=http://${RELAY_ENDPOINT_IP}:${RELAY_PORT} >> ${CNODE_HOME}/mithril/mithril.env" - fi + [[ -d "${LOG_DIR}"/archive ]] || mkdir -p "${LOG_DIR}"/archive + [[ -f "${LOG_DIR}"/$(basename "${0::-3}").log ]] && mv "${LOG_DIR}/$(basename "${0::-3}")".log "${LOG_DIR}"/archive/ ; touch "${LOG_DIR}/$(basename "${0::-3}")".log } deploy_systemd() { - echo "Creating ${CNODE_VNAME}-mithril-signer systemd service environment file.." - if [[ ! -f "${CNODE_HOME}"/mithril/mithril.env ]]; then - generate_environment_file && echo "Mithril environment file created successfully!!" - fi + echo "Creating ${CNODE_VNAME}-$(basename "${0::-3}") systemd service environment file.." - echo "Deploying ${CNODE_VNAME}-mithril-signer as systemd service.." - sudo bash -c "cat <<-'EOF' > /etc/systemd/system/${CNODE_VNAME}-mithril-signer.service + echo "Deploying ${CNODE_VNAME}-$(basename "${0::-3}") as systemd service.." + sudo bash -c "cat <<-'EOF' > /etc/systemd/system/${CNODE_VNAME}-$(basename "${0::-3}").service [Unit] Description=Cardano Mithril signer service StartLimitIntervalSec=0 @@ -136,35 +67,116 @@ deploy_systemd() { RestartSec=60 User=${USER} EnvironmentFile=${CNODE_HOME}/mithril/mithril.env - ExecStart=/bin/bash -l -c \"exec ${HOME}/.local/bin/mithril-signer -vv\" + ExecStart=/bin/bash -l -c \"exec ${HOME}/.local/bin/$(basename "${0::-3}") -vv\" KillSignal=SIGINT SuccessExitStatus=143 StandardOutput=syslog StandardError=syslog - SyslogIdentifier=${CNODE_VNAME}-mithril-signer + SyslogIdentifier=${CNODE_VNAME}-$(basename "${0::-3}") TimeoutStopSec=5 KillMode=mixed [Install] WantedBy=multi-user.target - EOF" && echo "${CNODE_VNAME}-mithril-signer.service deployed successfully!!" && sudo systemctl daemon-reload && sudo systemctl enable ${CNODE_VNAME}-mithril-signer.service + EOF" && echo "${CNODE_VNAME}-$(basename "${0::-3}").service deployed successfully!!" && sudo systemctl daemon-reload && sudo systemctl enable ${CNODE_VNAME}-"$(basename "${0::-3}")".service +} + +stop_signer() { + CNODE_PID=$(pgrep -fn "$(basename ${CNODEBIN}).*.--port ${CNODE_PORT}" 2>/dev/null) # env was only called in offline mode + kill -2 ${CNODE_PID} 2>/dev/null + # touch clean "${CNODE_HOME}"/db/clean # Disabled as it's a bit hacky, but only runs when SIGINT is passed to node process. Should not be needed if node does it's job + echo " Sending SIGINT to $(basename "${0::-3}") process.." + sleep 5 + exit 0 } -################### -# Execution # -################### + +user_interrupt_received() { + echo " SIGINT received, stopping $(basename "${0::-3}").." |tee -a "${LOG_DIR}/$(basename "${0::-3}")".log 2>&1 + stop_signer + +} + +verify_signer_registration() { + set -e + + if [ -z "$AGGREGATOR_ENDPOINT" ] || [ -z "$PARTY_ID" ]; then + echo ">> ERROR: Required environment variables AGGREGATOR_ENDPOINT and/or PARTY_ID are not set." + exit 1 + fi + + CURRENT_EPOCH=$(curl -s "$AGGREGATOR_ENDPOINT/epoch-settings" -H 'accept: application/json' | jq -r '.epoch') + SIGNERS_REGISTERED_RESPONSE=$(curl -s "$AGGREGATOR_ENDPOINT/signers/registered/$CURRENT_EPOCH" -H 'accept: application/json') + + if echo "$SIGNERS_REGISTERED_RESPONSE" | grep -q "$PARTY_ID"; then + echo ">> Congrats, your signer node is registered!" + else + echo ">> Oops, your signer node is not registered. Party ID not found among the signers registered at epoch ${CURRENT_EPOCH}." + fi + +} + +verify_signer_signature() { + set -e + + if [ -z "$AGGREGATOR_ENDPOINT" ] || [ -z "$PARTY_ID" ]; then + echo ">> ERROR: Required environment variables AGGREGATOR_ENDPOINT and/or PARTY_ID are not set." + exit 1 + fi + + CERTIFICATES_RESPONSE=$(curl -s "$AGGREGATOR_ENDPOINT/certificates" -H 'accept: application/json') + CERTIFICATES_COUNT=$(echo "$CERTIFICATES_RESPONSE" | jq '. | length') + + echo "$CERTIFICATES_RESPONSE" | jq -r '.[] | .hash' | while read -r HASH; do + RESPONSE=$(curl -s "$AGGREGATOR_ENDPOINT/certificate/$HASH" -H 'accept: application/json') + SIGNER_COUNT=$(echo "$RESPONSE" | jq '.metadata.signers | length') + for (( i=0; i < SIGNER_COUNT; i++ )); do + PARTY_ID_RESPONSE=$(echo "$RESPONSE" | jq -r ".metadata.signers[$i].party_id") + if [[ "$PARTY_ID_RESPONSE" == "$PARTY_ID" ]]; then + echo ">> Congrats, you have signed this certificate: $AGGREGATOR_ENDPOINT/certificate/$HASH !" + exit 1 + fi + done + done + + echo ">> Oops, your party id was not found in the last ${CERTIFICATES_COUNT} certificates. Please try again later." + +} + + +##################### +# Execution / Main # +##################### # Parse command line options -while getopts :duh opt; do +while getopts :dDekrsuh opt; do case ${opt} in - d ) DEPLOY_SYSTEMD="Y" ;; - u ) UPDATE_ENVIRONMENT="Y" ;; + d ) + DEPLOY_SYSTEMD="Y" ;; + D ) + SIGNER_DAEMON="Y" + ;; + e ) + export UPDATE_ENVIRONMENT="Y" + ;; + k ) + STOP_SIGNER="Y" + ;; + r ) + VERIFY_REGISTRATION="Y" + ;; + s ) + VERIFY_SIGNATURE="Y" + ;; + u ) + export SKIP_UPDATE="Y" + ;; h) usage exit 0 ;; \?) - echo "Invalid option: -${OPTARG}" >&2 + echo "Invalid $(basename "$0") option: -${OPTARG}" >&2 usage exit 1 ;; @@ -176,32 +188,46 @@ while getopts :duh opt; do esac done -# Check if env file is missing in current folder (no update checks as will mostly run as daemon), source env if present -[[ ! -f "$(dirname $0)"/env ]] && echo -e "\nCommon env file missing, please ensure latest guild-deploy.sh was run and this script is being run from ${CNODE_HOME}/scripts folder! \n" && exit 1 -. "$(dirname $0)"/env -case $? in - 1) echo -e "ERROR: Failed to load common env file\nPlease verify set values in 'User Variables' section in env file or log an issue on GitHub" && exit 1;; - 2) clear ;; -esac +[[ "${STOP_SIGNER}" == "Y" ]] && stop_signer + +# Check for updates +update_check "$@" # Set defaults and do basic sanity checks set_defaults + + #Deploy systemd if -d argument was specified -if [[ "${UPDATE_ENVIRONMENT}" == "Y" && "${DEPLOY_SYSTEMD}" == "Y" ]]; then - generate_environment_file && echo "Environment file updated successfully" && deploy_systemd && echo "Mithril signer service successfully deployed" && exit 0 - exit 2 -elif [[ "${UPDATE_ENVIRONMENT}" == "Y" ]]; then - generate_environment_file && echo "Environment file updated successfully" && exit 0 - exit 2 -elif [[ "${DEPLOY_SYSTEMD}" == "Y" ]]; then - deploy_systemd && echo "Mithril signer service successfully deployed" && exit 0 - exit 2 -fi - -pre_startup_sanity - -# Run Mithril Signer Server -echo "Sourcing the Mithril Signer environment file.." -. "${CNODE_HOME}"/mithril/mithril.env -echo "Starting Mithril Signer Server.." -"${MITHRILBIN}" -vvv >> "${LOG_DIR}"/mithril-signer.log 2>&1 +if [[ "${UPDATE_ENVIRONMENT}" == "Y" ]]; then + generate_environment_file + exit 0 +else + mithril_init + if [[ "${DEPLOY_SYSTEMD}" == "Y" ]]; then + if deploy_systemd ; then + echo "Mithril signer Systemd service successfully deployed" + exit 0 + else + echo "Failed to deploy Mithril signer Systemd service" + exit 2 + fi + elif [[ "${VERIFY_REGISTRATION}" == "Y" ]]; then + # Verify signer registration + echo "Verifying Mithril Signer registration.." + verify_signer_registration + exit 0 + elif [[ "${VERIFY_SIGNATURE}" == "Y" ]]; then + # Verify signer signature + echo "Verifying Mithril Signer signature.." + verify_signer_signature + exit 0 + elif [[ "${SIGNER_DAEMON}" == "Y" ]]; then + # Run Mithril Signer Server + echo "Starting Mithril Signer Server.." + trap 'user_interrupt_received' INT + if ! "${MITHRILBIN}" -vv | tee -a "${LOG_DIR}/$(basename "${0::-3}")".log 2>&1 ; then + echo "Failed to start Mithril Signer Server" | tee -a "${LOG_DIR}/$(basename "${0::-3}")".log 2>&1 + exit 1 + fi + fi +fi \ No newline at end of file diff --git a/scripts/cnode-helper-scripts/mithril.library b/scripts/cnode-helper-scripts/mithril.library new file mode 100644 index 000000000..2619a6dea --- /dev/null +++ b/scripts/cnode-helper-scripts/mithril.library @@ -0,0 +1,199 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2034,SC2086,SC2230,SC2206,SC2140,SC2059,SC2154 +#shellcheck source=/dev/null + +###################################### +# Do NOT modify code below # +###################################### + +. "$(dirname $0)"/env offline + +U_ID=$(id -u) +G_ID=$(id -g) +MITHRILBIN="${HOME}"/.local/bin/$(basename "${0::-3}") + +compare_versions() { + local min_version=$1 + local test_version=$2 + if [[ $(printf '%s\n' "$min_version" "$test_version" | sort -V | head -n1) = "$min_version" ]]; then + return 0 + else + return 1 + fi +} + +set_node_minimum_version() { + response_file=$(mktemp) + status_code=$(curl -s -o "$response_file" -w "%{http_code}" https://raw.githubusercontent.com/input-output-hk/mithril/${MITHRIL_LATEST_VERSION}/networks.json) + + if [[ "$status_code" -eq 404 ]]; then + NODE_MINIMUM_VERSION="" + else + NODE_MINIMUM_VERSION=$(jq -r ".${NETWORK}.\"cardano-minimum-version\".\"mithril-signer\"" "$response_file") + fi + rm -f "$response_file" +} + +update_check() { + # Check availability of checkUpdate function + if [[ ! $(command -v checkUpdate) ]]; then + echo -e "\nCould not find checkUpdate function in env, make sure you're using official guild docos for installation!" + exit 1 + fi + # Check if flag is set by script to skip update check + [[ ${SKIP_UPDATE} == Y ]] && return 0 + # Check if flag is set by user as a global (container environments etc.) to skip update check + if [[ ${UPDATE_CHECK} = Y ]]; then + echo "Checking for script updates..." + # check for env update + ENV_UPDATED=${BATCH_AUTO_UPDATE} + checkUpdate "${PARENT}"/env N N N + case $? in + 1) ENV_UPDATED=Y ;; + 2) exit 1 ;; + esac + # check for mithril.library update + checkUpdate "${PARENT}"/mithril.library N N N + # borrow ENV_UPDATED for mithril.library updates + case $? in + 1) ENV_UPDATED=Y ;; + 2) exit 1 ;; + esac + # check the script update + checkUpdate "${PARENT}"/"$(basename "$0")" ${ENV_UPDATED} + case $? in + 1) echo ""; $0 "-u" "$@"; exit 0 ;; # re-launch script with same args skipping update check + 2) exit 1 ;; + esac + fi +} + + +set_defaults() { + MITHRIL_LATEST_VERSION=$(curl -s https://raw.githubusercontent.com/cardano-community/guild-operators/alpha/files/docker/node/release-versions/mithril-latest.txt) + set_node_minimum_version + NODE_CURRENT_VERSION=$(cardano-node --version | awk 'NR==1{print $2}') + + [[ -z "${MITHRILBIN}" ]] && MITHRILBIN="${HOME}"/.local/bin/"$(basename "${0::-3}")" + if [[ $(basename "${0::-3}") == "mithril-signer" ]] && { [[ -z "${POOL_NAME}" ]] || [[ "${POOL_NAME}" == "CHANGE_ME" ]]; }; then + echo "ERROR: The POOL_NAME must be set before deploying mithril-signer as a systemd service!!" + exit 1 + else + case "${NETWORK_NAME,,}" in + mainnet|preprod|guild) + RELEASE="release" + ;; + preview) + RELEASE="pre-release" + ;; + sanchonet) + RELEASE="testing" + ;; + *) + echo "ERROR: The NETWORK_NAME must be set to mainnet, preprod, preview, or sanchonet before $(basename "${0::-3}") can be deployed!!" + exit 1 + esac + fi + AGGREGATOR_ENDPOINT=https://aggregator.${RELEASE}-${NETWORK_NAME,,}.api.mithril.network/aggregator + GENESIS_VERIFICATION_KEY=$(wget -q -O - https://raw.githubusercontent.com/input-output-hk/mithril/main/mithril-infra/configuration/${RELEASE}-${NETWORK_NAME,,}/genesis.vkey) +} + +create_data_stores_directory() { + if [[ ! -d "${CNODE_HOME}/mithril/data-stores" ]]; then + sudo mkdir -p "${CNODE_HOME}"/mithril/data-stores + sudo chown -R "$U_ID":"$G_ID" "${CNODE_HOME}"/mithril 2>/dev/null + fi +} + +set_env_file_ownership() { + chown $USER:$USER "${CNODE_HOME}"/mithril/mithril.env +} + + +check_mithril_environment_file_exists() { + local env_file="${CNODE_HOME}/mithril/mithril.env" + + if [[ -f "$env_file" ]]; then + if [[ "$UPDATE_ENVIRONMENT" != "Y" ]]; then + echo "Error: $env_file already exists. To update it, set UPDATE_ENVIRONMENT to 'Y'." >&2 + return 1 + else + echo "Updating $env_file..." + fi + else + echo "Creating $env_file..." + fi +} + +get_relay_endpoint() { + read -r -p "Enter the IP address of the relay endpoint: " RELAY_ENDPOINT_IP + read -r -p "Enter the port of the relay endpoint (press Enter to use default 3132): " RELAY_PORT + RELAY_PORT=${RELAY_PORT:-3132} + echo "Using RELAY_ENDPOINT=${RELAY_ENDPOINT_IP}:${RELAY_PORT} for the Mithril signer relay endpoint." +} + +update_mithril_environment_for_signer() { + echo "Info: Setting all environment variables, supporting the Mithril signer use case." + # Inquire about the relay endpoint + read -r -p "Are you using a relay endpoint? (y/n, press Enter to use default y): " ENABLE_RELAY_ENDPOINT + ENABLE_RELAY_ENDPOINT=${ENABLE_RELAY_ENDPOINT:-y} + if [[ "${ENABLE_RELAY_ENDPOINT}" == "y" ]]; then + get_relay_endpoint + else + echo "Using a naive Mithril configuration without a mithril relay." + fi + # Generate the full set of environment variables required by Mithril signer use case + export ERA_READER_ADDRESS=https://raw.githubusercontent.com/input-output-hk/mithril/main/mithril-infra/configuration/${RELEASE}-${NETWORK_NAME,,}/era.addr + export ERA_READER_VKEY=https://raw.githubusercontent.com/input-output-hk/mithril/main/mithril-infra/configuration/${RELEASE}-${NETWORK_NAME,,}/era.vkey + sudo bash -c "cat <<-'EOF' > ${CNODE_HOME}/mithril/mithril.env + KES_SECRET_KEY_PATH=${POOL_DIR}/${POOL_HOTKEY_SK_FILENAME} + OPERATIONAL_CERTIFICATE_PATH=${POOL_DIR}/${POOL_OPCERT_FILENAME} + NETWORK=${NETWORK_NAME,,} + RELEASE=${RELEASE} + AGGREGATOR_ENDPOINT=https://aggregator.${RELEASE}-${NETWORK_NAME,,}.api.mithril.network/aggregator + RUN_INTERVAL=60000 + DB_DIRECTORY=${CNODE_HOME}/db + CARDANO_NODE_SOCKET_PATH=${CARDANO_NODE_SOCKET_PATH} + CARDANO_CLI_PATH=${HOME}/.local/bin/cardano-cli + DATA_STORES_DIRECTORY=${CNODE_HOME}/mithril/data-stores + STORE_RETENTION_LIMITS=5 + ERA_READER_ADAPTER_TYPE=cardano-chain + ERA_READER_ADAPTER_PARAMS=$(jq -nc --arg address "$(wget -q -O - "${ERA_READER_ADDRESS}")" --arg verification_key "$(wget -q -O - "${ERA_READER_VKEY}")" '{"address": $address, "verification_key": $verification_key}') + GENESIS_VERIFICATION_KEY=$(wget -q -O - https://raw.githubusercontent.com/input-output-hk/mithril/main/mithril-infra/configuration/${RELEASE}-${NETWORK_NAME,,}/genesis.vkey) + PARTY_ID=$(cat ${POOL_DIR}/${POOL_ID_FILENAME}-bech32) + SNAPSHOT_DIGEST=latest + EOF" + + if [[ "${ENABLE_RELAY_ENDPOINT}" == "y" ]]; then + sudo bash -c "echo RELAY_ENDPOINT=http://${RELAY_ENDPOINT_IP}:${RELAY_PORT} >> ${CNODE_HOME}/mithril/mithril.env" + fi +} + +update_mithril_environment_for_client() { + echo "Info: Setting minimal environment variables supporting only the Mithril client use case." + bash -c "cat <<-'EOF' > ${CNODE_HOME}/mithril/mithril.env + NETWORK=${NETWORK_NAME,,} + RELEASE=${RELEASE} + AGGREGATOR_ENDPOINT=https://aggregator.${RELEASE}-${NETWORK_NAME,,}.api.mithril.network/aggregator + DB_DIRECTORY=${CNODE_HOME}/db + GENESIS_VERIFICATION_KEY=$(wget -q -O - https://raw.githubusercontent.com/input-output-hk/mithril/main/mithril-infra/configuration/${RELEASE}-${NETWORK_NAME,,}/genesis.vkey) + SNAPSHOT_DIGEST=latest + EOF" +} + +component_environment_setup() { + check_mithril_environment_file_exists + + if [[ -n "${POOL_NAME}" ]] && [[ "${POOL_NAME}" != "CHANGE_ME" ]] && [[ "$(basename "$0")" == "mithril-signer.sh" ]]; then + update_mithril_environment_for_signer + else + update_mithril_environment_for_client + fi +} + +generate_environment_file() { + create_data_stores_directory + component_environment_setup + set_env_file_ownership +} +