From e7a8f3ad6749aa68fd7dc63814246452b0476d5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damjan=20Ostreli=C4=8D?= Date: Thu, 20 Aug 2020 22:23:41 +0100 Subject: [PATCH 01/24] Itnrewards key errorchecking 427 (#434) * 427 implement error checking for key files * add removed wallet error log * remove space change * file exist check Co-authored-by: Ola [AHLNET] --- scripts/cnode-helper-scripts/itnRewards.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/cnode-helper-scripts/itnRewards.sh b/scripts/cnode-helper-scripts/itnRewards.sh index 34cd189fb..26b5046c9 100755 --- a/scripts/cnode-helper-scripts/itnRewards.sh +++ b/scripts/cnode-helper-scripts/itnRewards.sh @@ -23,6 +23,16 @@ wallet_name="$1" itn_signing_key_file="$2" itn_verification_key_file="$3" +if [[ ! -f "${itn_signing_key_file}" || ! $(cat "${itn_signing_key_file}") =~ ^ed25519e?_sk* ]]; then + echo -e "\n${RED}ERROR${NC}: Invalid ITN Signing Key provided\n" + exit 1 +fi + +if [[ ! -f "${itn_verification_key_file}" || $(cat "${itn_verification_key_file}") != ed25519_pk* ]]; then + echo -e "\n${RED}ERROR${NC}: Invalid ITN Verification Key provided\n" + exit 1 +fi + if [[ -d "${WALLET_FOLDER}/${wallet_name}" ]]; then echo -e "\n${RED}ERROR${NC}: Wallet already exist, please use another name" echo -e "${WALLET_FOLDER}/${wallet_name}\n" From aacca1ae5c644acde8105a64af3213567007d800 Mon Sep 17 00:00:00 2001 From: Priyank <3169068+rdlrt@users.noreply.github.com> Date: Fri, 21 Aug 2020 07:56:12 +1000 Subject: [PATCH 02/24] [CNTOOLS] 5.3.5 - Move baseline support cardano-node to 1.19.0 (#431) ## [5.3.5] - 2020-08-20 ##### Changed - CNTools now uses and works with `cardano-node 1.19.0`, please upgrade if you're not using this version. ##### Fixed - A new getPoolID helper function added to extract both hex and bech32 pool ID - Added `--output-format hex` when extracting pool ID in hex format - A new pool.id-bech32 file gets created if cold.vkey is available and decrypted - Added error check to see if cardano-cli is in $PATH before continuing. Co-authored-by: Ola --- docs/Build/node-cli.md | 12 ++--- docs/Scripts/cntools-changelog.md | 11 +++++ docs/Scripts/itnrewards.md | 9 ---- scripts/cnode-helper-scripts/cntools.library | 23 ++++++++- scripts/cnode-helper-scripts/cntools.sh | 52 ++++++++++---------- scripts/cnode-helper-scripts/env | 6 ++- 6 files changed, 70 insertions(+), 43 deletions(-) diff --git a/docs/Build/node-cli.md b/docs/Build/node-cli.md index 8b4a75d47..ee9cae369 100644 --- a/docs/Build/node-cli.md +++ b/docs/Build/node-cli.md @@ -18,9 +18,9 @@ You can use the instructions below to build the cardano-node, same steps can be ``` bash git fetch --tags --all -# Replace release 1.18.1 with the version/branch/tag you'd like to build -git checkout tags/1.18.1 +# Replace release 1.19.0 with the version/branch/tag you'd like to build git pull +git checkout 1.19.0 echo -e "package cardano-crypto-praos\n flags: -external-libsodium-vrf" > cabal.project.local $CNODE_HOME/scripts/cabal-build-all.sh @@ -34,11 +34,11 @@ Execute cardano-cli and cardano-node to verify output as below: ```bash cardano-cli version -# cardano-cli 1.18.1 - linux-x86_64 - ghc-8.6 -# git rev a4b6dae699fa21dc3c025c8a83d1718475cb3afc +# cardano-cli 1.19.0 - linux-x86_64 - ghc-8.6 +# git rev 4814003f14340d5a1fc02f3ac15437387a7ada9f cardano-node version -# cardano-node 1.18.1 - linux-x86_64 - ghc-8.6 -# git rev a4b6dae699fa21dc3c025c8a83d1718475cb3afc +# cardano-node 1.19.0 - linux-x86_64 - ghc-8.6 +# git rev 4814003f14340d5a1fc02f3ac15437387a7ada9f ``` ##### Start a passive node diff --git a/docs/Scripts/cntools-changelog.md b/docs/Scripts/cntools-changelog.md index d2ca4f6b1..31ff4da4a 100644 --- a/docs/Scripts/cntools-changelog.md +++ b/docs/Scripts/cntools-changelog.md @@ -5,6 +5,17 @@ All notable changes to this tool will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [5.3.5] - 2020-08-20 + +##### Changed +- CNTools now uses and works with `cardano-node 1.19.0`, please upgrade if you're not using this version. + +##### Fixed +- A new getPoolID helper function added to extract both hex and bech32 pool ID + - Added `--output-format hex` when extracting pool ID in hex format + - A new pool.id-bech32 file gets created if cold.vkey is available and decrypted +- Added error check to see if cardano-cli is in $PATH before continuing. + ## [5.3.4] - 2020-08-18 ##### Changed diff --git a/docs/Scripts/itnrewards.md b/docs/Scripts/itnrewards.md index 43fd7376b..ec2e634dd 100644 --- a/docs/Scripts/itnrewards.md +++ b/docs/Scripts/itnrewards.md @@ -28,15 +28,6 @@ graph TB cd $CNODE_HOME/scripts ./itnRewards.sh MyITNWallet ~/jormu/account/priv/owner.sk ~/jormu/account/priv/owner.pk ``` -- However, if an extended secret key was used(ed25519e_sk), a recent version (min 1.18.x) of cardano-cli is needed to convert the key. - - Follow these instructions to build this version of cardano-cli: -``` bash -cd ~/git/cardano-node # Go to folder where you normally build cardano-node -git checkout release/1.18.x -git pull -$CNODE_HOME/scripts/cabal-build-all.sh -``` - - Re-run `itnRewards.sh` - Start CNTools and verify that correct balance is shown in the wallet reward address - Fund base address of wallet with enough funds to pay for withdraw tx fee - Use FUNDS >> WITHDRAW to move rewards to base address of wallet diff --git a/scripts/cnode-helper-scripts/cntools.library b/scripts/cnode-helper-scripts/cntools.library index 8e150f24c..572d5e65e 100644 --- a/scripts/cnode-helper-scripts/cntools.library +++ b/scripts/cnode-helper-scripts/cntools.library @@ -11,7 +11,7 @@ CNTOOLS_MAJOR_VERSION=5 # Changes that can be applied without breaking existing functionality that can be applied from within CNTools CNTOOLS_MINOR_VERSION=3 # Backwards compatible bug fixes. No additional functionality or major changes and can be applied from within CNTools -CNTOOLS_PATCH_VERSION=4 +CNTOOLS_PATCH_VERSION=5 CNTOOLS_VERSION="${CNTOOLS_MAJOR_VERSION}.${CNTOOLS_MINOR_VERSION}.${CNTOOLS_PATCH_VERSION}" ############################################################ @@ -615,6 +615,25 @@ fractionToPCT() { } +# Command : getPoolID [pool name] +# Description: create and save pool id in hex & bech32 encoded format +# Return : populates $pool_id & $pool_id_bech32 +getPoolID() { + pool_id_file="${POOL_FOLDER}/${1}/${POOL_ID_FILENAME}" + pool_id="" + pool_id_bech32_file="${POOL_FOLDER}/${1}/${POOL_ID_FILENAME}-bech32" + pool_id_bech32="" + pool_coldkey_vk_file="${POOL_FOLDER}/${1}/${POOL_COLDKEY_VK_FILENAME}" + if [[ -f ${pool_coldkey_vk_file} ]]; then + pool_id=$(${CCLI} shelley stake-pool id --verification-key-file "${pool_coldkey_vk_file}" --output-format hex 2>/dev/null | tee "${pool_id_file}") && \ + pool_id_bech32=$(${CCLI} shelley stake-pool id --verification-key-file "${pool_coldkey_vk_file}" 2>/dev/null | tee "${pool_id_bech32_file}") && \ + return 0 || return 1 + fi + [[ -f ${pool_id_file} ]] && pool_id=$(cat ${pool_id_file}) + [[ -f ${pool_id_bech32_file} ]] && pool_id_bech32=$(cat ${pool_id_bech32_file}) +} + + # Command : getPayAddress [wallet name] # Description: create and save payment address # Return : populates $pay_addr @@ -861,7 +880,7 @@ sendADA() { # Return : 0 if registered, else 1 isWalletRegistered() { if getRewardAddress $1; then - stakeAddressInfo=$(${CCLI} shelley query stake-address-info ${PROTOCOL_IDENTIFIER} ${NETWORK_IDENTIFIER} --address ${reward_addr} | jq -r '.[] // empty') + stakeAddressInfo=$(${CCLI} shelley query stake-address-info ${PROTOCOL_IDENTIFIER} ${NETWORK_IDENTIFIER} --address ${reward_addr} | jq -r '.[0] // empty') [[ -n "${stakeAddressInfo}" ]] && return 0 fi return 1 diff --git a/scripts/cnode-helper-scripts/cntools.sh b/scripts/cnode-helper-scripts/cntools.sh index 8b540caec..9b3805110 100755 --- a/scripts/cnode-helper-scripts/cntools.sh +++ b/scripts/cnode-helper-scripts/cntools.sh @@ -346,8 +346,8 @@ case $OPERATION in if [[ -n ${delegation_pool_id} ]]; then unset poolName while IFS= read -r -d '' pool; do - pool_id=$(cat "${pool}/${POOL_ID_FILENAME}") - if [[ "${pool_id}" = "${delegation_pool_id}" ]]; then + getPoolID "$(basename ${pool})" + if [[ "${pool_id_bech32}" = "${delegation_pool_id}" ]]; then poolName=$(basename ${pool}) && break fi done < <(find "${POOL_FOLDER}" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z) @@ -437,8 +437,8 @@ case $OPERATION in if [[ -n ${delegation_pool_id} ]]; then unset poolName while IFS= read -r -d '' pool; do - pool_id=$(cat "${pool}/${POOL_ID_FILENAME}") - if [[ "${pool_id}" = "${delegation_pool_id}" ]]; then + getPoolID "$(basename ${pool})" + if [[ "${pool_id_bech32}" = "${delegation_pool_id}" ]]; then poolName=$(basename ${pool}) && break fi done < <(find "${POOL_FOLDER}" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z) @@ -1017,12 +1017,12 @@ case $OPERATION in getBalance ${base_addr} [[ ${lovelace} -eq 0 ]] && continue if getRewardAddress ${dir}; then - delegation_pool_id=$(${CCLI} shelley query stake-address-info ${PROTOCOL_IDENTIFIER} ${NETWORK_IDENTIFIER} --address "${reward_addr}" | jq -r '.[].delegation // empty') + delegation_pool_id=$(${CCLI} shelley query stake-address-info ${PROTOCOL_IDENTIFIER} ${NETWORK_IDENTIFIER} --address "${reward_addr}" | jq -r '.[0].delegation // empty') unset poolName if [[ -n ${delegation_pool_id} ]]; then while IFS= read -r -d '' pool; do - pool_id=$(cat "${pool}/${POOL_ID_FILENAME}") - if [[ "${pool_id}" = "${delegation_pool_id}" ]]; then + getPoolID "$(basename ${pool})" + if [[ "${pool_id_bech32}" = "${delegation_pool_id}" ]]; then poolName=$(basename ${pool}) && break fi done < <(find "${POOL_FOLDER}" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z) @@ -1193,7 +1193,6 @@ case $OPERATION in say "" mkdir -p "${POOL_FOLDER}/${pool_name}" - pool_id_file="${POOL_FOLDER}/${pool_name}/${POOL_ID_FILENAME}" pool_hotkey_vk_file="${POOL_FOLDER}/${pool_name}/${POOL_HOTKEY_VK_FILENAME}" pool_hotkey_sk_file="${POOL_FOLDER}/${pool_name}/${POOL_HOTKEY_SK_FILENAME}" pool_coldkey_vk_file="${POOL_FOLDER}/${pool_name}/${POOL_COLDKEY_VK_FILENAME}" @@ -1214,12 +1213,13 @@ case $OPERATION in rm -r ${POOL_FOLDER}'-pregen/'${pool_name} else ${CCLI} shelley node key-gen --cold-verification-key-file "${pool_coldkey_vk_file}" --cold-signing-key-file "${pool_coldkey_sk_file}" --operational-certificate-issue-counter-file "${pool_opcert_counter_file}" - ${CCLI} shelley stake-pool id --verification-key-file "${pool_coldkey_vk_file}" > "${pool_id_file}" fi ${CCLI} shelley node key-gen-VRF --verification-key-file "${pool_vrf_vk_file}" --signing-key-file "${pool_vrf_sk_file}" + getPoolID ${pool_name} say "Pool: ${GREEN}${pool_name}${NC}" "log" - say "PoolPubKey: $(cat "${pool_id_file}")" "log" + [[ -n ${pool_id} ]] && say "ID (hex) : ${pool_id}" "log" + [[ -n ${pool_id_bech32} ]] && say "ID (bech32) : ${pool_id_bech32}" "log" say "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" waitForInput && continue @@ -1495,12 +1495,12 @@ case $OPERATION in getBalance ${base_addr} [[ ${lovelace} -eq 0 ]] && continue if getRewardAddress ${dir}; then - delegation_pool_id=$(${CCLI} shelley query stake-address-info ${PROTOCOL_IDENTIFIER} ${NETWORK_IDENTIFIER} --address "${reward_addr}" | jq -r '.[].delegation // empty') + delegation_pool_id=$(${CCLI} shelley query stake-address-info ${PROTOCOL_IDENTIFIER} ${NETWORK_IDENTIFIER} --address "${reward_addr}" | jq -r '.[0].delegation // empty') unset poolName if [[ -n ${delegation_pool_id} ]]; then while IFS= read -r -d '' pool; do - pool_id=$(cat "${pool}/${POOL_ID_FILENAME}") - if [[ "${pool_id}" = "${delegation_pool_id}" ]]; then + getPoolID "$(basename ${pool})" + if [[ "${pool_id_bech32}" = "${delegation_pool_id}" ]]; then poolName=$(basename ${pool}) && break fi done < <(find "${POOL_FOLDER}" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z) @@ -1973,12 +1973,12 @@ case $OPERATION in getBalance ${base_addr} [[ ${lovelace} -eq 0 ]] && continue if getRewardAddress ${dir}; then - delegation_pool_id=$(${CCLI} shelley query stake-address-info ${PROTOCOL_IDENTIFIER} ${NETWORK_IDENTIFIER} --address "${reward_addr}" | jq -r '.[].delegation // empty') + delegation_pool_id=$(${CCLI} shelley query stake-address-info ${PROTOCOL_IDENTIFIER} ${NETWORK_IDENTIFIER} --address "${reward_addr}" | jq -r '.[0].delegation // empty') unset poolName if [[ -n ${delegation_pool_id} ]]; then while IFS= read -r -d '' pool; do - pool_id=$(cat "${pool}/${POOL_ID_FILENAME}") - if [[ "${pool_id}" = "${delegation_pool_id}" ]]; then + getPoolID "$(basename ${pool})" + if [[ "${pool_id_bech32}" = "${delegation_pool_id}" ]]; then poolName=$(basename ${pool}) && break fi done < <(find "${POOL_FOLDER}" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z) @@ -2284,11 +2284,12 @@ case $OPERATION in while IFS= read -r -d '' pool; do say "" - pool_id=$(cat "${pool}/${POOL_ID_FILENAME}") + getPoolID "$(basename ${pool})" pool_regcert_file="${pool}/${POOL_REGCERT_FILENAME}" [[ -f "${pool_regcert_file}" ]] && pool_registered="YES" || pool_registered="NO" say "${GREEN}$(basename ${pool})${NC} " - say "$(printf "%-21s : %s" "ID" "${pool_id}")" "log" + say "$(printf "%-21s : %s" "ID (hex)" "${pool_id}")" "log" + [[ -n ${pool_id_bech32} ]] && say "$(printf "%-21s : %s" "ID (bech32)" "${pool_id_bech32}")" "log" say "$(printf "%-21s : %s" "Registered" "${pool_registered}")" "log" if [[ -f "${pool}/${POOL_CURRENT_KES_START}" ]]; then kesExpiration "$(cat "${pool}/${POOL_CURRENT_KES_START}")" @@ -2327,8 +2328,8 @@ case $OPERATION in pool_dirs=() if ! getDirs "${POOL_FOLDER}"; then continue; fi # dirs() array populated with all pool folders for dir in "${dirs[@]}"; do - pool_id="${POOL_FOLDER}/${dir}/${POOL_ID_FILENAME}" - [[ ! -f "${pool_id}" ]] && continue + pool_id_file="${POOL_FOLDER}/${dir}/${POOL_ID_FILENAME}" + [[ ! -f "${pool_id_file}" ]] && continue pool_dirs+=("${dir}") done if [[ ${#pool_dirs[@]} -eq 0 ]]; then @@ -2349,13 +2350,14 @@ case $OPERATION in say "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" say "" - pool_id=$(cat "${POOL_FOLDER}/${pool_name}/${POOL_ID_FILENAME}") + getPoolID ${pool_name} ledger_pParams=$(jq -r '.esLState._delegationState._pstate._pParams."'"${pool_id}"'" // empty' "${TMP_FOLDER}"/ledger-state.json) ledger_fPParams=$(jq -r '.esLState._delegationState._pstate._fPParams."'"${pool_id}"'" // empty' "${TMP_FOLDER}"/ledger-state.json) [[ -z "${ledger_fPParams}" ]] && ledger_fPParams="${ledger_pParams}" [[ -n "${ledger_pParams}" ]] && pool_registered="YES" || pool_registered="NO" say "${GREEN}${pool_name}${NC} " - say "$(printf "%-21s : %s" "ID" "${pool_id}")" "log" + say "$(printf "%-21s : %s" "ID (hex)" "${pool_id}")" "log" + [[ -n ${pool_id_bech32} ]] && say "$(printf "%-21s : %s" "ID (bech32)" "${pool_id_bech32}")" "log" say "$(printf "%-21s : %s" "Registered" "${pool_registered}")" "log" pool_config="${POOL_FOLDER}/${pool_name}/${POOL_CONFIG_FILENAME}" if [[ -f "${pool_config}" ]]; then @@ -2498,8 +2500,8 @@ case $OPERATION in pool_dirs=() if ! getDirs "${POOL_FOLDER}"; then continue; fi # dirs() array populated with all pool folders for dir in "${dirs[@]}"; do - pool_id="${POOL_FOLDER}/${dir}/${POOL_ID_FILENAME}" - [[ ! -f "${pool_id}" ]] && continue + pool_id_file="${POOL_FOLDER}/${dir}/${POOL_ID_FILENAME}" + [[ ! -f "${pool_id_file}" ]] && continue pool_dirs+=("${dir}") done if [[ ${#pool_dirs[@]} -eq 0 ]]; then @@ -2510,7 +2512,7 @@ case $OPERATION in say "Select Pool:\n" if ! selectDir "${pool_dirs[@]}"; then continue; fi # ${dir_name} populated by selectDir function pool_name="${dir_name}" - pool_id=$(cat "${POOL_FOLDER}/${pool_name}/${POOL_ID_FILENAME}") + getPoolID ${pool_name} say "Looking for delegators, please wait..." if ! getDelegators ${pool_id}; then diff --git a/scripts/cnode-helper-scripts/env b/scripts/cnode-helper-scripts/env index f43b860b7..547e64917 100644 --- a/scripts/cnode-helper-scripts/env +++ b/scripts/cnode-helper-scripts/env @@ -1,6 +1,10 @@ #!/usr/bin/env bash # shellcheck disable=SC2034,SC2086,SC2230 -CCLI=$(which cardano-cli) +CCLI=$(command -v cardano-cli) +if [[ -z "${CCLI}" ]]; then + echo "You do not have a cardano-cli binary available in \$PATH. Please make it available before using CNTools. Refer to guild-operators documentation for the same." + exit 1 +fi CNODE_HOME=/opt/cardano/cnode CONFIG=$CNODE_HOME/files/config.json PROTOCOL=$(jq -r .Protocol "$CONFIG") From 3e4fae54b2cc1ab9ed807626fe639152ba392e20 Mon Sep 17 00:00:00 2001 From: Straightpool <42584250+Straightpool@users.noreply.github.com> Date: Sat, 22 Aug 2020 00:44:23 +0200 Subject: [PATCH 03/24] [CNTOOLs] Change KES rotation to use current period -1 for 1.19.0 (#436) * Update cntools.library On KES rotation the starting period is now "current period -1" to accomomate for the following 1.19.0 issue, so the KES period has already evolved to keep the KES metrics: https://github.com/input-output-hk/cardano-node/issues/1742 * Update patch version number * Update cntools-changelog.md Co-authored-by: Priyank <3169068+rdlrt@users.noreply.github.com> --- docs/Scripts/cntools-changelog.md | 5 +++++ scripts/cnode-helper-scripts/cntools.library | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/Scripts/cntools-changelog.md b/docs/Scripts/cntools-changelog.md index 31ff4da4a..87f637ddd 100644 --- a/docs/Scripts/cntools-changelog.md +++ b/docs/Scripts/cntools-changelog.md @@ -5,6 +5,11 @@ All notable changes to this tool will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [5.3.6] - 2020-08-22 + +##### Fixed +- cardano-node 1.19.0 introduced an issue that required us to use KES as current - 1 while rotating. + ## [5.3.5] - 2020-08-20 ##### Changed diff --git a/scripts/cnode-helper-scripts/cntools.library b/scripts/cnode-helper-scripts/cntools.library index 572d5e65e..17c763186 100644 --- a/scripts/cnode-helper-scripts/cntools.library +++ b/scripts/cnode-helper-scripts/cntools.library @@ -11,7 +11,7 @@ CNTOOLS_MAJOR_VERSION=5 # Changes that can be applied without breaking existing functionality that can be applied from within CNTools CNTOOLS_MINOR_VERSION=3 # Backwards compatible bug fixes. No additional functionality or major changes and can be applied from within CNTools -CNTOOLS_PATCH_VERSION=5 +CNTOOLS_PATCH_VERSION=6 CNTOOLS_VERSION="${CNTOOLS_MAJOR_VERSION}.${CNTOOLS_MINOR_VERSION}.${CNTOOLS_PATCH_VERSION}" ############################################################ @@ -1728,7 +1728,7 @@ rotatePoolKeys() { return 1 fi - start_kes_period=$(getCurrentKESperiod) + start_kes_period=$(( $(getCurrentKESperiod) - 1 )) echo "${start_kes_period}" > ${pool_saved_kes_start} say "creating new hot keys and certificate" 1 From eaa16f605467098604d0bf8e3e2649d52b9be5be Mon Sep 17 00:00:00 2001 From: Straightpool <42584250+Straightpool@users.noreply.github.com> Date: Sun, 23 Aug 2020 10:35:53 +0200 Subject: [PATCH 04/24] Update cnode.sh.templ (#439) Added sanity check before potentially killing another already running cardano node accidently executing this script. --- scripts/cnode-helper-scripts/cnode.sh.templ | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/cnode-helper-scripts/cnode.sh.templ b/scripts/cnode-helper-scripts/cnode.sh.templ index ec652a0ea..adf458fb3 100755 --- a/scripts/cnode-helper-scripts/cnode.sh.templ +++ b/scripts/cnode-helper-scripts/cnode.sh.templ @@ -3,6 +3,11 @@ [[ -z "$CNODE_HOME" ]] && CNODE_HOME="/opt/cardano/cnode" +if [[ -S "$CNODE_HOME/sockets/node0.socket" ]]; then + echo "ERROR: A Cardano node is already running, please terminate this node before starting a new one with this script." + exit 1 +fi + [[ ! -d "$CNODE_HOME/logs/archive" ]] && mkdir -p "$CNODE_HOME/logs/archive" [[ $(find "$CNODE_HOME"/logs/*.json | wc -l) -gt 0 ]] && mv $CNODE_HOME/logs/*.json $CNODE_HOME/logs/archive/ From cf818151fa0ae4038768b947741aaba521f170bf Mon Sep 17 00:00:00 2001 From: "Ola [AHLNET]" Date: Mon, 24 Aug 2020 13:58:07 +0200 Subject: [PATCH 05/24] CNTools - 5.4.0 (#440) * CNTools - 5.4.0 ##### Added - Sanity check before launching a second instance of cnode.sh [eaa16f6] ##### Removed - `Pool >> Delegators` removed. [closes #435] - If/when a better option than dumping and parsing ledger-state dump arise re-adding it will be considered. - Utilize the community explorers listed at https://cardano-community.github.io/support-faq/#/explorers ##### Fixed - Block Collector script adapted for cardano-node 1.19.0. - Block hash is now truncated in log, issue https://github.com/input-output-hk/cardano-node/issues/1738 - High cpu usage reported in a few cases when running Block Collector - Depending on log level, parsing and byte64 enc each entry with jq could potentially put high load on weaker systems. Replaced with grep to only parse entries containing specific traces. --- docs/Build/node-cli.md | 56 +++++++++++++++++ docs/Scripts/cntools-blocks.md | 6 +- docs/Scripts/cntools-changelog.md | 43 ++++++++++--- scripts/cnode-helper-scripts/cntools.library | 4 +- scripts/cnode-helper-scripts/cntools.sh | 63 ++----------------- .../cntoolsBlockCollector.sh | 25 ++++---- 6 files changed, 110 insertions(+), 87 deletions(-) diff --git a/docs/Build/node-cli.md b/docs/Build/node-cli.md index ee9cae369..7a9be2fe2 100644 --- a/docs/Build/node-cli.md +++ b/docs/Build/node-cli.md @@ -50,3 +50,59 @@ cd $CNODE_HOME/scripts ./cnode.sh ``` +##### Run as systemd service + +The preferred way to run the node is through a service manager like systemd. This section explains how to setup a systemd service file. + +**1. Create systemd service file** +Replace `$USER` with the correct user for your system. Copy & paste all code below to create the service file. +``` bash +sudo bash -c "cat << 'EOF' > /etc/systemd/system/cnode.service +[Unit] +Description=Cardano Node +After=network.target + +[Service] +Type=simple +Restart=on-failure +RestartSec=5 +User=$USER +LimitNOFILE=1048576 +WorkingDirectory=/opt/cardano/cnode/scripts +ExecStart=/bin/bash -l -c 'exec \"\$@\"' _ cnode.sh +KillSignal=SIGINT +SuccessExitStatus=143 +StandardOutput=syslog +StandardError=syslog +SyslogIdentifier=cnode + +[Install] +WantedBy=multi-user.target +EOF" +``` + +**2. Reload systemd and enable automatic start of service on startup** +``` +sudo systemctl daemon-reload +sudo systemctl enable cnode.service +``` + +**3. Modify configuration to run with view mode SimpleView** +``` +pushd $CNODE_HOME/files >/dev/null && \ +tmpConfig=$(mktemp) && \ +jq '.ViewMode = "SimpleView"' config.json > "${tmpConfig}" && mv -f "${tmpConfig}" config.json && \ +popd >/dev/null +``` + +**4. Start the node** +Run below commands to enable automatic start of service on startup and start it. +``` +sudo systemctl start cnode.service +``` + +**5. Check status and stop/start commands** +Replace `status` with `stop`/`start`/`restart` depending on what action to take. +``` +sudo systemctl status cnode.service +``` diff --git a/docs/Scripts/cntools-blocks.md b/docs/Scripts/cntools-blocks.md index 39b2f9eb4..9a727fb43 100644 --- a/docs/Scripts/cntools-blocks.md +++ b/docs/Scripts/cntools-blocks.md @@ -17,7 +17,7 @@ In this example normal output from the `cntoolsBlockCollector.sh` script is igno **1. Create systemd service file** Replace `$USER` with the correct user for your system. Copy & paste all code below to create the service file. ``` bash -sudo bash -c 'cat < /etc/systemd/system/cntools-blockcollector.service +sudo bash -c "cat << 'EOF' > /etc/systemd/system/cntools-blockcollector.service [Unit] Description=CNTools - Block Collector After=network.target @@ -28,7 +28,7 @@ Restart=on-failure RestartSec=10 User=$USER WorkingDirectory=/opt/cardano/cnode/scripts -ExecStart=/opt/cardano/cnode/scripts/cntoolsBlockCollector.sh +ExecStart=/bin/bash -l -c 'exec \"\$@\"' _ /opt/cardano/cnode/scripts/cntoolsBlockCollector.sh SuccessExitStatus=143 StandardOutput=null StandardError=syslog @@ -36,7 +36,7 @@ SyslogIdentifier=cntools-blockcollector [Install] WantedBy=multi-user.target -EOF' +EOF" ``` **2. Reload systemd** diff --git a/docs/Scripts/cntools-changelog.md b/docs/Scripts/cntools-changelog.md index 87f637ddd..ae8cd3bd9 100644 --- a/docs/Scripts/cntools-changelog.md +++ b/docs/Scripts/cntools-changelog.md @@ -5,11 +5,41 @@ All notable changes to this tool will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [5.4.0] - 2020-08-23 + +> A non-breaking change have been made to files outside of CNTools. Internal update function is not enough to update all files. +> - Execute the below (by default it will set you up against mainnet network), do not overwrite config please: +> `cd "$CNODE_HOME"/scripts` +> `curl -sS -o prereqs.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/prereqs.sh` +> `chmod 755 prereqs.sh` +> `./prereqs.sh -s` +> - Start using updated cnode.sh to run a passive node, or edit the cnode.sh to include your pool keys and run as pool owner. + +======= + +##### Added +- Sanity check before launching a second instance of cnode.sh +- Doc update to run cnode.sh as a systemd service + +##### Removed +- `Pool >> Delegators` removed. + - If/when a better option than dumping and parsing ledger-state dump arise re-adding it will be considered. + - Utilize the community explorers listed at https://cardano-community.github.io/support-faq/#/explorers + +##### Fixed +- Block Collector script adapted for cardano-node 1.19.0. + - Block hash is now truncated in log, issue https://github.com/input-output-hk/cardano-node/issues/1738 +- High cpu usage reported in a few cases when running Block Collector + - Depending on log level, parsing and byte64 enc each entry with jq could potentially put high load on weaker systems. Replaced with grep to only parse entries containing specific traces. +- Docs for creating systemd block collector service file updated to include user env in run command + + ## [5.3.6] - 2020-08-22 ##### Fixed - cardano-node 1.19.0 introduced an issue that required us to use KES as current - 1 while rotating. + ## [5.3.5] - 2020-08-20 ##### Changed @@ -21,6 +51,7 @@ and this adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - A new pool.id-bech32 file gets created if cold.vkey is available and decrypted - Added error check to see if cardano-cli is in $PATH before continuing. + ## [5.3.4] - 2020-08-18 ##### Changed @@ -31,17 +62,8 @@ and this adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ##### Added - Use secure remove (`srm`) when available when deleting files. -## [5.3.2] - 2020-08-05 -> If you're coming version 5.2.1 (not required if you're on 5.3.0), We have made quite a few changes to not use ptn0 in our scripts and source github structures (except template files), alongwith other changes listed beneath. Please follow steps below for upgrade: -> - Execute the below (by default it will set you up against mainnet network), do not overwrite config please: -> `cd "$CNODE_HOME"/scripts` -> `curl -sS -o prereqs.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/prereqs.sh` -> `chmod 755 prereqs.sh` -> `./prereqs.sh -s` -> - Start using updated cnode.sh to run a passive node, or edit the cnode.sh to include your pool keys and run as pool owner. - -======= +## [5.3.2] - 2020-08-05 #### Fixed - Backup & Restore paths were failing on machines due to alnum class availability on certain interpreters. @@ -61,6 +83,7 @@ and this adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Balance check added to `Funds >> Withdraw` for base address as this is used to pay the withdraw transaction fee - Resolve issue with Multi Owner causing an error with new pool registration (error was due to quotes) + ## [5.3.0] - 2020-08-03 ##### Added - Ability to select a different pool owner and reward wallet diff --git a/scripts/cnode-helper-scripts/cntools.library b/scripts/cnode-helper-scripts/cntools.library index 17c763186..50087b84e 100644 --- a/scripts/cnode-helper-scripts/cntools.library +++ b/scripts/cnode-helper-scripts/cntools.library @@ -9,9 +9,9 @@ # Any breaking changes (eg: that requires change of cntools.config, env or a change in priv folder would be considered breaking and will be exempt from auto-update) CNTOOLS_MAJOR_VERSION=5 # Changes that can be applied without breaking existing functionality that can be applied from within CNTools -CNTOOLS_MINOR_VERSION=3 +CNTOOLS_MINOR_VERSION=4 # Backwards compatible bug fixes. No additional functionality or major changes and can be applied from within CNTools -CNTOOLS_PATCH_VERSION=6 +CNTOOLS_PATCH_VERSION=0 CNTOOLS_VERSION="${CNTOOLS_MAJOR_VERSION}.${CNTOOLS_MINOR_VERSION}.${CNTOOLS_PATCH_VERSION}" ############################################################ diff --git a/scripts/cnode-helper-scripts/cntools.sh b/scripts/cnode-helper-scripts/cntools.sh index 9b3805110..d15790b03 100755 --- a/scripts/cnode-helper-scripts/cntools.sh +++ b/scripts/cnode-helper-scripts/cntools.sh @@ -1155,25 +1155,23 @@ case $OPERATION in say " ) Retire - de-register stake pool from chain in specified epoch" say " ) List - a compact list view of available local pools" say " ) Show - detailed view of specified pool" - say " ) Delegators - list all delegators for pool" say " ) Rotate - rotate pool KES keys" say " ) Decrypt - remove write protection and decrypt pool" say " ) Encrypt - encrypt pool cold keys and make all files immutable" say "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" say " Select Pool operation\n" - case $(select_opt "[n] New" "[r] Register" "[m] Modify" "[x] Retire" "[l] List" "[s] Show" "[g] Delegators" "[o] Rotate" "[d] Decrypt" "[e] Encrypt" "[h] Home") in + case $(select_opt "[n] New" "[r] Register" "[m] Modify" "[x] Retire" "[l] List" "[s] Show" "[o] Rotate" "[d] Decrypt" "[e] Encrypt" "[h] Home") in 0) SUBCOMMAND="new" ;; 1) SUBCOMMAND="register" ;; 2) SUBCOMMAND="modify" ;; 3) SUBCOMMAND="retire" ;; 4) SUBCOMMAND="list" ;; 5) SUBCOMMAND="show" ;; - 6) SUBCOMMAND="delegators" ;; - 7) SUBCOMMAND="rotate" ;; - 8) SUBCOMMAND="decrypt" ;; - 9) SUBCOMMAND="encrypt" ;; - 10) continue ;; + 6) SUBCOMMAND="rotate" ;; + 7) SUBCOMMAND="decrypt" ;; + 8) SUBCOMMAND="encrypt" ;; + 9) continue ;; esac case $SUBCOMMAND in @@ -2485,57 +2483,6 @@ case $OPERATION in ;; ################################################################### - delegators) - - clear - say " >> POOL >> DELEGATORS" "log" - say "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - say "" - - if [[ ! -f "${TMP_FOLDER}"/protparams.json ]]; then - say "${RED}ERROR${NC}: CNTools started without node access, only offline functions available!" - waitForInput && continue - fi - - pool_dirs=() - if ! getDirs "${POOL_FOLDER}"; then continue; fi # dirs() array populated with all pool folders - for dir in "${dirs[@]}"; do - pool_id_file="${POOL_FOLDER}/${dir}/${POOL_ID_FILENAME}" - [[ ! -f "${pool_id_file}" ]] && continue - pool_dirs+=("${dir}") - done - if [[ ${#pool_dirs[@]} -eq 0 ]]; then - say "${ORANGE}WARN${NC}: No pools available!" - say "first create a pool" - waitForInput && continue - fi - say "Select Pool:\n" - if ! selectDir "${pool_dirs[@]}"; then continue; fi # ${dir_name} populated by selectDir function - pool_name="${dir_name}" - getPoolID ${pool_name} - - say "Looking for delegators, please wait..." - if ! getDelegators ${pool_id}; then - waitForInput && continue - fi - - clear - say " >> POOL >> DELEGATORS" "log" - say "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - say "" - say "${BLUE}${delegator_nbr}${NC} wallet(s) delegated to ${GREEN}${pool_name}${NC} of which ${ORANGE}${owner_nbr}${NC} are owner(s)\n" - say "Total Stake: $(formatLovelace ${total_stake}) ADA [ owners pledge: $(formatLovelace ${total_pledged}) | delegators: $(formatLovelace $((total_stake-total_pledged))) ]\n" - - if [[ ${total_pledged} -lt ${pledge} ]]; then - say "${ORANGE}WARN${NC}: Owners pledge does not cover registered pledge of $(formatLovelace ${pledge}) ADA\n" - fi - - printTable ';' "$(say 'Hex Key;Stake;Rewards' | cat - <(jq -r -c '.[] | "\(.hex_key);\(.stake);\(.rewards)"' <<< "${delegators_json}"))" - - waitForInput && continue - - ;; ################################################################### - rotate) clear diff --git a/scripts/cnode-helper-scripts/cntoolsBlockCollector.sh b/scripts/cnode-helper-scripts/cntoolsBlockCollector.sh index 8d728091e..e4ab32fb8 100755 --- a/scripts/cnode-helper-scripts/cntoolsBlockCollector.sh +++ b/scripts/cnode-helper-scripts/cntoolsBlockCollector.sh @@ -46,13 +46,10 @@ echo "monitoring json logfile for block traces" # Continuously parse cardano-node json log file for block traces while read -r logentry; do - _jq() { - echo "${logentry}" | base64 --decode | jq -r "${1}" - } - if [[ $(_jq '.data.kind') = "TraceNodeIsLeader" ]]; then - at="$(_jq '.at')" + if grep -q "TraceNodeIsLeader" <<< "${logentry}"; then + at="$(jq -r '.at' <<< ${logentry})" at_local="$(date '+%F_%T_%Z' -d "${at}")" - slot="$(_jq '.data.slot')" + slot="$(jq -r '.data.slot' <<< ${logentry})" epoch=$(getEpoch) # create epoch block file if missing blocks_file="${BLOCK_LOG_DIR}/blocks_${epoch}.json" @@ -70,10 +67,10 @@ while read -r logentry; do '. += [{"at": $_at,"slot": $_slot}]' \ "${blocks_file}" > "${TMP_FOLDER}/blocks.json" && mv -f "${TMP_FOLDER}/blocks.json" "${blocks_file}" fi - elif [[ $(_jq '.data.kind') = "TraceAdoptedBlock" ]]; then - slot="$(_jq '.data.slot')" - [[ "$(_jq '.data."block hash"')" =~ ([[:alnum:]]+) ]] && block_hash="${BASH_REMATCH[1]}" || block_hash="" - block_size="$(_jq '.data."block size"')" + elif grep -q "TraceAdoptedBlock" <<< "${logentry}"; then + slot="$(jq -r '.data.slot' <<< ${logentry})" + [[ "$(jq -r '.data.blockHash' <<< ${logentry})" =~ ([[:alnum:]]+) ]] && block_hash="${BASH_REMATCH[1]}" || block_hash="" + block_size="$(jq -r '.data.blockSize' <<< ${logentry})" epoch=$(( slot / $(jq -r .epochLength "${GENESIS_JSON}") )) echo " ~~ ADOPTED BLOCK ~~" printTable ',' "Size,Hash\n${block_size},${block_hash}" @@ -82,15 +79,15 @@ while read -r logentry; do --arg _block_hash "${block_hash}" \ '[.[] | select(.slot == $_slot) += {"size": $_block_size,"hash": $_block_hash}]' \ "${blocks_file}" > "${TMP_FOLDER}/blocks.json" && mv -f "${TMP_FOLDER}/blocks.json" "${blocks_file}" - elif [[ $(_jq '.data.kind') = "TraceForgedInvalidBlock" ]]; then - slot="$(_jq '.data.slot')" + elif grep -q "TraceForgedInvalidBlock" <<< "${logentry}"; then + slot="$(jq -r '.data.slot' <<< ${logentry})" epoch=$(( slot / $(jq -r .epochLength "${GENESIS_JSON}") )) echo " ~~ INVALID BLOCK ~~" echo "Base 64 encoded json trace" echo -e "run this command to decode:\necho ${logentry} | base64 -d | jq -r" jq --arg _slot "${slot}" \ - --arg _json_trace "Invalid Block (base64 enc json): ${logentry}" \ + --arg _json_trace "Invalid Block (base64 enc json): $(jq -c -r '. | @base64' <<< ${logentry})" \ '[.[] | select(.slot == $_slot) += {"hash": $_json_trace}]' \ "${blocks_file}" > "${TMP_FOLDER}/blocks.json" && mv -f "${TMP_FOLDER}/blocks.json" "${blocks_file}" fi -done < <(tail -F -n0 "${logfile}" | jq -c -r '. | @base64') \ No newline at end of file +done < <(tail -F -n0 "${logfile}") \ No newline at end of file From 6151d31dbda0f0200301065049308f9eb651980e Mon Sep 17 00:00:00 2001 From: dmitrystas Date: Mon, 24 Aug 2020 16:41:40 +0200 Subject: [PATCH 06/24] Some trick for CentOS 7 (#443) --- docs/Build/node-cli.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/Build/node-cli.md b/docs/Build/node-cli.md index 7a9be2fe2..e6aaacfc7 100644 --- a/docs/Build/node-cli.md +++ b/docs/Build/node-cli.md @@ -23,6 +23,9 @@ git pull git checkout 1.19.0 echo -e "package cardano-crypto-praos\n flags: -external-libsodium-vrf" > cabal.project.local +# On CentOS 7 (GCC 4.8.5) we should also do +# echo -e "package cryptonite\n flags: -use_target_attributes" >> cabal.project.local + $CNODE_HOME/scripts/cabal-build-all.sh ``` From 3a252eee5b867298959be3ea0567e65ea76ac422 Mon Sep 17 00:00:00 2001 From: Straightpool <42584250+Straightpool@users.noreply.github.com> Date: Tue, 25 Aug 2020 01:54:24 +0200 Subject: [PATCH 07/24] [CNTools] More robust cnode.sh socket check (#444) When a Cardano node was not cleanly shut down, so the socket file still exists, cnode.sh will now delete the socket file before starting the node provided there is no cardano-node process running. --- scripts/cnode-helper-scripts/cnode.sh.templ | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/cnode-helper-scripts/cnode.sh.templ b/scripts/cnode-helper-scripts/cnode.sh.templ index adf458fb3..ca50d107d 100755 --- a/scripts/cnode-helper-scripts/cnode.sh.templ +++ b/scripts/cnode-helper-scripts/cnode.sh.templ @@ -4,8 +4,13 @@ [[ -z "$CNODE_HOME" ]] && CNODE_HOME="/opt/cardano/cnode" if [[ -S "$CNODE_HOME/sockets/node0.socket" ]]; then - echo "ERROR: A Cardano node is already running, please terminate this node before starting a new one with this script." - exit 1 + if [ `ps -ef | grep -c cardano-node.*.$CNODE_HOME/sockets/node0.socket` -gt 0 ]; then + echo "ERROR: A Cardano node is already running, please terminate this node before starting a new one with this script." + exit 1 + else + echo "WARN: A prior running Cardano node was not cleanly shutdown, socket file still exists. Cleaning up." + unlink $CNODE_HOME/sockets/node0.socket + fi fi [[ ! -d "$CNODE_HOME/logs/archive" ]] && mkdir -p "$CNODE_HOME/logs/archive" From 20a2970445e3d3dde3630d381984c95f10a12daf Mon Sep 17 00:00:00 2001 From: "Ola [AHLNET]" Date: Thu, 27 Aug 2020 10:46:23 +0200 Subject: [PATCH 08/24] Run node as systemd by default, add sLiveView.sh (#447) - Add SimpleView as default config - Update systemd to include kill signal for faster boot - Update node-cli.md doco for using systemd setup - Add sLiveView.sh from Adam for monitoring script - Customise sLiveView.sh to remove hardcoded entries and shellcheck - Switch to EKG instead of prom endpoints - Add instructions to update use of newer scripts for smoother transition Co-authored-by: rdlrt <3169068+rdlrt@users.noreply.github.com> --- docs/Build/node-cli.md | 38 +++--- docs/Scripts/sliveview.md | 79 +++++++++++ docs/_sidebar.md | 1 + docs/contributors.md | 4 +- files/ptn0-combinator.json | 4 +- files/ptn0-mainnet.json | 4 +- files/ptn0-praos.json | 4 +- scripts/cnode-helper-scripts/prereqs.sh | 5 +- scripts/cnode-helper-scripts/sLiveView.sh | 159 ++++++++++++++++++++++ 9 files changed, 273 insertions(+), 25 deletions(-) create mode 100644 docs/Scripts/sliveview.md create mode 100755 scripts/cnode-helper-scripts/sLiveView.sh diff --git a/docs/Build/node-cli.md b/docs/Build/node-cli.md index e6aaacfc7..29e99c970 100644 --- a/docs/Build/node-cli.md +++ b/docs/Build/node-cli.md @@ -46,7 +46,7 @@ cardano-node version ##### Start a passive node -To start the node in passive mode, you can use the pre-built script below: +To test starting the node in interactive mode, you can use the pre-built script below (note that the config now uses `SimpleView` so you may not see much output): ```bash cd $CNODE_HOME/scripts @@ -71,13 +71,16 @@ Restart=on-failure RestartSec=5 User=$USER LimitNOFILE=1048576 -WorkingDirectory=/opt/cardano/cnode/scripts -ExecStart=/bin/bash -l -c 'exec \"\$@\"' _ cnode.sh +WorkingDirectory=$CNODE_HOME/scripts +ExecStart=/bin/bash -l -c \"exec $CNODE_HOME/scripts/cnode.sh\" +ExecStop=/bin/bash -l -c \"exec kill -2 \$(ps -ef | grep [c]ardano-node.*.node0.socket | tr -s ' ' | cut -d ' ' -f2)\" KillSignal=SIGINT SuccessExitStatus=143 StandardOutput=syslog StandardError=syslog SyslogIdentifier=cnode +TimeoutStopSec=5 +KillMode=mixed [Install] WantedBy=multi-user.target @@ -85,27 +88,30 @@ EOF" ``` **2. Reload systemd and enable automatic start of service on startup** -``` +``` bash sudo systemctl daemon-reload sudo systemctl enable cnode.service ``` -**3. Modify configuration to run with view mode SimpleView** -``` -pushd $CNODE_HOME/files >/dev/null && \ -tmpConfig=$(mktemp) && \ -jq '.ViewMode = "SimpleView"' config.json > "${tmpConfig}" && mv -f "${tmpConfig}" config.json && \ -popd >/dev/null -``` - -**4. Start the node** +**3. Start the node** Run below commands to enable automatic start of service on startup and start it. -``` +``` bash sudo systemctl start cnode.service ``` -**5. Check status and stop/start commands** +**4. Check status and stop/start commands** Replace `status` with `stop`/`start`/`restart` depending on what action to take. -``` +``` bash sudo systemctl status cnode.service ``` + +You can use [sLiveView](Scripts/sliveview.md) to monitor your pool that was started as systemd, if you miss the LiveView functionality. + +##### Steps to transition from LiveView in tmux to systemd setup + +If you've followed guide from this repo previously and would like to transfer to systemd usage, please checkout the steps below: + +1. Stop previous instance of node if already running (eg: in tmux) +2. Run `prereqs.sh` OR simply replace `LiveView` to `SimpleView` in your $CNODE_HOME/files/config.json. +3. Follow the instructions [above](#run-as-systemd-service) to setup your node as a service and start it using systemctl as directed. +4. If you need to monitor via interactive terminal as before, use [sLiveView](Scripts/sliveview.md). diff --git a/docs/Scripts/sliveview.md b/docs/Scripts/sliveview.md new file mode 100644 index 000000000..b87ea1209 --- /dev/null +++ b/docs/Scripts/sliveview.md @@ -0,0 +1,79 @@ +!> Ensure the [Pre-Requisites](basics.md#pre-requisites) are in place before you proceed. + +**Simple LiveView - sLiveView** is a small utility to display an equivalent subset of LiveView interface that cardano-node users have grown accustomed to. This is useful when changing to `SimpleView` and moving to a systemd deployment - if you haven't done so already - while looking for a familiar UI to monitor the node status. + +The tool is independent from other files and can run as a standalone utility that can be stopped/started without affecting the status of cardano-node. + +##### Download & Setup + +The tool in itself should only require a single file. If you've used [prereqs.sh](basics.md#pre-requisites), you can skip this part , as this is already set up for you. + +?> For those who follow guild's [folder structure](basics.md#folder-structure) and do not wish to run prereqs.sh, you can run the below in `$CNODE_HOME/scripts` folder + +To download the script: +```bash +curl -s -o sLiveView.sh curl -s -o sLiveView.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/sLiveView.sh +chmod 755 sLiveView.sh +``` + +##### Startup + +For most standard deployments, this should lead you to a stage where you can now start running sLiveView.sh - it will automatically detect when you're running as a Core or Relay and show fields accordingly, a sample output below: + +```bash +./sLiveView.sh ++----------------------------------------+ +| Simple Node Stats | ++-----------------------+----------------+ +| Name: TESTPOOL - Core | ++-----------------------+----------------+ +| Version | 1.19.0 | ++-----------------------+----------------+ +| Revision | 49536693 | ++-----------------------+----------------+ +| Peers (Out / In) | 8 / 16 | ++-----------------------+----------------+ +| Epoch / Slot | 213 / 296153 | ++-----------------------+----------------+ +| Block | 4612464 | ++-----------------------+----------------+ +| Density | 4.99 % | ++-----------------------+----------------+ +| Uptime (D:H:M:S) | 13:07:01:04 | ++-----------------------+----------------+ +| Transactions | 72528 | ++-----------------------+----------------+ +| KES PERIOD | 53 | ++-----------------------+----------------+ +| KES REMAINING | 53 | ++-----------------------+----------------+ +| SLOTS LED | 62 | ++-----------------------+----------------+ +| BLOCKS FORGED/ADOPTED | 62/62 | ++-----------------------+----------------+ + +Press [CTRL+C] to stop... +``` + +##### Troubleshooting/Customisations + +In case you run into trouble while running the script, you might want to edit `sLiveView.sh` and look at initialisation parameters below. You can hardcode the values if the commands do not provide the right information, but we would appreciate if you could also notify us by raising an issue against github repo: + +```bash +##################################### +# Change variables below as desired # +##################################### + +# The commands below will try to detect the information assuming you run single node on a machine. Please override values if they dont match your system + +cardanoport=$(ps -ef | grep "[c]ardano-node.*.port" | awk -F 'port ' '{print $2}' | awk '{print $1}') # example value: 6000 +nodename="TESTPOOL" # Change your node's name prefix here, 24 character limit!!! +refreshrate=2 # How often (in seconds) to refresh the view +config=$(ps -ef | grep "[c]ardano-node.*.config" | awk -F 'config ' '{print $2}' | awk '{print $1}') # example: /opt/cardano/cnode/files/config.json +ekghost=127.0.0.1 +if [[ -f "${config}" ]]; then + ekgport=$(jq -r '.hasEKG //empty' "${config}" 2>/dev/null) +else + ekgport=12788 +fi +``` diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 70d0349ea..ef5ce4aeb 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -11,6 +11,7 @@ - [Common tasks](Scripts/cntools-common.md) - [Block Collector](Scripts/cntools-blocks.md) - [Changelog](Scripts/cntools-changelog.md) + * [Simple LiveView](Scripts/sliveview.md) * [ITN Metadata Proof](Scripts/itnwitness.md) * [ITN Rewards](Scripts/itnrewards.md) * [Topology Updater](Scripts/topologyupdater.md) diff --git a/docs/contributors.md b/docs/contributors.md index d192d0ad2..314315254 100644 --- a/docs/contributors.md +++ b/docs/contributors.md @@ -8,11 +8,13 @@ Everyone is welcome to contribute to the guide, as well as the repository. Below [Bergr01](https://github.com/bergr01) [Ola Ahlman](https://github.com/Scitz0) [SmaugPool](https://github.com/SmaugPool) +[Adam](https://github.com/Crypto2099) +[Chris](https://github.com/Straightpool) +[Damjan](https://github.com/DamjanOstrelic) [Priyank](https://github.com/rdlrt) [Psychomb](https://github.com/psychomb) [PegasusPool](https://github.com/PegasusPool) [Matthijs](https://github.com/matthijs-aeon) [Marek](https://github.com/mmahut) - > To start contributing, simply hit the [github repository](https://github.com/cardano-community/guild-operators) and raise Issue/Pull Request diff --git a/files/ptn0-combinator.json b/files/ptn0-combinator.json index feaf54d30..2c96af9fc 100644 --- a/files/ptn0-combinator.json +++ b/files/ptn0-combinator.json @@ -41,7 +41,7 @@ "TracingVerbosity": "MaximalVerbosity", "TurnOnLogMetrics": true, "TurnOnLogging": true, - "ViewMode": "LiveView", + "ViewMode": "SimpleView", "defaultBackends": [ "KatipBK" ], @@ -156,7 +156,7 @@ }, "rotation": { "rpKeepFilesNum": 10, - "rpLogLimitBytes": 5000000, + "rpLogLimitBytes": 50000000, "rpMaxAgeHours": 24 }, "setupBackends": [ diff --git a/files/ptn0-mainnet.json b/files/ptn0-mainnet.json index 12d685962..f330474c5 100644 --- a/files/ptn0-mainnet.json +++ b/files/ptn0-mainnet.json @@ -39,7 +39,7 @@ "TracingVerbosity": "NormalVerbosity", "TurnOnLogMetrics": true, "TurnOnLogging": true, - "ViewMode": "LiveView", + "ViewMode": "SimpleView", "defaultBackends": [ "KatipBK" ], @@ -154,7 +154,7 @@ }, "rotation": { "rpKeepFilesNum": 10, - "rpLogLimitBytes": 5000000, + "rpLogLimitBytes": 50000000, "rpMaxAgeHours": 24 }, "setupBackends": [ diff --git a/files/ptn0-praos.json b/files/ptn0-praos.json index d84f86e78..0d60f51c0 100644 --- a/files/ptn0-praos.json +++ b/files/ptn0-praos.json @@ -36,7 +36,7 @@ "TracingVerbosity": "MaximalVerbosity", "TurnOnLogMetrics": true, "TurnOnLogging": true, - "ViewMode": "LiveView", + "ViewMode": "SimpleView", "defaultBackends": [ "KatipBK" ], @@ -151,7 +151,7 @@ }, "rotation": { "rpKeepFilesNum": 10, - "rpLogLimitBytes": 5000000, + "rpLogLimitBytes": 50000000, "rpMaxAgeHours": 24 }, "setupBackends": [ diff --git a/scripts/cnode-helper-scripts/prereqs.sh b/scripts/cnode-helper-scripts/prereqs.sh index 0175d77b9..3bd505742 100755 --- a/scripts/cnode-helper-scripts/prereqs.sh +++ b/scripts/cnode-helper-scripts/prereqs.sh @@ -114,7 +114,7 @@ if [ "$WANT_BUILD_DEPS" = 'Y' ]; then echo "deb https://dl.yarnpkg.com/debian/ stable main" | $sudo tee /etc/apt/sources.list.d/yarn.list > /dev/null $sudo apt-get -y update > /dev/null echo " Installing missing prerequisite packages, if any.." - $sudo apt-get -y install libpq-dev python3 build-essential pkg-config libffi-dev libgmp-dev libssl-dev libtinfo-dev systemd libsystemd-dev libsodium-dev zlib1g-dev yarn make g++ tmux git jq wget libncursesw5 gnupg aptitude libtool autoconf secure-delete > /dev/null;rc=$? + $sudo apt-get -y install libpq-dev python3 build-essential pkg-config libffi-dev libgmp-dev libssl-dev libtinfo-dev systemd libsystemd-dev libsodium-dev zlib1g-dev yarn make g++ tmux git jq wget libncursesw5 gnupg aptitude libtool autoconf secure-delete net-tools > /dev/null;rc=$? if [ $rc != 0 ]; then echo "An error occurred while installing the prerequisite packages, please investigate by using the command below:" echo "sudo apt-get -y install python3 build-essential pkg-config libffi-dev libgmp-dev libssl-dev libtinfo-dev systemd libsystemd-dev libsodium-dev zlib1g-dev npm yarn make g++ tmux git jq wget libncursesw5 gnupg libtool autoconf bsdmainutils" @@ -132,7 +132,7 @@ if [ "$WANT_BUILD_DEPS" = 'Y' ]; then $sudo rpm --import https://dl.yarnpkg.com/rpm/pubkey.gpg > /dev/null $sudo yum -y update > /dev/null echo " Installing missing prerequisite packages, if any.." - $sudo yum -y install python3 coreutils pkgconfig libffi-devel gmp-devel openssl-devel ncurses-libs ncurses-compat-libs systemd systemd-devel libsodium-devel zlib-devel npm yarn make gcc-c++ tmux git wget epel-release jq gnupg libtool autoconf srm > /dev/null;rc=$? + $sudo yum -y install python3 coreutils pkgconfig libffi-devel gmp-devel openssl-devel ncurses-libs ncurses-compat-libs systemd systemd-devel libsodium-devel zlib-devel npm yarn make gcc-c++ tmux git wget epel-release jq gnupg libtool autoconf srm net-tools > /dev/null;rc=$? if [ $rc != 0 ]; then echo "An error occurred while installing the prerequisite packages, please investigate by using the command below:" echo "sudo yum -y install coreutils python3 pkgconfig libffi-devel gmp-devel openssl-devel ncurses-libs ncurses-compat-libs systemd systemd-devel libsodium-devel zlib-devel npm yarn make gcc-c++ tmux git wget epel-release jq gnupg libtool autoconf util-linux" @@ -257,6 +257,7 @@ sed -e "s@CNODE_HOME=.*@${CNODE_VNAME}_HOME=${CNODE_HOME}@g" -e "s@CNODE_HOME@${ curl -s -o cabal-build-all.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/cabal-build-all.sh curl -s -o stack-build.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/stack-build.sh curl -s -o system-info.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/system-info.sh +curl -s -o sLiveView.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/sLiveView.sh chmod 755 ./*.sh # If you opt for an alternate CNODE_HOME, please run the below: # sed -i -e "s#/opt/cardano/cnode#${CNODE_HOME}#" *.sh diff --git a/scripts/cnode-helper-scripts/sLiveView.sh b/scripts/cnode-helper-scripts/sLiveView.sh new file mode 100755 index 000000000..383369372 --- /dev/null +++ b/scripts/cnode-helper-scripts/sLiveView.sh @@ -0,0 +1,159 @@ +#!/bin/bash +#shellcheck disable=SC2009,SC2034 + +# Credits to original Author of the script : Adam Dean (from BUFFY | SPIKE pool) by Crypto2099 + +##################################### +# Change variables below as desired # +##################################### + +# The commands below will try to detect the information assuming you run single node on a machine. Please override values if they dont match your system + +cardanoport=$(ps -ef | grep "[c]ardano-node.*.port" | awk -F 'port ' '{print $2}' | awk '{print $1}') # example value: 6000 +nodename="RTFM Lazy Guy" # Change your node's name prefix here, 24 character limit!!! +refreshrate=2 # How often (in seconds) to refresh the view +config=$(ps -ef | grep "[c]ardano-node.*.config" | awk -F 'config ' '{print $2}' | awk '{print $1}') # example: /opt/cardano/cnode/files/config.json +ekghost=127.0.0.1 +if [[ -f "${config}" ]]; then + ekgport=$(jq -r '.hasEKG //empty' "${config}" 2>/dev/null) +else + ekgport=12788 +fi + + +##################################### +# Do NOT Modify below # +##################################### + + +version=$("$(command -v cardano-node)" version) +node_version=$(grep -oP '(?<=cardano-node )[0-9\.]+' <<< "${version}") +node_rev=$(grep -oP '(?<=rev )[a-z0-9]+' <<< "${version}" | cut -c1-8) + +node_version=$(printf "%14s" "${node_version}") +node_rev=$(printf "%14s" "${node_rev}") + +# Add some colors +REKT='\033[1;31m' +GOOD='\033[0;32m' +NC='\033[0m' +INFO='\033[1;34m' +while true +do + data=$(curl -s -H 'Accept: application/json' http://${ekghost}:${ekgport}/ 2>/dev/null) + remotepeers=$(netstat -an|awk "\$4 ~ /${cardanoport}/"|grep -c ESTABLISHED) + peers=$(jq '.cardano.node.BlockFetchDecision.peers.connectedPeers.int.val //0' <<< "${data}") + blocknum=$(jq '.cardano.node.ChainDB.metrics.blockNum.int.val //0' <<< "${data}") + epochnum=$(jq '.cardano.node.ChainDB.metrics.epoch.int.val //0' <<< "${data}") + slotnum=$(jq '.cardano.node.ChainDB.metrics.slotInEpoch.int.val //0' <<< "${data}") + density=$(jq -r '.cardano.node.ChainDB.metrics.density.real.val //0' <<< "${data}") + uptimens=$(jq '.cardano.node.metrics.upTime.ns.val //0' <<< "${data}") + transactions=$(jq '.cardano.node.metrics.txsProcessedNum.int.val //0' <<< "${data}") + kesperiod=$(jq '.cardano.node.Forge.metrics.currentKESPeriod.int.val //0' <<< "${data}") + kesremain=$(jq '.cardano.node.Forge.metrics.remainingKESPeriods.int.val //0' <<< "${data}") + isleader=$(jq '.cardano.node.metrics.Forge["node-is-leader"].int.val //0' <<< "${data}") + abouttolead=$(jq '.cardano.node.metrics.Forge["forge-about-to-lead"].int.val //0' <<< "${data}") + forged=$(jq '.cardano.node.metrics.Forge.forged.int.val //0' <<< "${data}") + adopted=$(jq '.cardano.node.metrics.Forge.adopted.int.val //0' <<< "${data}") + + if [[ ${abouttolead} -gt 0 ]]; then + name=$(printf "%s - Core\n" "${nodename}") + else + name=$(printf "%s - Relay\n" "${nodename}") + fi + + if ((uptimens<=0)); then + echo -e "${REKT}COULD NOT CONNECT TO A RUNNING INSTANCE! PLEASE CHECK THE PROMETHEUS PORT AND TRY AGAIN!${NC}" + exit + fi + +# remotepeers=$(printf "%14s" "${remotepeers}") + peers=$(printf "%14s" "${peers} / ${remotepeers}") + epoch=$(printf "%14s" "${epochnum} / ${slotnum}") + block=$(printf "%14s" "${blocknum}") + txcount=$(printf "%14s" "${transactions}") + density=$(printf "%12.4s %%" "${density}"*100) + + if [[ isleader -lt 0 ]]; then + isleader=0 + forged=0 + fi + + uptimes=$(( uptimens / 1000000000)) + min=0 + hour=0 + day=0 + if((uptimes > 59)); then + ((sec=uptimes%60)) + ((uptimes=uptimes/60)) + if((uptimes > 59)); then + ((min=uptimes%60)) + ((uptimes=uptimes/60)) + if((uptimes > 23)); then + ((hour=uptimes%24)) + ((day=uptimes/24)) + else + ((hour=uptimes)) + fi + else + ((min=uptimes)) + fi + else + ((sec=uptimes)) + fi + + day=$(printf "%02d\n" "${day}") + hour=$(printf "%02d\n" "${hour}") + min=$(printf "%02d\n" "${min}") + sec=$(printf "%02d\n" "${sec}") + + uptime="${day}":"${hour}":"${min}":"${sec}" + uptime=$(printf "%14s" "${uptime}") + + clear + echo -e '+----------------------------------------+' + echo -e '| Simple Node Stats |' + echo -e '+-----------------------+----------------+' + if [[ -n "${nodename}" ]]; then + name=$(printf "%32s" "${name}") + echo -e "| Name: ${INFO}${name}${NC} |" + echo -e '+-----------------------+----------------+' + fi + echo -e "| Version | ${INFO}${node_version}${NC} |" + echo -e '+-----------------------+----------------+' + echo -e "| Revision | ${INFO}${node_rev}${NC} |" + echo -e '+-----------------------+----------------+' + echo -e "| Peers (Out / In) | ${peers} |" + echo -e "+-----------------------+----------------+" + echo -e "| Epoch / Slot | ${epoch} |" + echo -e '+-----------------------+----------------+' + echo -e "| Block | ${block} |" + echo -e '+-----------------------+----------------+' + echo -e "| Density | ${density} |" + echo -e '+-----------------------+----------------+' + echo -e "| Uptime (D:H:M:S) | ${uptime} |" + echo -e '+-----------------------+----------------+' + echo -e "| Transactions | ${txcount} |" + echo -e '+-----------------------+----------------+' + if [[ ${abouttolead} -gt 0 ]]; then + kesperiod=$(printf "%14s" "${kesperiod}") + kesremain=$(printf "%14s" "${kesremain}") + isleader=$(printf "%14s" "${isleader}") + forged=$(printf "%14s" "${forged}/${adopted}") + echo -e "| KES PERIOD | ${kesperiod} |" + echo -e "+-----------------------+----------------+" + echo -e "| KES REMAINING | ${kesremain} |" + echo -e "+-----------------------+----------------+" + echo -e "| SLOTS LED | ${isleader} |" + echo -e "+-----------------------+----------------+" + echo -e "| BLOCKS FORGED/ADOPTED | ${forged} |" + echo -e "+-----------------------+----------------+" + else + echo -e "+----------------------------------------+" + fi + + + echo -e "\n${INFO}Press [CTRL+C] to stop...${NC}" + sleep ${refreshrate} +done + From 1d3dd6ba845f481dc5cf3d678acfb256da9ce22a Mon Sep 17 00:00:00 2001 From: Priyank <3169068+rdlrt@users.noreply.github.com> Date: Fri, 28 Aug 2020 13:03:57 +1000 Subject: [PATCH 09/24] Add PATH environment variable to env file, and calling cnode.sh from that file (#449) * Add PATH environment variable to env * Add a point in node-cli.md to clarify overwrites --- docs/Build/node-cli.md | 1 + scripts/cnode-helper-scripts/cnode.sh.templ | 4 +++- scripts/cnode-helper-scripts/env | 10 ++++++++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/Build/node-cli.md b/docs/Build/node-cli.md index 29e99c970..57ace9189 100644 --- a/docs/Build/node-cli.md +++ b/docs/Build/node-cli.md @@ -113,5 +113,6 @@ If you've followed guide from this repo previously and would like to transfer to 1. Stop previous instance of node if already running (eg: in tmux) 2. Run `prereqs.sh` OR simply replace `LiveView` to `SimpleView` in your $CNODE_HOME/files/config.json. + (PS: Remember to preserve your customisations to cnode.sh, topology.json, env files - you can refer to changes in [PR-449](https://github.com/cardano-community/guild-operators/pull/449/files) to manually apply changes without affecting your setup much) 3. Follow the instructions [above](#run-as-systemd-service) to setup your node as a service and start it using systemctl as directed. 4. If you need to monitor via interactive terminal as before, use [sLiveView](Scripts/sliveview.md). diff --git a/scripts/cnode-helper-scripts/cnode.sh.templ b/scripts/cnode-helper-scripts/cnode.sh.templ index ca50d107d..e6513cf7b 100755 --- a/scripts/cnode-helper-scripts/cnode.sh.templ +++ b/scripts/cnode-helper-scripts/cnode.sh.templ @@ -3,8 +3,10 @@ [[ -z "$CNODE_HOME" ]] && CNODE_HOME="/opt/cardano/cnode" +. "${CNODE_HOME}"/scripts/env + if [[ -S "$CNODE_HOME/sockets/node0.socket" ]]; then - if [ `ps -ef | grep -c cardano-node.*.$CNODE_HOME/sockets/node0.socket` -gt 0 ]; then + if [ `ps -ef | grep -c [c]ardano-node.*.$CNODE_HOME/sockets/node0.socket` -gt 0 ]; then echo "ERROR: A Cardano node is already running, please terminate this node before starting a new one with this script." exit 1 else diff --git a/scripts/cnode-helper-scripts/env b/scripts/cnode-helper-scripts/env index 547e64917..ef7724212 100644 --- a/scripts/cnode-helper-scripts/env +++ b/scripts/cnode-helper-scripts/env @@ -2,8 +2,14 @@ # shellcheck disable=SC2034,SC2086,SC2230 CCLI=$(command -v cardano-cli) if [[ -z "${CCLI}" ]]; then - echo "You do not have a cardano-cli binary available in \$PATH. Please make it available before using CNTools. Refer to guild-operators documentation for the same." - exit 1 + if [[ -f "${HOME}/.cabal/bin/cardano-cli" ]]; then + # Assumption being made that cardano-cli and cardano-node are both present, if not - prereqs and build instructions were not followed + export PATH="${HOME}/.cabal/bin":$PATH + CCLI=$(command -v cardano-cli) + else + echo "You do not have a cardano-cli binary available in \$PATH. Please make it available before using CNTools. Refer to guild-operators documentation for the same." + exit 1 + fi fi CNODE_HOME=/opt/cardano/cnode CONFIG=$CNODE_HOME/files/config.json From c09352b9b03fb4d858d5d3d9e87a6808abfaf856 Mon Sep 17 00:00:00 2001 From: "Ola [AHLNET]" Date: Thu, 3 Sep 2020 11:46:10 +0200 Subject: [PATCH 10/24] Guild LiveView - RC1 (#451) A replacement/compliment to the recently added sLiveView and the official built in cardano-node LiveView. The utility work independently of LiveView/SimpleView configuration and is as such a good way to get visual node metrics when cardano-node is deployed through systemd in SimpleView. Inspiration is taken from a mix of community scripts(Adam@BUFFY Simple LiveView, CNTools, Martin@ATADA pingNodes) combined with the original LiveView. Metrics are taken from node EKG API combined with network tools to query peers. If CNTools Block Collector is enabled and used current epoch blocks are also displayed for core node. System metrics are intentionally left out for now as these are better monitored using pre-existing Linux tools like top, atop, htop, iotop etc. Known issues: - [x] Screen too small / resize can mess up output in some situations. - [x] Offline tip ref & chain epoch calculation is coded for MainNet, add support for TestNets. - [x] When node isnt in sync to shelley era, the prompt and errors remain hidden due to `tput` ![image](https://user-images.githubusercontent.com/15903629/91892130-6c070080-ec92-11ea-9839-b3b9c3757fbf.png) ![image](https://user-images.githubusercontent.com/15903629/91892516-141cc980-ec93-11ea-81cf-9ed931d51bad.png) Side - optimisations: - [x] Move systemd install instructions to deploy-as-systemd.sh file - [x] Make use of CNODE_NAME uniformly across the script to start using environment variables and folder names that begin with CNODE_NAME in respective cases. - [x] Add`bc` to prereqs.sh - [x] Move list of OS packages to pkg_list variable Co-authored-by: rdlrt <3169068+rdlrt@users.noreply.github.com> --- docs/Build/node-cli.md | 50 +- docs/Contributors.md | 18 - docs/Scripts/gliveview.md | 46 ++ docs/Scripts/sliveview.md | 79 -- docs/_sidebar.md | 2 +- docs/basics.md | 4 +- .../cnode-helper-scripts/deploy-as-systemd.sh | 28 + scripts/cnode-helper-scripts/gLiveView.sh | 701 ++++++++++++++++++ scripts/cnode-helper-scripts/prereqs.sh | 36 +- 9 files changed, 809 insertions(+), 155 deletions(-) delete mode 100644 docs/Contributors.md create mode 100644 docs/Scripts/gliveview.md delete mode 100644 docs/Scripts/sliveview.md create mode 100755 scripts/cnode-helper-scripts/deploy-as-systemd.sh create mode 100755 scripts/cnode-helper-scripts/gLiveView.sh diff --git a/docs/Build/node-cli.md b/docs/Build/node-cli.md index 57ace9189..82a7e9ec4 100644 --- a/docs/Build/node-cli.md +++ b/docs/Build/node-cli.md @@ -57,62 +57,34 @@ cd $CNODE_HOME/scripts The preferred way to run the node is through a service manager like systemd. This section explains how to setup a systemd service file. -**1. Create systemd service file** -Replace `$USER` with the correct user for your system. Copy & paste all code below to create the service file. -``` bash -sudo bash -c "cat << 'EOF' > /etc/systemd/system/cnode.service -[Unit] -Description=Cardano Node -After=network.target - -[Service] -Type=simple -Restart=on-failure -RestartSec=5 -User=$USER -LimitNOFILE=1048576 -WorkingDirectory=$CNODE_HOME/scripts -ExecStart=/bin/bash -l -c \"exec $CNODE_HOME/scripts/cnode.sh\" -ExecStop=/bin/bash -l -c \"exec kill -2 \$(ps -ef | grep [c]ardano-node.*.node0.socket | tr -s ' ' | cut -d ' ' -f2)\" -KillSignal=SIGINT -SuccessExitStatus=143 -StandardOutput=syslog -StandardError=syslog -SyslogIdentifier=cnode -TimeoutStopSec=5 -KillMode=mixed - -[Install] -WantedBy=multi-user.target -EOF" -``` - -**2. Reload systemd and enable automatic start of service on startup** -``` bash -sudo systemctl daemon-reload -sudo systemctl enable cnode.service +**1. Deploy as a systemd service** +Execute the below command to deploy your node as a systemd service (from the respective scripts folder): +```bash +cd $CNODE_HOME/scripts +./deploy-as-systemd.sh ``` -**3. Start the node** +**2. Start the node** Run below commands to enable automatic start of service on startup and start it. ``` bash sudo systemctl start cnode.service ``` -**4. Check status and stop/start commands** +**3. Check status and stop/start commands** Replace `status` with `stop`/`start`/`restart` depending on what action to take. ``` bash sudo systemctl status cnode.service ``` -You can use [sLiveView](Scripts/sliveview.md) to monitor your pool that was started as systemd, if you miss the LiveView functionality. +?> In case you see the node exit unsuccessfully upon checking status, please verify you've followed the transition process correctly as documented below, and that you do not have another instance of node already running. It would help to check your system logs (/var/log/syslog for debian-based and /var/log/messages for redhat/CentOS/Fedora systems) for any errors while starting node. + +You can use [gLiveView](Scripts/gliveview.md) to monitor your pool that was started as systemd, if you miss the LiveView functionality. ##### Steps to transition from LiveView in tmux to systemd setup If you've followed guide from this repo previously and would like to transfer to systemd usage, please checkout the steps below: 1. Stop previous instance of node if already running (eg: in tmux) -2. Run `prereqs.sh` OR simply replace `LiveView` to `SimpleView` in your $CNODE_HOME/files/config.json. - (PS: Remember to preserve your customisations to cnode.sh, topology.json, env files - you can refer to changes in [PR-449](https://github.com/cardano-community/guild-operators/pull/449/files) to manually apply changes without affecting your setup much) +2. Run `prereqs.sh`, but remember to preserve your customisations to cnode.sh, topology.json, env files. 3. Follow the instructions [above](#run-as-systemd-service) to setup your node as a service and start it using systemctl as directed. 4. If you need to monitor via interactive terminal as before, use [sLiveView](Scripts/sliveview.md). diff --git a/docs/Contributors.md b/docs/Contributors.md deleted file mode 100644 index d192d0ad2..000000000 --- a/docs/Contributors.md +++ /dev/null @@ -1,18 +0,0 @@ -Everyone is welcome to contribute to the guide, as well as the repository. Below is just a thank you to people who have been contributing consistently: - -[Markus](https://github.com/gufmar) -[Pal Dorogi](https://github.com/ilap) -[OCG](https://github.com/oldcryptogeek) -[RedOracle](https://github.com/RedOracle) -[Papacarp](https://github.com/papacarp) -[Bergr01](https://github.com/bergr01) -[Ola Ahlman](https://github.com/Scitz0) -[SmaugPool](https://github.com/SmaugPool) -[Priyank](https://github.com/rdlrt) -[Psychomb](https://github.com/psychomb) -[PegasusPool](https://github.com/PegasusPool) -[Matthijs](https://github.com/matthijs-aeon) -[Marek](https://github.com/mmahut) - - -> To start contributing, simply hit the [github repository](https://github.com/cardano-community/guild-operators) and raise Issue/Pull Request diff --git a/docs/Scripts/gliveview.md b/docs/Scripts/gliveview.md new file mode 100644 index 000000000..d605a51ac --- /dev/null +++ b/docs/Scripts/gliveview.md @@ -0,0 +1,46 @@ +!> Ensure the [Pre-Requisites](basics.md#pre-requisites) are in place before you proceed. + +**Guild LiveView - gLiveView** is a utility to display an equivalent subset of LiveView interface that cardano-node users have grown accustomed to. This is especially useful when moving to a systemd deployment - if you haven't done so already - while looking for a familiar UI to monitor the node status. + +The tool is independent from other files and can run as a standalone utility that can be stopped/started without affecting the status of cardano-node. + +##### Download & Setup + +The tool in itself should only require a single file. If you've used [prereqs.sh](basics.md#pre-requisites), you can skip this part , as this is already set up for you. +To get current epoch blocks, [cntoolsBlockCollector.sh](Scripts/cntools-blocks.md) script is needed. This is optional and **Guild LiveView** will function without it. + +?> For those who follow guild's [folder structure](basics.md#folder-structure) and do not wish to run prereqs.sh, you can run the below in `$CNODE_HOME/scripts` folder + +To download the script: +```bash +curl -s -o gLiveView.sh curl -s -o gLiveView.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/gLiveView.sh +chmod 755 gLiveView.sh +``` + +##### Startup + +For most standard deployments, this should lead you to a stage where you can now start running `./gLiveView.sh` in the folder you downloaded the script (default location for cntools users would be `$CNODE_HOME/scripts`). Note that the script is smart enough to automatically detect when you're running as a Core or Relay and will show fields accordingly. +A sample output from both core and relay(with peer analysis run): + +![Core](https://raw.githubusercontent.com/cardano-community/guild-operators/images/gliveview-core.png) + +![Relay](https://raw.githubusercontent.com/cardano-community/guild-operators/images/gliveview-relay.png) + +##### Troubleshooting/Customisations + +In case you run into trouble while running the script, you might want to edit `gLiveView.sh` and look at User Variables section shown below. You can override the values if the automatic detection do not provide the right information, but we would appreciate if you could also notify us by raising an issue against github repo: + +```bash +###################################### +# User Variables - Change as desired # +###################################### + +#CNODE_HOME="/opt/cardano/cnode" # Override default CNODE_HOME path +#CNODE_PORT=6000 # Override automatic detection of node port +NODE_NAME="Cardano Node" # Change your node's name prefix here, keep at or below 19 characters for proper formatting +REFRESH_RATE=2 # How often (in seconds) to refresh the view +#CONFIG="${CNODE_HOME}/files/config.json" # Override automatic detection of node config path +EKG_HOST=127.0.0.1 # Set node EKG host +#EKG_PORT=12788 # Override automatic detection of node EKG port +#BLOCK_LOG_DIR="${CNODE_HOME}/db/blocks" # CNTools Block Collector block dir set in cntools.config, override path if enabled and using non standard path +``` diff --git a/docs/Scripts/sliveview.md b/docs/Scripts/sliveview.md deleted file mode 100644 index b87ea1209..000000000 --- a/docs/Scripts/sliveview.md +++ /dev/null @@ -1,79 +0,0 @@ -!> Ensure the [Pre-Requisites](basics.md#pre-requisites) are in place before you proceed. - -**Simple LiveView - sLiveView** is a small utility to display an equivalent subset of LiveView interface that cardano-node users have grown accustomed to. This is useful when changing to `SimpleView` and moving to a systemd deployment - if you haven't done so already - while looking for a familiar UI to monitor the node status. - -The tool is independent from other files and can run as a standalone utility that can be stopped/started without affecting the status of cardano-node. - -##### Download & Setup - -The tool in itself should only require a single file. If you've used [prereqs.sh](basics.md#pre-requisites), you can skip this part , as this is already set up for you. - -?> For those who follow guild's [folder structure](basics.md#folder-structure) and do not wish to run prereqs.sh, you can run the below in `$CNODE_HOME/scripts` folder - -To download the script: -```bash -curl -s -o sLiveView.sh curl -s -o sLiveView.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/sLiveView.sh -chmod 755 sLiveView.sh -``` - -##### Startup - -For most standard deployments, this should lead you to a stage where you can now start running sLiveView.sh - it will automatically detect when you're running as a Core or Relay and show fields accordingly, a sample output below: - -```bash -./sLiveView.sh -+----------------------------------------+ -| Simple Node Stats | -+-----------------------+----------------+ -| Name: TESTPOOL - Core | -+-----------------------+----------------+ -| Version | 1.19.0 | -+-----------------------+----------------+ -| Revision | 49536693 | -+-----------------------+----------------+ -| Peers (Out / In) | 8 / 16 | -+-----------------------+----------------+ -| Epoch / Slot | 213 / 296153 | -+-----------------------+----------------+ -| Block | 4612464 | -+-----------------------+----------------+ -| Density | 4.99 % | -+-----------------------+----------------+ -| Uptime (D:H:M:S) | 13:07:01:04 | -+-----------------------+----------------+ -| Transactions | 72528 | -+-----------------------+----------------+ -| KES PERIOD | 53 | -+-----------------------+----------------+ -| KES REMAINING | 53 | -+-----------------------+----------------+ -| SLOTS LED | 62 | -+-----------------------+----------------+ -| BLOCKS FORGED/ADOPTED | 62/62 | -+-----------------------+----------------+ - -Press [CTRL+C] to stop... -``` - -##### Troubleshooting/Customisations - -In case you run into trouble while running the script, you might want to edit `sLiveView.sh` and look at initialisation parameters below. You can hardcode the values if the commands do not provide the right information, but we would appreciate if you could also notify us by raising an issue against github repo: - -```bash -##################################### -# Change variables below as desired # -##################################### - -# The commands below will try to detect the information assuming you run single node on a machine. Please override values if they dont match your system - -cardanoport=$(ps -ef | grep "[c]ardano-node.*.port" | awk -F 'port ' '{print $2}' | awk '{print $1}') # example value: 6000 -nodename="TESTPOOL" # Change your node's name prefix here, 24 character limit!!! -refreshrate=2 # How often (in seconds) to refresh the view -config=$(ps -ef | grep "[c]ardano-node.*.config" | awk -F 'config ' '{print $2}' | awk '{print $1}') # example: /opt/cardano/cnode/files/config.json -ekghost=127.0.0.1 -if [[ -f "${config}" ]]; then - ekgport=$(jq -r '.hasEKG //empty' "${config}" 2>/dev/null) -else - ekgport=12788 -fi -``` diff --git a/docs/_sidebar.md b/docs/_sidebar.md index ef5ce4aeb..c9e25670d 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -11,7 +11,7 @@ - [Common tasks](Scripts/cntools-common.md) - [Block Collector](Scripts/cntools-blocks.md) - [Changelog](Scripts/cntools-changelog.md) - * [Simple LiveView](Scripts/sliveview.md) + * [Guild LiveView](Scripts/gliveview.md) * [ITN Metadata Proof](Scripts/itnwitness.md) * [ITN Rewards](Scripts/itnrewards.md) * [Topology Updater](Scripts/topologyupdater.md) diff --git a/docs/basics.md b/docs/basics.md index 9ace11c2b..d922a32de 100644 --- a/docs/basics.md +++ b/docs/basics.md @@ -27,13 +27,11 @@ chmod 755 prereqs.sh # -i Interactive mode (Default: silent mode) # -g Connect to guild network instead of public network (Default: connect to public cardano network) # -p Copy Transitional Praos config as default instead of Combinator networks (Default: copies combinator network) - +# -t Alternate name for top level folder # You can use one of the options above, if you'd like to defer from defaults (below). # Running without any parameters will run script in silent mode with OS Dependencies, and overwriting existing files. ./prereqs.sh - -## Follow the prompts for execution. To make sure environment variables are available for session you're running, make sure to source bashrc . "${HOME}/.bashrc" ``` diff --git a/scripts/cnode-helper-scripts/deploy-as-systemd.sh b/scripts/cnode-helper-scripts/deploy-as-systemd.sh new file mode 100755 index 000000000..5040b0066 --- /dev/null +++ b/scripts/cnode-helper-scripts/deploy-as-systemd.sh @@ -0,0 +1,28 @@ +sudo bash -c "cat << 'EOF' > /etc/systemd/system/cnode.service +[Unit] +Description=Cardano Node +After=network.target + +[Service] +Type=simple +Restart=on-failure +RestartSec=5 +User=$USER +LimitNOFILE=1048576 +WorkingDirectory=$CNODE_HOME/scripts +ExecStart=/bin/bash -l -c \"exec $CNODE_HOME/scripts/cnode.sh\" +ExecStop=/bin/bash -l -c \"exec kill -2 \$(ps -ef | grep [c]ardano-node.*.${CNODE_HOME} | tr -s ' ' | cut -d ' ' -f2)\" +KillSignal=SIGINT +SuccessExitStatus=143 +StandardOutput=syslog +StandardError=syslog +SyslogIdentifier=cnode +TimeoutStopSec=5 +KillMode=mixed + +[Install] +WantedBy=multi-user.target +EOF" + +sudo systemctl daemon-reload +sudo systemctl enable diff --git a/scripts/cnode-helper-scripts/gLiveView.sh b/scripts/cnode-helper-scripts/gLiveView.sh new file mode 100755 index 000000000..c7abb6b90 --- /dev/null +++ b/scripts/cnode-helper-scripts/gLiveView.sh @@ -0,0 +1,701 @@ +#!/bin/bash +#shellcheck disable=SC2009,SC2034,SC2059 + +################################################################### +# Automatically grab a few parameters # +# Do NOT modify, can be overridden 'User Variables' section below # +################################################################### + +# The commands below will try to detect the information assuming you run single node on a machine. +# Please override values if they dont match your system in the 'User Variables' section below +[[ -z "${CNODE_HOME}" ]] && CNODE_HOME=/opt/cardano/cnode +[[ "$(ps -ef | grep "[c]ardano-node.*.${CNODE_HOME}")" =~ --port[[:space:]]([[:digit:]]+) ]] +CNODE_PORT=${BASH_REMATCH[1]:-6000} # default value: 6000 +[[ "$(ps -ef | grep "[c]ardano-node.*.${CNODE_HOME}")" =~ --config[[:space:]]([^[:space:]]+) ]] +CONFIG="${BASH_REMATCH[1]:-${CNODE_HOME}/files/config.json}" # default value: /opt/cardano/cnode/files/config.json +if [[ -f "${CONFIG}" ]]; then + EKG_PORT=$(jq -r '.hasEKG //empty' "${CONFIG}" 2>/dev/null) +else + EKG_PORT=12788 +fi +PROTOCOL=$(jq -r '.Protocol //empty' "${CONFIG}" 2>/dev/null) +[[ -d "${CNODE_HOME}/db/blocks" ]] && BLOCK_LOG_DIR="${CNODE_HOME}/db/blocks" + +###################################### +# User Variables - Change as desired # +# Leave as is if usure # +###################################### + +#CNODE_HOME="/opt/cardano/cnode" # Override default CNODE_HOME path +#CNODE_PORT=6000 # Override automatic detection of node port +NODE_NAME="Cardano Node" # Change your node's name prefix here, keep at or below 19 characters for proper formatting +REFRESH_RATE=2 # How often (in seconds) to refresh the view +#CONFIG="${CNODE_HOME}/files/config.json" # Override automatic detection of node config path +EKG_HOST=127.0.0.1 # Set node EKG host +#EKG_PORT=12788 # Override automatic detection of node EKG port +#PROTOCOL="Cardano" # Default: Combinator network. Leave commented if unsure. +#BLOCK_LOG_DIR="${CNODE_HOME}/db/blocks" # CNTools Block Collector block dir set in cntools.config, override path if enabled and using non standard path + +##################################### +# Do NOT Modify below # +##################################### + +tput smcup # Save screen +tput civis # Disable cursor +stty -echo # Disable user input + +# Style +width=53 +second_col=28 +FG_RED=$(tput setaf 1) +FG_GREEN=$(tput setaf 2) +FG_YELLOW=$(tput setaf 3) +FG_BLUE=$(tput setaf 4) +FG_MAGENTA=$(tput setaf 5) +FG_CYAN=$(tput setaf 6) +STANDOUT=$(tput smso) +BOLD=$(tput bold) +VL="\\u2502" +HL="\\u2500" +NC=$(tput sgr0) + +# Progressbar +char_marked=$(printf "\\u258C") +char_unmarked=$(printf "\\u2596") +granularity=50 +granularity_small=25 +step_size=$((100/granularity)) +step_size_small=$((100/granularity_small)) +bar_col_small=$((width - granularity_small)) + +# Lines +tdivider=$(printf "\\u250C" && printf "%0.s${HL}" $(seq $((width-1))) && printf "\\u2510") +mdivider=$(printf "\\u251C" && printf "%0.s${HL}" $(seq $((width-1))) && printf "\\u2524") +m2divider=$(printf "\\u251C" && printf "%0.s-" $(seq $((width-1))) && printf "\\u2524") +bdivider=$(printf "\\u2514" && printf "%0.s${HL}" $(seq $((width-1))) && printf "\\u2518") + +# Title +title=$(printf "${FG_MAGENTA}${BOLD}Guild LiveView${NC}") + +##################################### +# Helper functions # +##################################### + +# Command : myExit [message] +# Description : gracefully handle an exit and restore terminal to original state +myExit() { + tput rmcup # restore screen + [[ -n $2 ]] && echo -e "\n$2" + stty echo # Enable user input + tput cnorm # restore cursor + echo -e "${NC}" # turn off all attributes + exit "$1" +} + +# General exit handler +cleanup() { + err=$? + trap '' INT TERM + myExit $err "Guild LiveView terminated, cleaning up..." +} +sig_cleanup() { + trap '' EXIT # some shells will call EXIT after the INT handler + false # sets $? + cleanup +} +trap sig_cleanup INT TERM + +# Command : waitForInput +# Description : wait for user keypress to quit, else do nothing if timeout expire +waitForInput() { + ESC=$(printf "\033") + if ! read -rsn1 -t ${REFRESH_RATE} key1; then return; fi + [[ ${key1} = "${ESC}" ]] && read -rsn2 -t 0.3 key2 # read 2 more chars + [[ ${key1} = "p" ]] && check_peers="true" && show_peers="true" && return + [[ ${key1} = "h" ]] && show_peers="hide" && return + [[ ${key1} = "q" ]] && myExit 0 "Guild LiveView stopped!" + [[ ${key1} = "${ESC}" && ${key2} = "" ]] && myExit 0 "Guild LiveView stopped!" + sleep 1 +} + + + +# Command : showTimeLeft time_in_seconds +# Description: calculation of days, hours, minutes and seconds +timeLeft() { + local T=$1 + local D=$((T/60/60/24)) + local H=$((T/60/60%24)) + local M=$((T/60%60)) + local S=$((T%60)) + (( D > 0 )) && printf '%d day' $D && { + (( D > 1 )) && printf 's ' || printf ' ' + } + printf '%02d:%02d:%02d' $H $M $S +} + +# Command : getEpoch +# Description: Offline calculation of current epoch based on genesis file +getShelleyTransitionEpoch() { + calc_slot=0 + byron_epochs=${epochnum} + shelley_epochs=0 + while [[ ${byron_epochs} -ge 0 ]]; do + calc_slot=$(( (byron_epochs*byron_epoch_length) + (shelley_epochs*epoch_length) + slotinepoch )) + [[ ${calc_slot} -eq ${slotnum} ]] && break + ((byron_epochs--)) + ((shelley_epochs++)) + done + if [[ "${nwmagic}" = "764824073" ]]; then + shelley_transition_epoch=208 + elif [[ ${calc_slot} -ne ${slotnum} || ${shelley_epochs} -eq 0 ]]; then + clear + printf "\n ${FG_RED}Failed${NC} to calculate shelley transition epoch!" + printf "\n Calculations might not work correctly until Shelley era is reached." + printf "\n\n ${FG_BLUE}Press c to continue or any other key to quit${NC}" + read -r -n 1 -s -p "" answer + [[ "${answer}" != "c" ]] && myExit 1 "Guild LiveView terminated!" + shelley_transition_epoch=0 + else + shelley_transition_epoch=${byron_epochs} + fi +} + +# Command : getEpoch +# Description: Offline calculation of current epoch based on genesis file +getEpoch() { + current_time_sec=$(date -u +%s) + if [[ "${PROTOCOL}" = "Cardano" ]]; then + byron_end_time=$(( byron_genesis_start_sec + ( shelley_transition_epoch * byron_epoch_length * byron_slot_length ) )) + echo $(( shelley_transition_epoch + ( (current_time_sec - byron_end_time) / slot_length / epoch_length ) )) + else + echo $(( (current_time_sec - shelley_genesis_start_sec) / slot_length / epoch_length )) + fi +} + +# Command : getTimeUntilNextEpoch +# Description: Offline calculation of time in seconds until next epoch +timeUntilNextEpoch() { + echo $(( (shelley_transition_epoch * byron_slot_length * byron_epoch_length) + ( ( $(getEpoch) + 1 - shelley_transition_epoch ) * slot_length * epoch_length ) - $(date -u +%s) + byron_genesis_start_sec )) +} + +# Command : getSlotTipRef +# Description: Get calculated slot number tip +getSlotTipRef() { + current_time_sec=$(date -u +%s) + if [[ "${PROTOCOL}" = "Cardano" ]]; then + # Combinator network + byron_slots=$(( shelley_transition_epoch * byron_epoch_length )) # since this point will only be reached once we're in Shelley phase + byron_end_time=$(( byron_genesis_start_sec + ( shelley_transition_epoch * byron_epoch_length * byron_slot_length ) )) + if [[ "${current_time_sec}" -lt "${byron_end_time}" ]]; then + # In Byron phase + echo $(( ( current_time_sec - byron_genesis_start_sec ) / byron_slot_length )) + else + # In Shelley phase + echo $(( byron_slots + (( current_time_sec - byron_end_time ) / slot_length ) )) + fi + else + # Shelley Mode only, no Byron slots + echo $(( ( current_time_sec - shelley_genesis_start_sec ) / slot_length )) + fi +} + +# Command : kesExpiration [pools remaining KES periods] +# Description: Calculate KES expiration +kesExpiration() { + remaining_kes_periods=$1 + slot_in_epoch=$2 + current_time_sec=$(date -u +%s) + expiration_time_sec=$(( current_time_sec - ( slot_length * slot_in_epoch ) + ( slot_length * slots_per_kes_period * remaining_kes_periods ) )) + date '+%F %T Z' --date=@${expiration_time_sec} +} + +endLine() { + tput -S </dev/null | grep -e ":${CNODE_PORT}" | awk '{print $7}' | tail -n 1 | cut -d"/" -f1) + [[ -z ${pid} || ${pid} = "-" ]] && return + + if [[ ${direction} = "out" ]]; then + netstatPeers=$(netstat -np 2>/dev/null | grep -e "ESTABLISHED.* ${pid}/" | grep -v ":${CNODE_PORT}" | awk '{print $5}') + else + netstatPeers=$(netstat -np 2>/dev/null | grep -e "ESTABLISHED.* ${pid}/" | grep ":${CNODE_PORT}" | awk '{print $5}') + fi + netstatSorted=$(printf '%s\n' "${netstatPeers[@]}" | sort ) + + # Sort/filter peers + lastpeerIP=""; lastpeerPORT="" + for peer in $netstatSorted; do + peerIP=$(echo "${peer}" | cut -d: -f1); peerPORT=$(echo "${peer}" | cut -d: -f2) + if [[ ! "$peerIP" = "$lastpeerIP" ]]; then + lastpeerIP=${peerIP} + lastpeerPORT=${peerPORT} + uniqPeers+=("${peerIP}:${peerPORT} ") + ((peerCNTABS++)) + fi + done + netstatPeers=$(printf '%s\n' "${uniqPeers[@]}") + + # Ping every node in the list + for peer in ${netstatPeers}; do + peerIP=$(echo "${peer}" | cut -d: -f1) + peerPORT=$(echo "${peer}" | cut -d: -f2) + + if checkPEER=$(ping -c 2 -i 0.3 -w 1 "${peerIP}" 2>&1); then # Ping OK, show RTT + peerRTT=$(echo "${checkPEER}" | tail -n 1 | cut -d/ -f5 | cut -d. -f1) + ((peerCNT++)) + peerRTTSUM=$((peerRTTSUM + peerRTT)) + elif [[ ${direction} = "in" ]]; then # No need to continue with tcptraceroute for incoming connection as destination port is unknown + peerRTT=-1 + else # Normal ping is not working, try tcptraceroute to the given port + checkPEER=$(tcptraceroute -n -S -f 255 -m 255 -q 1 -w 1 "${peerIP}" "${peerPORT}" 2>&1 | tail -n 1) + if [[ ${checkPEER} = *'[open]'* ]]; then + peerRTT=$(echo "${checkPEER}" | awk '{print $4}' | cut -d. -f1) + ((peerCNT++)) + peerRTTSUM=$((peerRTTSUM + peerRTT)) + else # Nope, no response + peerRTT=-1 + fi + fi + + # Update counters + if [[ ${peerRTT} -ge 200 ]]; then ((peerCNT4++)) + elif [[ ${peerRTT} -ge 100 ]]; then ((peerCNT3++)) + elif [[ ${peerRTT} -ge 50 ]]; then ((peerCNT2++)) + elif [[ ${peerRTT} -ge 0 ]]; then ((peerCNT1++)) + else ((peerCNT0++)); fi + done + if [[ ${peerCNT} -gt 0 ]]; then + peerRTTAVG=$((peerRTTSUM / peerCNT)) + fi + peerCNTSKIPPED=$((peerCNTABS - peerCNT - peerCNT0)) + + peerMAX=0 + if [[ ${peerCNT} -gt 0 ]]; then + peerPCT1=$(echo "scale=4;(${peerCNT1}/${peerCNT})*100" | bc -l) + peerPCT1items=$(printf %.0f "$(echo "scale=4;${peerPCT1}/${step_size_small}" | bc -l)") + peerPCT2=$(echo "scale=4;(${peerCNT2}/${peerCNT})*100" | bc -l) + peerPCT2items=$(printf %.0f "$(echo "scale=4;${peerPCT2}/${step_size_small}" | bc -l)") + peerPCT3=$(echo "scale=4;(${peerCNT3}/${peerCNT})*100" | bc -l) + peerPCT3items=$(printf %.0f "$(echo "scale=4;${peerPCT3}/${step_size_small}" | bc -l)") + peerPCT4=$(echo "scale=4;(${peerCNT4}/${peerCNT})*100" | bc -l) + peerPCT4items=$(printf %.0f "$(echo "scale=4;${peerPCT4}/${step_size_small}" | bc -l)") + fi +} + +##################################### +# Static variables/calculations # +##################################### +version=$("$(command -v cardano-node)" version) +node_version=$(grep "cardano-node" <<< "${version}" | cut -d ' ' -f2) +node_rev=$(grep "git rev" <<< "${version}" | cut -d ' ' -f3 | cut -c1-8) +check_peers="false" +show_peers="false" +line_end=0 +data=$(curl -s -H 'Accept: application/json' http://${EKG_HOST}:${EKG_PORT}/ 2>/dev/null) +abouttolead=$(jq '.cardano.node.metrics.Forge["forge-about-to-lead"].int.val //0' <<< "${data}") +epochnum=$(jq '.cardano.node.ChainDB.metrics.epoch.int.val //0' <<< "${data}") +slotinepoch=$(jq '.cardano.node.ChainDB.metrics.slotInEpoch.int.val //0' <<< "${data}") +slotnum=$(jq '.cardano.node.ChainDB.metrics.slotNum.int.val //0' <<< "${data}") +kesremain=$(jq '.cardano.node.Forge.metrics.remainingKESPeriods.int.val //0' <<< "${data}") +[[ ${abouttolead} -gt 0 ]] && nodemode="Core" || nodemode="Relay" +kes_expiration="$(kesExpiration "${kesremain}" "${slotinepoch}")" # Wont change until KES rotation and node restart + +##################################### +# Static genesis variables # +##################################### +shelley_genesis_file=$(jq -r .ShelleyGenesisFile "${CONFIG}") +byron_genesis_file=$(jq -r .ByronGenesisFile "${CONFIG}") +nwmagic=$(jq -r .networkMagic < "${shelley_genesis_file}") +shelley_genesis_start=$(jq -r .systemStart "${shelley_genesis_file}") +shelley_genesis_start_sec=$(date --date="${shelley_genesis_start}" +%s) +epoch_length=$(jq -r .epochLength "${shelley_genesis_file}") +slot_length=$(jq -r .slotLength "${shelley_genesis_file}") +active_slots_coeff=$(jq -r .activeSlotsCoeff "${shelley_genesis_file}") +decentralisation=$(jq -r .protocolParams.decentralisationParam "${shelley_genesis_file}") +slots_per_kes_period=$(jq -r .slotsPerKESPeriod "${shelley_genesis_file}") +max_kes_evolutions=$(jq -r .maxKESEvolutions "${shelley_genesis_file}") +if [[ "${PROTOCOL}" = "Cardano" ]]; then + byron_genesis_start_sec=$(jq -r .startTime "${byron_genesis_file}") + byron_k=$(jq -r .protocolConsts.k "${byron_genesis_file}") + byron_slot_length=$(( $(jq -r .blockVersionData.slotDuration "${byron_genesis_file}") / 1000 )) + byron_epoch_length=$(( 10 * byron_k )) + getShelleyTransitionEpoch +else + shelley_transition_epoch=-1 +fi +slot_interval=$(echo "(${slot_length} / ${active_slots_coeff} / ${decentralisation}) + 0.5" | bc -l | awk '{printf "%.0f\n", $1}') +##################################### + +clear +tlines=$(tput lines) # set initial terminal lines +tcols=$(tput cols) # set initial terminal columns + +##################################### +# MAIN LOOP # +##################################### +while true; do + [[ ${tlines} -ne $(tput lines) || ${tcols} -ne $(tput cols) ]] && redraw_peers=true || redraw_peers=false + tlines=$(tput lines) # update terminal lines + tcols=$(tput cols) # update terminal columns + [[ ${width} -ge $((tcols-1)) || ${line_end} -ge $((tlines-1)) ]] && clear + while [[ ${width} -ge $((tcols-1)) ]]; do + tput cup 1 1 + printf "${FG_RED}Terminal width too small!${NC}" + tput cup 3 1 + printf "Please increase by ${FG_MAGENTA}$(( width - tcols + 2 ))${NC} columns" + tput cup 5 1 + printf "${FG_CYAN}Use CTRL + C to force quit${NC}" + sleep 2 + tlines=$(tput lines) # update terminal lines + tcols=$(tput cols) # update terminal columns + redraw_peers=true + done + while [[ ${line_end} -ge $((tlines-1)) ]]; do + tput cup 1 1 + printf "${FG_RED}Terminal height too small!${NC}" + tput cup 3 1 + printf "Please increase by ${FG_MAGENTA}$(( line_end - tlines + 2 ))${NC} lines" + tput cup 5 1 + printf "${FG_CYAN}Use CTRL + C to force quit${NC}" + sleep 2 + tlines=$(tput lines) # update terminal lines + tcols=$(tput cols) # update terminal columns + redraw_peers=true + done + + line=0; tput cup 0 0 # reset position + + # Gather some data + data=$(curl -s -H 'Accept: application/json' http://${EKG_HOST}:${EKG_PORT}/ 2>/dev/null) + uptimens=$(jq '.cardano.node.metrics.upTime.ns.val //0' <<< "${data}") + if ((uptimens<=0)); then + myExit 1 "${FG_RED}COULD NOT CONNECT TO A RUNNING INSTANCE!${NC}\nPLEASE CHECK THE EKG PORT AND TRY AGAIN!" + fi + peers_in=$(netstat -an|awk "\$4 ~ /${CNODE_PORT}/"|grep -c ESTABLISHED) + peers_out=$(jq '.cardano.node.BlockFetchDecision.peers.connectedPeers.int.val //0' <<< "${data}") + blocknum=$(jq '.cardano.node.ChainDB.metrics.blockNum.int.val //0' <<< "${data}") + epochnum=$(jq '.cardano.node.ChainDB.metrics.epoch.int.val //0' <<< "${data}") + slotinepoch=$(jq '.cardano.node.ChainDB.metrics.slotInEpoch.int.val //0' <<< "${data}") + slotnum=$(jq '.cardano.node.ChainDB.metrics.slotNum.int.val //0' <<< "${data}") + density=$(jq -r '.cardano.node.ChainDB.metrics.density.real.val //0' <<< "${data}") + density=$(printf "%3.3e" "${density}"| cut -d 'e' -f1) + tx_processed=$(jq '.cardano.node.metrics.txsProcessedNum.int.val //0' <<< "${data}") + mempool_tx=$(jq '.cardano.node.metrics.txsInMempool.int.val //0' <<< "${data}") + mempool_bytes=$(jq '.cardano.node.metrics.mempoolBytes.int.val //0' <<< "${data}") + kesperiod=$(jq '.cardano.node.Forge.metrics.currentKESPeriod.int.val //0' <<< "${data}") + kesremain=$(jq '.cardano.node.Forge.metrics.remainingKESPeriods.int.val //0' <<< "${data}") + isleader=$(jq '.cardano.node.metrics.Forge["node-is-leader"].int.val //0' <<< "${data}") + forged=$(jq '.cardano.node.metrics.Forge.forged.int.val //0' <<< "${data}") + adopted=$(jq '.cardano.node.metrics.Forge.adopted.int.val //0' <<< "${data}") + didntadopt=$(jq '.cardano.node.metrics.Forge["didnt-adopt"].int.val //0' <<< "${data}") + + header_length=$(( ${#NODE_NAME} + ${#nodemode} + ${#node_version} + ${#node_rev} + 16 )) + [[ ${header_length} -gt ${width} ]] && header_padding=0 || header_padding=$(( (width - header_length) / 2 )) + printf "%${header_padding}s >> ${FG_GREEN}%s${NC} - ${FG_GREEN}%s${NC} : ${FG_BLUE}%s${NC} [${FG_BLUE}%s${NC}] <<\n" "" "${NODE_NAME}" "${nodemode}" "${node_version}" "${node_rev}" + ((line++)) + + ## Base section ## + printf "${tdivider}" + tput cup ${line} $(( width - 17 )) + printf "\\u252C" + tput cup $((++line)) 0 + + printf "${VL} Uptime: $(timeLeft $(( uptimens/1000000000 )))" + tput cup ${line} $(( width - 17 )) + printf "${VL} ${title} ${VL}\n" + ((line++)) + printf "${m2divider}" + tput cup ${line} $(( width - 17 )) + printf "\\u2514" + printf "%0.s${HL}" $(seq 16) + printf "\\u2524\n" + ((line++)) + + if [[ ${shelley_transition_epoch} = -1 || ${epochnum} -ge ${shelley_transition_epoch} ]]; then + epoch_progress=$(echo "(${slotinepoch}/${epoch_length})*100" | bc -l) # in Shelley era or Shelley only TestNet + else + epoch_progress=$(echo "(${slotinepoch}/${byron_epoch_length})*100" | bc -l) # in Byron era + fi + printf "${VL} Epoch ${FG_BLUE}%s${NC} [%2.1f%%] (node)" "${epochnum}" "${epoch_progress}" + endLine $((line++)) + printf "${VL} %s until epoch boundary (chain)" "$(timeLeft "$(timeUntilNextEpoch)")" + endLine $((line++)) + + epoch_items=$(( $(printf %.0f "${epoch_progress}") / step_size )) + printf "${VL} ${FG_BLUE}" + for i in $(seq 0 $((granularity-1))); do + [[ $i -lt ${epoch_items} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC} ${VL}\n"; ((line++)) + + printf "${VL}"; tput cup $((line++)) ${width}; printf "${VL}\n" # empty line + + tip_ref=$(getSlotTipRef) + tip_diff=$(( tip_ref - slotnum )) + printf "${VL} Block : ${FG_BLUE}%s${NC}" "${blocknum}" + tput cup ${line} ${second_col} + printf "Tip (ref) : ${FG_BLUE}%s${NC}" "${tip_ref}" + endLine $((line++)) + printf "${VL} Slot : ${FG_BLUE}%s${NC}" "${slotinepoch}" + tput cup ${line} ${second_col} + printf "Tip (node) : ${FG_BLUE}%s${NC}" "${slotnum}" + endLine $((line++)) + printf "${VL} Density : ${FG_BLUE}%s${NC}" "${density}" + tput cup ${line} ${second_col} + if [[ ${tip_diff} -le $(( slot_interval * 2 )) ]]; then + printf "Tip (diff) : ${FG_GREEN}%s${NC}" "-${tip_diff} :)" + elif [[ ${tip_diff} -le $(( slot_interval * 3 )) ]]; then + printf "Tip (diff) : %s" "-${tip_diff} :|" + else + printf "Tip (diff) : ${FG_RED}%s${NC}" "-${tip_diff} :(" + fi + endLine $((line++)) + + echo "${m2divider}" + ((line++)) + + printf "${VL} Processed TX : ${FG_BLUE}%s${NC}" "${tx_processed}" + tput cup ${line} $((second_col+7)) + printf " In / Out" + endLine $((line++)) + printf "${VL} Mempool TX/Bytes : ${FG_BLUE}%s${NC} / ${FG_BLUE}%s${NC}" "${mempool_tx}" "${mempool_bytes}" + tput el; tput cup ${line} $((second_col+7)) + printf "Peers : ${FG_BLUE}%s${NC} / ${FG_BLUE}%s${NC}" "${peers_in}" "${peers_out}" + endLine $((line++)) + + ## Core section ## + if [[ ${nodemode} = "Core" ]]; then + echo "${mdivider}" + ((line++)) + + printf "${VL} KES current/remaining : ${FG_BLUE}%s${NC} / " "${kesperiod}" + if [[ ${kesremain} -le 0 ]]; then + printf "${FG_RED}%s${NC}" "${kesremain}" + elif [[ ${kesremain} -le 8 ]]; then + printf "${FG_YELLOW}%s${NC}" "${kesremain}" + else + printf "${FG_BLUE}%s${NC}" "${kesremain}" + fi + endLine $((line++)) + printf "${VL} KES expiration date : ${FG_BLUE}%s${NC}" "${kes_expiration}" + endLine $((line++)) + + echo "${m2divider}" + ((line++)) + + printf "${VL} %49s" "IsLeader/Adopted/Missed" + endLine $((line++)) + printf "${VL} Blocks since node start : ${FG_BLUE}%s${NC} / " "${isleader}" + if [[ ${adopted} -ne ${isleader} ]]; then + printf "${FG_YELLOW}%s${NC} / " "${adopted}" + else + printf "${FG_BLUE}%s${NC} / " "${adopted}" + fi + if [[ ${didntadopt} -gt 0 ]]; then + printf "${FG_RED}%s${NC}" "${didntadopt}" + else + printf "${FG_BLUE}%s${NC}" "${didntadopt}" + fi + endLine $((line++)) + + if [[ -n ${BLOCK_LOG_DIR} ]]; then + blocks_file="${BLOCK_LOG_DIR}/blocks_${epochnum}.json" + if [[ -f "${blocks_file}" ]]; then + isleader_epoch=$(jq -c '[.[].slot //empty] | length' "${blocks_file}") + invalid_epoch=$(jq -c '[.[].hash //empty | select(startswith("Invalid"))] | length' "${blocks_file}") + adopted_epoch=$(( $(jq -c '[.[].hash //empty] | length' "${blocks_file}") - invalid_epoch )) + else + isleader_epoch=0 + invalid_epoch=0 + adopted_epoch=0 + fi + printf "${VL} Blocks this epoch : ${FG_BLUE}%s${NC} / " "${isleader_epoch}" + if [[ ${adopted_epoch} -ne ${isleader_epoch} ]]; then + printf "${FG_YELLOW}%s${NC} / " "${adopted_epoch}" + else + printf "${FG_BLUE}%s${NC} / " "${adopted_epoch}" + fi + if [[ ${invalid_epoch} -gt 0 ]]; then + printf "${FG_RED}%s${NC}" "${invalid_epoch}" + else + printf "${FG_BLUE}%s${NC}" "${invalid_epoch}" + fi + endLine $((line++)) + fi + fi + line_wo_peers=${line} + + ## Peer Analysis ## + if [[ ${show_peers} = "true" ]]; then + echo "${mdivider}" + ((line++)) + + if [[ ${check_peers} = "true" ]]; then + redraw_peers=true + tput ed + printf "${VL} ${FG_YELLOW}Output peer analysis started... update paused${NC}" + endLine ${line} + echo "${bdivider}" + checkPeers out + # Save values + peerCNT0_out=${peerCNT0}; peerCNT1_out=${peerCNT1}; peerCNT2_out=${peerCNT2}; peerCNT3_out=${peerCNT3}; peerCNT4_out=${peerCNT4} + peerPCT1_out=${peerPCT1}; peerPCT2_out=${peerPCT2}; peerPCT3_out=${peerPCT3}; peerPCT4_out=${peerPCT4} + peerPCT1items_out=${peerPCT1items}; peerPCT2items_out=${peerPCT2items}; peerPCT3items_out=${peerPCT3items}; peerPCT4items_out=${peerPCT4items} + peerRTT_out=${peerRTT}; peerRTTAVG_out=${peerRTTAVG}; peerCNTABS_out=${peerCNTABS}; peerCNTSKIPPED_out=${peerCNTSKIPPED} + fi + + if [[ ${redraw_peers} = "true" ]]; then + + tput cup ${line} 0 + + printf "${VL}${STANDOUT} OUT ${NC} RTT : Peers / Percent - %s" "$(date -u '+%F %T Z')" + endLine $((line++)) + printf "${VL} 0-50ms : %5s / %.f%% ${FG_GREEN}" "${peerCNT1_out}" "${peerPCT1_out}" + tput el && tput cup ${line} ${bar_col_small} + for i in $(seq 0 $((granularity_small-1))); do + [[ $i -lt ${peerPCT1items_out} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC}" + endLine $((line++)) + + printf "${VL} 50-100ms : %5s / %.f%% ${FG_YELLOW}" "${peerCNT2_out}" "${peerPCT2_out}" + tput el && tput cup ${line} ${bar_col_small} + for i in $(seq 0 $((granularity_small-1))); do + [[ $i -lt ${peerPCT2items_out} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC}" + endLine $((line++)) + + printf "${VL} 100-200ms : %5s / %.f%% ${FG_RED}" "${peerCNT3_out}" "${peerPCT3_out}" + tput el && tput cup ${line} ${bar_col_small} + for i in $(seq 0 $((granularity_small-1))); do + [[ $i -lt ${peerPCT3items_out} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC}" + endLine $((line++)) + + printf "${VL} 200ms < : %5s / %.f%% ${FG_MAGENTA}" "${peerCNT4_out}" "${peerPCT4_out}" + tput el && tput cup ${line} ${bar_col_small} + for i in $(seq 0 $((granularity_small-1))); do + [[ $i -lt ${peerPCT4items_out} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC}" + endLine $((line++)) + if [[ ${peerRTT_out} -ge 200 ]]; then printf "${VL} Average : ${FG_MAGENTA}%s${NC} ms" "${peerRTTAVG_out}" + elif [[ ${peerRTT_out} -ge 100 ]]; then printf "${VL} Average : ${FG_RED}%s${NC} ms" "${peerRTTAVG_out}" + elif [[ ${peerRTT_out} -ge 50 ]]; then printf "${VL} Average : ${FG_YELLOW}%s${NC} ms" "${peerRTTAVG_out}" + elif [[ ${peerRTT_out} -ge 0 ]]; then printf "${VL} Average : ${FG_GREEN}%s${NC} ms" "${peerRTTAVG_out}"; fi + endLine $((line++)) + + echo "${m2divider}" + ((line++)) + + printf "${VL} Peers Total / Unreachable / Skipped : ${FG_BLUE}%s${NC} / " "${peerCNTABS_out}" + [[ ${peerCNT0_out} -eq 0 ]] && printf "${FG_BLUE}%s${NC} / " "${peerCNT0_out}" || printf "${FG_RED}%s${NC} / " "${peerCNT0_out}" + [[ ${peerCNTSKIPPED_out} -eq 0 ]] && printf "${FG_BLUE}%s${NC}" "${peerCNTSKIPPED_out}" || printf "${FG_YELLOW}%s${NC}" "${peerCNTSKIPPED_out}" + endLine $((line++)) + + echo "${m2divider}" + ((line++)) + + if [[ ${check_peers} = "true" ]]; then + printf "${VL} ${FG_YELLOW}Input peer analysis started... update paused${NC}" + endLine ${line} + echo "${bdivider}" + checkPeers in + # Save values + peerCNT0_in=${peerCNT0}; peerCNT1_in=${peerCNT1}; peerCNT2_in=${peerCNT2}; peerCNT3_in=${peerCNT3}; peerCNT4_in=${peerCNT4} + peerPCT1_in=${peerPCT1}; peerPCT2_in=${peerPCT2}; peerPCT3_in=${peerPCT3}; peerPCT4_in=${peerPCT4} + peerPCT1items_in=${peerPCT1items}; peerPCT2items_in=${peerPCT2items}; peerPCT3items_in=${peerPCT3items}; peerPCT4items_in=${peerPCT4items} + peerRTT_in=${peerRTT}; peerRTTAVG_in=${peerRTTAVG}; peerCNTABS_in=${peerCNTABS}; peerCNTSKIPPED_in=${peerCNTSKIPPED} + fi + + tput cup ${line} 0 + + printf "${VL}${STANDOUT} In ${NC} RTT : Peers / Percent" + endLine $((line++)) + printf "${VL} 0-50ms : %5s / %.f%% ${FG_GREEN}" "${peerCNT1_in}" "${peerPCT1_in}" + tput el && tput cup ${line} ${bar_col_small} + for i in $(seq 0 $((granularity_small-1))); do + [[ $i -lt ${peerPCT1items_in} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC}" + endLine $((line++)) + + printf "${VL} 50-100ms : %5s / %.f%% ${FG_YELLOW}" "${peerCNT2_in}" "${peerPCT2_in}" + tput el && tput cup ${line} ${bar_col_small} + for i in $(seq 0 $((granularity_small-1))); do + [[ $i -lt ${peerPCT2items_in} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC}" + endLine $((line++)) + + printf "${VL} 100-200ms : %5s / %.f%% ${FG_RED}" "${peerCNT3_in}" "${peerPCT3_in}" + tput el && tput cup ${line} ${bar_col_small} + for i in $(seq 0 $((granularity_small-1))); do + [[ $i -lt ${peerPCT3items_in} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC}" + endLine $((line++)) + + printf "${VL} 200ms < : %5s / %.f%% ${FG_MAGENTA}" "${peerCNT4_in}" "${peerPCT4_in}" + tput el && tput cup ${line} ${bar_col_small} + for i in $(seq 0 $((granularity_small-1))); do + [[ $i -lt ${peerPCT4items_in} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC}" + endLine $((line++)) + if [[ ${peerRTT_in} -ge 200 ]]; then printf "${VL} Average : ${FG_MAGENTA}%s${NC} ms" "${peerRTTAVG_in}" + elif [[ ${peerRTT_in} -ge 100 ]]; then printf "${VL} Average : ${FG_RED}%s${NC} ms" "${peerRTTAVG_in}" + elif [[ ${peerRTT_in} -ge 50 ]]; then printf "${VL} Average : ${FG_YELLOW}%s${NC} ms" "${peerRTTAVG_in}" + elif [[ ${peerRTT_in} -ge 0 ]]; then printf "${VL} Average : ${FG_GREEN}%s${NC} ms" "${peerRTTAVG_in}"; fi + endLine $((line++)) + + echo "${m2divider}" + ((line++)) + + printf "${VL} Peers Total / Unreachable / Skipped : ${FG_BLUE}%s${NC} / " "${peerCNTABS_in}" + [[ ${peerCNT0_in} -eq 0 ]] && printf "${FG_BLUE}%s${NC} / " "${peerCNT0_in}" || printf "${FG_RED}%s${NC} / " "${peerCNT0_in}" + [[ ${peerCNTSKIPPED_in} -eq 0 ]] && printf "${FG_BLUE}%s${NC}" "${peerCNTSKIPPED_in}" || printf "${FG_YELLOW}%s${NC}" "${peerCNTSKIPPED_in}" + endLine $((line++)) + fi + fi + + if [[ ${show_peers} = "hide" ]]; then + show_peers=false + tput ed + line_end=${line_wo_peers} + elif [[ ${line_end} -lt ${line} ]]; then + line_end=${line} + fi + tput cup ${line_end} 0 + echo "${bdivider}" + printf " ${FG_YELLOW}[esc/q] Quit${NC} | ${FG_YELLOW}[p] Peer Analysis${NC}" + if [[ "${check_peers}" = "true" ]]; then + check_peers="false" + fi + if [[ "${show_peers}" = "true" ]]; then + printf " | ${FG_YELLOW}[h] Hide Peers${NC}" + else + tput el + fi + waitForInput +done diff --git a/scripts/cnode-helper-scripts/prereqs.sh b/scripts/cnode-helper-scripts/prereqs.sh index 3bd505742..03a311568 100755 --- a/scripts/cnode-helper-scripts/prereqs.sh +++ b/scripts/cnode-helper-scripts/prereqs.sh @@ -1,5 +1,8 @@ #!/bin/bash # shellcheck disable=SC2086 + +unset CNODE_HOME + get_input() { printf "%s (default: %s): " "$1" "$2" >&2; read -r answer if [ -z "$answer" ]; then echo "$2"; else echo "$answer"; fi @@ -35,6 +38,7 @@ Install pre-requisites for building cardano node and using cntools -i Interactive mode (Default: silent mode) -g Connect to guild network instead of public network (Default: connect to public cardano network) -p Copy Transitional Praos config as default instead of Combinator networks (Default: copies combinator network) +-t Alternate name for top level folder EOF exit 1 } @@ -42,7 +46,7 @@ EOF WANT_BUILD_DEPS='Y' OVERWRITE=' ' -while getopts :igpso opt; do +while getopts :igpsot: opt; do case ${opt} in i ) INTERACTIVE='Y' @@ -59,6 +63,9 @@ while getopts :igpso opt; do o ) OVERWRITE=' -C -' ;; + t ) + CNODE_NAME=${OPTARG} + ;; \? ) usage ;; @@ -72,7 +79,7 @@ G_ID=$(id -g) # Defaults CNODE_PATH="/opt/cardano" -CNODE_NAME="cnode" +[[ -z "${CNODE_NAME}" ]] && CNODE_NAME="cnode" CNODE_HOME=${CNODE_PATH}/${CNODE_NAME} CNODE_VNAME=$(echo "$CNODE_NAME" | awk '{print toupper($0)}') @@ -114,10 +121,11 @@ if [ "$WANT_BUILD_DEPS" = 'Y' ]; then echo "deb https://dl.yarnpkg.com/debian/ stable main" | $sudo tee /etc/apt/sources.list.d/yarn.list > /dev/null $sudo apt-get -y update > /dev/null echo " Installing missing prerequisite packages, if any.." - $sudo apt-get -y install libpq-dev python3 build-essential pkg-config libffi-dev libgmp-dev libssl-dev libtinfo-dev systemd libsystemd-dev libsodium-dev zlib1g-dev yarn make g++ tmux git jq wget libncursesw5 gnupg aptitude libtool autoconf secure-delete net-tools > /dev/null;rc=$? + pkg_list="libpq-dev python3 build-essential pkg-config libffi-dev libgmp-dev libssl-dev libtinfo-dev systemd libsystemd-dev libsodium-dev zlib1g-dev yarn make g++ tmux git jq wget libncursesw5 gnupg aptitude libtool autoconf secure-delete net-tools bc tcptraceroute" + $sudo apt-get -y install ${pkg_list} > /dev/null;rc=$? if [ $rc != 0 ]; then echo "An error occurred while installing the prerequisite packages, please investigate by using the command below:" - echo "sudo apt-get -y install python3 build-essential pkg-config libffi-dev libgmp-dev libssl-dev libtinfo-dev systemd libsystemd-dev libsodium-dev zlib1g-dev npm yarn make g++ tmux git jq wget libncursesw5 gnupg libtool autoconf bsdmainutils" + echo "sudo apt-get -y install ${pkg_list}" echo "It would be best if you could submit an issue at https://github.com/cardano-community/guild-operators with the details to tackle in future, as some errors may be due to external/already present dependencies" exit; else @@ -132,10 +140,11 @@ if [ "$WANT_BUILD_DEPS" = 'Y' ]; then $sudo rpm --import https://dl.yarnpkg.com/rpm/pubkey.gpg > /dev/null $sudo yum -y update > /dev/null echo " Installing missing prerequisite packages, if any.." - $sudo yum -y install python3 coreutils pkgconfig libffi-devel gmp-devel openssl-devel ncurses-libs ncurses-compat-libs systemd systemd-devel libsodium-devel zlib-devel npm yarn make gcc-c++ tmux git wget epel-release jq gnupg libtool autoconf srm net-tools > /dev/null;rc=$? + pkg_list="python3 coreutils pkgconfig libffi-devel gmp-devel openssl-devel ncurses-libs ncurses-compat-libs systemd systemd-devel libsodium-devel zlib-devel npm yarn make gcc-c++ tmux git wget epel-release jq gnupg libtool autoconf srm net-tools bc tcptraceroute" + $sudo yum -y install ${pkg_list} > /dev/null;rc=$? if [ $rc != 0 ]; then echo "An error occurred while installing the prerequisite packages, please investigate by using the command below:" - echo "sudo yum -y install coreutils python3 pkgconfig libffi-devel gmp-devel openssl-devel ncurses-libs ncurses-compat-libs systemd systemd-devel libsodium-devel zlib-devel npm yarn make gcc-c++ tmux git wget epel-release jq gnupg libtool autoconf util-linux" + echo "sudo yum -y ${pkg_list}" echo "It would be best if you could submit an issue at https://github.com/cardano-community/guild-operators with the details to tackle in future, as some errors may be due to external/already present dependencies" exit; fi @@ -232,15 +241,11 @@ else cp ptn0-mainnet.json config.json fi -# If using a different CNODE_HOME than in this example, execute the below: -# sed -i -e "s#/opt/cardano/cnode#${CNODE_HOME}#" $CNODE_HOME/files/*.json -## For future use: -## It generates random NodeID: -## -e "s#NodeId:.*#NodeId:$(od -A n -t u8 -N 8 /dev/urandom$(#" \ +sed -i -e "s#/opt/cardano/cnode#${CNODE_HOME}#" $CNODE_HOME/files/*.json cd "$CNODE_HOME"/scripts || return curl -s -o env https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/env -sed -e "s@CNODE_HOME@${CNODE_VNAME}_HOME@g" -i env +sed -e "s@CNODE_HOME=.*@${CNODE_VNAME}_HOME=${CNODE_HOME}@g" -e "s@CNODE_HOME@${CNODE_VNAME}_HOME@g" -i env curl -s -o createAddr.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/createAddr.sh curl -s -o sendADA.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/sendADA.sh curl -s -o balance.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/balance.sh @@ -253,12 +258,13 @@ curl -s -o cntoolsBlockCollector.sh https://raw.githubusercontent.com/cardano-co curl -s -o setup_mon.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/setup_mon.sh curl -s -o topologyUpdater.sh ${OVERWRITE} https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/topologyUpdater.sh curl -s -o itnRewards.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/itnRewards.sh -sed -e "s@CNODE_HOME=.*@${CNODE_VNAME}_HOME=${CNODE_HOME}@g" -e "s@CNODE_HOME@${CNODE_VNAME}_HOME@g" -i cnode.sh curl -s -o cabal-build-all.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/cabal-build-all.sh curl -s -o stack-build.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/stack-build.sh curl -s -o system-info.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/system-info.sh curl -s -o sLiveView.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/sLiveView.sh +curl -s -o gLiveView.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/gLiveView.sh +curl -s -o deploy-as-systemd.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/deploy-as-systemd.sh +sed -e "s@SyslogIdentifier=.*@SyslogIdentifier=${CNODE_NAME}@g" -e "s@cnode.service@${CNODE_NAME}.service@g" -i deploy-as-systemd.sh +sed -e "s@CNODE_HOME=.*@${CNODE_VNAME}_HOME=${CNODE_HOME}@g" -e "s@CNODE_HOME@${CNODE_VNAME}_HOME@g" -i ./*.* chmod 755 ./*.sh -# If you opt for an alternate CNODE_HOME, please run the below: -# sed -i -e "s#/opt/cardano/cnode#${CNODE_HOME}#" *.sh cd - || return From 3a620db64ac7c6d6cd696c62b06848811497a101 Mon Sep 17 00:00:00 2001 From: "Ola [AHLNET]" Date: Thu, 3 Sep 2020 14:53:03 +0200 Subject: [PATCH 11/24] typo (#453) --- docs/Scripts/gliveview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Scripts/gliveview.md b/docs/Scripts/gliveview.md index d605a51ac..1693049f3 100644 --- a/docs/Scripts/gliveview.md +++ b/docs/Scripts/gliveview.md @@ -13,7 +13,7 @@ To get current epoch blocks, [cntoolsBlockCollector.sh](Scripts/cntools-blocks.m To download the script: ```bash -curl -s -o gLiveView.sh curl -s -o gLiveView.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/gLiveView.sh +curl -s -o gLiveView.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/gLiveView.sh chmod 755 gLiveView.sh ``` From effad51d9b34bf9affa41396f98e84434cd493aa Mon Sep 17 00:00:00 2001 From: "Ola [AHLNET]" Date: Thu, 3 Sep 2020 17:10:18 +0200 Subject: [PATCH 12/24] KES expiration fix (#455) KES expiration calculation was done before genesis variables was defined. Some minor edits here and there but basically just moved calculation to after genesis variables are set. --- scripts/cnode-helper-scripts/gLiveView.sh | 41 +++++++++++------------ 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/scripts/cnode-helper-scripts/gLiveView.sh b/scripts/cnode-helper-scripts/gLiveView.sh index c7abb6b90..947ff8e89 100755 --- a/scripts/cnode-helper-scripts/gLiveView.sh +++ b/scripts/cnode-helper-scripts/gLiveView.sh @@ -134,14 +134,14 @@ timeLeft() { printf '%02d:%02d:%02d' $H $M $S } -# Command : getEpoch -# Description: Offline calculation of current epoch based on genesis file +# Command : getShelleyTransitionEpoch +# Description: Calculate shelley transition epoch getShelleyTransitionEpoch() { calc_slot=0 byron_epochs=${epochnum} shelley_epochs=0 while [[ ${byron_epochs} -ge 0 ]]; do - calc_slot=$(( (byron_epochs*byron_epoch_length) + (shelley_epochs*epoch_length) + slotinepoch )) + calc_slot=$(( (byron_epochs*byron_epoch_length) + (shelley_epochs*epoch_length) + slot_in_epoch )) [[ ${calc_slot} -eq ${slotnum} ]] && break ((byron_epochs--)) ((shelley_epochs++)) @@ -203,11 +203,9 @@ getSlotTipRef() { # Command : kesExpiration [pools remaining KES periods] # Description: Calculate KES expiration kesExpiration() { - remaining_kes_periods=$1 - slot_in_epoch=$2 current_time_sec=$(date -u +%s) expiration_time_sec=$(( current_time_sec - ( slot_length * slot_in_epoch ) + ( slot_length * slots_per_kes_period * remaining_kes_periods ) )) - date '+%F %T Z' --date=@${expiration_time_sec} + kes_expiration=$(date '+%F %T Z' --date=@${expiration_time_sec}) } endLine() { @@ -310,13 +308,12 @@ check_peers="false" show_peers="false" line_end=0 data=$(curl -s -H 'Accept: application/json' http://${EKG_HOST}:${EKG_PORT}/ 2>/dev/null) -abouttolead=$(jq '.cardano.node.metrics.Forge["forge-about-to-lead"].int.val //0' <<< "${data}") +about_to_lead=$(jq '.cardano.node.metrics.Forge["forge-about-to-lead"].int.val //0' <<< "${data}") epochnum=$(jq '.cardano.node.ChainDB.metrics.epoch.int.val //0' <<< "${data}") -slotinepoch=$(jq '.cardano.node.ChainDB.metrics.slotInEpoch.int.val //0' <<< "${data}") +slot_in_epoch=$(jq '.cardano.node.ChainDB.metrics.slotInEpoch.int.val //0' <<< "${data}") slotnum=$(jq '.cardano.node.ChainDB.metrics.slotNum.int.val //0' <<< "${data}") -kesremain=$(jq '.cardano.node.Forge.metrics.remainingKESPeriods.int.val //0' <<< "${data}") -[[ ${abouttolead} -gt 0 ]] && nodemode="Core" || nodemode="Relay" -kes_expiration="$(kesExpiration "${kesremain}" "${slotinepoch}")" # Wont change until KES rotation and node restart +remaining_kes_periods=$(jq '.cardano.node.Forge.metrics.remainingKESPeriods.int.val //0' <<< "${data}") +[[ ${about_to_lead} -gt 0 ]] && nodemode="Core" || nodemode="Relay" ##################################### # Static genesis variables # @@ -341,7 +338,9 @@ if [[ "${PROTOCOL}" = "Cardano" ]]; then else shelley_transition_epoch=-1 fi +##################################### slot_interval=$(echo "(${slot_length} / ${active_slots_coeff} / ${decentralisation}) + 0.5" | bc -l | awk '{printf "%.0f\n", $1}') +kesExpiration # Static and wont change until KES rotation and node restart ##################################### clear @@ -393,7 +392,7 @@ while true; do peers_out=$(jq '.cardano.node.BlockFetchDecision.peers.connectedPeers.int.val //0' <<< "${data}") blocknum=$(jq '.cardano.node.ChainDB.metrics.blockNum.int.val //0' <<< "${data}") epochnum=$(jq '.cardano.node.ChainDB.metrics.epoch.int.val //0' <<< "${data}") - slotinepoch=$(jq '.cardano.node.ChainDB.metrics.slotInEpoch.int.val //0' <<< "${data}") + slot_in_epoch=$(jq '.cardano.node.ChainDB.metrics.slotInEpoch.int.val //0' <<< "${data}") slotnum=$(jq '.cardano.node.ChainDB.metrics.slotNum.int.val //0' <<< "${data}") density=$(jq -r '.cardano.node.ChainDB.metrics.density.real.val //0' <<< "${data}") density=$(printf "%3.3e" "${density}"| cut -d 'e' -f1) @@ -401,7 +400,7 @@ while true; do mempool_tx=$(jq '.cardano.node.metrics.txsInMempool.int.val //0' <<< "${data}") mempool_bytes=$(jq '.cardano.node.metrics.mempoolBytes.int.val //0' <<< "${data}") kesperiod=$(jq '.cardano.node.Forge.metrics.currentKESPeriod.int.val //0' <<< "${data}") - kesremain=$(jq '.cardano.node.Forge.metrics.remainingKESPeriods.int.val //0' <<< "${data}") + remaining_kes_periods=$(jq '.cardano.node.Forge.metrics.remainingKESPeriods.int.val //0' <<< "${data}") isleader=$(jq '.cardano.node.metrics.Forge["node-is-leader"].int.val //0' <<< "${data}") forged=$(jq '.cardano.node.metrics.Forge.forged.int.val //0' <<< "${data}") adopted=$(jq '.cardano.node.metrics.Forge.adopted.int.val //0' <<< "${data}") @@ -430,9 +429,9 @@ while true; do ((line++)) if [[ ${shelley_transition_epoch} = -1 || ${epochnum} -ge ${shelley_transition_epoch} ]]; then - epoch_progress=$(echo "(${slotinepoch}/${epoch_length})*100" | bc -l) # in Shelley era or Shelley only TestNet + epoch_progress=$(echo "(${slot_in_epoch}/${epoch_length})*100" | bc -l) # in Shelley era or Shelley only TestNet else - epoch_progress=$(echo "(${slotinepoch}/${byron_epoch_length})*100" | bc -l) # in Byron era + epoch_progress=$(echo "(${slot_in_epoch}/${byron_epoch_length})*100" | bc -l) # in Byron era fi printf "${VL} Epoch ${FG_BLUE}%s${NC} [%2.1f%%] (node)" "${epochnum}" "${epoch_progress}" endLine $((line++)) @@ -454,7 +453,7 @@ while true; do tput cup ${line} ${second_col} printf "Tip (ref) : ${FG_BLUE}%s${NC}" "${tip_ref}" endLine $((line++)) - printf "${VL} Slot : ${FG_BLUE}%s${NC}" "${slotinepoch}" + printf "${VL} Slot : ${FG_BLUE}%s${NC}" "${slot_in_epoch}" tput cup ${line} ${second_col} printf "Tip (node) : ${FG_BLUE}%s${NC}" "${slotnum}" endLine $((line++)) @@ -487,12 +486,12 @@ while true; do ((line++)) printf "${VL} KES current/remaining : ${FG_BLUE}%s${NC} / " "${kesperiod}" - if [[ ${kesremain} -le 0 ]]; then - printf "${FG_RED}%s${NC}" "${kesremain}" - elif [[ ${kesremain} -le 8 ]]; then - printf "${FG_YELLOW}%s${NC}" "${kesremain}" + if [[ ${remaining_kes_periods} -le 0 ]]; then + printf "${FG_RED}%s${NC}" "${remaining_kes_periods}" + elif [[ ${remaining_kes_periods} -le 8 ]]; then + printf "${FG_YELLOW}%s${NC}" "${remaining_kes_periods}" else - printf "${FG_BLUE}%s${NC}" "${kesremain}" + printf "${FG_BLUE}%s${NC}" "${remaining_kes_periods}" fi endLine $((line++)) printf "${VL} KES expiration date : ${FG_BLUE}%s${NC}" "${kes_expiration}" From 250c06a3e98e15b2f297eef3213226d52f1f3429 Mon Sep 17 00:00:00 2001 From: Priyank <3169068+rdlrt@users.noreply.github.com> Date: Fri, 4 Sep 2020 17:26:19 +1000 Subject: [PATCH 13/24] Rename node-0 to node0 for log files (#456) --- files/ptn0-combinator.json | 4 ++-- files/ptn0-mainnet.json | 4 ++-- files/ptn0-praos.json | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/files/ptn0-combinator.json b/files/ptn0-combinator.json index 2c96af9fc..1124c2dd7 100644 --- a/files/ptn0-combinator.json +++ b/files/ptn0-combinator.json @@ -48,7 +48,7 @@ "defaultScribes": [ [ "FileSK", - "/opt/cardano/cnode/logs/node-0.json" + "/opt/cardano/cnode/logs/node0.json" ] ], "hasEKG": 12788, @@ -166,7 +166,7 @@ "setupScribes": [ { "scKind": "FileSK", - "scName": "/opt/cardano/cnode/logs/node-0.json", + "scName": "/opt/cardano/cnode/logs/node0.json", "scFormat": "ScJson", "scRotation": null } diff --git a/files/ptn0-mainnet.json b/files/ptn0-mainnet.json index f330474c5..f287289d8 100644 --- a/files/ptn0-mainnet.json +++ b/files/ptn0-mainnet.json @@ -46,7 +46,7 @@ "defaultScribes": [ [ "FileSK", - "/opt/cardano/cnode/logs/node-0.json" + "/opt/cardano/cnode/logs/node0.json" ] ], "hasEKG": 12788, @@ -164,7 +164,7 @@ "setupScribes": [ { "scKind": "FileSK", - "scName": "/opt/cardano/cnode/logs/node-0.json", + "scName": "/opt/cardano/cnode/logs/node0.json", "scFormat": "ScJson", "scRotation": null } diff --git a/files/ptn0-praos.json b/files/ptn0-praos.json index 0d60f51c0..c5070140e 100644 --- a/files/ptn0-praos.json +++ b/files/ptn0-praos.json @@ -43,7 +43,7 @@ "defaultScribes": [ [ "FileSK", - "/opt/cardano/cnode/logs/node-0.json" + "/opt/cardano/cnode/logs/node0.json" ] ], "hasEKG": 12788, @@ -161,7 +161,7 @@ "setupScribes": [ { "scKind": "FileSK", - "scName": "/opt/cardano/cnode/logs/node-0.json", + "scName": "/opt/cardano/cnode/logs/node0.json", "scFormat": "ScJson", "scRotation": null } From c3f13315ed6e3fab1ec8657f137ac27791952fec Mon Sep 17 00:00:00 2001 From: "Ola [AHLNET]" Date: Sat, 5 Sep 2020 03:11:37 +0200 Subject: [PATCH 14/24] Improved netstat parsing and peer analysis output (#457) * netstat parsing uniformity between peer analysis and live summary * netstat parsing improved, would in some situation not parse incoming/outgoing correctly. * peer analysis output timestamp made more defined and date skipped to make it clear that this is static information after analysis is done. * peer analysis summary name changed from Peers Total to Unique Peers to make it clearer that multiple connections from same IPs are truncated. * Skipped metric changed to be the difference between unique and total. --- scripts/cnode-helper-scripts/gLiveView.sh | 50 +++++++++++++---------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/scripts/cnode-helper-scripts/gLiveView.sh b/scripts/cnode-helper-scripts/gLiveView.sh index 947ff8e89..5679ca985 100755 --- a/scripts/cnode-helper-scripts/gLiveView.sh +++ b/scripts/cnode-helper-scripts/gLiveView.sh @@ -224,32 +224,30 @@ checkPeers() { peerCNT=0; peerCNT0=0; peerCNT1=0; peerCNT2=0; peerCNT3=0; peerCNT4=0 peerPCT1=0; peerPCT2=0; peerPCT3=0; peerPCT4=0 peerPCT1items=0; peerPCT2items=0; peerPCT3items=0; peerPCT4items=0 - peerRTTSUM=0; peerCNTSKIPPED=0; peerCNTABS=0; peerRTTAVG=0 - uniqPeers=() + peerRTTSUM=0; peerCNTSKIPPED=0; peerCNTUnique=0; peerCNTABS=0; peerRTTAVG=0 + uniquePeers=() direction=$1 - - pid=$(netstat -lnp 2>/dev/null | grep -e ":${CNODE_PORT}" | awk '{print $7}' | tail -n 1 | cut -d"/" -f1) - [[ -z ${pid} || ${pid} = "-" ]] && return if [[ ${direction} = "out" ]]; then - netstatPeers=$(netstat -np 2>/dev/null | grep -e "ESTABLISHED.* ${pid}/" | grep -v ":${CNODE_PORT}" | awk '{print $5}') + netstatPeers=$(netstat -np 2>/dev/null | grep -e "ESTABLISHED.* ${pid}/" | awk -v port=":${CNODE_PORT}" '$4 !~ port {print $5}') else - netstatPeers=$(netstat -np 2>/dev/null | grep -e "ESTABLISHED.* ${pid}/" | grep ":${CNODE_PORT}" | awk '{print $5}') + netstatPeers=$(netstat -np 2>/dev/null | grep -e "ESTABLISHED.* ${pid}/" | awk -v port=":${CNODE_PORT}" '$4 ~ port {print $5}') fi netstatSorted=$(printf '%s\n' "${netstatPeers[@]}" | sort ) + peerCNTABS=$(printf '%s\n' "${netstatPeers[@]}" | wc -l) # Sort/filter peers lastpeerIP=""; lastpeerPORT="" - for peer in $netstatSorted; do + for peer in ${netstatSorted}; do peerIP=$(echo "${peer}" | cut -d: -f1); peerPORT=$(echo "${peer}" | cut -d: -f2) - if [[ ! "$peerIP" = "$lastpeerIP" ]]; then + if [[ ! "${peerIP}" = "${lastpeerIP}" ]]; then lastpeerIP=${peerIP} lastpeerPORT=${peerPORT} - uniqPeers+=("${peerIP}:${peerPORT} ") - ((peerCNTABS++)) + uniquePeers+=("${peerIP}:${peerPORT} ") + ((peerCNTUnique++)) fi done - netstatPeers=$(printf '%s\n' "${uniqPeers[@]}") + netstatPeers=$(printf '%s\n' "${uniquePeers[@]}") # Ping every node in the list for peer in ${netstatPeers}; do @@ -283,7 +281,7 @@ checkPeers() { if [[ ${peerCNT} -gt 0 ]]; then peerRTTAVG=$((peerRTTSUM / peerCNT)) fi - peerCNTSKIPPED=$((peerCNTABS - peerCNT - peerCNT0)) + peerCNTSKIPPED=$(( peerCNTABS - peerCNTUnique )) peerMAX=0 if [[ ${peerCNT} -gt 0 ]]; then @@ -304,6 +302,8 @@ checkPeers() { version=$("$(command -v cardano-node)" version) node_version=$(grep "cardano-node" <<< "${version}" | cut -d ' ' -f2) node_rev=$(grep "git rev" <<< "${version}" | cut -d ' ' -f3 | cut -c1-8) +pid=$(ps -ef | grep "[-]-port ${CNODE_PORT}" | awk '{print $2}') +[[ -z ${pid} ]] && myExit 1 "Failed to locate cardano-node process ID, make sure CNODE_PORT is correctly set in script!" check_peers="false" show_peers="false" line_end=0 @@ -388,7 +388,7 @@ while true; do if ((uptimens<=0)); then myExit 1 "${FG_RED}COULD NOT CONNECT TO A RUNNING INSTANCE!${NC}\nPLEASE CHECK THE EKG PORT AND TRY AGAIN!" fi - peers_in=$(netstat -an|awk "\$4 ~ /${CNODE_PORT}/"|grep -c ESTABLISHED) + peers_in=$(netstat -np 2>/dev/null | grep -e "ESTABLISHED.* ${pid}/" | awk -v port=":${CNODE_PORT}" '$4 ~ port {print}' | wc -l) peers_out=$(jq '.cardano.node.BlockFetchDecision.peers.connectedPeers.int.val //0' <<< "${data}") blocknum=$(jq '.cardano.node.ChainDB.metrics.blockNum.int.val //0' <<< "${data}") epochnum=$(jq '.cardano.node.ChainDB.metrics.epoch.int.val //0' <<< "${data}") @@ -558,15 +558,19 @@ while true; do peerCNT0_out=${peerCNT0}; peerCNT1_out=${peerCNT1}; peerCNT2_out=${peerCNT2}; peerCNT3_out=${peerCNT3}; peerCNT4_out=${peerCNT4} peerPCT1_out=${peerPCT1}; peerPCT2_out=${peerPCT2}; peerPCT3_out=${peerPCT3}; peerPCT4_out=${peerPCT4} peerPCT1items_out=${peerPCT1items}; peerPCT2items_out=${peerPCT2items}; peerPCT3items_out=${peerPCT3items}; peerPCT4items_out=${peerPCT4items} - peerRTT_out=${peerRTT}; peerRTTAVG_out=${peerRTTAVG}; peerCNTABS_out=${peerCNTABS}; peerCNTSKIPPED_out=${peerCNTSKIPPED} + peerRTT_out=${peerRTT}; peerRTTAVG_out=${peerRTTAVG}; peerCNTUnique_out=${peerCNTUnique}; peerCNTSKIPPED_out=${peerCNTSKIPPED} + time_out=$(date -u '+%T Z') fi if [[ ${redraw_peers} = "true" ]]; then tput cup ${line} 0 - printf "${VL}${STANDOUT} OUT ${NC} RTT : Peers / Percent - %s" "$(date -u '+%F %T Z')" - endLine $((line++)) + printf "${VL}${STANDOUT} OUT ${NC} RTT : Peers / Percent" + tput el && tput cup ${line} $(( width - 20 )) + printf "Updated: ${FG_YELLOW}%s${NC} ${VL}\n" "${time_out}" + ((line++)) + printf "${VL} 0-50ms : %5s / %.f%% ${FG_GREEN}" "${peerCNT1_out}" "${peerPCT1_out}" tput el && tput cup ${line} ${bar_col_small} for i in $(seq 0 $((granularity_small-1))); do @@ -607,7 +611,7 @@ while true; do echo "${m2divider}" ((line++)) - printf "${VL} Peers Total / Unreachable / Skipped : ${FG_BLUE}%s${NC} / " "${peerCNTABS_out}" + printf "${VL} Unique Peers / Unreachable / Skipped : ${FG_BLUE}%s${NC} / " "${peerCNTUnique_out}" [[ ${peerCNT0_out} -eq 0 ]] && printf "${FG_BLUE}%s${NC} / " "${peerCNT0_out}" || printf "${FG_RED}%s${NC} / " "${peerCNT0_out}" [[ ${peerCNTSKIPPED_out} -eq 0 ]] && printf "${FG_BLUE}%s${NC}" "${peerCNTSKIPPED_out}" || printf "${FG_YELLOW}%s${NC}" "${peerCNTSKIPPED_out}" endLine $((line++)) @@ -624,13 +628,17 @@ while true; do peerCNT0_in=${peerCNT0}; peerCNT1_in=${peerCNT1}; peerCNT2_in=${peerCNT2}; peerCNT3_in=${peerCNT3}; peerCNT4_in=${peerCNT4} peerPCT1_in=${peerPCT1}; peerPCT2_in=${peerPCT2}; peerPCT3_in=${peerPCT3}; peerPCT4_in=${peerPCT4} peerPCT1items_in=${peerPCT1items}; peerPCT2items_in=${peerPCT2items}; peerPCT3items_in=${peerPCT3items}; peerPCT4items_in=${peerPCT4items} - peerRTT_in=${peerRTT}; peerRTTAVG_in=${peerRTTAVG}; peerCNTABS_in=${peerCNTABS}; peerCNTSKIPPED_in=${peerCNTSKIPPED} + peerRTT_in=${peerRTT}; peerRTTAVG_in=${peerRTTAVG}; peerCNTUnique_in=${peerCNTUnique}; peerCNTSKIPPED_in=${peerCNTSKIPPED} + time_in=$(date -u '+%T Z') fi tput cup ${line} 0 printf "${VL}${STANDOUT} In ${NC} RTT : Peers / Percent" - endLine $((line++)) + tput el && tput cup ${line} $(( width - 20 )) + printf "Updated: ${FG_YELLOW}%s${NC} ${VL}\n" "${time_in}" + ((line++)) + printf "${VL} 0-50ms : %5s / %.f%% ${FG_GREEN}" "${peerCNT1_in}" "${peerPCT1_in}" tput el && tput cup ${line} ${bar_col_small} for i in $(seq 0 $((granularity_small-1))); do @@ -671,7 +679,7 @@ while true; do echo "${m2divider}" ((line++)) - printf "${VL} Peers Total / Unreachable / Skipped : ${FG_BLUE}%s${NC} / " "${peerCNTABS_in}" + printf "${VL} Unique Peers / Unreachable / Skipped : ${FG_BLUE}%s${NC} / " "${peerCNTUnique_in}" [[ ${peerCNT0_in} -eq 0 ]] && printf "${FG_BLUE}%s${NC} / " "${peerCNT0_in}" || printf "${FG_RED}%s${NC} / " "${peerCNT0_in}" [[ ${peerCNTSKIPPED_in} -eq 0 ]] && printf "${FG_BLUE}%s${NC}" "${peerCNTSKIPPED_in}" || printf "${FG_YELLOW}%s${NC}" "${peerCNTSKIPPED_in}" endLine $((line++)) From 6bd9677a4429499a9f002f3980ed0798083d2eba Mon Sep 17 00:00:00 2001 From: tbenson Date: Sat, 5 Sep 2020 18:13:03 -0700 Subject: [PATCH 15/24] Update deploy-as-systemd.sh (#459) Fix to properly enable cnode.service. --- scripts/cnode-helper-scripts/deploy-as-systemd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cnode-helper-scripts/deploy-as-systemd.sh b/scripts/cnode-helper-scripts/deploy-as-systemd.sh index 5040b0066..203c2118c 100755 --- a/scripts/cnode-helper-scripts/deploy-as-systemd.sh +++ b/scripts/cnode-helper-scripts/deploy-as-systemd.sh @@ -25,4 +25,4 @@ WantedBy=multi-user.target EOF" sudo systemctl daemon-reload -sudo systemctl enable +sudo systemctl enable cnode.service From cd160a08fd39831ff5ce8eb758c0988eff7139dd Mon Sep 17 00:00:00 2001 From: "Ola [AHLNET]" Date: Sun, 6 Sep 2020 15:13:33 +0200 Subject: [PATCH 16/24] gLiveView - Color themes, legacy mode and config check (#463) Addresses enhancements mentioned in #458 - New color theme config option has been added (dark|light). Colors have also been slightly modified to better suite different terminals. If user wants to override colors set in the two themes or add their own this should be easier as well. - New legacy config option added. If enabled, unicode box-drawing characters will be replaced by standard ASCII characters. It was noticed that on mobile apps UTF-8 characters often have different spacings. - Sanity checks added that configuration values are correctly set or identified. - Documentation updated to reflect changes and a new 'Description' section added to explain the different metrics. --- docs/Scripts/gliveview.md | 24 +- scripts/cnode-helper-scripts/gLiveView.sh | 394 ++++++++++++++-------- 2 files changed, 278 insertions(+), 140 deletions(-) diff --git a/docs/Scripts/gliveview.md b/docs/Scripts/gliveview.md index 1693049f3..58dcbe84a 100644 --- a/docs/Scripts/gliveview.md +++ b/docs/Scripts/gliveview.md @@ -20,12 +20,28 @@ chmod 755 gLiveView.sh ##### Startup For most standard deployments, this should lead you to a stage where you can now start running `./gLiveView.sh` in the folder you downloaded the script (default location for cntools users would be `$CNODE_HOME/scripts`). Note that the script is smart enough to automatically detect when you're running as a Core or Relay and will show fields accordingly. -A sample output from both core and relay(with peer analysis run): + +The tool can be run in legacy mode with only standard ASCII characters for terminals with trouble displaying the box-drawing characters. Run `./gLiveView.sh -h` to show available command-line parameters or permanently set it directly in script. + +A sample output from both core and relay(with peer analysis): ![Core](https://raw.githubusercontent.com/cardano-community/guild-operators/images/gliveview-core.png) ![Relay](https://raw.githubusercontent.com/cardano-community/guild-operators/images/gliveview-relay.png) +##### Description + +**Upper main section** +Displays live metrics gathered from EKG. Epoch number and progress is live from node while date calculation until epoch boundary is based on offline genesis parameters. Reference tip is also an offline calculation based on genesis values used to compare against the node tip to see how far of the tip(diff value) the node is. With current parameters a slot diff up to 40 from reference tip is considered good but it ussually stay below 30. In/Out peers show how many connections the node have established in and out. + +**Core section** +If the node is run as a core, identified by the 'forge-about-to-lead' EKG parameter, a second core section is displayed. This section contain current and remaining KES periods as well as a calculated date for the expiration. When getting close to expire date the values will change color. Blocks created by the node since node start is another metric shown in this section. If [cntoolsBlockCollector.sh](Scripts/cntools-blocks.md) is running for the core node a second row with current epoch blocks is displayed. + +**Peer analysis** +A manual peer analysis can be triggered by key press `p`. A latency test will be done on incoming and outgoing connections to the node. For outgoing connections a normal ICMP ping is done as a first try. If this is blocked, tcptraceroute program is used to do a tcp ping against the cardano-node port of the remote peer. For incoming connections only ICMP ping is used as remote peer port is unknown. It's not uncommon to see many unreachable peers for incoming connections as it's a good security practice to disable ICMP in firewall. + +Once run it will display RTT for the peers and group them in the ranges 0-50, 50-100, 100-200, 200<. The analysis filter out multiple connections to the same IP. Unique Peers + Skipped should match the total number seen in top section. The analysis is **NOT** live. Last update timestamp is shown to know when it was last run. Press `p` for update or `h` to hide it. + ##### Troubleshooting/Customisations In case you run into trouble while running the script, you might want to edit `gLiveView.sh` and look at User Variables section shown below. You can override the values if the automatic detection do not provide the right information, but we would appreciate if you could also notify us by raising an issue against github repo: @@ -37,10 +53,14 @@ In case you run into trouble while running the script, you might want to edit `g #CNODE_HOME="/opt/cardano/cnode" # Override default CNODE_HOME path #CNODE_PORT=6000 # Override automatic detection of node port -NODE_NAME="Cardano Node" # Change your node's name prefix here, keep at or below 19 characters for proper formatting +NODE_NAME="Cardano Node" # Change your node's name prefix here, keep at or below 19 characters! REFRESH_RATE=2 # How often (in seconds) to refresh the view #CONFIG="${CNODE_HOME}/files/config.json" # Override automatic detection of node config path EKG_HOST=127.0.0.1 # Set node EKG host #EKG_PORT=12788 # Override automatic detection of node EKG port +#PROTOCOL="Cardano" # Default: Combinator network (leave commented if unsure) #BLOCK_LOG_DIR="${CNODE_HOME}/db/blocks" # CNTools Block Collector block dir set in cntools.config, override path if enabled and using non standard path +legacy_mode=false # (true|false) If enabled unicode box-drawing characters will be replaced by standard ASCII characters +THEME="dark" # dark = suited for terminals with a dark background + # light = suited for terminals with a bright background ``` diff --git a/scripts/cnode-helper-scripts/gLiveView.sh b/scripts/cnode-helper-scripts/gLiveView.sh index 5679ca985..f10570853 100755 --- a/scripts/cnode-helper-scripts/gLiveView.sh +++ b/scripts/cnode-helper-scripts/gLiveView.sh @@ -1,25 +1,5 @@ #!/bin/bash -#shellcheck disable=SC2009,SC2034,SC2059 - -################################################################### -# Automatically grab a few parameters # -# Do NOT modify, can be overridden 'User Variables' section below # -################################################################### - -# The commands below will try to detect the information assuming you run single node on a machine. -# Please override values if they dont match your system in the 'User Variables' section below -[[ -z "${CNODE_HOME}" ]] && CNODE_HOME=/opt/cardano/cnode -[[ "$(ps -ef | grep "[c]ardano-node.*.${CNODE_HOME}")" =~ --port[[:space:]]([[:digit:]]+) ]] -CNODE_PORT=${BASH_REMATCH[1]:-6000} # default value: 6000 -[[ "$(ps -ef | grep "[c]ardano-node.*.${CNODE_HOME}")" =~ --config[[:space:]]([^[:space:]]+) ]] -CONFIG="${BASH_REMATCH[1]:-${CNODE_HOME}/files/config.json}" # default value: /opt/cardano/cnode/files/config.json -if [[ -f "${CONFIG}" ]]; then - EKG_PORT=$(jq -r '.hasEKG //empty' "${CONFIG}" 2>/dev/null) -else - EKG_PORT=12788 -fi -PROTOCOL=$(jq -r '.Protocol //empty' "${CONFIG}" 2>/dev/null) -[[ -d "${CNODE_HOME}/db/blocks" ]] && BLOCK_LOG_DIR="${CNODE_HOME}/db/blocks" +#shellcheck disable=SC2009,SC2034,SC2059,SC2206 ###################################### # User Variables - Change as desired # @@ -28,13 +8,46 @@ PROTOCOL=$(jq -r '.Protocol //empty' "${CONFIG}" 2>/dev/null) #CNODE_HOME="/opt/cardano/cnode" # Override default CNODE_HOME path #CNODE_PORT=6000 # Override automatic detection of node port -NODE_NAME="Cardano Node" # Change your node's name prefix here, keep at or below 19 characters for proper formatting +NODE_NAME="Cardano Node" # Change your node's name prefix here, keep at or below 19 characters! REFRESH_RATE=2 # How often (in seconds) to refresh the view #CONFIG="${CNODE_HOME}/files/config.json" # Override automatic detection of node config path EKG_HOST=127.0.0.1 # Set node EKG host #EKG_PORT=12788 # Override automatic detection of node EKG port -#PROTOCOL="Cardano" # Default: Combinator network. Leave commented if unsure. +#PROTOCOL="Cardano" # Default: Combinator network (leave commented if unsure) #BLOCK_LOG_DIR="${CNODE_HOME}/db/blocks" # CNTools Block Collector block dir set in cntools.config, override path if enabled and using non standard path +LEGACY_MODE=false # (true|false) If enabled unicode box-drawing characters will be replaced by standard ASCII characters +THEME="dark" # dark = suited for terminals with a dark background + # light = suited for terminals with a bright background + +##################################### +# Themes # +##################################### + +setTheme() { + if [[ ${THEME} = "dark" ]]; then + style_title=${FG_MAGENTA}${BOLD} # style of title + style_base=${FG_WHITE} # default color for text and lines + style_values_1=${FG_CYAN} # color of most live values + style_values_2=${FG_GREEN} # color of node name + style_info=${FG_YELLOW} # info messages + style_status_1=${FG_GREEN} # :) + style_status_2=${FG_YELLOW} # :| + style_status_3=${FG_RED} # :( + style_status_4=${FG_MAGENTA} # :(( + elif [[ ${THEME} = "light" ]]; then + style_title=${FG_MAGENTA}${BOLD} # style of title + style_base=${FG_BLACK} # default color for text and lines + style_values_1=${FG_BLUE} # color of most live values + style_values_2=${FG_GREEN} # color of node name + style_info=${FG_YELLOW} # info messages + style_status_1=${FG_GREEN} # :) + style_status_2=${FG_YELLOW} # :| + style_status_3=${FG_RED} # :( + style_status_4=${FG_MAGENTA} # :(( + else + myExit 1 "Please specify a valid THEME name!" + fi +} ##################################### # Do NOT Modify below # @@ -44,24 +57,123 @@ tput smcup # Save screen tput civis # Disable cursor stty -echo # Disable user input +# Command : myExit [message] +# Description : gracefully handle an exit and restore terminal to original state +myExit() { + tput rmcup # restore screen + [[ -n $2 ]] && echo -e "\n$2\n" + stty echo # Enable user input + tput cnorm # restore cursor + tput sgr0 # turn off all attributes + exit "$1" +} + +# General exit handler +cleanup() { + err=$? + trap '' INT TERM + myExit $err "Guild LiveView terminated, cleaning up..." +} +sig_cleanup() { + trap '' EXIT # some shells will call EXIT after the INT handler + false # sets $? + cleanup +} +trap sig_cleanup INT TERM + +####################################################### +# Automatically grab a few parameters # +# Can be overridden in 'User Variables' section above # +####################################################### + +usage() { + cat </dev/null); then + myExit 1 "Could not get 'hasEKG' port from the node configuration file" + fi + if ! PROTOCOL=$(jq -er '.Protocol' "${CONFIG}" 2>/dev/null); then + myExit 1 "Could not get 'Protocol' from the node configuration file" + fi +else + myExit 1 "Node config not found: ${CONFIG}" +fi +[[ -z ${BLOCK_LOG_DIR} && -d "${CNODE_HOME}/db/blocks" ]] && BLOCK_LOG_DIR="${CNODE_HOME}/db/blocks" # optional + # Style width=53 second_col=28 +FG_BLACK=$(tput setaf 0) FG_RED=$(tput setaf 1) FG_GREEN=$(tput setaf 2) FG_YELLOW=$(tput setaf 3) FG_BLUE=$(tput setaf 4) FG_MAGENTA=$(tput setaf 5) FG_CYAN=$(tput setaf 6) +FG_WHITE=$(tput setaf 7) STANDOUT=$(tput smso) BOLD=$(tput bold) -VL="\\u2502" -HL="\\u2500" -NC=$(tput sgr0) + +setTheme # call function to set theme colors +NC=$(tput sgr0 && printf "${style_base}") # reset style and set base color # Progressbar -char_marked=$(printf "\\u258C") -char_unmarked=$(printf "\\u2596") +if [[ ${LEGACY_MODE} = "true" ]]; then + char_marked="#" + char_unmarked="." +else + char_marked=$(printf "\\u258C") + char_unmarked=$(printf "\\u2596") +fi granularity=50 granularity_small=25 step_size=$((100/granularity)) @@ -69,42 +181,47 @@ step_size_small=$((100/granularity_small)) bar_col_small=$((width - granularity_small)) # Lines -tdivider=$(printf "\\u250C" && printf "%0.s${HL}" $(seq $((width-1))) && printf "\\u2510") -mdivider=$(printf "\\u251C" && printf "%0.s${HL}" $(seq $((width-1))) && printf "\\u2524") -m2divider=$(printf "\\u251C" && printf "%0.s-" $(seq $((width-1))) && printf "\\u2524") -bdivider=$(printf "\\u2514" && printf "%0.s${HL}" $(seq $((width-1))) && printf "\\u2518") +if [[ ${LEGACY_MODE} = "true" ]]; then + VL=$(printf "${NC}|") + HL=$(printf "${NC}=") + LVL=$(printf "${NC}|") + RVL=$(printf "${NC}|") + UHL=$(printf "${NC}=") + DHL=$(printf "${NC}=") + UR=$(printf "${NC}=") + UL=$(printf "${NC}|") + DR=$(printf "${NC}|") + DL=$(printf "${NC}|") + tdivider=$(printf "${NC}|" && printf "%0.s=" $(seq $((width-1))) && printf "|") + mdivider=$(printf "${NC}|" && printf "%0.s=" $(seq $((width-1))) && printf "|") + m2divider=$(printf "${NC}|" && printf "%0.s-" $(seq $((width-1))) && printf "|") + m3divider=$(printf "${NC}|" && printf "%0.s- " $(seq $((width/2))) && printf "|") + bdivider=$(printf "${NC}|" && printf "%0.s=" $(seq $((width-1))) && printf "|") +else + VL=$(printf "${NC}\\u2502") + HL=$(printf "${NC}\\u2500") + LVL=$(printf "${NC}\\u2524") + RVL=$(printf "${NC}\\u251C") + UHL=$(printf "${NC}\\u2534") + DHL=$(printf "${NC}\\u252C") + UR=$(printf "${NC}\\u2514") + UL=$(printf "${NC}\\u2518") + DR=$(printf "${NC}\\u250C") + DL=$(printf "${NC}\\u2510") + tdivider=$(printf "${NC}\\u250C" && printf "%0.s\\u2500" $(seq $((width-1))) && printf "\\u2510") + mdivider=$(printf "${NC}\\u251C" && printf "%0.s\\u2500" $(seq $((width-1))) && printf "\\u2524") + m2divider=$(printf "${NC}\\u2502" && printf "%0.s-" $(seq $((width-1))) && printf "\\u2502") + m3divider=$(printf "${NC}\\u2502" && printf "%0.s- " $(seq $((width/2))) && printf "\\u2502") + bdivider=$(printf "${NC}\\u2514" && printf "%0.s\\u2500" $(seq $((width-1))) && printf "\\u2518") +fi # Title -title=$(printf "${FG_MAGENTA}${BOLD}Guild LiveView${NC}") +title="Guild LiveView" ##################################### # Helper functions # ##################################### -# Command : myExit [message] -# Description : gracefully handle an exit and restore terminal to original state -myExit() { - tput rmcup # restore screen - [[ -n $2 ]] && echo -e "\n$2" - stty echo # Enable user input - tput cnorm # restore cursor - echo -e "${NC}" # turn off all attributes - exit "$1" -} - -# General exit handler -cleanup() { - err=$? - trap '' INT TERM - myExit $err "Guild LiveView terminated, cleaning up..." -} -sig_cleanup() { - trap '' EXIT # some shells will call EXIT after the INT handler - false # sets $? - cleanup -} -trap sig_cleanup INT TERM - # Command : waitForInput # Description : wait for user keypress to quit, else do nothing if timeout expire waitForInput() { @@ -118,8 +235,6 @@ waitForInput() { sleep 1 } - - # Command : showTimeLeft time_in_seconds # Description: calculation of days, hours, minutes and seconds timeLeft() { @@ -150,9 +265,9 @@ getShelleyTransitionEpoch() { shelley_transition_epoch=208 elif [[ ${calc_slot} -ne ${slotnum} || ${shelley_epochs} -eq 0 ]]; then clear - printf "\n ${FG_RED}Failed${NC} to calculate shelley transition epoch!" + printf "\n ${style_status_3}Failed${NC} to calculate shelley transition epoch!" printf "\n Calculations might not work correctly until Shelley era is reached." - printf "\n\n ${FG_BLUE}Press c to continue or any other key to quit${NC}" + printf "\n\n ${style_info}Press c to continue or any other key to quit${NC}" read -r -n 1 -s -p "" answer [[ "${answer}" != "c" ]] && myExit 1 "Guild LiveView terminated!" shelley_transition_epoch=0 @@ -307,7 +422,7 @@ pid=$(ps -ef | grep "[-]-port ${CNODE_PORT}" | awk '{print $2}') check_peers="false" show_peers="false" line_end=0 -data=$(curl -s -H 'Accept: application/json' http://${EKG_HOST}:${EKG_PORT}/ 2>/dev/null) +data=$(curl -s -H 'Accept: application/json' "http://${EKG_HOST}:${EKG_PORT}/" 2>/dev/null) about_to_lead=$(jq '.cardano.node.metrics.Forge["forge-about-to-lead"].int.val //0' <<< "${data}") epochnum=$(jq '.cardano.node.ChainDB.metrics.epoch.int.val //0' <<< "${data}") slot_in_epoch=$(jq '.cardano.node.ChainDB.metrics.slotInEpoch.int.val //0' <<< "${data}") @@ -319,7 +434,9 @@ remaining_kes_periods=$(jq '.cardano.node.Forge.metrics.remainingKESPeriods.int. # Static genesis variables # ##################################### shelley_genesis_file=$(jq -r .ShelleyGenesisFile "${CONFIG}") +[[ ! ${shelley_genesis_file} =~ ^/ ]] && shelley_genesis_file="$(dirname "${CONFIG}")/${shelley_genesis_file}" byron_genesis_file=$(jq -r .ByronGenesisFile "${CONFIG}") +[[ ! ${byron_genesis_file} =~ ^/ ]] && byron_genesis_file="$(dirname "${CONFIG}")/${byron_genesis_file}" nwmagic=$(jq -r .networkMagic < "${shelley_genesis_file}") shelley_genesis_start=$(jq -r .systemStart "${shelley_genesis_file}") shelley_genesis_start_sec=$(date --date="${shelley_genesis_start}" +%s) @@ -346,6 +463,7 @@ kesExpiration # Static and wont change until KES rotation and node restart clear tlines=$(tput lines) # set initial terminal lines tcols=$(tput cols) # set initial terminal columns +printf "${NC}" # reset and set default color ##################################### # MAIN LOOP # @@ -357,11 +475,11 @@ while true; do [[ ${width} -ge $((tcols-1)) || ${line_end} -ge $((tlines-1)) ]] && clear while [[ ${width} -ge $((tcols-1)) ]]; do tput cup 1 1 - printf "${FG_RED}Terminal width too small!${NC}" + printf "${style_status_3}Terminal width too small!${NC}" tput cup 3 1 - printf "Please increase by ${FG_MAGENTA}$(( width - tcols + 2 ))${NC} columns" + printf "Please increase by ${style_info}$(( width - tcols + 2 ))${NC} columns" tput cup 5 1 - printf "${FG_CYAN}Use CTRL + C to force quit${NC}" + printf "${style_info}Use CTRL + C to force quit${NC}" sleep 2 tlines=$(tput lines) # update terminal lines tcols=$(tput cols) # update terminal columns @@ -369,11 +487,11 @@ while true; do done while [[ ${line_end} -ge $((tlines-1)) ]]; do tput cup 1 1 - printf "${FG_RED}Terminal height too small!${NC}" + printf "${style_status_3}Terminal height too small!${NC}" tput cup 3 1 - printf "Please increase by ${FG_MAGENTA}$(( line_end - tlines + 2 ))${NC} lines" + printf "Please increase by ${style_info}$(( line_end - tlines + 2 ))${NC} lines" tput cup 5 1 - printf "${FG_CYAN}Use CTRL + C to force quit${NC}" + printf "${style_info}Use CTRL + C to force quit${NC}" sleep 2 tlines=$(tput lines) # update terminal lines tcols=$(tput cols) # update terminal columns @@ -383,10 +501,10 @@ while true; do line=0; tput cup 0 0 # reset position # Gather some data - data=$(curl -s -H 'Accept: application/json' http://${EKG_HOST}:${EKG_PORT}/ 2>/dev/null) + data=$(curl -s -H 'Accept: application/json' "http://${EKG_HOST}:${EKG_PORT}/" 2>/dev/null) uptimens=$(jq '.cardano.node.metrics.upTime.ns.val //0' <<< "${data}") if ((uptimens<=0)); then - myExit 1 "${FG_RED}COULD NOT CONNECT TO A RUNNING INSTANCE!${NC}\nPLEASE CHECK THE EKG PORT AND TRY AGAIN!" + myExit 1 "${style_status_3}COULD NOT CONNECT TO A RUNNING INSTANCE!${NC}" fi peers_in=$(netstat -np 2>/dev/null | grep -e "ESTABLISHED.* ${pid}/" | awk -v port=":${CNODE_PORT}" '$4 ~ port {print}' | wc -l) peers_out=$(jq '.cardano.node.BlockFetchDecision.peers.connectedPeers.int.val //0' <<< "${data}") @@ -408,24 +526,24 @@ while true; do header_length=$(( ${#NODE_NAME} + ${#nodemode} + ${#node_version} + ${#node_rev} + 16 )) [[ ${header_length} -gt ${width} ]] && header_padding=0 || header_padding=$(( (width - header_length) / 2 )) - printf "%${header_padding}s >> ${FG_GREEN}%s${NC} - ${FG_GREEN}%s${NC} : ${FG_BLUE}%s${NC} [${FG_BLUE}%s${NC}] <<\n" "" "${NODE_NAME}" "${nodemode}" "${node_version}" "${node_rev}" + printf "%${header_padding}s >> ${style_values_2}%s${NC} - ${style_info}%s${NC} : ${style_values_1}%s${NC} [${style_values_1}%s${NC}] <<\n" "" "${NODE_NAME}" "${nodemode}" "${node_version}" "${node_rev}" ((line++)) ## Base section ## printf "${tdivider}" - tput cup ${line} $(( width - 17 )) - printf "\\u252C" + tput cup ${line} $(( width - ${#title} - 3 )) + printf "${DHL}" tput cup $((++line)) 0 printf "${VL} Uptime: $(timeLeft $(( uptimens/1000000000 )))" - tput cup ${line} $(( width - 17 )) - printf "${VL} ${title} ${VL}\n" + tput cup ${line} $(( width - ${#title} - 3 )) + printf "${VL} ${style_title}${title} ${VL}\n" ((line++)) printf "${m2divider}" - tput cup ${line} $(( width - 17 )) - printf "\\u2514" - printf "%0.s${HL}" $(seq 16) - printf "\\u2524\n" + tput cup ${line} $(( width - ${#title} - 3 )) + printf "${UR}" + printf "%0.s${HL}" $(seq $(( ${#title} + 2 ))) + printf "${LVL}\n" ((line++)) if [[ ${shelley_transition_epoch} = -1 || ${epochnum} -ge ${shelley_transition_epoch} ]]; then @@ -433,13 +551,13 @@ while true; do else epoch_progress=$(echo "(${slot_in_epoch}/${byron_epoch_length})*100" | bc -l) # in Byron era fi - printf "${VL} Epoch ${FG_BLUE}%s${NC} [%2.1f%%] (node)" "${epochnum}" "${epoch_progress}" + printf "${VL} Epoch ${style_values_1}%s${NC} [${style_values_1}%2.1f%%${NC}] (node)" "${epochnum}" "${epoch_progress}" endLine $((line++)) - printf "${VL} %s until epoch boundary (chain)" "$(timeLeft "$(timeUntilNextEpoch)")" + printf "${VL} ${style_values_1}%s${NC} until epoch boundary (chain)" "$(timeLeft "$(timeUntilNextEpoch)")" endLine $((line++)) epoch_items=$(( $(printf %.0f "${epoch_progress}") / step_size )) - printf "${VL} ${FG_BLUE}" + printf "${VL} ${style_values_1}" for i in $(seq 0 $((granularity-1))); do [[ $i -lt ${epoch_items} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" done @@ -449,35 +567,35 @@ while true; do tip_ref=$(getSlotTipRef) tip_diff=$(( tip_ref - slotnum )) - printf "${VL} Block : ${FG_BLUE}%s${NC}" "${blocknum}" + printf "${VL} Block : ${style_values_1}%s${NC}" "${blocknum}" tput cup ${line} ${second_col} - printf "Tip (ref) : ${FG_BLUE}%s${NC}" "${tip_ref}" + printf "Tip (ref) : ${style_values_1}%s${NC}" "${tip_ref}" endLine $((line++)) - printf "${VL} Slot : ${FG_BLUE}%s${NC}" "${slot_in_epoch}" + printf "${VL} Slot : ${style_values_1}%s${NC}" "${slot_in_epoch}" tput cup ${line} ${second_col} - printf "Tip (node) : ${FG_BLUE}%s${NC}" "${slotnum}" + printf "Tip (node) : ${style_values_1}%s${NC}" "${slotnum}" endLine $((line++)) - printf "${VL} Density : ${FG_BLUE}%s${NC}" "${density}" + printf "${VL} Density : ${style_values_1}%s${NC}%%" "${density}" tput cup ${line} ${second_col} if [[ ${tip_diff} -le $(( slot_interval * 2 )) ]]; then - printf "Tip (diff) : ${FG_GREEN}%s${NC}" "-${tip_diff} :)" + printf "Tip (diff) : ${style_status_1}%s${NC}" "-${tip_diff} :)" elif [[ ${tip_diff} -le $(( slot_interval * 3 )) ]]; then - printf "Tip (diff) : %s" "-${tip_diff} :|" + printf "Tip (diff) : ${style_status_2}%s${NC}" "-${tip_diff} :|" else - printf "Tip (diff) : ${FG_RED}%s${NC}" "-${tip_diff} :(" + printf "Tip (diff) : ${style_status_3}%s${NC}" "-${tip_diff} :(" fi endLine $((line++)) echo "${m2divider}" ((line++)) - printf "${VL} Processed TX : ${FG_BLUE}%s${NC}" "${tx_processed}" + printf "${VL} Processed TX : ${style_values_1}%s${NC}" "${tx_processed}" tput cup ${line} $((second_col+7)) printf " In / Out" endLine $((line++)) - printf "${VL} Mempool TX/Bytes : ${FG_BLUE}%s${NC} / ${FG_BLUE}%s${NC}" "${mempool_tx}" "${mempool_bytes}" + printf "${VL} Mempool TX/Bytes : ${style_values_1}%s${NC} / ${style_values_1}%s${NC}" "${mempool_tx}" "${mempool_bytes}" tput el; tput cup ${line} $((second_col+7)) - printf "Peers : ${FG_BLUE}%s${NC} / ${FG_BLUE}%s${NC}" "${peers_in}" "${peers_out}" + printf "Peers : ${style_values_1}%s${NC} / ${style_values_1}%s${NC}" "${peers_in}" "${peers_out}" endLine $((line++)) ## Core section ## @@ -485,16 +603,16 @@ while true; do echo "${mdivider}" ((line++)) - printf "${VL} KES current/remaining : ${FG_BLUE}%s${NC} / " "${kesperiod}" + printf "${VL} KES current/remaining : ${style_values_1}%s${NC} / " "${kesperiod}" if [[ ${remaining_kes_periods} -le 0 ]]; then - printf "${FG_RED}%s${NC}" "${remaining_kes_periods}" + printf "${style_status_4}%s${NC}" "${remaining_kes_periods}" elif [[ ${remaining_kes_periods} -le 8 ]]; then - printf "${FG_YELLOW}%s${NC}" "${remaining_kes_periods}" + printf "${style_status_3}%s${NC}" "${remaining_kes_periods}" else - printf "${FG_BLUE}%s${NC}" "${remaining_kes_periods}" + printf "${style_values_1}%s${NC}" "${remaining_kes_periods}" fi endLine $((line++)) - printf "${VL} KES expiration date : ${FG_BLUE}%s${NC}" "${kes_expiration}" + printf "${VL} KES expiration date : ${style_values_1}%s${NC}" "${kes_expiration}" endLine $((line++)) echo "${m2divider}" @@ -502,16 +620,16 @@ while true; do printf "${VL} %49s" "IsLeader/Adopted/Missed" endLine $((line++)) - printf "${VL} Blocks since node start : ${FG_BLUE}%s${NC} / " "${isleader}" + printf "${VL} Blocks since node start : ${style_values_1}%s${NC} / " "${isleader}" if [[ ${adopted} -ne ${isleader} ]]; then - printf "${FG_YELLOW}%s${NC} / " "${adopted}" + printf "${style_status_2}%s${NC} / " "${adopted}" else - printf "${FG_BLUE}%s${NC} / " "${adopted}" + printf "${style_values_1}%s${NC} / " "${adopted}" fi if [[ ${didntadopt} -gt 0 ]]; then - printf "${FG_RED}%s${NC}" "${didntadopt}" + printf "${style_status_3}%s${NC}" "${didntadopt}" else - printf "${FG_BLUE}%s${NC}" "${didntadopt}" + printf "${style_values_1}%s${NC}" "${didntadopt}" fi endLine $((line++)) @@ -526,16 +644,16 @@ while true; do invalid_epoch=0 adopted_epoch=0 fi - printf "${VL} Blocks this epoch : ${FG_BLUE}%s${NC} / " "${isleader_epoch}" + printf "${VL} Blocks this epoch : ${style_values_1}%s${NC} / " "${isleader_epoch}" if [[ ${adopted_epoch} -ne ${isleader_epoch} ]]; then - printf "${FG_YELLOW}%s${NC} / " "${adopted_epoch}" + printf "${style_status_2}%s${NC} / " "${adopted_epoch}" else - printf "${FG_BLUE}%s${NC} / " "${adopted_epoch}" + printf "${style_values_1}%s${NC} / " "${adopted_epoch}" fi if [[ ${invalid_epoch} -gt 0 ]]; then - printf "${FG_RED}%s${NC}" "${invalid_epoch}" + printf "${style_status_3}%s${NC}" "${invalid_epoch}" else - printf "${FG_BLUE}%s${NC}" "${invalid_epoch}" + printf "${style_values_1}%s${NC}" "${invalid_epoch}" fi endLine $((line++)) fi @@ -550,7 +668,7 @@ while true; do if [[ ${check_peers} = "true" ]]; then redraw_peers=true tput ed - printf "${VL} ${FG_YELLOW}Output peer analysis started... update paused${NC}" + printf "${VL} ${style_info}Output peer analysis started... update paused${NC}" endLine ${line} echo "${bdivider}" checkPeers out @@ -568,10 +686,10 @@ while true; do printf "${VL}${STANDOUT} OUT ${NC} RTT : Peers / Percent" tput el && tput cup ${line} $(( width - 20 )) - printf "Updated: ${FG_YELLOW}%s${NC} ${VL}\n" "${time_out}" + printf "Updated: ${style_info}%s${NC} ${VL}\n" "${time_out}" ((line++)) - printf "${VL} 0-50ms : %5s / %.f%% ${FG_GREEN}" "${peerCNT1_out}" "${peerPCT1_out}" + printf "${VL} 0-50ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_1}" "${peerCNT1_out}" "${peerPCT1_out}" tput el && tput cup ${line} ${bar_col_small} for i in $(seq 0 $((granularity_small-1))); do [[ $i -lt ${peerPCT1items_out} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" @@ -579,7 +697,7 @@ while true; do printf "${NC}" endLine $((line++)) - printf "${VL} 50-100ms : %5s / %.f%% ${FG_YELLOW}" "${peerCNT2_out}" "${peerPCT2_out}" + printf "${VL} 50-100ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_2}" "${peerCNT2_out}" "${peerPCT2_out}" tput el && tput cup ${line} ${bar_col_small} for i in $(seq 0 $((granularity_small-1))); do [[ $i -lt ${peerPCT2items_out} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" @@ -587,7 +705,7 @@ while true; do printf "${NC}" endLine $((line++)) - printf "${VL} 100-200ms : %5s / %.f%% ${FG_RED}" "${peerCNT3_out}" "${peerPCT3_out}" + printf "${VL} 100-200ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_3}" "${peerCNT3_out}" "${peerPCT3_out}" tput el && tput cup ${line} ${bar_col_small} for i in $(seq 0 $((granularity_small-1))); do [[ $i -lt ${peerPCT3items_out} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" @@ -595,32 +713,32 @@ while true; do printf "${NC}" endLine $((line++)) - printf "${VL} 200ms < : %5s / %.f%% ${FG_MAGENTA}" "${peerCNT4_out}" "${peerPCT4_out}" + printf "${VL} 200ms < : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_4}" "${peerCNT4_out}" "${peerPCT4_out}" tput el && tput cup ${line} ${bar_col_small} for i in $(seq 0 $((granularity_small-1))); do [[ $i -lt ${peerPCT4items_out} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" done printf "${NC}" endLine $((line++)) - if [[ ${peerRTT_out} -ge 200 ]]; then printf "${VL} Average : ${FG_MAGENTA}%s${NC} ms" "${peerRTTAVG_out}" - elif [[ ${peerRTT_out} -ge 100 ]]; then printf "${VL} Average : ${FG_RED}%s${NC} ms" "${peerRTTAVG_out}" - elif [[ ${peerRTT_out} -ge 50 ]]; then printf "${VL} Average : ${FG_YELLOW}%s${NC} ms" "${peerRTTAVG_out}" - elif [[ ${peerRTT_out} -ge 0 ]]; then printf "${VL} Average : ${FG_GREEN}%s${NC} ms" "${peerRTTAVG_out}"; fi + if [[ ${peerRTT_out} -ge 200 ]]; then printf "${VL} Average : ${style_status_4}%s${NC} ms" "${peerRTTAVG_out}" + elif [[ ${peerRTT_out} -ge 100 ]]; then printf "${VL} Average : ${style_status_3}%s${NC} ms" "${peerRTTAVG_out}" + elif [[ ${peerRTT_out} -ge 50 ]]; then printf "${VL} Average : ${style_status_2}%s${NC} ms" "${peerRTTAVG_out}" + elif [[ ${peerRTT_out} -ge 0 ]]; then printf "${VL} Average : ${style_status_1}%s${NC} ms" "${peerRTTAVG_out}"; fi endLine $((line++)) - echo "${m2divider}" + echo "${m3divider}" ((line++)) - printf "${VL} Unique Peers / Unreachable / Skipped : ${FG_BLUE}%s${NC} / " "${peerCNTUnique_out}" - [[ ${peerCNT0_out} -eq 0 ]] && printf "${FG_BLUE}%s${NC} / " "${peerCNT0_out}" || printf "${FG_RED}%s${NC} / " "${peerCNT0_out}" - [[ ${peerCNTSKIPPED_out} -eq 0 ]] && printf "${FG_BLUE}%s${NC}" "${peerCNTSKIPPED_out}" || printf "${FG_YELLOW}%s${NC}" "${peerCNTSKIPPED_out}" + printf "${VL} Unique Peers / Unreachable / Skipped : ${style_values_1}%s${NC} / " "${peerCNTUnique_out}" + [[ ${peerCNT0_out} -eq 0 ]] && printf "${style_values_1}%s${NC} / " "${peerCNT0_out}" || printf "${style_status_3}%s${NC} / " "${peerCNT0_out}" + [[ ${peerCNTSKIPPED_out} -eq 0 ]] && printf "${style_values_1}%s${NC}" "${peerCNTSKIPPED_out}" || printf "${style_status_2}%s${NC}" "${peerCNTSKIPPED_out}" endLine $((line++)) echo "${m2divider}" ((line++)) if [[ ${check_peers} = "true" ]]; then - printf "${VL} ${FG_YELLOW}Input peer analysis started... update paused${NC}" + printf "${VL} ${style_info}Input peer analysis started... update paused${NC}" endLine ${line} echo "${bdivider}" checkPeers in @@ -636,10 +754,10 @@ while true; do printf "${VL}${STANDOUT} In ${NC} RTT : Peers / Percent" tput el && tput cup ${line} $(( width - 20 )) - printf "Updated: ${FG_YELLOW}%s${NC} ${VL}\n" "${time_in}" + printf "Updated: ${style_info}%s${NC} ${VL}\n" "${time_in}" ((line++)) - printf "${VL} 0-50ms : %5s / %.f%% ${FG_GREEN}" "${peerCNT1_in}" "${peerPCT1_in}" + printf "${VL} 0-50ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_1}" "${peerCNT1_in}" "${peerPCT1_in}" tput el && tput cup ${line} ${bar_col_small} for i in $(seq 0 $((granularity_small-1))); do [[ $i -lt ${peerPCT1items_in} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" @@ -647,7 +765,7 @@ while true; do printf "${NC}" endLine $((line++)) - printf "${VL} 50-100ms : %5s / %.f%% ${FG_YELLOW}" "${peerCNT2_in}" "${peerPCT2_in}" + printf "${VL} 50-100ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_2}" "${peerCNT2_in}" "${peerPCT2_in}" tput el && tput cup ${line} ${bar_col_small} for i in $(seq 0 $((granularity_small-1))); do [[ $i -lt ${peerPCT2items_in} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" @@ -655,7 +773,7 @@ while true; do printf "${NC}" endLine $((line++)) - printf "${VL} 100-200ms : %5s / %.f%% ${FG_RED}" "${peerCNT3_in}" "${peerPCT3_in}" + printf "${VL} 100-200ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_3}" "${peerCNT3_in}" "${peerPCT3_in}" tput el && tput cup ${line} ${bar_col_small} for i in $(seq 0 $((granularity_small-1))); do [[ $i -lt ${peerPCT3items_in} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" @@ -663,25 +781,25 @@ while true; do printf "${NC}" endLine $((line++)) - printf "${VL} 200ms < : %5s / %.f%% ${FG_MAGENTA}" "${peerCNT4_in}" "${peerPCT4_in}" + printf "${VL} 200ms < : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_4}" "${peerCNT4_in}" "${peerPCT4_in}" tput el && tput cup ${line} ${bar_col_small} for i in $(seq 0 $((granularity_small-1))); do [[ $i -lt ${peerPCT4items_in} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" done printf "${NC}" endLine $((line++)) - if [[ ${peerRTT_in} -ge 200 ]]; then printf "${VL} Average : ${FG_MAGENTA}%s${NC} ms" "${peerRTTAVG_in}" - elif [[ ${peerRTT_in} -ge 100 ]]; then printf "${VL} Average : ${FG_RED}%s${NC} ms" "${peerRTTAVG_in}" - elif [[ ${peerRTT_in} -ge 50 ]]; then printf "${VL} Average : ${FG_YELLOW}%s${NC} ms" "${peerRTTAVG_in}" - elif [[ ${peerRTT_in} -ge 0 ]]; then printf "${VL} Average : ${FG_GREEN}%s${NC} ms" "${peerRTTAVG_in}"; fi + if [[ ${peerRTT_in} -ge 200 ]]; then printf "${VL} Average : ${style_status_4}%s${NC} ms" "${peerRTTAVG_in}" + elif [[ ${peerRTT_in} -ge 100 ]]; then printf "${VL} Average : ${style_status_3}%s${NC} ms" "${peerRTTAVG_in}" + elif [[ ${peerRTT_in} -ge 50 ]]; then printf "${VL} Average : ${style_status_2}%s${NC} ms" "${peerRTTAVG_in}" + elif [[ ${peerRTT_in} -ge 0 ]]; then printf "${VL} Average : ${style_status_1}%s${NC} ms" "${peerRTTAVG_in}"; fi endLine $((line++)) - echo "${m2divider}" + echo "${m3divider}" ((line++)) - printf "${VL} Unique Peers / Unreachable / Skipped : ${FG_BLUE}%s${NC} / " "${peerCNTUnique_in}" - [[ ${peerCNT0_in} -eq 0 ]] && printf "${FG_BLUE}%s${NC} / " "${peerCNT0_in}" || printf "${FG_RED}%s${NC} / " "${peerCNT0_in}" - [[ ${peerCNTSKIPPED_in} -eq 0 ]] && printf "${FG_BLUE}%s${NC}" "${peerCNTSKIPPED_in}" || printf "${FG_YELLOW}%s${NC}" "${peerCNTSKIPPED_in}" + printf "${VL} Unique Peers / Unreachable / Skipped : ${style_values_1}%s${NC} / " "${peerCNTUnique_in}" + [[ ${peerCNT0_in} -eq 0 ]] && printf "${style_values_1}%s${NC} / " "${peerCNT0_in}" || printf "${style_status_3}%s${NC} / " "${peerCNT0_in}" + [[ ${peerCNTSKIPPED_in} -eq 0 ]] && printf "${style_values_1}%s${NC}" "${peerCNTSKIPPED_in}" || printf "${style_status_2}%s${NC}" "${peerCNTSKIPPED_in}" endLine $((line++)) fi fi @@ -695,12 +813,12 @@ while true; do fi tput cup ${line_end} 0 echo "${bdivider}" - printf " ${FG_YELLOW}[esc/q] Quit${NC} | ${FG_YELLOW}[p] Peer Analysis${NC}" + printf " ${style_info}[esc/q] Quit${NC} | ${style_info}[p] Peer Analysis${NC}" if [[ "${check_peers}" = "true" ]]; then check_peers="false" fi if [[ "${show_peers}" = "true" ]]; then - printf " | ${FG_YELLOW}[h] Hide Peers${NC}" + printf " | ${style_info}[h] Hide Peers${NC}" else tput el fi From 6949619ff2be71aa215b60a18ddaab0a99ce37f9 Mon Sep 17 00:00:00 2001 From: tbenson Date: Sun, 6 Sep 2020 16:55:39 -0700 Subject: [PATCH 17/24] Fix cardano-db-sync build instructions (#465) * Update dbsync.md * Add additional comment for CentOS 7 Co-authored-by: Priyank <3169068+rdlrt@users.noreply.github.com> --- docs/Build/dbsync.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/Build/dbsync.md b/docs/Build/dbsync.md index d3bcf4c95..45ac318e4 100644 --- a/docs/Build/dbsync.md +++ b/docs/Build/dbsync.md @@ -22,6 +22,10 @@ You can use the instructions below to build the cardano-db-sync, same steps can ``` bash git fetch --tags --all git pull +# Include the cardano-crypto-praos and libsodium components for db-sync +# On CentOS 7 (GCC 4.8.5) we should also do +# echo -e "package cryptonite\n flags: -use_target_attributes" >> cabal.project.local +echo -e "package cardano-crypto-praos\n flags: -external-libsodium-vrf" > cabal.project.local # Replace master with appropriate tag if you'd like to avoid compiling against master git checkout master $CNODE_HOME/scripts/cabal-build-all.sh From 06d6fad49e3e7e3081877f2df46505c75da5a29d Mon Sep 17 00:00:00 2001 From: Priyank <3169068+rdlrt@users.noreply.github.com> Date: Tue, 8 Sep 2020 11:50:31 +1000 Subject: [PATCH 18/24] Update config and run command for dbsync (mainnet); closes #466 (#467) * Update config and run command for dbsync (mainnet); closes #466 * Force overwrite in cabal-build-all.sh --- docs/Build/dbsync.md | 2 +- files/ptn0-mainnet.json | 3 +++ scripts/cnode-helper-scripts/cabal-build-all.sh | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/Build/dbsync.md b/docs/Build/dbsync.md index 45ac318e4..62d27d2e8 100644 --- a/docs/Build/dbsync.md +++ b/docs/Build/dbsync.md @@ -46,7 +46,7 @@ scripts/postgresql-setup.sh --createdb ##### Start cardano-db-sync-tool ``` bash cd ~/git/cardano-db-sync -PGPASSFILE=$CNODE_HOME/priv/.pgpass cardano-db-sync-extended --config $CNODE_HOME/files/config.json --genesis-file $CNODE_HOME/files/genesis.json --socket-path $CNODE_HOME/sockets/node0.socket --schema-dir schema/ +PGPASSFILE=$CNODE_HOME/priv/.pgpass cardano-db-sync-extended --config $CNODE_HOME/files/config.json --socket-path $CNODE_HOME/sockets/node0.socket --schema-dir schema/ ``` You can use same instructions above to repeat and execute `cardano-db-sync` as well, but [cardano-graphql](Build/graphql.md) uses `cardano-db-sync-extended`, so we'll stick to it diff --git a/files/ptn0-mainnet.json b/files/ptn0-mainnet.json index f287289d8..f315e1df9 100644 --- a/files/ptn0-mainnet.json +++ b/files/ptn0-mainnet.json @@ -2,6 +2,7 @@ "ApplicationName": "cardano-sl", "ApplicationVersion": 1, "ByronGenesisFile": "/opt/cardano/cnode/files/byron-genesis.json", + "ByronGenesisHash": "5f20df933584822601f9e3f8c024eb5eb252fe8cefb24d1317dc3d432e940ebb", "LastKnownBlockVersion-Alt": 0, "LastKnownBlockVersion-Major": 2, "LastKnownBlockVersion-Minor": 0, @@ -9,6 +10,7 @@ "Protocol": "Cardano", "RequiresNetworkMagic": "RequiresNoMagic", "ShelleyGenesisFile": "/opt/cardano/cnode/files/genesis.json", + "ShelleyGenesisHash": "1a3be38bcbb7911969283716ad7aa550250226b76a61fc51cc9a9a35d9276d81", "bfcMaxConcurrencyDeadline": 2, "TraceBlockFetchClient": true, "TraceBlockFetchDecisions": true, @@ -170,6 +172,7 @@ } ], "SocketPath": "/opt/cardano/cnode/sockets/node0.socket", + "NetworkName": "mainnet", "EnableLogging": true, "EnableLogMetrics": false } diff --git a/scripts/cnode-helper-scripts/cabal-build-all.sh b/scripts/cnode-helper-scripts/cabal-build-all.sh index 2b26ebe60..e5ed540aa 100755 --- a/scripts/cnode-helper-scripts/cabal-build-all.sh +++ b/scripts/cnode-helper-scripts/cabal-build-all.sh @@ -14,6 +14,6 @@ grep "^Linking" /tmp/build.log | while read -r line ; do act_bin_path=$(echo "$line" | awk '{print $2}') act_bin=$(echo "$act_bin_path" | awk -F "/" '{print $NF}') echo "Copying $act_bin to $HOME/.cabal/bin/" - cp "$act_bin_path" "$HOME/.cabal/bin/" + cp -f "$act_bin_path" "$HOME/.cabal/bin/" done From 6112a723b6846031534ff843d4895fc2bd038108 Mon Sep 17 00:00:00 2001 From: Priyank <3169068+rdlrt@users.noreply.github.com> Date: Thu, 10 Sep 2020 18:13:51 +1000 Subject: [PATCH 19/24] [CNTOOLS 5.4.1] - Fix KES Expiry, closes #469 (#470) * Fix KES Expiry, closes #467 * remove slot_in_epoch variable Variable not needed after change in calculation. Co-authored-by: Ola [AHLNET] --- docs/Build/node-cli.md | 4 ++-- docs/Scripts/cntools-changelog.md | 6 ++++++ scripts/cnode-helper-scripts/cntools.library | 5 ++--- scripts/cnode-helper-scripts/gLiveView.sh | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/Build/node-cli.md b/docs/Build/node-cli.md index 82a7e9ec4..352ee8f15 100644 --- a/docs/Build/node-cli.md +++ b/docs/Build/node-cli.md @@ -85,6 +85,6 @@ You can use [gLiveView](Scripts/gliveview.md) to monitor your pool that was star If you've followed guide from this repo previously and would like to transfer to systemd usage, please checkout the steps below: 1. Stop previous instance of node if already running (eg: in tmux) -2. Run `prereqs.sh`, but remember to preserve your customisations to cnode.sh, topology.json, env files. +2. Run `prereqs.sh`, but remember to preserve your customisations to cnode.sh, topology.json, env files (you can also compare and update cnode.sh and env files from github repo). 3. Follow the instructions [above](#run-as-systemd-service) to setup your node as a service and start it using systemctl as directed. -4. If you need to monitor via interactive terminal as before, use [sLiveView](Scripts/sliveview.md). +4. If you need to monitor via interactive terminal as before, use [gLiveView](Scripts/gliveview.md). diff --git a/docs/Scripts/cntools-changelog.md b/docs/Scripts/cntools-changelog.md index ae8cd3bd9..0241f8993 100644 --- a/docs/Scripts/cntools-changelog.md +++ b/docs/Scripts/cntools-changelog.md @@ -5,6 +5,12 @@ All notable changes to this tool will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [5.4.1] - 2020-09-10 + +##### Fixed +- KES Expiry to use KES Period instead of Epoch duration + + ## [5.4.0] - 2020-08-23 > A non-breaking change have been made to files outside of CNTools. Internal update function is not enough to update all files. diff --git a/scripts/cnode-helper-scripts/cntools.library b/scripts/cnode-helper-scripts/cntools.library index 50087b84e..bc7767054 100644 --- a/scripts/cnode-helper-scripts/cntools.library +++ b/scripts/cnode-helper-scripts/cntools.library @@ -11,7 +11,7 @@ CNTOOLS_MAJOR_VERSION=5 # Changes that can be applied without breaking existing functionality that can be applied from within CNTools CNTOOLS_MINOR_VERSION=4 # Backwards compatible bug fixes. No additional functionality or major changes and can be applied from within CNTools -CNTOOLS_PATCH_VERSION=0 +CNTOOLS_PATCH_VERSION=1 CNTOOLS_VERSION="${CNTOOLS_MAJOR_VERSION}.${CNTOOLS_MINOR_VERSION}.${CNTOOLS_PATCH_VERSION}" ############################################################ @@ -486,8 +486,7 @@ kesExpiration() { current_kes_period=$(getCurrentKESperiod) remaining_kes_periods=$(( max_kes_evolutions - ( current_kes_period - pool_kes_start_period ) )) current_time_sec=$(date -u +%s) - slot_in_epoch=$(grep "cardano_node_ChainDB_metrics_slotInEpoch_int" "${TMP_FOLDER}"/prom_metrics | awk '{print $2}') - expiration_time_sec=$(( current_time_sec - ( slot_length * slot_in_epoch ) + ( slot_length * slots_per_kes_period * remaining_kes_periods ) )) + expiration_time_sec=$(( current_time_sec - ( slot_length * slots_per_kes_period ) + ( slot_length * slots_per_kes_period * remaining_kes_periods ) )) expiration_time_sec_diff=$(( expiration_time_sec - current_time_sec )) expiration_date=$(date --date=@${expiration_time_sec}) } diff --git a/scripts/cnode-helper-scripts/gLiveView.sh b/scripts/cnode-helper-scripts/gLiveView.sh index f10570853..64b9b39d6 100755 --- a/scripts/cnode-helper-scripts/gLiveView.sh +++ b/scripts/cnode-helper-scripts/gLiveView.sh @@ -319,7 +319,7 @@ getSlotTipRef() { # Description: Calculate KES expiration kesExpiration() { current_time_sec=$(date -u +%s) - expiration_time_sec=$(( current_time_sec - ( slot_length * slot_in_epoch ) + ( slot_length * slots_per_kes_period * remaining_kes_periods ) )) + expiration_time_sec=$(( current_time_sec - ( slot_length * slots_per_kes_period ) + ( slot_length * slots_per_kes_period * remaining_kes_periods ) )) kes_expiration=$(date '+%F %T Z' --date=@${expiration_time_sec}) } From 9f3cd72a3698d97da4fb48fedfc0fd1b053d9f07 Mon Sep 17 00:00:00 2001 From: "Ola [AHLNET]" Date: Sat, 12 Sep 2020 01:06:01 +0200 Subject: [PATCH 20/24] Replace netstat with ss (#473) Closes #472 --- scripts/cnode-helper-scripts/gLiveView.sh | 12 +++++++++--- scripts/cnode-helper-scripts/prereqs.sh | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/scripts/cnode-helper-scripts/gLiveView.sh b/scripts/cnode-helper-scripts/gLiveView.sh index 64b9b39d6..c6e2f6025 100755 --- a/scripts/cnode-helper-scripts/gLiveView.sh +++ b/scripts/cnode-helper-scripts/gLiveView.sh @@ -107,6 +107,12 @@ while getopts :l opt; do done shift $((OPTIND -1)) +if ! command -v "ss" &>/dev/null; then + myExit 1 "'ss' command missing, please install using latest prereqs.sh script or with your packet manager of choice.\nhttps://command-not-found.com/ss can be used to check package name to install." +elif ! command -v "tcptraceroute" &>/dev/null; then + myExit 1 "'tcptraceroute' command missing, please install using latest prereqs.sh script or with your packet manager of choice.\nhttps://command-not-found.com/tcptraceroute can be used to check package name to install." +fi + # The commands below will try to detect the information assuming you run single node on a machine. # Please override values if they dont match your system in the 'User Variables' section below [[ ${#NODE_NAME} -gt 19 ]] && myExit 1 "Please keep node name at or below 19 characters in length!" @@ -344,9 +350,9 @@ checkPeers() { direction=$1 if [[ ${direction} = "out" ]]; then - netstatPeers=$(netstat -np 2>/dev/null | grep -e "ESTABLISHED.* ${pid}/" | awk -v port=":${CNODE_PORT}" '$4 !~ port {print $5}') + netstatPeers=$(ss -tnp state established 2>/dev/null | grep "${pid}," | awk -v port=":${CNODE_PORT}" '$3 !~ port {print $4}') else - netstatPeers=$(netstat -np 2>/dev/null | grep -e "ESTABLISHED.* ${pid}/" | awk -v port=":${CNODE_PORT}" '$4 ~ port {print $5}') + netstatPeers=$(ss -tnp state established 2>/dev/null | grep "${pid}," | awk -v port=":${CNODE_PORT}" '$3 ~ port {print $4}') fi netstatSorted=$(printf '%s\n' "${netstatPeers[@]}" | sort ) peerCNTABS=$(printf '%s\n' "${netstatPeers[@]}" | wc -l) @@ -506,7 +512,7 @@ while true; do if ((uptimens<=0)); then myExit 1 "${style_status_3}COULD NOT CONNECT TO A RUNNING INSTANCE!${NC}" fi - peers_in=$(netstat -np 2>/dev/null | grep -e "ESTABLISHED.* ${pid}/" | awk -v port=":${CNODE_PORT}" '$4 ~ port {print}' | wc -l) + peers_in=$(ss -tnp state established 2>/dev/null | grep "${pid}," | awk -v port=":${CNODE_PORT}" '$3 ~ port {print}' | wc -l) peers_out=$(jq '.cardano.node.BlockFetchDecision.peers.connectedPeers.int.val //0' <<< "${data}") blocknum=$(jq '.cardano.node.ChainDB.metrics.blockNum.int.val //0' <<< "${data}") epochnum=$(jq '.cardano.node.ChainDB.metrics.epoch.int.val //0' <<< "${data}") diff --git a/scripts/cnode-helper-scripts/prereqs.sh b/scripts/cnode-helper-scripts/prereqs.sh index 03a311568..b07799750 100755 --- a/scripts/cnode-helper-scripts/prereqs.sh +++ b/scripts/cnode-helper-scripts/prereqs.sh @@ -121,7 +121,7 @@ if [ "$WANT_BUILD_DEPS" = 'Y' ]; then echo "deb https://dl.yarnpkg.com/debian/ stable main" | $sudo tee /etc/apt/sources.list.d/yarn.list > /dev/null $sudo apt-get -y update > /dev/null echo " Installing missing prerequisite packages, if any.." - pkg_list="libpq-dev python3 build-essential pkg-config libffi-dev libgmp-dev libssl-dev libtinfo-dev systemd libsystemd-dev libsodium-dev zlib1g-dev yarn make g++ tmux git jq wget libncursesw5 gnupg aptitude libtool autoconf secure-delete net-tools bc tcptraceroute" + pkg_list="libpq-dev python3 build-essential pkg-config libffi-dev libgmp-dev libssl-dev libtinfo-dev systemd libsystemd-dev libsodium-dev zlib1g-dev yarn make g++ tmux git jq wget libncursesw5 gnupg aptitude libtool autoconf secure-delete iproute2 bc tcptraceroute" $sudo apt-get -y install ${pkg_list} > /dev/null;rc=$? if [ $rc != 0 ]; then echo "An error occurred while installing the prerequisite packages, please investigate by using the command below:" @@ -140,7 +140,7 @@ if [ "$WANT_BUILD_DEPS" = 'Y' ]; then $sudo rpm --import https://dl.yarnpkg.com/rpm/pubkey.gpg > /dev/null $sudo yum -y update > /dev/null echo " Installing missing prerequisite packages, if any.." - pkg_list="python3 coreutils pkgconfig libffi-devel gmp-devel openssl-devel ncurses-libs ncurses-compat-libs systemd systemd-devel libsodium-devel zlib-devel npm yarn make gcc-c++ tmux git wget epel-release jq gnupg libtool autoconf srm net-tools bc tcptraceroute" + pkg_list="python3 coreutils pkgconfig libffi-devel gmp-devel openssl-devel ncurses-libs ncurses-compat-libs systemd systemd-devel libsodium-devel zlib-devel npm yarn make gcc-c++ tmux git wget epel-release jq gnupg libtool autoconf srm iproute bc tcptraceroute" $sudo yum -y install ${pkg_list} > /dev/null;rc=$? if [ $rc != 0 ]; then echo "An error occurred while installing the prerequisite packages, please investigate by using the command below:" From 943419044f5767cb189db9d3b707682ee32d9774 Mon Sep 17 00:00:00 2001 From: Priyank <3169068+rdlrt@users.noreply.github.com> Date: Mon, 14 Sep 2020 20:01:46 +1000 Subject: [PATCH 21/24] Prereqs update - closes #474 and #475 (#476) - Add special case for Fedora in pre-requisites - Eliminate GraphQL dependencies from common pre-requisites , as it's an "odd-man-out" (does not follow rest of the components , besides feels forced usage of node for a very minimalistic outcome). - Take backup before overwriting `topology.json`, `topologyUpdater.sh` and handle `cnode.sh` in a way that it can preserve port as well as information to start node as core (path to keys) v/s relay. --- docs/Build/graphql.md | 2 +- docs/Build/node-cli.md | 17 +++++++++- scripts/cnode-helper-scripts/cnode.sh.templ | 28 +++++++++++++++-- scripts/cnode-helper-scripts/prereqs.sh | 35 ++++++++++++++------- 4 files changed, 65 insertions(+), 17 deletions(-) diff --git a/docs/Build/graphql.md b/docs/Build/graphql.md index 86a4e7201..0b893172c 100644 --- a/docs/Build/graphql.md +++ b/docs/Build/graphql.md @@ -1,4 +1,4 @@ -!> - An average pool operator may not require cardano-wallet at all. Please verify if it is required for your use as mentioned [here](build.md#components) +!> We have temporarily disabled updating build documentation for Cardano-GraphQL. The specific component does not follow the process/technology/language (requires npm, yarn) used by other components (cabal/stack), and the value provided by `cardano-graphql` over the (haskell-based) hasura instance has been negligible. Also, an average pool operator may not require cardano-graphql at all, please verify if it is required for your use as mentioned [here](build.md#components). The instructions below are `out of date`. > Ensure the [Pre-Requisites](basics.md#pre-requisites) are in place before you proceed. diff --git a/docs/Build/node-cli.md b/docs/Build/node-cli.md index 352ee8f15..8bedabcbe 100644 --- a/docs/Build/node-cli.md +++ b/docs/Build/node-cli.md @@ -44,7 +44,22 @@ cardano-node version # git rev 4814003f14340d5a1fc02f3ac15437387a7ada9f ``` -##### Start a passive node +##### Update port number or pool name for relative paths + +Before you go ahead with starting your node, you may want to update values for CNODE_PORT in `$CNODE_HOME/scripts/cnode.sh`. Note that it is imperative for operational relays and pools to ensure that the port mentioned is opened via firewall to the destination your node is supposed to connect from. Update your network/firewall configuration accordingly. Future executions of prereqs.sh will preserve and not overwrite these values. + +```bash +## Static (content that will not be overwritten by prereqs.sh) +## Begin + +POOL_NAME="GUILD" +CNODE_PORT=6000 +POOL_DIR="$CNODE_HOME/priv/pool/$POOL_NAME" +``` + +> POOL_NAME is the name of folder that you will use when registering pools and starting node in core mode. This folder would typically contain your `hot.skey`,`vrf.skey` and `op.cert` files required. If the mentioned files are absent, the node will automatically start in a passive mode. + +##### Start the node To test starting the node in interactive mode, you can use the pre-built script below (note that the config now uses `SimpleView` so you may not see much output): diff --git a/scripts/cnode-helper-scripts/cnode.sh.templ b/scripts/cnode-helper-scripts/cnode.sh.templ index e6513cf7b..7d61f48ce 100755 --- a/scripts/cnode-helper-scripts/cnode.sh.templ +++ b/scripts/cnode-helper-scripts/cnode.sh.templ @@ -17,12 +17,34 @@ fi [[ ! -d "$CNODE_HOME/logs/archive" ]] && mkdir -p "$CNODE_HOME/logs/archive" -[[ $(find "$CNODE_HOME"/logs/*.json | wc -l) -gt 0 ]] && mv $CNODE_HOME/logs/*.json $CNODE_HOME/logs/archive/ +[[ $(find "$CNODE_HOME"/logs/*.json 2>/dev/null | wc -l) -gt 0 ]] && mv $CNODE_HOME/logs/*.json $CNODE_HOME/logs/archive/ -cardano-node run \ +## Static (content that will not be overwritten by prereqs.sh) +## Begin + +POOL_NAME="TEST" +CNODE_PORT=6000 +POOL_DIR="$CNODE_HOME/priv/pool/$POOL_NAME" + +if [[ -f "$POOL_DIR/op.cert" && -f "$POOL_DIR/vrf.skey" && -f "$POOL_DIR/hot.skey" ]]; then + cardano-node run \ --topology $CNODE_HOME/files/topology.json \ --config $CNODE_HOME/files/config.json \ --database-path $CNODE_HOME/db \ --socket-path $CNODE_HOME/sockets/node0.socket \ --host-addr 0.0.0.0 \ - --port 6000 + --shelley-kes-key $POOL_DIR/hot.skey \ + --shelley-vrf-key $POOL_DIR/vrf.skey \ + --shelley-operational-certificate $POOL_DIR/op.cert \ + --port $CNODE_PORT +else + cardano-node run \ + --topology $CNODE_HOME/files/topology.json \ + --config $CNODE_HOME/files/config.json \ + --database-path $CNODE_HOME/db \ + --socket-path $CNODE_HOME/sockets/node0.socket \ + --host-addr 0.0.0.0 \ + --port $CNODE_PORT +fi + +## End diff --git a/scripts/cnode-helper-scripts/prereqs.sh b/scripts/cnode-helper-scripts/prereqs.sh index b07799750..404354814 100755 --- a/scripts/cnode-helper-scripts/prereqs.sh +++ b/scripts/cnode-helper-scripts/prereqs.sh @@ -33,7 +33,7 @@ usage() { Usage: $(basename "$0") [-o] [-s] [-i] [-g] [-p] Install pre-requisites for building cardano node and using cntools --o Do *NOT* overwrite existing cnode.sh, genesis.json, topology.json and topology-updater.sh files (Default: will overwrite) +-o Do *NOT* overwrite existing genesis.json, topology.json and topology-updater.sh files (Default: will overwrite) -s Skip installing OS level dependencies (Default: will check and install any missing OS level prerequisites) -i Interactive mode (Default: silent mode) -g Connect to guild network instead of public network (Default: connect to public cardano network) @@ -112,35 +112,30 @@ if [ "$WANT_BUILD_DEPS" = 'Y' ]; then OS_ID=$(grep -i ^id_like= /etc/os-release | cut -d= -f 2) DISTRO=$(grep -i ^NAME= /etc/os-release | cut -d= -f 2) - if [ -z "${OS_ID##*debian*}" ]; then + if [[ "${OS_ID}" =~ ebian ]]; then #Debian/Ubuntu echo "Using apt to prepare packages for ${DISTRO} system" echo " Updating system packages..." $sudo apt-get -y install curl > /dev/null - curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | $sudo apt-key add - > /dev/null - echo "deb https://dl.yarnpkg.com/debian/ stable main" | $sudo tee /etc/apt/sources.list.d/yarn.list > /dev/null $sudo apt-get -y update > /dev/null echo " Installing missing prerequisite packages, if any.." - pkg_list="libpq-dev python3 build-essential pkg-config libffi-dev libgmp-dev libssl-dev libtinfo-dev systemd libsystemd-dev libsodium-dev zlib1g-dev yarn make g++ tmux git jq wget libncursesw5 gnupg aptitude libtool autoconf secure-delete iproute2 bc tcptraceroute" + pkg_list="libpq-dev python3 build-essential pkg-config libffi-dev libgmp-dev libssl-dev libtinfo-dev systemd libsystemd-dev libsodium-dev zlib1g-dev make g++ tmux git jq wget libncursesw5 gnupg aptitude libtool autoconf secure-delete iproute2 bc tcptraceroute" $sudo apt-get -y install ${pkg_list} > /dev/null;rc=$? if [ $rc != 0 ]; then echo "An error occurred while installing the prerequisite packages, please investigate by using the command below:" echo "sudo apt-get -y install ${pkg_list}" echo "It would be best if you could submit an issue at https://github.com/cardano-community/guild-operators with the details to tackle in future, as some errors may be due to external/already present dependencies" exit; - else - $sudo aptitude install npm -yq > /dev/null fi - elif [ -z "${OS_ID##*rhel*}" ]; then + elif [[ "${OS_ID}" =~ rhel ]] || [[ "${DISTRO}" =~ Fedora ]]; then #CentOS/RHEL/Fedora echo "Using yum to prepare packages for ${DISTRO} system" echo " Updating system packages..." $sudo yum -y install curl > /dev/null - curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | $sudo tee /etc/yum.repos.d/yarn.repo > /dev/null - $sudo rpm --import https://dl.yarnpkg.com/rpm/pubkey.gpg > /dev/null $sudo yum -y update > /dev/null echo " Installing missing prerequisite packages, if any.." - pkg_list="python3 coreutils pkgconfig libffi-devel gmp-devel openssl-devel ncurses-libs ncurses-compat-libs systemd systemd-devel libsodium-devel zlib-devel npm yarn make gcc-c++ tmux git wget epel-release jq gnupg libtool autoconf srm iproute bc tcptraceroute" + pkg_list="python3 coreutils pkgconfig libffi-devel gmp-devel openssl-devel ncurses-libs ncurses-compat-libs systemd systemd-devel libsodium-devel zlib-devel make gcc-c++ tmux git wget jq gnupg libtool autoconf srm iproute bc tcptraceroute" + [[ ! "${DISTRO}" =~ Fedora ]] && pkg_list="epel-release $pkg_list" $sudo yum -y install ${pkg_list} > /dev/null;rc=$? if [ $rc != 0 ]; then echo "An error occurred while installing the prerequisite packages, please investigate by using the command below:" @@ -232,6 +227,7 @@ if [[ "$GUILD" = "Y" ]]; then else curl -sL -o byron-genesis.json ${OVERWRITE} https://hydra.iohk.io/job/Cardano/iohk-nix/cardano-deployment/latest-finished/download/1/mainnet-byron-genesis.json curl -sL -o genesis.json ${OVERWRITE} https://hydra.iohk.io/job/Cardano/iohk-nix/cardano-deployment/latest-finished/download/1/mainnet-shelley-genesis.json + [[ -f topology.json ]] && cp topology.json "topology.json_bkp$(date +%s)" curl -sL -o topology.json ${OVERWRITE} https://hydra.iohk.io/job/Cardano/iohk-nix/cardano-deployment/latest-finished/download/1/mainnet-topology.json fi @@ -250,12 +246,13 @@ curl -s -o createAddr.sh https://raw.githubusercontent.com/cardano-community/gui curl -s -o sendADA.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/sendADA.sh curl -s -o balance.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/balance.sh curl -s -o rotatePoolKeys.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/rotatePoolKeys.sh -curl -s -o cnode.sh ${OVERWRITE} https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/cnode.sh.templ +curl -s -o cnode.sh.templ https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/cnode.sh.templ curl -s -o cntools.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/cntools.sh curl -s -o cntools.config https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/cntools.config curl -s -o cntools.library https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/cntools.library curl -s -o cntoolsBlockCollector.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/cntoolsBlockCollector.sh curl -s -o setup_mon.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/setup_mon.sh +[[ -f topologyUpdater.sh ]] && cp topologyUpdater.sh "topologyUpdater.sh_bkp$(date +%s)" curl -s -o topologyUpdater.sh ${OVERWRITE} https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/topologyUpdater.sh curl -s -o itnRewards.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/itnRewards.sh curl -s -o cabal-build-all.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/cabal-build-all.sh @@ -266,5 +263,19 @@ curl -s -o gLiveView.sh https://raw.githubusercontent.com/cardano-community/guil curl -s -o deploy-as-systemd.sh https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/deploy-as-systemd.sh sed -e "s@SyslogIdentifier=.*@SyslogIdentifier=${CNODE_NAME}@g" -e "s@cnode.service@${CNODE_NAME}.service@g" -i deploy-as-systemd.sh sed -e "s@CNODE_HOME=.*@${CNODE_VNAME}_HOME=${CNODE_HOME}@g" -e "s@CNODE_HOME@${CNODE_VNAME}_HOME@g" -i ./*.* + +### Update cnode.sh retaining existing custom configs +if grep '## Static' cnode.sh >/dev/null 2>&1; then + TEMPL_CMD=$(awk '/#!/,/## Static/' cnode.sh.templ) + STATIC_CMD=$(awk '/## Begin/,/## End/' cnode.sh) + printf '%s\n%s\n' "$TEMPL_CMD" "$STATIC_CMD" > cnode.sh +elif grep 'cardano-node' cnode.sh >/dev/null 2>&1;then + cp cnode.sh "cnode.sh.bkp_$(date +%s)" + cp -f cnode.sh.templ cnode.sh + echo "One-time upgrade! Please edit ${CNODE_HOME}/scripts/cnode.sh for values against POOL_NAME and CNODE_PORT variables" +else + cp -f cnode.sh.templ cnode.sh +fi chmod 755 ./*.sh + cd - || return From f13a347dc3693ef9fc6b55d094ca764d96c5b92d Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 14 Sep 2020 12:45:14 +0200 Subject: [PATCH 22/24] Update prereqs.sh (#480) little fix for Debian recognition within prereq --- scripts/cnode-helper-scripts/prereqs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cnode-helper-scripts/prereqs.sh b/scripts/cnode-helper-scripts/prereqs.sh index 404354814..ec8d8e6b3 100755 --- a/scripts/cnode-helper-scripts/prereqs.sh +++ b/scripts/cnode-helper-scripts/prereqs.sh @@ -112,7 +112,7 @@ if [ "$WANT_BUILD_DEPS" = 'Y' ]; then OS_ID=$(grep -i ^id_like= /etc/os-release | cut -d= -f 2) DISTRO=$(grep -i ^NAME= /etc/os-release | cut -d= -f 2) - if [[ "${OS_ID}" =~ ebian ]]; then +if [[ "${OS_ID}" =~ ebian ]] || [[ "${DISTRO}" =~ ebian ]]; then #Debian/Ubuntu echo "Using apt to prepare packages for ${DISTRO} system" echo " Updating system packages..." From d124af964151ffad5c23108d37aa45594fd2f4a0 Mon Sep 17 00:00:00 2001 From: "Ola [AHLNET]" Date: Tue, 15 Sep 2020 10:21:39 +0200 Subject: [PATCH 23/24] Version control and trap improvement (#481) * Version control and trap improvement * SC2086 fix * variable fix * Misc changes - Improve notification on boot for shelley transition epoch calculation failure - Return 0 in helper functions dependent on shelley transition epoch in calculation failed - Add PROTOCOL check to timeUntilNextEpoch and shelley testnet calculation - Return correct number of peers in peer analysis if none are found (previously 1 skipped instead of 0) - Continuously check node mode in case of boot/sync at startup - Retry shelley transition epoch calculation & KES expiration until successful - Change peer count order In<->Out to better match peer analysis section - Correctly calculate KES expiration date based on how many slots are left of current KES period instead of subtracting a full KES period causing date to diff on each start * SC2086 fix * RTT average bug fix in peer analysis * Backup gLiveView.sh before update, change version to rc1, address #482 * Starting/Syncing status + various tweaks * Simplified version handling Co-authored-by: rdlrt <3169068+rdlrt@users.noreply.github.com> --- scripts/cnode-helper-scripts/gLiveView.sh | 161 ++++++++++++++-------- scripts/cnode-helper-scripts/prereqs.sh | 4 +- 2 files changed, 108 insertions(+), 57 deletions(-) diff --git a/scripts/cnode-helper-scripts/gLiveView.sh b/scripts/cnode-helper-scripts/gLiveView.sh index c6e2f6025..899ab8743 100755 --- a/scripts/cnode-helper-scripts/gLiveView.sh +++ b/scripts/cnode-helper-scripts/gLiveView.sh @@ -1,6 +1,8 @@ #!/bin/bash #shellcheck disable=SC2009,SC2034,SC2059,SC2206 +GLV_VERSION=v1.0 + ###################################### # User Variables - Change as desired # # Leave as is if usure # @@ -57,34 +59,24 @@ tput smcup # Save screen tput civis # Disable cursor stty -echo # Disable user input -# Command : myExit [message] -# Description : gracefully handle an exit and restore terminal to original state -myExit() { +# General exit handler +cleanup() { + [[ -n $1 ]] && err=$1 || err=$? tput rmcup # restore screen - [[ -n $2 ]] && echo -e "\n$2\n" - stty echo # Enable user input tput cnorm # restore cursor tput sgr0 # turn off all attributes - exit "$1" + [[ -n ${exit_msg} ]] && echo -e "\n${exit_msg}\n" || echo -e "\nGuild LiveView terminated, cleaning up...\n" + exit $err } +trap cleanup HUP INT TERM +trap 'stty echo' EXIT -# General exit handler -cleanup() { - err=$? - trap '' INT TERM - myExit $err "Guild LiveView terminated, cleaning up..." -} -sig_cleanup() { - trap '' EXIT # some shells will call EXIT after the INT handler - false # sets $? - cleanup +# Command : myExit [exit code] [message] +# Description : gracefully handle an exit and restore terminal to original state +myExit() { + exit_msg="$2" + cleanup "$1" } -trap sig_cleanup INT TERM - -####################################################### -# Automatically grab a few parameters # -# Can be overridden in 'User Variables' section above # -####################################################### usage() { cat </dev/null; then myExit 1 "'tcptraceroute' command missing, please install using latest prereqs.sh script or with your packet manager of choice.\nhttps://command-not-found.com/tcptraceroute can be used to check package name to install." fi +####################################################### +# Version Check # +####################################################### +clear +echo "Guild LiveView version check..." +URL="https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts" +if wget -q -T 10 -O /tmp/gLiveView.sh "${URL}/gLiveView.sh" 2>/dev/null; then + GIT_VERSION=$(grep -r ^GLV_VERSION= /tmp/gLiveView.sh | cut -d'=' -f2) + : "${GIT_VERSION:=v0.0}" + if [[ "${GLV_VERSION}" != "${GIT_VERSION}" ]]; then + echo -e "\nA new version of Guild LiveView is available" + echo "Installed Version : ${GLV_VERSION}" + echo "Available Version : ${GIT_VERSION}" + echo -e "\nPress 'u' to update to latest version, or any other key to continue\n" + read -r -n 1 -s -p "" answer + if [[ "${answer}" = "u" ]]; then + mv "${CNODE_HOME}/scripts/gLiveView.sh" "${CNODE_HOME}/scripts/gLiveView.sh.bkp_$(date +%s)" + cp -f /tmp/gLiveView.sh "${CNODE_HOME}/scripts/gLiveView.sh" + chmod 750 "${CNODE_HOME}/scripts/gLiveView.sh" + myExit 0 "Update applied successfully!\n\nPlease start Guild LiveView again!" + fi + fi +else + echo -e "\nFailed to download gLiveView.sh from GitHub, unable to perform version check!\n" + read -r -n 1 -s -p "press any key to proceed" answer +fi + +####################################################### +# Automatically grab a few parameters # +# Can be overridden in 'User Variables' section above # +####################################################### + # The commands below will try to detect the information assuming you run single node on a machine. # Please override values if they dont match your system in the 'User Variables' section below [[ ${#NODE_NAME} -gt 19 ]] && myExit 1 "Please keep node name at or below 19 characters in length!" @@ -222,7 +246,7 @@ else fi # Title -title="Guild LiveView" +title="Guild LiveView ${GLV_VERSION}" ##################################### # Helper functions # @@ -255,7 +279,7 @@ timeLeft() { printf '%02d:%02d:%02d' $H $M $S } -# Command : getShelleyTransitionEpoch +# Command : getShelleyTransitionEpoch [1 = no user verification] # Description: Calculate shelley transition epoch getShelleyTransitionEpoch() { calc_slot=0 @@ -270,13 +294,18 @@ getShelleyTransitionEpoch() { if [[ "${nwmagic}" = "764824073" ]]; then shelley_transition_epoch=208 elif [[ ${calc_slot} -ne ${slotnum} || ${shelley_epochs} -eq 0 ]]; then - clear - printf "\n ${style_status_3}Failed${NC} to calculate shelley transition epoch!" - printf "\n Calculations might not work correctly until Shelley era is reached." - printf "\n\n ${style_info}Press c to continue or any other key to quit${NC}" - read -r -n 1 -s -p "" answer - [[ "${answer}" != "c" ]] && myExit 1 "Guild LiveView terminated!" - shelley_transition_epoch=0 + if [[ $1 -ne 1 ]]; then + clear + printf "\n ${style_status_3}Failed${NC} to get shelley transition epoch, calculations will not work correctly!" + printf "\n\n Possible causes:" + printf "\n - Node in startup mode" + printf "\n - Shelley era not reached" + printf "\n After successful node boot or when sync to shelley era has been reached, calculations will be correct" + printf "\n\n ${style_info}Press c to continue or any other key to quit${NC}" + read -r -n 1 -s -p "" answer + [[ "${answer}" != "c" ]] && myExit 1 "Guild LiveView terminated!" + fi + shelley_transition_epoch=-1 else shelley_transition_epoch=${byron_epochs} fi @@ -287,6 +316,7 @@ getShelleyTransitionEpoch() { getEpoch() { current_time_sec=$(date -u +%s) if [[ "${PROTOCOL}" = "Cardano" ]]; then + [[ shelley_transition_epoch -eq -1 ]] && echo 0 && return byron_end_time=$(( byron_genesis_start_sec + ( shelley_transition_epoch * byron_epoch_length * byron_slot_length ) )) echo $(( shelley_transition_epoch + ( (current_time_sec - byron_end_time) / slot_length / epoch_length ) )) else @@ -297,7 +327,13 @@ getEpoch() { # Command : getTimeUntilNextEpoch # Description: Offline calculation of time in seconds until next epoch timeUntilNextEpoch() { - echo $(( (shelley_transition_epoch * byron_slot_length * byron_epoch_length) + ( ( $(getEpoch) + 1 - shelley_transition_epoch ) * slot_length * epoch_length ) - $(date -u +%s) + byron_genesis_start_sec )) + current_time_sec=$(date -u +%s) + if [[ "${PROTOCOL}" = "Cardano" ]]; then + [[ shelley_transition_epoch -eq -1 ]] && echo 0 && return + echo $(( (shelley_transition_epoch * byron_slot_length * byron_epoch_length) + ( ( $(getEpoch) + 1 - shelley_transition_epoch ) * slot_length * epoch_length ) - current_time_sec + byron_genesis_start_sec )) + else + echo $(( ( ( ( (current_time_sec - shelley_genesis_start_sec) / slot_length / epoch_length ) + 1 ) * slot_length * epoch_length ) - current_time_sec + shelley_genesis_start_sec )) + fi } # Command : getSlotTipRef @@ -305,6 +341,7 @@ timeUntilNextEpoch() { getSlotTipRef() { current_time_sec=$(date -u +%s) if [[ "${PROTOCOL}" = "Cardano" ]]; then + [[ shelley_transition_epoch -eq -1 ]] && echo 0 && return # Combinator network byron_slots=$(( shelley_transition_epoch * byron_epoch_length )) # since this point will only be reached once we're in Shelley phase byron_end_time=$(( byron_genesis_start_sec + ( shelley_transition_epoch * byron_epoch_length * byron_slot_length ) )) @@ -325,7 +362,8 @@ getSlotTipRef() { # Description: Calculate KES expiration kesExpiration() { current_time_sec=$(date -u +%s) - expiration_time_sec=$(( current_time_sec - ( slot_length * slots_per_kes_period ) + ( slot_length * slots_per_kes_period * remaining_kes_periods ) )) + tip_ref=$(getSlotTipRef) + expiration_time_sec=$(( current_time_sec - ( slot_length * (tip_ref % slots_per_kes_period) ) + ( slot_length * slots_per_kes_period * remaining_kes_periods ) )) kes_expiration=$(date '+%F %T Z' --date=@${expiration_time_sec}) } @@ -354,8 +392,10 @@ checkPeers() { else netstatPeers=$(ss -tnp state established 2>/dev/null | grep "${pid}," | awk -v port=":${CNODE_PORT}" '$3 ~ port {print $4}') fi + [[ -z ${netstatPeers} ]] && return + netstatSorted=$(printf '%s\n' "${netstatPeers[@]}" | sort ) - peerCNTABS=$(printf '%s\n' "${netstatPeers[@]}" | wc -l) + peerCNTABS=$(wc -w <<< "${netstatPeers}") # Sort/filter peers lastpeerIP=""; lastpeerPORT="" @@ -429,12 +469,10 @@ check_peers="false" show_peers="false" line_end=0 data=$(curl -s -H 'Accept: application/json' "http://${EKG_HOST}:${EKG_PORT}/" 2>/dev/null) -about_to_lead=$(jq '.cardano.node.metrics.Forge["forge-about-to-lead"].int.val //0' <<< "${data}") epochnum=$(jq '.cardano.node.ChainDB.metrics.epoch.int.val //0' <<< "${data}") slot_in_epoch=$(jq '.cardano.node.ChainDB.metrics.slotInEpoch.int.val //0' <<< "${data}") slotnum=$(jq '.cardano.node.ChainDB.metrics.slotNum.int.val //0' <<< "${data}") remaining_kes_periods=$(jq '.cardano.node.Forge.metrics.remainingKESPeriods.int.val //0' <<< "${data}") -[[ ${about_to_lead} -gt 0 ]] && nodemode="Core" || nodemode="Relay" ##################################### # Static genesis variables # @@ -459,11 +497,11 @@ if [[ "${PROTOCOL}" = "Cardano" ]]; then byron_epoch_length=$(( 10 * byron_k )) getShelleyTransitionEpoch else - shelley_transition_epoch=-1 + shelley_transition_epoch=-2 fi ##################################### slot_interval=$(echo "(${slot_length} / ${active_slots_coeff} / ${decentralisation}) + 0.5" | bc -l | awk '{printf "%.0f\n", $1}') -kesExpiration # Static and wont change until KES rotation and node restart +kesExpiration ##################################### clear @@ -529,6 +567,13 @@ while true; do forged=$(jq '.cardano.node.metrics.Forge.forged.int.val //0' <<< "${data}") adopted=$(jq '.cardano.node.metrics.Forge.adopted.int.val //0' <<< "${data}") didntadopt=$(jq '.cardano.node.metrics.Forge["didnt-adopt"].int.val //0' <<< "${data}") + about_to_lead=$(jq '.cardano.node.metrics.Forge["forge-about-to-lead"].int.val //0' <<< "${data}") + + [[ ${about_to_lead} -gt 0 ]] && nodemode="Core" || nodemode="Relay" + if [[ "${PROTOCOL}" = "Cardano" && ${shelley_transition_epoch} -eq -1 ]]; then # if Shelley transition epoch calc failed during start, try until successful + getShelleyTransitionEpoch 1 + kesExpiration + fi header_length=$(( ${#NODE_NAME} + ${#nodemode} + ${#node_version} + ${#node_rev} + 16 )) [[ ${header_length} -gt ${width} ]] && header_padding=0 || header_padding=$(( (width - header_length) / 2 )) @@ -552,7 +597,7 @@ while true; do printf "${LVL}\n" ((line++)) - if [[ ${shelley_transition_epoch} = -1 || ${epochnum} -ge ${shelley_transition_epoch} ]]; then + if [[ ${shelley_transition_epoch} -eq -2 ]] || [[ ${shelley_transition_epoch} -ne -1 && ${epochnum} -ge ${shelley_transition_epoch} ]]; then epoch_progress=$(echo "(${slot_in_epoch}/${epoch_length})*100" | bc -l) # in Shelley era or Shelley only TestNet else epoch_progress=$(echo "(${slot_in_epoch}/${byron_epoch_length})*100" | bc -l) # in Byron era @@ -583,12 +628,16 @@ while true; do endLine $((line++)) printf "${VL} Density : ${style_values_1}%s${NC}%%" "${density}" tput cup ${line} ${second_col} - if [[ ${tip_diff} -le $(( slot_interval * 2 )) ]]; then - printf "Tip (diff) : ${style_status_1}%s${NC}" "-${tip_diff} :)" + if [[ ${slotnum} -eq 0 ]]; then + printf "Status : ${style_info}starting...${NC}" + elif [[ "${PROTOCOL}" = "Cardano" && ${shelley_transition_epoch} -eq -1 ]]; then + printf "Status : ${style_info}syncing...${NC}" + elif [[ ${tip_diff} -le $(( slot_interval * 2 )) ]]; then + printf "Tip (diff) : ${style_status_1}%s${NC}" "${tip_diff} :)" elif [[ ${tip_diff} -le $(( slot_interval * 3 )) ]]; then - printf "Tip (diff) : ${style_status_2}%s${NC}" "-${tip_diff} :|" + printf "Tip (diff) : ${style_status_2}%s${NC}" "${tip_diff} :|" else - printf "Tip (diff) : ${style_status_3}%s${NC}" "-${tip_diff} :(" + printf "Tip (diff) : ${style_status_3}%s${NC}" "${tip_diff} :(" fi endLine $((line++)) @@ -597,11 +646,11 @@ while true; do printf "${VL} Processed TX : ${style_values_1}%s${NC}" "${tx_processed}" tput cup ${line} $((second_col+7)) - printf " In / Out" + printf " Out / In" endLine $((line++)) printf "${VL} Mempool TX/Bytes : ${style_values_1}%s${NC} / ${style_values_1}%s${NC}" "${mempool_tx}" "${mempool_bytes}" tput el; tput cup ${line} $((second_col+7)) - printf "Peers : ${style_values_1}%s${NC} / ${style_values_1}%s${NC}" "${peers_in}" "${peers_out}" + printf "Peers : ${style_values_1}%s${NC} / ${style_values_1}%s${NC}" "${peers_out}" "${peers_in}" endLine $((line++)) ## Core section ## @@ -682,7 +731,7 @@ while true; do peerCNT0_out=${peerCNT0}; peerCNT1_out=${peerCNT1}; peerCNT2_out=${peerCNT2}; peerCNT3_out=${peerCNT3}; peerCNT4_out=${peerCNT4} peerPCT1_out=${peerPCT1}; peerPCT2_out=${peerPCT2}; peerPCT3_out=${peerPCT3}; peerPCT4_out=${peerPCT4} peerPCT1items_out=${peerPCT1items}; peerPCT2items_out=${peerPCT2items}; peerPCT3items_out=${peerPCT3items}; peerPCT4items_out=${peerPCT4items} - peerRTT_out=${peerRTT}; peerRTTAVG_out=${peerRTTAVG}; peerCNTUnique_out=${peerCNTUnique}; peerCNTSKIPPED_out=${peerCNTSKIPPED} + peerRTTAVG_out=${peerRTTAVG}; peerCNTUnique_out=${peerCNTUnique}; peerCNTSKIPPED_out=${peerCNTSKIPPED} time_out=$(date -u '+%T Z') fi @@ -726,10 +775,11 @@ while true; do done printf "${NC}" endLine $((line++)) - if [[ ${peerRTT_out} -ge 200 ]]; then printf "${VL} Average : ${style_status_4}%s${NC} ms" "${peerRTTAVG_out}" - elif [[ ${peerRTT_out} -ge 100 ]]; then printf "${VL} Average : ${style_status_3}%s${NC} ms" "${peerRTTAVG_out}" - elif [[ ${peerRTT_out} -ge 50 ]]; then printf "${VL} Average : ${style_status_2}%s${NC} ms" "${peerRTTAVG_out}" - elif [[ ${peerRTT_out} -ge 0 ]]; then printf "${VL} Average : ${style_status_1}%s${NC} ms" "${peerRTTAVG_out}"; fi + if [[ ${peerRTTAVG_out} -ge 200 ]]; then printf "${VL} Average : ${style_status_4}%s${NC} ms" "${peerRTTAVG_out}" + elif [[ ${peerRTTAVG_out} -ge 100 ]]; then printf "${VL} Average : ${style_status_3}%s${NC} ms" "${peerRTTAVG_out}" + elif [[ ${peerRTTAVG_out} -ge 50 ]]; then printf "${VL} Average : ${style_status_2}%s${NC} ms" "${peerRTTAVG_out}" + elif [[ ${peerRTTAVG_out} -ge 0 ]]; then printf "${VL} Average : ${style_status_1}%s${NC} ms" "${peerRTTAVG_out}" + else printf "${VL} Average : - ms"; fi endLine $((line++)) echo "${m3divider}" @@ -752,7 +802,7 @@ while true; do peerCNT0_in=${peerCNT0}; peerCNT1_in=${peerCNT1}; peerCNT2_in=${peerCNT2}; peerCNT3_in=${peerCNT3}; peerCNT4_in=${peerCNT4} peerPCT1_in=${peerPCT1}; peerPCT2_in=${peerPCT2}; peerPCT3_in=${peerPCT3}; peerPCT4_in=${peerPCT4} peerPCT1items_in=${peerPCT1items}; peerPCT2items_in=${peerPCT2items}; peerPCT3items_in=${peerPCT3items}; peerPCT4items_in=${peerPCT4items} - peerRTT_in=${peerRTT}; peerRTTAVG_in=${peerRTTAVG}; peerCNTUnique_in=${peerCNTUnique}; peerCNTSKIPPED_in=${peerCNTSKIPPED} + peerRTTAVG_in=${peerRTTAVG}; peerCNTUnique_in=${peerCNTUnique}; peerCNTSKIPPED_in=${peerCNTSKIPPED} time_in=$(date -u '+%T Z') fi @@ -794,10 +844,11 @@ while true; do done printf "${NC}" endLine $((line++)) - if [[ ${peerRTT_in} -ge 200 ]]; then printf "${VL} Average : ${style_status_4}%s${NC} ms" "${peerRTTAVG_in}" - elif [[ ${peerRTT_in} -ge 100 ]]; then printf "${VL} Average : ${style_status_3}%s${NC} ms" "${peerRTTAVG_in}" - elif [[ ${peerRTT_in} -ge 50 ]]; then printf "${VL} Average : ${style_status_2}%s${NC} ms" "${peerRTTAVG_in}" - elif [[ ${peerRTT_in} -ge 0 ]]; then printf "${VL} Average : ${style_status_1}%s${NC} ms" "${peerRTTAVG_in}"; fi + if [[ ${peerRTTAVG_in} -ge 200 ]]; then printf "${VL} Average : ${style_status_4}%s${NC} ms" "${peerRTTAVG_in}" + elif [[ ${peerRTTAVG_in} -ge 100 ]]; then printf "${VL} Average : ${style_status_3}%s${NC} ms" "${peerRTTAVG_in}" + elif [[ ${peerRTTAVG_in} -ge 50 ]]; then printf "${VL} Average : ${style_status_2}%s${NC} ms" "${peerRTTAVG_in}" + elif [[ ${peerRTTAVG_in} -ge 0 ]]; then printf "${VL} Average : ${style_status_1}%s${NC} ms" "${peerRTTAVG_in}" + else printf "${VL} Average : - ms"; fi endLine $((line++)) echo "${m3divider}" diff --git a/scripts/cnode-helper-scripts/prereqs.sh b/scripts/cnode-helper-scripts/prereqs.sh index ec8d8e6b3..87a079ac4 100755 --- a/scripts/cnode-helper-scripts/prereqs.sh +++ b/scripts/cnode-helper-scripts/prereqs.sh @@ -135,11 +135,11 @@ if [[ "${OS_ID}" =~ ebian ]] || [[ "${DISTRO}" =~ ebian ]]; then $sudo yum -y update > /dev/null echo " Installing missing prerequisite packages, if any.." pkg_list="python3 coreutils pkgconfig libffi-devel gmp-devel openssl-devel ncurses-libs ncurses-compat-libs systemd systemd-devel libsodium-devel zlib-devel make gcc-c++ tmux git wget jq gnupg libtool autoconf srm iproute bc tcptraceroute" - [[ ! "${DISTRO}" =~ Fedora ]] && pkg_list="epel-release $pkg_list" + [[ ! "${DISTRO}" =~ Fedora ]] && sudo yum -y install epel-release > /dev/null $sudo yum -y install ${pkg_list} > /dev/null;rc=$? if [ $rc != 0 ]; then echo "An error occurred while installing the prerequisite packages, please investigate by using the command below:" - echo "sudo yum -y ${pkg_list}" + echo "sudo yum -y install ${pkg_list}" echo "It would be best if you could submit an issue at https://github.com/cardano-community/guild-operators with the details to tackle in future, as some errors may be due to external/already present dependencies" exit; fi From 27027dbd17b9f91e2f722bd734bc755bbfbbb1f1 Mon Sep 17 00:00:00 2001 From: Priyank <3169068+rdlrt@users.noreply.github.com> Date: Fri, 18 Sep 2020 11:36:30 +1000 Subject: [PATCH 24/24] [gLiveView] - Add Network field; closes #483 (#487) * Add Network field to title bar; closes #483 * Redesign peer Analysis * Peer list - as a seperate screen * Alignment changes to make use of width parameter * Use ss instead of relying on BlockFetchDecision Co-authored-by: Ola --- scripts/cnode-helper-scripts/gLiveView.sh | 686 +++++++++++----------- 1 file changed, 359 insertions(+), 327 deletions(-) diff --git a/scripts/cnode-helper-scripts/gLiveView.sh b/scripts/cnode-helper-scripts/gLiveView.sh index 899ab8743..4929b2305 100755 --- a/scripts/cnode-helper-scripts/gLiveView.sh +++ b/scripts/cnode-helper-scripts/gLiveView.sh @@ -1,7 +1,7 @@ #!/bin/bash -#shellcheck disable=SC2009,SC2034,SC2059,SC2206 +#shellcheck disable=SC2009,SC2034,SC2059,SC2206,SC2086,SC2015 -GLV_VERSION=v1.0 +GLV_VERSION=v1.1 ###################################### # User Variables - Change as desired # @@ -180,8 +180,8 @@ fi [[ -z ${BLOCK_LOG_DIR} && -d "${CNODE_HOME}/db/blocks" ]] && BLOCK_LOG_DIR="${CNODE_HOME}/db/blocks" # optional # Style -width=53 -second_col=28 +width=63 +second_col=$((width/2 + 3)) FG_BLACK=$(tput setaf 0) FG_RED=$(tput setaf 1) FG_GREEN=$(tput setaf 2) @@ -204,10 +204,8 @@ else char_marked=$(printf "\\u258C") char_unmarked=$(printf "\\u2596") fi -granularity=50 -granularity_small=25 -step_size=$((100/granularity)) -step_size_small=$((100/granularity_small)) +granularity=$((width-3)) +granularity_small=$((granularity/2)) bar_col_small=$((width - granularity_small)) # Lines @@ -258,8 +256,8 @@ waitForInput() { ESC=$(printf "\033") if ! read -rsn1 -t ${REFRESH_RATE} key1; then return; fi [[ ${key1} = "${ESC}" ]] && read -rsn2 -t 0.3 key2 # read 2 more chars - [[ ${key1} = "p" ]] && check_peers="true" && show_peers="true" && return - [[ ${key1} = "h" ]] && show_peers="hide" && return + [[ ${key1} = "p" && ${show_peers} = "false" ]] && check_peers="true" && clear && return + [[ ${key1} = "h" && ${show_peers} = "true" ]] && show_peers="false" && clear && return [[ ${key1} = "q" ]] && myExit 0 "Guild LiveView stopped!" [[ ${key1} = "${ESC}" && ${key2} = "" ]] && myExit 0 "Guild LiveView stopped!" sleep 1 @@ -384,7 +382,7 @@ checkPeers() { peerPCT1=0; peerPCT2=0; peerPCT3=0; peerPCT4=0 peerPCT1items=0; peerPCT2items=0; peerPCT3items=0; peerPCT4items=0 peerRTTSUM=0; peerCNTSKIPPED=0; peerCNTUnique=0; peerCNTABS=0; peerRTTAVG=0 - uniquePeers=() + uniquePeers=(); rttResults=(); rttResultsSorted="" direction=$1 if [[ ${direction} = "out" ]]; then @@ -420,7 +418,7 @@ checkPeers() { ((peerCNT++)) peerRTTSUM=$((peerRTTSUM + peerRTT)) elif [[ ${direction} = "in" ]]; then # No need to continue with tcptraceroute for incoming connection as destination port is unknown - peerRTT=-1 + peerRTT=99999 else # Normal ping is not working, try tcptraceroute to the given port checkPEER=$(tcptraceroute -n -S -f 255 -m 255 -q 1 -w 1 "${peerIP}" "${peerPORT}" 2>&1 | tail -n 1) if [[ ${checkPEER} = *'[open]'* ]]; then @@ -428,17 +426,19 @@ checkPeers() { ((peerCNT++)) peerRTTSUM=$((peerRTTSUM + peerRTT)) else # Nope, no response - peerRTT=-1 + peerRTT=99999 fi fi # Update counters - if [[ ${peerRTT} -ge 200 ]]; then ((peerCNT4++)) - elif [[ ${peerRTT} -ge 100 ]]; then ((peerCNT3++)) - elif [[ ${peerRTT} -ge 50 ]]; then ((peerCNT2++)) - elif [[ ${peerRTT} -ge 0 ]]; then ((peerCNT1++)) + if [[ ${peerRTT} -lt 50 ]]; then ((peerCNT1++)) + elif [[ ${peerRTT} -lt 100 ]]; then ((peerCNT2++)) + elif [[ ${peerRTT} -lt 200 ]]; then ((peerCNT3++)) + elif [[ ${peerRTT} -lt 99999 ]]; then ((peerCNT4++)) else ((peerCNT0++)); fi + rttResults+=("${peerRTT}:${peerIP}:${peerPORT} ") done + rttResultsSorted=$(printf '%s\n' "${rttResults[@]}" | sort -n) if [[ ${peerCNT} -gt 0 ]]; then peerRTTAVG=$((peerRTTSUM / peerCNT)) fi @@ -447,13 +447,13 @@ checkPeers() { peerMAX=0 if [[ ${peerCNT} -gt 0 ]]; then peerPCT1=$(echo "scale=4;(${peerCNT1}/${peerCNT})*100" | bc -l) - peerPCT1items=$(printf %.0f "$(echo "scale=4;${peerPCT1}/${step_size_small}" | bc -l)") + peerPCT1items=$(printf %.0f "$(echo "scale=4;${peerPCT1}*${granularity_small}/100" | bc -l)") peerPCT2=$(echo "scale=4;(${peerCNT2}/${peerCNT})*100" | bc -l) - peerPCT2items=$(printf %.0f "$(echo "scale=4;${peerPCT2}/${step_size_small}" | bc -l)") + peerPCT2items=$(printf %.0f "$(echo "scale=4;${peerPCT2}*${granularity_small}/100" | bc -l)") peerPCT3=$(echo "scale=4;(${peerCNT3}/${peerCNT})*100" | bc -l) - peerPCT3items=$(printf %.0f "$(echo "scale=4;${peerPCT3}/${step_size_small}" | bc -l)") + peerPCT3items=$(printf %.0f "$(echo "scale=4;${peerPCT3}*${granularity_small}/100" | bc -l)") peerPCT4=$(echo "scale=4;(${peerCNT4}/${peerCNT})*100" | bc -l) - peerPCT4items=$(printf %.0f "$(echo "scale=4;${peerPCT4}/${step_size_small}" | bc -l)") + peerPCT4items=$(printf %.0f "$(echo "scale=4;${peerPCT4}*${granularity_small}/100" | bc -l)") fi } @@ -467,7 +467,6 @@ pid=$(ps -ef | grep "[-]-port ${CNODE_PORT}" | awk '{print $2}') [[ -z ${pid} ]] && myExit 1 "Failed to locate cardano-node process ID, make sure CNODE_PORT is correctly set in script!" check_peers="false" show_peers="false" -line_end=0 data=$(curl -s -H 'Accept: application/json' "http://${EKG_HOST}:${EKG_PORT}/" 2>/dev/null) epochnum=$(jq '.cardano.node.ChainDB.metrics.epoch.int.val //0' <<< "${data}") slot_in_epoch=$(jq '.cardano.node.ChainDB.metrics.slotInEpoch.int.val //0' <<< "${data}") @@ -482,6 +481,7 @@ shelley_genesis_file=$(jq -r .ShelleyGenesisFile "${CONFIG}") byron_genesis_file=$(jq -r .ByronGenesisFile "${CONFIG}") [[ ! ${byron_genesis_file} =~ ^/ ]] && byron_genesis_file="$(dirname "${CONFIG}")/${byron_genesis_file}" nwmagic=$(jq -r .networkMagic < "${shelley_genesis_file}") +[[ "${nwmagic}" == "764824073" ]] && NWNAME="Mainnet" || { [[ "${nwmagic}" = "1097911063" ]] && NWNAME="Testnet" || NWNAME="Custom"; } shelley_genesis_start=$(jq -r .systemStart "${shelley_genesis_file}") shelley_genesis_start_sec=$(date --date="${shelley_genesis_start}" +%s) epoch_length=$(jq -r .epochLength "${shelley_genesis_file}") @@ -513,371 +513,403 @@ printf "${NC}" # reset and set default color # MAIN LOOP # ##################################### while true; do - [[ ${tlines} -ne $(tput lines) || ${tcols} -ne $(tput cols) ]] && redraw_peers=true || redraw_peers=false tlines=$(tput lines) # update terminal lines tcols=$(tput cols) # update terminal columns - [[ ${width} -ge $((tcols-1)) || ${line_end} -ge $((tlines-1)) ]] && clear - while [[ ${width} -ge $((tcols-1)) ]]; do + [[ ${width} -ge $((tcols)) || ${line} -ge $((tlines)) ]] && clear + while [[ ${width} -ge $((tcols)) ]]; do tput cup 1 1 printf "${style_status_3}Terminal width too small!${NC}" tput cup 3 1 - printf "Please increase by ${style_info}$(( width - tcols + 2 ))${NC} columns" + printf "Please increase by ${style_info}$(( width - tcols + 1 ))${NC} columns" tput cup 5 1 - printf "${style_info}Use CTRL + C to force quit${NC}" - sleep 2 + printf "${style_info}[esc/q] Quit${NC}" + waitForInput tlines=$(tput lines) # update terminal lines tcols=$(tput cols) # update terminal columns - redraw_peers=true done - while [[ ${line_end} -ge $((tlines-1)) ]]; do + while [[ ${line} -ge $((tlines)) ]]; do tput cup 1 1 printf "${style_status_3}Terminal height too small!${NC}" tput cup 3 1 - printf "Please increase by ${style_info}$(( line_end - tlines + 2 ))${NC} lines" + printf "Please increase by ${style_info}$(( line - tlines + 1 ))${NC} lines" tput cup 5 1 - printf "${style_info}Use CTRL + C to force quit${NC}" - sleep 2 + printf "${style_info}[esc/q] Quit${NC}" + waitForInput tlines=$(tput lines) # update terminal lines tcols=$(tput cols) # update terminal columns - redraw_peers=true done line=0; tput cup 0 0 # reset position - # Gather some data - data=$(curl -s -H 'Accept: application/json' "http://${EKG_HOST}:${EKG_PORT}/" 2>/dev/null) - uptimens=$(jq '.cardano.node.metrics.upTime.ns.val //0' <<< "${data}") - if ((uptimens<=0)); then - myExit 1 "${style_status_3}COULD NOT CONNECT TO A RUNNING INSTANCE!${NC}" - fi - peers_in=$(ss -tnp state established 2>/dev/null | grep "${pid}," | awk -v port=":${CNODE_PORT}" '$3 ~ port {print}' | wc -l) - peers_out=$(jq '.cardano.node.BlockFetchDecision.peers.connectedPeers.int.val //0' <<< "${data}") - blocknum=$(jq '.cardano.node.ChainDB.metrics.blockNum.int.val //0' <<< "${data}") - epochnum=$(jq '.cardano.node.ChainDB.metrics.epoch.int.val //0' <<< "${data}") - slot_in_epoch=$(jq '.cardano.node.ChainDB.metrics.slotInEpoch.int.val //0' <<< "${data}") - slotnum=$(jq '.cardano.node.ChainDB.metrics.slotNum.int.val //0' <<< "${data}") - density=$(jq -r '.cardano.node.ChainDB.metrics.density.real.val //0' <<< "${data}") - density=$(printf "%3.3e" "${density}"| cut -d 'e' -f1) - tx_processed=$(jq '.cardano.node.metrics.txsProcessedNum.int.val //0' <<< "${data}") - mempool_tx=$(jq '.cardano.node.metrics.txsInMempool.int.val //0' <<< "${data}") - mempool_bytes=$(jq '.cardano.node.metrics.mempoolBytes.int.val //0' <<< "${data}") - kesperiod=$(jq '.cardano.node.Forge.metrics.currentKESPeriod.int.val //0' <<< "${data}") - remaining_kes_periods=$(jq '.cardano.node.Forge.metrics.remainingKESPeriods.int.val //0' <<< "${data}") - isleader=$(jq '.cardano.node.metrics.Forge["node-is-leader"].int.val //0' <<< "${data}") - forged=$(jq '.cardano.node.metrics.Forge.forged.int.val //0' <<< "${data}") - adopted=$(jq '.cardano.node.metrics.Forge.adopted.int.val //0' <<< "${data}") - didntadopt=$(jq '.cardano.node.metrics.Forge["didnt-adopt"].int.val //0' <<< "${data}") - about_to_lead=$(jq '.cardano.node.metrics.Forge["forge-about-to-lead"].int.val //0' <<< "${data}") - - [[ ${about_to_lead} -gt 0 ]] && nodemode="Core" || nodemode="Relay" - if [[ "${PROTOCOL}" = "Cardano" && ${shelley_transition_epoch} -eq -1 ]]; then # if Shelley transition epoch calc failed during start, try until successful - getShelleyTransitionEpoch 1 - kesExpiration + if [[ ${show_peers} = "false" ]]; then + # Gather some data + data=$(curl -s -H 'Accept: application/json' "http://${EKG_HOST}:${EKG_PORT}/" 2>/dev/null) + uptimens=$(jq '.cardano.node.metrics.upTime.ns.val //0' <<< "${data}") + if ((uptimens<=0)); then + myExit 1 "${style_status_3}COULD NOT CONNECT TO A RUNNING INSTANCE!${NC}" + fi + peers_in=$(ss -tnp state established 2>/dev/null | grep "${pid}," | awk -v port=":${CNODE_PORT}" '$3 ~ port {print}' | wc -l) + peers_out=$(ss -tnp state established 2>/dev/null | grep "${pid}," | awk -v port=":${CNODE_PORT}" '$3 !~ port {print}' | wc -l) + blocknum=$(jq '.cardano.node.ChainDB.metrics.blockNum.int.val //0' <<< "${data}") + epochnum=$(jq '.cardano.node.ChainDB.metrics.epoch.int.val //0' <<< "${data}") + slot_in_epoch=$(jq '.cardano.node.ChainDB.metrics.slotInEpoch.int.val //0' <<< "${data}") + slotnum=$(jq '.cardano.node.ChainDB.metrics.slotNum.int.val //0' <<< "${data}") + density=$(jq -r '.cardano.node.ChainDB.metrics.density.real.val //0' <<< "${data}") + density=$(printf "%3.3e" "${density}"| cut -d 'e' -f1) + tx_processed=$(jq '.cardano.node.metrics.txsProcessedNum.int.val //0' <<< "${data}") + mempool_tx=$(jq '.cardano.node.metrics.txsInMempool.int.val //0' <<< "${data}") + mempool_bytes=$(jq '.cardano.node.metrics.mempoolBytes.int.val //0' <<< "${data}") + kesperiod=$(jq '.cardano.node.Forge.metrics.currentKESPeriod.int.val //0' <<< "${data}") + remaining_kes_periods=$(jq '.cardano.node.Forge.metrics.remainingKESPeriods.int.val //0' <<< "${data}") + isleader=$(jq '.cardano.node.metrics.Forge["node-is-leader"].int.val //0' <<< "${data}") + forged=$(jq '.cardano.node.metrics.Forge.forged.int.val //0' <<< "${data}") + adopted=$(jq '.cardano.node.metrics.Forge.adopted.int.val //0' <<< "${data}") + didntadopt=$(jq '.cardano.node.metrics.Forge["didnt-adopt"].int.val //0' <<< "${data}") + about_to_lead=$(jq '.cardano.node.metrics.Forge["forge-about-to-lead"].int.val //0' <<< "${data}") + [[ ${about_to_lead} -gt 0 ]] && nodemode="Core" || nodemode="Relay" + if [[ "${PROTOCOL}" = "Cardano" && ${shelley_transition_epoch} -eq -1 ]]; then # if Shelley transition epoch calc failed during start, try until successful + getShelleyTransitionEpoch 1 + kesExpiration + fi fi - header_length=$(( ${#NODE_NAME} + ${#nodemode} + ${#node_version} + ${#node_rev} + 16 )) + header_length=$(( ${#NODE_NAME} + ${#nodemode} + ${#node_version} + ${#node_rev} + ${#NWNAME} + 20 )) [[ ${header_length} -gt ${width} ]] && header_padding=0 || header_padding=$(( (width - header_length) / 2 )) - printf "%${header_padding}s >> ${style_values_2}%s${NC} - ${style_info}%s${NC} : ${style_values_1}%s${NC} [${style_values_1}%s${NC}] <<\n" "" "${NODE_NAME}" "${nodemode}" "${node_version}" "${node_rev}" + printf "%${header_padding}s > ${style_values_2}%s${NC} - ${style_info}(%s - %s)${NC} : ${style_values_1}%s${NC} [${style_values_1}%s${NC}] < \n" "" "${NODE_NAME}" "${nodemode}" "${NWNAME}" "${node_version}" "${node_rev}" ((line++)) ## Base section ## printf "${tdivider}" - tput cup ${line} $(( width - ${#title} - 3 )) - printf "${DHL}" + if [[ ${show_peers} = "false" && ${check_peers} = "false" ]]; then + tput cup ${line} $(( width - ${#title} - 3 )) + printf "${DHL}" + fi tput cup $((++line)) 0 - printf "${VL} Uptime: $(timeLeft $(( uptimens/1000000000 )))" - tput cup ${line} $(( width - ${#title} - 3 )) - printf "${VL} ${style_title}${title} ${VL}\n" - ((line++)) - printf "${m2divider}" - tput cup ${line} $(( width - ${#title} - 3 )) - printf "${UR}" - printf "%0.s${HL}" $(seq $(( ${#title} + 2 ))) - printf "${LVL}\n" - ((line++)) + if [[ ${check_peers} = "true" ]]; then + tput ed + printf "${VL} ${style_info}Output peer analysis started... please wait!${NC}" + endLine ${line} + echo "${bdivider}" + checkPeers out + # Save values + peerCNT0_out=${peerCNT0}; peerCNT1_out=${peerCNT1}; peerCNT2_out=${peerCNT2}; peerCNT3_out=${peerCNT3}; peerCNT4_out=${peerCNT4} + peerPCT1_out=${peerPCT1}; peerPCT2_out=${peerPCT2}; peerPCT3_out=${peerPCT3}; peerPCT4_out=${peerPCT4} + peerPCT1items_out=${peerPCT1items}; peerPCT2items_out=${peerPCT2items}; peerPCT3items_out=${peerPCT3items}; peerPCT4items_out=${peerPCT4items} + peerRTTAVG_out=${peerRTTAVG}; peerCNTUnique_out=${peerCNTUnique}; peerCNTSKIPPED_out=${peerCNTSKIPPED}; rttResultsSorted_out=${rttResultsSorted} + time_out=$(date -u '+%T Z') + tput cup ${line} 0 + tput ed + printf "${VL} ${style_info}Output peer analysis done!${NC}" + endLine $((line++)) + + echo "${m2divider}" + ((line++)) + + printf "${VL} ${style_info}Input peer analysis started... please wait!${NC}" + endLine $((line++)) + echo "${bdivider}" + ((line++)) + checkPeers in + # Save values + peerCNT0_in=${peerCNT0}; peerCNT1_in=${peerCNT1}; peerCNT2_in=${peerCNT2}; peerCNT3_in=${peerCNT3}; peerCNT4_in=${peerCNT4} + peerPCT1_in=${peerPCT1}; peerPCT2_in=${peerPCT2}; peerPCT3_in=${peerPCT3}; peerPCT4_in=${peerPCT4} + peerPCT1items_in=${peerPCT1items}; peerPCT2items_in=${peerPCT2items}; peerPCT3items_in=${peerPCT3items}; peerPCT4items_in=${peerPCT4items} + peerRTTAVG_in=${peerRTTAVG}; peerCNTUnique_in=${peerCNTUnique}; peerCNTSKIPPED_in=${peerCNTSKIPPED}; rttResultsSorted_in=${rttResultsSorted} + time_in=$(date -u '+%T Z') + elif [[ ${show_peers} = "true" ]]; then + printf "${VL}${STANDOUT} OUT ${NC} RTT : Peers / Percent" + tput cup ${line} $(( width - 20 )) + printf "Updated: ${style_info}%s${NC} ${VL}\n" "${time_out}" + ((line++)) - if [[ ${shelley_transition_epoch} -eq -2 ]] || [[ ${shelley_transition_epoch} -ne -1 && ${epochnum} -ge ${shelley_transition_epoch} ]]; then - epoch_progress=$(echo "(${slot_in_epoch}/${epoch_length})*100" | bc -l) # in Shelley era or Shelley only TestNet - else - epoch_progress=$(echo "(${slot_in_epoch}/${byron_epoch_length})*100" | bc -l) # in Byron era - fi - printf "${VL} Epoch ${style_values_1}%s${NC} [${style_values_1}%2.1f%%${NC}] (node)" "${epochnum}" "${epoch_progress}" - endLine $((line++)) - printf "${VL} ${style_values_1}%s${NC} until epoch boundary (chain)" "$(timeLeft "$(timeUntilNextEpoch)")" - endLine $((line++)) - - epoch_items=$(( $(printf %.0f "${epoch_progress}") / step_size )) - printf "${VL} ${style_values_1}" - for i in $(seq 0 $((granularity-1))); do - [[ $i -lt ${epoch_items} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" - done - printf "${NC} ${VL}\n"; ((line++)) - - printf "${VL}"; tput cup $((line++)) ${width}; printf "${VL}\n" # empty line - - tip_ref=$(getSlotTipRef) - tip_diff=$(( tip_ref - slotnum )) - printf "${VL} Block : ${style_values_1}%s${NC}" "${blocknum}" - tput cup ${line} ${second_col} - printf "Tip (ref) : ${style_values_1}%s${NC}" "${tip_ref}" - endLine $((line++)) - printf "${VL} Slot : ${style_values_1}%s${NC}" "${slot_in_epoch}" - tput cup ${line} ${second_col} - printf "Tip (node) : ${style_values_1}%s${NC}" "${slotnum}" - endLine $((line++)) - printf "${VL} Density : ${style_values_1}%s${NC}%%" "${density}" - tput cup ${line} ${second_col} - if [[ ${slotnum} -eq 0 ]]; then - printf "Status : ${style_info}starting...${NC}" - elif [[ "${PROTOCOL}" = "Cardano" && ${shelley_transition_epoch} -eq -1 ]]; then - printf "Status : ${style_info}syncing...${NC}" - elif [[ ${tip_diff} -le $(( slot_interval * 2 )) ]]; then - printf "Tip (diff) : ${style_status_1}%s${NC}" "${tip_diff} :)" - elif [[ ${tip_diff} -le $(( slot_interval * 3 )) ]]; then - printf "Tip (diff) : ${style_status_2}%s${NC}" "${tip_diff} :|" - else - printf "Tip (diff) : ${style_status_3}%s${NC}" "${tip_diff} :(" - fi - endLine $((line++)) - - echo "${m2divider}" - ((line++)) - - printf "${VL} Processed TX : ${style_values_1}%s${NC}" "${tx_processed}" - tput cup ${line} $((second_col+7)) - printf " Out / In" - endLine $((line++)) - printf "${VL} Mempool TX/Bytes : ${style_values_1}%s${NC} / ${style_values_1}%s${NC}" "${mempool_tx}" "${mempool_bytes}" - tput el; tput cup ${line} $((second_col+7)) - printf "Peers : ${style_values_1}%s${NC} / ${style_values_1}%s${NC}" "${peers_out}" "${peers_in}" - endLine $((line++)) - - ## Core section ## - if [[ ${nodemode} = "Core" ]]; then + printf "${VL} 0-50ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_1}" "${peerCNT1_out}" "${peerPCT1_out}" + tput cup ${line} ${bar_col_small} + for i in $(seq 0 $((granularity_small-1))); do + [[ $i -lt ${peerPCT1items_out} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC}" + endLine $((line++)) + + printf "${VL} 50-100ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_2}" "${peerCNT2_out}" "${peerPCT2_out}" + tput cup ${line} ${bar_col_small} + for i in $(seq 0 $((granularity_small-1))); do + [[ $i -lt ${peerPCT2items_out} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC}" + endLine $((line++)) + + printf "${VL} 100-200ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_3}" "${peerCNT3_out}" "${peerPCT3_out}" + tput cup ${line} ${bar_col_small} + for i in $(seq 0 $((granularity_small-1))); do + [[ $i -lt ${peerPCT3items_out} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC}" + endLine $((line++)) + + printf "${VL} 200ms < : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_4}" "${peerCNT4_out}" "${peerPCT4_out}" + tput cup ${line} ${bar_col_small} + for i in $(seq 0 $((granularity_small-1))); do + [[ $i -lt ${peerPCT4items_out} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC}" + endLine $((line++)) + if [[ ${peerRTTAVG_out} -ge 200 ]]; then printf "${VL} Average : ${style_status_4}%s${NC} ms" "${peerRTTAVG_out}" + elif [[ ${peerRTTAVG_out} -ge 100 ]]; then printf "${VL} Average : ${style_status_3}%s${NC} ms" "${peerRTTAVG_out}" + elif [[ ${peerRTTAVG_out} -ge 50 ]]; then printf "${VL} Average : ${style_status_2}%s${NC} ms" "${peerRTTAVG_out}" + elif [[ ${peerRTTAVG_out} -ge 0 ]]; then printf "${VL} Average : ${style_status_1}%s${NC} ms" "${peerRTTAVG_out}" + else printf "${VL} Average : - ms"; fi + endLine $((line++)) + + echo "${m3divider}" + ((line++)) + + printf "${VL} Unique Peers / Unreachable / Skipped : ${style_values_1}%s${NC} / " "${peerCNTUnique_out}" + [[ ${peerCNT0_out} -eq 0 ]] && printf "${style_values_1}%s${NC} / " "${peerCNT0_out}" || printf "${style_status_3}%s${NC} / " "${peerCNT0_out}" + [[ ${peerCNTSKIPPED_out} -eq 0 ]] && printf "${style_values_1}%s${NC}" "${peerCNTSKIPPED_out}" || printf "${style_status_2}%s${NC}" "${peerCNTSKIPPED_out}" + endLine $((line++)) + + echo "${m3divider}" + ((line++)) + + printf "${VL}${style_info} # : %20s : RTT (ms)${NC}" "REMOTE PEER" + tput cup ${line} $((width-6)) + printf "TOP 8 ${VL}\n" + ((line++)) + peerCNT=1 + for peer in ${rttResultsSorted_out}; do + peerRTT=$(echo ${peer} | cut -d: -f1) + peerIP=$(echo ${peer} | cut -d: -f2) + peerPORT=$(echo ${peer} | cut -d: -f3) + if [[ ${peerRTT} -lt 50 ]]; then printf "${VL} %3s : %15s:%-6s : ${style_status_1}%s${NC}" ${peerCNT} ${peerIP} ${peerPORT} ${peerRTT} + elif [[ ${peerRTT} -lt 100 ]]; then printf "${VL} %3s : %15s:%-6s : ${style_status_2}%s${NC}" ${peerCNT} ${peerIP} ${peerPORT} ${peerRTT} + elif [[ ${peerRTT} -lt 200 ]]; then printf "${VL} %3s : %15s:%-6s : ${style_status_3}%s${NC}" ${peerCNT} ${peerIP} ${peerPORT} ${peerRTT} + elif [[ ${peerRTT} -lt 99999 ]]; then printf "${VL} %3s : %15s:%-6s : ${style_status_4}%s${NC}" ${peerCNT} ${peerIP} ${peerPORT} ${peerRTT} + else printf "${VL} %3s : %15s:%-6s : ---" ${peerCNT} ${peerIP} ${peerPORT}; fi + endLine $((line++)) + [[ ${peerCNT} -eq 8 ]] && break + ((peerCNT++)) + done + echo "${mdivider}" ((line++)) - printf "${VL} KES current/remaining : ${style_values_1}%s${NC} / " "${kesperiod}" - if [[ ${remaining_kes_periods} -le 0 ]]; then - printf "${style_status_4}%s${NC}" "${remaining_kes_periods}" - elif [[ ${remaining_kes_periods} -le 8 ]]; then - printf "${style_status_3}%s${NC}" "${remaining_kes_periods}" - else - printf "${style_values_1}%s${NC}" "${remaining_kes_periods}" - fi + printf "${VL}${STANDOUT} In ${NC} RTT : Peers / Percent" + tput cup ${line} $(( width - 20 )) + printf "Updated: ${style_info}%s${NC} ${VL}\n" "${time_in}" + ((line++)) + + printf "${VL} 0-50ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_1}" "${peerCNT1_in}" "${peerPCT1_in}" + tput cup ${line} ${bar_col_small} + for i in $(seq 0 $((granularity_small-1))); do + [[ $i -lt ${peerPCT1items_in} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC}" + endLine $((line++)) + + printf "${VL} 50-100ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_2}" "${peerCNT2_in}" "${peerPCT2_in}" + tput cup ${line} ${bar_col_small} + for i in $(seq 0 $((granularity_small-1))); do + [[ $i -lt ${peerPCT2items_in} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC}" + endLine $((line++)) + + printf "${VL} 100-200ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_3}" "${peerCNT3_in}" "${peerPCT3_in}" + tput cup ${line} ${bar_col_small} + for i in $(seq 0 $((granularity_small-1))); do + [[ $i -lt ${peerPCT3items_in} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC}" + endLine $((line++)) + + printf "${VL} 200ms < : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_4}" "${peerCNT4_in}" "${peerPCT4_in}" + tput cup ${line} ${bar_col_small} + for i in $(seq 0 $((granularity_small-1))); do + [[ $i -lt ${peerPCT4items_in} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC}" endLine $((line++)) - printf "${VL} KES expiration date : ${style_values_1}%s${NC}" "${kes_expiration}" + if [[ ${peerRTTAVG_in} -ge 200 ]]; then printf "${VL} Average : ${style_status_4}%s${NC} ms" "${peerRTTAVG_in}" + elif [[ ${peerRTTAVG_in} -ge 100 ]]; then printf "${VL} Average : ${style_status_3}%s${NC} ms" "${peerRTTAVG_in}" + elif [[ ${peerRTTAVG_in} -ge 50 ]]; then printf "${VL} Average : ${style_status_2}%s${NC} ms" "${peerRTTAVG_in}" + elif [[ ${peerRTTAVG_in} -ge 0 ]]; then printf "${VL} Average : ${style_status_1}%s${NC} ms" "${peerRTTAVG_in}" + else printf "${VL} Average : - ms"; fi endLine $((line++)) - echo "${m2divider}" + echo "${m3divider}" ((line++)) - printf "${VL} %49s" "IsLeader/Adopted/Missed" + printf "${VL} Unique Peers / Unreachable / Skipped : ${style_values_1}%s${NC} / " "${peerCNTUnique_in}" + [[ ${peerCNT0_in} -eq 0 ]] && printf "${style_values_1}%s${NC} / " "${peerCNT0_in}" || printf "${style_status_3}%s${NC} / " "${peerCNT0_in}" + [[ ${peerCNTSKIPPED_in} -eq 0 ]] && printf "${style_values_1}%s${NC}" "${peerCNTSKIPPED_in}" || printf "${style_status_2}%s${NC}" "${peerCNTSKIPPED_in}" endLine $((line++)) - printf "${VL} Blocks since node start : ${style_values_1}%s${NC} / " "${isleader}" - if [[ ${adopted} -ne ${isleader} ]]; then - printf "${style_status_2}%s${NC} / " "${adopted}" + + echo "${m3divider}" + ((line++)) + + printf "${VL}${style_info} # : %20s : RTT (ms)${NC}" "REMOTE PEER" + tput cup ${line} $((width-6)) + printf "TOP 8 ${VL}\n" + ((line++)) + peerCNT=1 + for peer in ${rttResultsSorted_in}; do + peerRTT=$(echo ${peer} | cut -d: -f1) + peerIP=$(echo ${peer} | cut -d: -f2) + peerPORT=$(echo ${peer} | cut -d: -f3) + if [[ ${peerRTT} -lt 50 ]]; then printf "${VL} %3s : %15s:%-6s : ${style_status_1}%s${NC}" ${peerCNT} ${peerIP} ${peerPORT} ${peerRTT} + elif [[ ${peerRTT} -lt 100 ]]; then printf "${VL} %3s : %15s:%-6s : ${style_status_2}%s${NC}" ${peerCNT} ${peerIP} ${peerPORT} ${peerRTT} + elif [[ ${peerRTT} -lt 200 ]]; then printf "${VL} %3s : %15s:%-6s : ${style_status_3}%s${NC}" ${peerCNT} ${peerIP} ${peerPORT} ${peerRTT} + elif [[ ${peerRTT} -lt 99999 ]]; then printf "${VL} %3s : %15s:%-6s : ${style_status_4}%s${NC}" ${peerCNT} ${peerIP} ${peerPORT} ${peerRTT} + else printf "${VL} %3s : %15s:%-6s : ---" ${peerCNT} ${peerIP} ${peerPORT}; fi + endLine $((line++)) + [[ ${peerCNT} -eq 8 ]] && break + ((peerCNT++)) + done + else + printf "${VL} Uptime: ${style_values_1}%s${NC}" "$(timeLeft $(( uptimens/1000000000 )))" + tput cup ${line} $(( width - ${#title} - 3 )) + printf "${VL} ${style_title}${title} ${VL}\n" + ((line++)) + printf "${m2divider}" + tput cup ${line} $(( width - ${#title} - 3 )) + printf "${UR}" + printf "%0.s${HL}" $(seq $(( ${#title} + 2 ))) + printf "${LVL}\n" + ((line++)) + + if [[ ${shelley_transition_epoch} -eq -2 ]] || [[ ${shelley_transition_epoch} -ne -1 && ${epochnum} -ge ${shelley_transition_epoch} ]]; then + epoch_progress=$(echo "(${slot_in_epoch}/${epoch_length})*100" | bc -l) # in Shelley era or Shelley only TestNet else - printf "${style_values_1}%s${NC} / " "${adopted}" + epoch_progress=$(echo "(${slot_in_epoch}/${byron_epoch_length})*100" | bc -l) # in Byron era fi - if [[ ${didntadopt} -gt 0 ]]; then - printf "${style_status_3}%s${NC}" "${didntadopt}" + printf "${VL} Epoch ${style_values_1}%s${NC} [${style_values_1}%2.1f%%${NC}] (node)" "${epochnum}" "${epoch_progress}" + endLine $((line++)) + printf "${VL} ${style_values_1}%s${NC} until epoch boundary (chain)" "$(timeLeft "$(timeUntilNextEpoch)")" + endLine $((line++)) + + epoch_items=$(( $(printf %.0f "${epoch_progress}") * granularity / 100 )) + printf "${VL} ${style_values_1}" + for i in $(seq 0 $((granularity-1))); do + [[ $i -lt ${epoch_items} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" + done + printf "${NC} ${VL}\n"; ((line++)) + + printf "${VL}"; tput cup $((line++)) ${width}; printf "${VL}\n" # empty line + + tip_ref=$(getSlotTipRef) + tip_diff=$(( tip_ref - slotnum )) + printf "${VL} Block : ${style_values_1}%s${NC}" "${blocknum}" + tput cup ${line} ${second_col} + printf "Tip (ref) : ${style_values_1}%s${NC}" "${tip_ref}" + endLine $((line++)) + printf "${VL} Slot : ${style_values_1}%s${NC}" "${slot_in_epoch}" + tput cup ${line} ${second_col} + printf "Tip (node) : ${style_values_1}%s${NC}" "${slotnum}" + endLine $((line++)) + printf "${VL} Density : ${style_values_1}%s${NC}%%" "${density}" + tput cup ${line} ${second_col} + if [[ ${slotnum} -eq 0 ]]; then + printf "Status : ${style_info}starting...${NC}" + elif [[ "${PROTOCOL}" = "Cardano" && ${shelley_transition_epoch} -eq -1 ]]; then + printf "Status : ${style_info}syncing...${NC}" + elif [[ ${tip_diff} -le $(( slot_interval * 2 )) ]]; then + printf "Tip (diff) : ${style_status_1}%s${NC}" "${tip_diff} :)" + elif [[ ${tip_diff} -le $(( slot_interval * 3 )) ]]; then + printf "Tip (diff) : ${style_status_2}%s${NC}" "${tip_diff} :|" else - printf "${style_values_1}%s${NC}" "${didntadopt}" + printf "Tip (diff) : ${style_status_3}%s${NC}" "${tip_diff} :(" fi endLine $((line++)) - if [[ -n ${BLOCK_LOG_DIR} ]]; then - blocks_file="${BLOCK_LOG_DIR}/blocks_${epochnum}.json" - if [[ -f "${blocks_file}" ]]; then - isleader_epoch=$(jq -c '[.[].slot //empty] | length' "${blocks_file}") - invalid_epoch=$(jq -c '[.[].hash //empty | select(startswith("Invalid"))] | length' "${blocks_file}") - adopted_epoch=$(( $(jq -c '[.[].hash //empty] | length' "${blocks_file}") - invalid_epoch )) - else - isleader_epoch=0 - invalid_epoch=0 - adopted_epoch=0 - fi - printf "${VL} Blocks this epoch : ${style_values_1}%s${NC} / " "${isleader_epoch}" - if [[ ${adopted_epoch} -ne ${isleader_epoch} ]]; then - printf "${style_status_2}%s${NC} / " "${adopted_epoch}" - else - printf "${style_values_1}%s${NC} / " "${adopted_epoch}" - fi - if [[ ${invalid_epoch} -gt 0 ]]; then - printf "${style_status_3}%s${NC}" "${invalid_epoch}" - else - printf "${style_values_1}%s${NC}" "${invalid_epoch}" - fi - endLine $((line++)) - fi - fi - line_wo_peers=${line} - - ## Peer Analysis ## - if [[ ${show_peers} = "true" ]]; then - echo "${mdivider}" + echo "${m2divider}" ((line++)) - if [[ ${check_peers} = "true" ]]; then - redraw_peers=true - tput ed - printf "${VL} ${style_info}Output peer analysis started... update paused${NC}" - endLine ${line} - echo "${bdivider}" - checkPeers out - # Save values - peerCNT0_out=${peerCNT0}; peerCNT1_out=${peerCNT1}; peerCNT2_out=${peerCNT2}; peerCNT3_out=${peerCNT3}; peerCNT4_out=${peerCNT4} - peerPCT1_out=${peerPCT1}; peerPCT2_out=${peerPCT2}; peerPCT3_out=${peerPCT3}; peerPCT4_out=${peerPCT4} - peerPCT1items_out=${peerPCT1items}; peerPCT2items_out=${peerPCT2items}; peerPCT3items_out=${peerPCT3items}; peerPCT4items_out=${peerPCT4items} - peerRTTAVG_out=${peerRTTAVG}; peerCNTUnique_out=${peerCNTUnique}; peerCNTSKIPPED_out=${peerCNTSKIPPED} - time_out=$(date -u '+%T Z') - fi + printf "${VL} Processed TX : ${style_values_1}%s${NC}" "${tx_processed}" + tput cup ${line} $((second_col)) + printf " Out / In" + endLine $((line++)) + printf "${VL} Mempool TX/Bytes : ${style_values_1}%s${NC} / ${style_values_1}%s${NC}" "${mempool_tx}" "${mempool_bytes}" + tput el; tput cup ${line} $((second_col)) + printf "Peers : ${style_values_1}%3s${NC} ${style_values_1}%s${NC}" "${peers_out}" "${peers_in}" + endLine $((line++)) - if [[ ${redraw_peers} = "true" ]]; then - - tput cup ${line} 0 - - printf "${VL}${STANDOUT} OUT ${NC} RTT : Peers / Percent" - tput el && tput cup ${line} $(( width - 20 )) - printf "Updated: ${style_info}%s${NC} ${VL}\n" "${time_out}" - ((line++)) - - printf "${VL} 0-50ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_1}" "${peerCNT1_out}" "${peerPCT1_out}" - tput el && tput cup ${line} ${bar_col_small} - for i in $(seq 0 $((granularity_small-1))); do - [[ $i -lt ${peerPCT1items_out} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" - done - printf "${NC}" - endLine $((line++)) - - printf "${VL} 50-100ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_2}" "${peerCNT2_out}" "${peerPCT2_out}" - tput el && tput cup ${line} ${bar_col_small} - for i in $(seq 0 $((granularity_small-1))); do - [[ $i -lt ${peerPCT2items_out} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" - done - printf "${NC}" - endLine $((line++)) - - printf "${VL} 100-200ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_3}" "${peerCNT3_out}" "${peerPCT3_out}" - tput el && tput cup ${line} ${bar_col_small} - for i in $(seq 0 $((granularity_small-1))); do - [[ $i -lt ${peerPCT3items_out} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" - done - printf "${NC}" - endLine $((line++)) - - printf "${VL} 200ms < : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_4}" "${peerCNT4_out}" "${peerPCT4_out}" - tput el && tput cup ${line} ${bar_col_small} - for i in $(seq 0 $((granularity_small-1))); do - [[ $i -lt ${peerPCT4items_out} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" - done - printf "${NC}" - endLine $((line++)) - if [[ ${peerRTTAVG_out} -ge 200 ]]; then printf "${VL} Average : ${style_status_4}%s${NC} ms" "${peerRTTAVG_out}" - elif [[ ${peerRTTAVG_out} -ge 100 ]]; then printf "${VL} Average : ${style_status_3}%s${NC} ms" "${peerRTTAVG_out}" - elif [[ ${peerRTTAVG_out} -ge 50 ]]; then printf "${VL} Average : ${style_status_2}%s${NC} ms" "${peerRTTAVG_out}" - elif [[ ${peerRTTAVG_out} -ge 0 ]]; then printf "${VL} Average : ${style_status_1}%s${NC} ms" "${peerRTTAVG_out}" - else printf "${VL} Average : - ms"; fi - endLine $((line++)) - - echo "${m3divider}" + ## Core section ## + if [[ ${nodemode} = "Core" ]]; then + echo "${mdivider}" ((line++)) - printf "${VL} Unique Peers / Unreachable / Skipped : ${style_values_1}%s${NC} / " "${peerCNTUnique_out}" - [[ ${peerCNT0_out} -eq 0 ]] && printf "${style_values_1}%s${NC} / " "${peerCNT0_out}" || printf "${style_status_3}%s${NC} / " "${peerCNT0_out}" - [[ ${peerCNTSKIPPED_out} -eq 0 ]] && printf "${style_values_1}%s${NC}" "${peerCNTSKIPPED_out}" || printf "${style_status_2}%s${NC}" "${peerCNTSKIPPED_out}" + printf "${VL} KES current/remaining" + tput cup ${line} $((second_col-2)) + printf ": ${style_values_1}%s${NC} / " "${kesperiod}" + if [[ ${remaining_kes_periods} -le 0 ]]; then + printf "${style_status_4}%s${NC}" "${remaining_kes_periods}" + elif [[ ${remaining_kes_periods} -le 8 ]]; then + printf "${style_status_3}%s${NC}" "${remaining_kes_periods}" + else + printf "${style_values_1}%s${NC}" "${remaining_kes_periods}" + fi + endLine $((line++)) + printf "${VL} KES expiration date" + tput cup ${line} $((second_col-2)) + printf ": ${style_values_1}%s${NC}" "${kes_expiration}" endLine $((line++)) echo "${m2divider}" ((line++)) - if [[ ${check_peers} = "true" ]]; then - printf "${VL} ${style_info}Input peer analysis started... update paused${NC}" - endLine ${line} - echo "${bdivider}" - checkPeers in - # Save values - peerCNT0_in=${peerCNT0}; peerCNT1_in=${peerCNT1}; peerCNT2_in=${peerCNT2}; peerCNT3_in=${peerCNT3}; peerCNT4_in=${peerCNT4} - peerPCT1_in=${peerPCT1}; peerPCT2_in=${peerPCT2}; peerPCT3_in=${peerPCT3}; peerPCT4_in=${peerPCT4} - peerPCT1items_in=${peerPCT1items}; peerPCT2items_in=${peerPCT2items}; peerPCT3items_in=${peerPCT3items}; peerPCT4items_in=${peerPCT4items} - peerRTTAVG_in=${peerRTTAVG}; peerCNTUnique_in=${peerCNTUnique}; peerCNTSKIPPED_in=${peerCNTSKIPPED} - time_in=$(date -u '+%T Z') - fi - - tput cup ${line} 0 - - printf "${VL}${STANDOUT} In ${NC} RTT : Peers / Percent" - tput el && tput cup ${line} $(( width - 20 )) - printf "Updated: ${style_info}%s${NC} ${VL}\n" "${time_in}" - ((line++)) - - printf "${VL} 0-50ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_1}" "${peerCNT1_in}" "${peerPCT1_in}" - tput el && tput cup ${line} ${bar_col_small} - for i in $(seq 0 $((granularity_small-1))); do - [[ $i -lt ${peerPCT1items_in} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" - done - printf "${NC}" - endLine $((line++)) - - printf "${VL} 50-100ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_2}" "${peerCNT2_in}" "${peerPCT2_in}" - tput el && tput cup ${line} ${bar_col_small} - for i in $(seq 0 $((granularity_small-1))); do - [[ $i -lt ${peerPCT2items_in} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" - done - printf "${NC}" - endLine $((line++)) - - printf "${VL} 100-200ms : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_3}" "${peerCNT3_in}" "${peerPCT3_in}" - tput el && tput cup ${line} ${bar_col_small} - for i in $(seq 0 $((granularity_small-1))); do - [[ $i -lt ${peerPCT3items_in} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" - done - printf "${NC}" + printf "${VL}" + tput cup ${line} ${second_col} + printf "IsLeader / Adopted / Missed" endLine $((line++)) - - printf "${VL} 200ms < : ${style_values_1}%5s${NC} / ${style_values_1}%.f${NC}%% ${style_status_4}" "${peerCNT4_in}" "${peerPCT4_in}" - tput el && tput cup ${line} ${bar_col_small} - for i in $(seq 0 $((granularity_small-1))); do - [[ $i -lt ${peerPCT4items_in} ]] && printf "${char_marked}" || printf "${NC}${char_unmarked}" - done - printf "${NC}" - endLine $((line++)) - if [[ ${peerRTTAVG_in} -ge 200 ]]; then printf "${VL} Average : ${style_status_4}%s${NC} ms" "${peerRTTAVG_in}" - elif [[ ${peerRTTAVG_in} -ge 100 ]]; then printf "${VL} Average : ${style_status_3}%s${NC} ms" "${peerRTTAVG_in}" - elif [[ ${peerRTTAVG_in} -ge 50 ]]; then printf "${VL} Average : ${style_status_2}%s${NC} ms" "${peerRTTAVG_in}" - elif [[ ${peerRTTAVG_in} -ge 0 ]]; then printf "${VL} Average : ${style_status_1}%s${NC} ms" "${peerRTTAVG_in}" - else printf "${VL} Average : - ms"; fi + printf "${VL} Blocks since node start" + tput cup ${line} $((second_col-2)) + printf ": ${style_values_1}%-11s${NC}" "${isleader}" + if [[ ${adopted} -ne ${isleader} ]]; then + printf "${style_status_2}%-10s${NC}" "${adopted}" + else + printf "${style_values_1}%-10s${NC}" "${adopted}" + fi + if [[ ${didntadopt} -gt 0 ]]; then + printf "${style_status_3}%-9s${NC}" "${didntadopt}" + else + printf "${style_values_1}%-9s${NC}" "${didntadopt}" + fi endLine $((line++)) - echo "${m3divider}" - ((line++)) - - printf "${VL} Unique Peers / Unreachable / Skipped : ${style_values_1}%s${NC} / " "${peerCNTUnique_in}" - [[ ${peerCNT0_in} -eq 0 ]] && printf "${style_values_1}%s${NC} / " "${peerCNT0_in}" || printf "${style_status_3}%s${NC} / " "${peerCNT0_in}" - [[ ${peerCNTSKIPPED_in} -eq 0 ]] && printf "${style_values_1}%s${NC}" "${peerCNTSKIPPED_in}" || printf "${style_status_2}%s${NC}" "${peerCNTSKIPPED_in}" - endLine $((line++)) + if [[ -n ${BLOCK_LOG_DIR} ]]; then + blocks_file="${BLOCK_LOG_DIR}/blocks_${epochnum}.json" + if [[ -f "${blocks_file}" ]]; then + isleader_epoch=$(jq -c '[.[].slot //empty] | length' "${blocks_file}") + invalid_epoch=$(jq -c '[.[].hash //empty | select(startswith("Invalid"))] | length' "${blocks_file}") + adopted_epoch=$(( $(jq -c '[.[].hash //empty] | length' "${blocks_file}") - invalid_epoch )) + else + isleader_epoch=0 + invalid_epoch=0 + adopted_epoch=0 + fi + printf "${VL} Blocks this epoch : ${style_values_1}%-11s${NC}" "${isleader_epoch}" + if [[ ${adopted_epoch} -ne ${isleader_epoch} ]]; then + printf "${style_status_2}%-10s${NC}" "${adopted_epoch}" + else + printf "${style_values_1}%-10s${NC}" "${adopted_epoch}" + fi + if [[ ${invalid_epoch} -gt 0 ]]; then + printf "${style_status_3}%-9s${NC}" "${invalid_epoch}" + else + printf "${style_values_1}%-9s${NC}" "${invalid_epoch}" + fi + endLine $((line++)) + fi fi fi - if [[ ${show_peers} = "hide" ]]; then - show_peers=false - tput ed - line_end=${line_wo_peers} - elif [[ ${line_end} -lt ${line} ]]; then - line_end=${line} - fi - tput cup ${line_end} 0 + [[ ${check_peers} = "true" ]] && check_peers=false && show_peers=true && clear && continue + echo "${bdivider}" - printf " ${style_info}[esc/q] Quit${NC} | ${style_info}[p] Peer Analysis${NC}" - if [[ "${check_peers}" = "true" ]]; then - check_peers="false" - fi - if [[ "${show_peers}" = "true" ]]; then - printf " | ${style_info}[h] Hide Peers${NC}" - else - tput el - fi + ((line++)) + [[ ${show_peers} = "true" ]] && printf " ${style_info}[esc/q] Quit${NC} | ${style_info}[h] Home${NC}" || \ + printf " ${style_info}[esc/q] Quit${NC} | ${style_info}[p] Peer Analysis${NC}" + tput el waitForInput done