@@ -221,11 +221,11 @@ download_with_progress() {
221221 if [[ ! -t 1 ]]; then
222222 if [[ $use_curl -eq 1 ]]; then
223223 # Get size for percentage reporting
224- total_size=$( curl -sLI " $url " 2> /dev/null | grep -i ' ^content-length:' | tail -1 | awk ' {print $2}' | tr -d ' \r\n' )
224+ total_size=$( curl -sLI " $url " 2> /dev/null | grep -i ' ^content-length:' | tail -1 | awk ' {print $2}' | tr -d ' \r\n' || true )
225225 total_size=${total_size:- 0}
226226 curl -sL -o " $output_file " " $url " < /dev/null &
227227 else
228- total_size=$( wget --spider --server-response " $url " 2>&1 | grep -i ' content-length:' | tail -1 | awk ' {print $2}' | tr -d ' \r\n' )
228+ total_size=$( wget --spider --server-response " $url " 2>&1 | grep -i ' content-length:' | tail -1 | awk ' {print $2}' | tr -d ' \r\n' || true )
229229 total_size=${total_size:- 0}
230230 wget -q -O " $output_file " " $url " < /dev/null &
231231 fi
@@ -243,17 +243,17 @@ download_with_progress() {
243243 fi
244244 sleep 1
245245 done
246- wait " $dl_pid "
246+ wait " $dl_pid " || true
247247 return $?
248248 fi
249249
250250 # TTY mode: show progress bar
251251
252252 # Get Content-Length via HEAD request (follows redirects)
253253 if [[ $use_curl -eq 1 ]]; then
254- total_size=$( curl -sLI " $url " 2> /dev/null | grep -i ' ^content-length:' | tail -1 | awk ' {print $2}' | tr -d ' \r\n' )
254+ total_size=$( curl -sLI " $url " 2> /dev/null | grep -i ' ^content-length:' | tail -1 | awk ' {print $2}' | tr -d ' \r\n' || true )
255255 else
256- total_size=$( wget --spider --server-response " $url " 2>&1 | grep -i ' content-length:' | tail -1 | awk ' {print $2}' | tr -d ' \r\n' )
256+ total_size=$( wget --spider --server-response " $url " 2>&1 | grep -i ' content-length:' | tail -1 | awk ' {print $2}' | tr -d ' \r\n' || true )
257257 fi
258258 total_size=${total_size:- 0}
259259
@@ -280,8 +280,8 @@ download_with_progress() {
280280 done
281281
282282 # Capture exit code
283- wait " $dl_pid "
284- local dl_exit=$?
283+ local dl_exit=0
284+ wait " $dl_pid " || dl_exit=$?
285285
286286 # Final frame (100% if successful)
287287 if [[ $dl_exit -eq 0 && -f " $output_file " ]]; then
@@ -590,6 +590,33 @@ install_go() {
590590 fi
591591}
592592
593+ # Install Go 1.23 to a temporary directory (for cosmovisor build with Go 1.26+ systems)
594+ install_temp_go () {
595+ local go_version=" 1.23.3"
596+ local temp_dir=" $1 "
597+ local arch os download_url
598+
599+ case " $( uname -m) " in
600+ x86_64|amd64) arch=" amd64" ;;
601+ aarch64|arm64) arch=" arm64" ;;
602+ * ) return 1 ;;
603+ esac
604+
605+ os=" linux"
606+ [[ " $OSTYPE " == " darwin" * ]] && os=" darwin"
607+
608+ download_url=" https://go.dev/dl/go${go_version} .${os} -${arch} .tar.gz"
609+
610+ mkdir -p " $temp_dir "
611+ if command -v curl > /dev/null 2>&1 ; then
612+ curl -sL " $download_url " | tar -xzf - -C " $temp_dir " 2> /dev/null
613+ else
614+ wget -qO- " $download_url " | tar -xzf - -C " $temp_dir " 2> /dev/null
615+ fi
616+
617+ [[ -x " $temp_dir /go/bin/go" ]]
618+ }
619+
593620# Helper: Download pchaind binary from GitHub releases
594621download_pchaind () {
595622 local os arch version download_url checksum_url temp_dir filename ver_num
@@ -622,7 +649,7 @@ download_pchaind() {
622649 step " Fetching latest release version"
623650 if command -v curl > /dev/null 2>&1 ; then
624651 # Only use /releases/latest (stable releases, not pre-releases)
625- version=$( curl -sL https://api.github.com/repos/pushchain/push-chain-node/releases/latest 2> /dev/null | grep ' "tag_name"' | head -1 | sed ' s/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' )
652+ version=$( curl -sL https://api.github.com/repos/pushchain/push-chain-node/releases/latest 2> /dev/null | grep ' "tag_name"' | head -1 | sed ' s/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' || true )
626653 fi
627654 if [[ -z " $version " ]]; then
628655 verbose " Could not determine latest release version (no stable release found)"
@@ -767,7 +794,7 @@ download_push_validator() {
767794 else
768795 step " Fetching latest release version"
769796 if command -v curl > /dev/null 2>&1 ; then
770- version=$( curl -sL https://api.github.com/repos/pushchain/push-validator-cli/releases/latest 2> /dev/null | grep ' "tag_name"' | head -1 | sed ' s/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' )
797+ version=$( curl -sL https://api.github.com/repos/pushchain/push-validator-cli/releases/latest 2> /dev/null | grep ' "tag_name"' | head -1 | sed ' s/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' || true )
771798 fi
772799 if [[ -z " $version " ]]; then
773800 verbose " Could not determine latest release version (no stable release found)"
@@ -811,7 +838,7 @@ download_push_validator() {
811838 step " Verifying checksum"
812839 local expected_sum actual_sum
813840 # Extract checksum for our specific file from checksums.txt
814- expected_sum=$( grep " $filename " " $temp_dir /checksums.txt" 2> /dev/null | awk ' {print $1}' )
841+ expected_sum=$( grep " $filename " " $temp_dir /checksums.txt" 2> /dev/null | awk ' {print $1}' || true )
815842 if command -v sha256sum > /dev/null 2>&1 ; then
816843 actual_sum=$( sha256sum " $temp_dir /$filename " | awk ' {print $1}' )
817844 elif command -v shasum > /dev/null 2>&1 ; then
@@ -1353,7 +1380,7 @@ if [[ "$USE_LOCAL" = "yes" || -n "$LOCAL_REPO" ]]; then
13531380 if [[ -x " $MANAGER_BIN " ]]; then
13541381 CURRENT_COMMIT=$( cd " $REPO_DIR " && git rev-parse --short HEAD 2> /dev/null || echo " unknown" )
13551382 # Extract commit from version output (format: "push-validator vX.Y.Z (1f599bd) built ...")
1356- INSTALLED_COMMIT=$( " $MANAGER_BIN " version < /dev/null 2> /dev/null | sed -n ' s/.*(\([0-9a-f]\{7,\}\)).*/\1/p' )
1383+ INSTALLED_COMMIT=$( " $MANAGER_BIN " version < /dev/null 2> /dev/null | sed -n ' s/.*(\([0-9a-f]\{7,\}\)).*/\1/p' || true )
13571384 # Only skip build if both are valid hex commits and match
13581385 if [[ " $CURRENT_COMMIT " =~ ^[0-9a-f]+$ ]] && [[ " $INSTALLED_COMMIT " =~ ^[0-9a-f]+$ ]] && [[ " $CURRENT_COMMIT " == " $INSTALLED_COMMIT " ]]; then
13591386 step " Manager already up-to-date ($CURRENT_COMMIT ) - skipped"
@@ -1377,9 +1404,9 @@ if [[ "$USE_LOCAL" = "yes" || -n "$LOCAL_REPO" ]]; then
13771404
13781405 # Compute and display SHA256
13791406 if command -v sha256sum > /dev/null 2>&1 ; then
1380- MANAGER_SHA=$( sha256sum " $MANAGER_BIN " 2> /dev/null | awk ' {print $1}' )
1407+ MANAGER_SHA=$( sha256sum " $MANAGER_BIN " 2> /dev/null | awk ' {print $1}' || true )
13811408 elif command -v shasum > /dev/null 2>&1 ; then
1382- MANAGER_SHA=$( shasum -a 256 " $MANAGER_BIN " 2> /dev/null | awk ' {print $1}' )
1409+ MANAGER_SHA=$( shasum -a 256 " $MANAGER_BIN " 2> /dev/null | awk ' {print $1}' || true )
13831410 fi
13841411 if [[ -n " $MANAGER_SHA " ]]; then
13851412 SHA_SHORT=" ${MANAGER_SHA: 0: 8} ...${MANAGER_SHA: -8} "
@@ -1454,10 +1481,35 @@ verbose "Using built-in WebSocket monitor (no external dependency)"
14541481# Install Cosmovisor for automatic upgrades (pinned to v1.7.1)
14551482step " Installing Cosmovisor for automatic upgrades"
14561483if ! command -v cosmovisor > /dev/null 2>&1 ; then
1457- COSMOVISOR_LOG=$( mktemp /tmp/cosmovisor-install-XXXXXX.log)
1458- go install cosmossdk.io/tools/cosmovisor/cmd/cosmovisor@v1.7.1 < /dev/null > " $COSMOVISOR_LOG " 2>&1 &
1484+ COSMOVISOR_LOG=$( mktemp /tmp/cosmovisor-install-XXXXXX 2> /dev/null || echo " /tmp/cosmovisor-install-$$ .log" )
1485+ GO_BIN_DIR=" ${GOBIN:- ${GOPATH:- $HOME / go} / bin} "
1486+
1487+ # Check if system Go is 1.24+ (incompatible with cosmovisor due to sonic library)
1488+ SYSTEM_GO_MINOR=$( go version 2> /dev/null | grep -oE ' go1\.([0-9]+)' | sed ' s/go1\.//' || echo " 0" )
1489+ USE_TEMP_GO=no
1490+ TEMP_GO_DIR=" "
1491+
1492+ if [[ " $SYSTEM_GO_MINOR " -ge 24 ]]; then
1493+ verbose " System Go 1.${SYSTEM_GO_MINOR} detected (incompatible with cosmovisor)"
1494+ verbose " Downloading Go 1.23 for cosmovisor build..."
1495+ TEMP_GO_DIR=$( mktemp -d 2> /dev/null || echo " /tmp/temp-go-$$ " )
1496+ if install_temp_go " $TEMP_GO_DIR " ; then
1497+ USE_TEMP_GO=yes
1498+ verbose " Using temporary Go 1.23 from $TEMP_GO_DIR "
1499+ else
1500+ warn " Failed to download Go 1.23, trying with system Go anyway"
1501+ fi
1502+ fi
1503+
1504+ # Run go install with appropriate Go binary
1505+ if [[ " $USE_TEMP_GO " = " yes" ]]; then
1506+ GOBIN=" $GO_BIN_DIR " " $TEMP_GO_DIR /go/bin/go" install cosmossdk.io/tools/cosmovisor/cmd/cosmovisor@v1.7.1 < /dev/null > " $COSMOVISOR_LOG " 2>&1 &
1507+ else
1508+ GOBIN=" $GO_BIN_DIR " go install cosmossdk.io/tools/cosmovisor/cmd/cosmovisor@v1.7.1 < /dev/null > " $COSMOVISOR_LOG " 2>&1 &
1509+ fi
14591510 GO_PID=$!
1460- # Show spinner while go install runs
1511+
1512+ # Show spinner while go install runs (TTY only)
14611513 if [[ -t 1 ]]; then
14621514 spin_chars=' ⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
14631515 i=0
@@ -1466,16 +1518,18 @@ if ! command -v cosmovisor >/dev/null 2>&1; then
14661518 sleep 0.1 2> /dev/null || sleep 1
14671519 done
14681520 printf " \r\033[K"
1469- else
1470- # Non-TTY: just wait silently
1471- wait " $GO_PID "
14721521 fi
1473- wait " $GO_PID " 2> /dev/null
1474- GO_EXIT=$?
1522+
1523+ # Capture exit code (works for both TTY and non-TTY)
1524+ GO_EXIT=0
1525+ wait " $GO_PID " 2> /dev/null || GO_EXIT=$?
1526+
1527+ # Clean up temporary Go installation
1528+ [[ -n " $TEMP_GO_DIR " && -d " $TEMP_GO_DIR " ]] && rm -rf " $TEMP_GO_DIR "
1529+
14751530 if [[ $GO_EXIT -eq 0 ]]; then
14761531 rm -f " $COSMOVISOR_LOG "
14771532 # Ensure go bin directory is in PATH for current session and future shells
1478- GO_BIN_DIR=" ${GOBIN:- ${GOPATH:- $HOME / go} / bin} "
14791533 export PATH=" $GO_BIN_DIR :$PATH "
14801534 # Persist to shell profile if not already there
14811535 SHELL_CONFIG=" ${HOME} /.bashrc"
@@ -1487,8 +1541,23 @@ if ! command -v cosmovisor >/dev/null 2>&1; then
14871541 fi
14881542 ok " Cosmovisor v1.7.1 installed"
14891543 else
1490- err " Cosmovisor installation failed (see $COSMOVISOR_LOG )"
1491- exit 1
1544+ # Check if failure is due to Go compatibility issue
1545+ if [[ -f " $COSMOVISOR_LOG " ]] && grep -q " invalid reference to encoding/json" " $COSMOVISOR_LOG " 2> /dev/null; then
1546+ warn " Cosmovisor build failed (Go compatibility issue)"
1547+ warn " Automatic chain upgrades will not be available"
1548+ warn " You can install cosmovisor manually with Go 1.23"
1549+ rm -f " $COSMOVISOR_LOG "
1550+ # Continue without cosmovisor - the validator can still run
1551+ else
1552+ # Show actual error for debugging
1553+ if [[ -f " $COSMOVISOR_LOG " ]]; then
1554+ err " Cosmovisor installation failed:"
1555+ cat " $COSMOVISOR_LOG " | head -5
1556+ else
1557+ err " Cosmovisor installation failed (no log file)"
1558+ fi
1559+ exit 1
1560+ fi
14921561 fi
14931562else
14941563 ok " Cosmovisor already installed"
@@ -1660,7 +1729,7 @@ if [[ "$AUTO_START" = "yes" ]]; then
16601729 fi
16611730
16621731 # Prompt for validator registration if not already registered
1663- if [[ " $INTERACTIVE " == " yes" ]] && [[ " $ALREADY_VALIDATOR " == " no" ]]; then
1732+ if [[ " ${ INTERACTIVE:- } " == " yes" ]] && [[ " ${ ALREADY_VALIDATOR:- } " == " no" ]]; then
16641733 echo
16651734 echo " Next steps to become a validator:"
16661735 echo " 1. Get test tokens from: https://faucet.push.org"
@@ -1669,10 +1738,10 @@ if [[ "$AUTO_START" = "yes" ]]; then
16691738 fi
16701739
16711740 # Guard registration prompt in non-interactive mode
1672- if [[ " $ALREADY_VALIDATOR " == " yes" ]]; then
1741+ if [[ " ${ ALREADY_VALIDATOR:- } " == " yes" ]]; then
16731742 RESP=" N"
16741743 else
1675- if [[ " $INTERACTIVE " == " yes" ]]; then
1744+ if [[ " ${ INTERACTIVE:- } " == " yes" ]]; then
16761745 if [[ -e /dev/tty ]]; then
16771746 read -r -p " Register as a validator now? (y/N) " RESP < /dev/tty 2> /dev/tty || true
16781747 else
@@ -1698,7 +1767,7 @@ if [[ "$AUTO_START" = "yes" ]]; then
16981767 # Ensure clean separation before summary
16991768 echo
17001769 # Only mark as skipped if user declined and was not already a validator
1701- if [[ " $ALREADY_VALIDATOR " != " yes" ]]; then
1770+ if [[ " ${ ALREADY_VALIDATOR:- } " != " yes" ]]; then
17021771 REGISTRATION_STATUS=" skipped"
17031772 fi
17041773 ;;
@@ -1733,15 +1802,15 @@ else
17331802 STATUS_JSON=$( " $MANAGER_BIN " status --output json < /dev/null 2> /dev/null || echo " {}" )
17341803fi
17351804if command -v jq > /dev/null 2>&1 ; then
1736- NETWORK=$( echo " $STATUS_JSON " | jq -r ' .network // .node.network // empty' 2> /dev/null)
1737- MONIKER=$( echo " $STATUS_JSON " | jq -r ' .moniker // .node.moniker // empty' 2> /dev/null)
1738- SYNCED=$( echo " $STATUS_JSON " | jq -r ' .synced // .node.synced // empty' 2> /dev/null)
1739- PEERS=$( echo " $STATUS_JSON " | jq -r ' .peers // .node.peers // empty' 2> /dev/null)
1805+ NETWORK=$( echo " $STATUS_JSON " | jq -r ' .network // .node.network // empty' 2> /dev/null || true )
1806+ MONIKER=$( echo " $STATUS_JSON " | jq -r ' .moniker // .node.moniker // empty' 2> /dev/null || true )
1807+ SYNCED=$( echo " $STATUS_JSON " | jq -r ' .synced // .node.synced // empty' 2> /dev/null || true )
1808+ PEERS=$( echo " $STATUS_JSON " | jq -r ' .peers // .node.peers // empty' 2> /dev/null || true )
17401809else
1741- NETWORK=$( echo " $STATUS_JSON " | grep -o ' "network"[[:space:]]*:[[:space:]]*"[^"]*"' | sed ' s/.*"network"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' )
1742- MONIKER=$( echo " $STATUS_JSON " | grep -o ' "moniker"[[:space:]]*:[[:space:]]*"[^"]*"' | sed ' s/.*"moniker"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' )
1743- SYNCED=$( echo " $STATUS_JSON " | grep -o ' "synced"[[:space:]]*:[[:space:]]*"[^"]*"' | sed ' s/.*"synced"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' )
1744- PEERS=$( echo " $STATUS_JSON " | grep -o ' "peers"[[:space:]]*:[[:space:]]*[0-9]*' | sed ' s/.*"peers"[[:space:]]*:[[:space:]]*\([0-9]*\).*/\1/' )
1810+ NETWORK=$( echo " $STATUS_JSON " | grep -o ' "network"[[:space:]]*:[[:space:]]*"[^"]*"' | sed ' s/.*"network"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' || true )
1811+ MONIKER=$( echo " $STATUS_JSON " | grep -o ' "moniker"[[:space:]]*:[[:space:]]*"[^"]*"' | sed ' s/.*"moniker"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' || true )
1812+ SYNCED=$( echo " $STATUS_JSON " | grep -o ' "synced"[[:space:]]*:[[:space:]]*"[^"]*"' | sed ' s/.*"synced"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' || true )
1813+ PEERS=$( echo " $STATUS_JSON " | grep -o ' "peers"[[:space:]]*:[[:space:]]*[0-9]*' | sed ' s/.*"peers"[[:space:]]*:[[:space:]]*\([0-9]*\).*/\1/' || true )
17451814fi
17461815
17471816# Determine node status indicator
@@ -1751,7 +1820,7 @@ if [[ "$SYNCED" == "true" ]]; then
17511820fi
17521821
17531822VALIDATOR_STATUS_ICON=" ❌"
1754- if [[ " $ALREADY_VALIDATOR " == " yes" ]]; then
1823+ if [[ " ${ ALREADY_VALIDATOR:- } " == " yes" ]]; then
17551824 VALIDATOR_STATUS_ICON=" ✅"
17561825fi
17571826
@@ -1769,7 +1838,7 @@ echo
17691838echo " 📊 Node Status"
17701839echo " $NODE_STATUS_ICON Synced"
17711840echo " 🌐 Peers: $PEERS "
1772- if [[ " $ALREADY_VALIDATOR " == " yes" ]]; then
1841+ if [[ " ${ ALREADY_VALIDATOR:- } " == " yes" ]]; then
17731842 echo " $VALIDATOR_STATUS_ICON Validator Registered"
17741843fi
17751844echo
@@ -1793,13 +1862,13 @@ echo " • View dashboard: push-validator dashboard"
17931862echo " • View logs: push-validator logs"
17941863echo " • Stop node: push-validator stop"
17951864echo " • Restart node: push-validator restart"
1796- if [[ " $ALREADY_VALIDATOR " == " no" ]]; then
1865+ if [[ " ${ ALREADY_VALIDATOR:- } " == " no" ]]; then
17971866 echo " • Register: push-validator register-validator"
17981867fi
17991868echo " • All commands: push-validator help"
18001869echo
18011870
1802- if [[ " $INTERACTIVE " == " yes" ]]; then
1871+ if [[ " ${ INTERACTIVE:- } " == " yes" ]]; then
18031872 # Interactive mode: show registration action status and pause before dashboard
18041873 echo
18051874 case " $REGISTRATION_STATUS " in
0 commit comments