[node] new node.sh 3.0

* greatly simplified the node.sh to remove the legacy code
* mainly used to download latest harmony binaries
* added signature verification using gpg
* add ethrelay/btcrelay placeholder

Signed-off-by: Leo Chen <leo@harmony.one>
pull/3480/head
Leo Chen 4 years ago
parent 2877d3d769
commit 05de30e546
  1. 926
      scripts/node.sh

@ -1,838 +1,206 @@
#!/usr/bin/env bash
version="v2 20201023.0"
set -eu
unset -v progname
progname="${0##*/}"
unset -f msg err
msg() {
case $# in
[1-9]*)
echo "${progname}: $*" >&2
;;
esac
}
# This script is used to download latest harmony node release
# And run the binary. Many codes are copied from prysm.sh (eth2 client).
# Downloaded binaries is saved in staging/ directory
# Use HARMONY_RELEASE to specify a specific release version
# Example: HARMONY_RELEASE=v3.0.0 ./node.sh harmony
err() {
local code
code="${1}"
shift 1
msg "$@"
exit "${code}"
}
HARMONY_SIGNING_KEY=539910B02B5BAC637F6615C9799ACE3A9B83DF60
DOWNLOAD_URL=https://github.com/harmony-one/harmony/releases/download
HARMONY_PUB_KEY=https://harmony.one/releases/pgp_keys.asc
version="v3 20201206.0"
# b: beginning
# r: range
# return random number between b ~ b+r
random() {
local b=$1
local r=$2
if [ $r -le 0 ]; then
r=100
fi
local rand=$(( $(od -A n -t d -N 3 /dev/urandom | grep -oE '[0-9]+') % r ))
echo $(( b + rand ))
}
unset -f progname color usage print_usage get_version do_verify do_download
progname="${0##*/}"
# https://www.linuxjournal.com/content/validating-ip-address-bash-script
function valid_ip()
{
local ip=$1
local stat=1
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
OIFS=$IFS
IFS='.'
ip=($ip)
IFS=$OIFS
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
&& ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
stat=$?
color() {
# Usage: color "31;5" "string"
# Some valid values for color:
# - 5 blink, 1 strong, 4 underlined
# - fg: 31 red, 32 green, 33 yellow, 34 blue, 35 purple, 36 cyan, 37 white
# - bg: 40 black, 41 red, 44 blue, 45 purple
printf '\033[%sm%s\033[0m\n' "$@"
}
# return the harmony release version
get_version() {
if [[ -n ${HARMONY_RELEASE:-} ]]; then
readonly reason="specified in \$HARMONY_RELEASE"
readonly harmony_rel="${HARMONY_RELEASE}"
else
# Find the latest Harmony release available for download.
readonly reason="automatically selected latest available release"
harmony_rel=$(curl -f -s https://harmony.one/releases/latest) || (color "31" "Get latest version failed. You may manually download the binaries from Github release page. https://github.com/harmony-one/harmony/releases/" && exit 1)
readonly harmony_rel
fi
return $stat
}
function myip() {
# get ipv4 address only, right now only support ipv4 addresses
PUB_IP=$(dig -4 TXT +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'"' '{ print $2}')
if valid_ip $PUB_IP; then
msg "public IP address autodetected: $PUB_IP"
else
err 1 "NO valid public IP found: $PUB_IP"
fi
}
function check_root
{
if [[ $EUID -ne 0 ]]; then
msg "this script must be run as root to setup environment"
msg please use \"sudo ${progname}\"
msg "you may use -S option to run as normal user"
exit 1
fi
}
function add_env
{
filename=$1
shift
grep -qxF "$@" $filename || echo "$@" >> $filename
}
function setup_env
{
check_root
### KERNEL TUNING ###
# Increase size of file handles and inode cache
sysctl -w fs.file-max=2097152
# Do less swapping
sysctl -w vm.swappiness=10
sysctl -w vm.dirty_ratio=60
sysctl -w vm.dirty_background_ratio=2
# Sets the time before the kernel considers migrating a proccess to another core
sysctl -w kernel.sched_migration_cost_ns=5000000
### GENERAL NETWORK SECURITY OPTIONS ###
# Number of times SYNACKs for passive TCP connection.
sysctl -w net.ipv4.tcp_synack_retries=2
# Allowed local port range
sysctl -w net.ipv4.ip_local_port_range='2000 65535'
# Protect Against TCP Time-Wait
sysctl -w net.ipv4.tcp_rfc1337=1
# Control Syncookies
sysctl -w net.ipv4.tcp_syncookies=1
# Decrease the time default value for tcp_fin_timeout connection
sysctl -w net.ipv4.tcp_fin_timeout=15
# Decrease the time default value for connections to keep alive
sysctl -w net.ipv4.tcp_keepalive_time=300
sysctl -w net.ipv4.tcp_keepalive_probes=5
sysctl -w net.ipv4.tcp_keepalive_intvl=15
### TUNING NETWORK PERFORMANCE ###
# Default Socket Receive Buffer
sysctl -w net.core.rmem_default=31457280
# Maximum Socket Receive Buffer
sysctl -w net.core.rmem_max=33554432
# Default Socket Send Buffer
sysctl -w net.core.wmem_default=31457280
# Maximum Socket Send Buffer
sysctl -w net.core.wmem_max=33554432
# Increase number of incoming connections
sysctl -w net.core.somaxconn=8096
# Increase number of incoming connections backlog
sysctl -w net.core.netdev_max_backlog=65536
# Increase the maximum amount of option memory buffers
sysctl -w net.core.optmem_max=25165824
sysctl -w net.ipv4.tcp_max_syn_backlog=8192
# Increase the maximum total buffer-space allocatable
# This is measured in units of pages (4096 bytes)
sysctl -w net.ipv4.tcp_mem='786432 1048576 26777216'
sysctl -w net.ipv4.udp_mem='65536 131072 262144'
# Increase the read-buffer space allocatable
sysctl -w net.ipv4.tcp_rmem='8192 87380 33554432'
sysctl -w net.ipv4.udp_rmem_min=16384
# Increase the write-buffer-space allocatable
sysctl -w net.ipv4.tcp_wmem='8192 65536 33554432'
sysctl -w net.ipv4.udp_wmem_min=16384
# Increase the tcp-time-wait buckets pool size to prevent simple DOS attacks
sysctl -w net.ipv4.tcp_max_tw_buckets=1440000
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.tcp_fastopen=3
sysctl -w net.ipv4.tcp_window_scaling=1
add_env /etc/security/limits.conf "* soft nproc 65535"
add_env /etc/security/limits.conf "* hard nproc 65535"
add_env /etc/security/limits.conf "* soft nofile 65535"
add_env /etc/security/limits.conf "* hard nofile 65535"
add_env /etc/security/limits.conf "root soft nproc 65535"
add_env /etc/security/limits.conf "root hard nproc 65535"
add_env /etc/security/limits.conf "root soft nofile 65535"
add_env /etc/security/limits.conf "root hard nofile 65535"
add_env /etc/pam.d/common-session "session required pam_limits.so"
}
function check_pkg_management
{
if which yum > /dev/null; then
PKG_INSTALL='sudo yum install -y'
return
fi
if which apt-get > /dev/null; then
PKG_INSTALL='sudo apt-get install -y'
return
fi
}
######## main #########
print_usage() {
cat <<- ENDEND
usage: ${progname} [options]
usage: ${progname} [OPTIONS] PROCESS [ARGS]
PROCESS can be: validator/harmony, btcrelay, ethrelay
options:
-c back up database/logs and start clean (not for mainnet)
(use only when directed by Harmony)
-C disable interactive console for bls passphrase (default: enabled)
-1 do not loop; run once and exit
OPTIONS:
-h print this help and exit
-k KEYFILE use the given BLS key files
-s run setup env only (must run as root)
-S run the ${progname} as non-root user (default: run as root)
-p passfile use the given BLS passphrase file
-d just download the Harmony binaries (default: off)
-D do not download Harmony binaries (default: download when start)
-N network join the given network (mainnet, testnet, staking, partner, stress, devnet, tnet; default: mainnet)
-n port specify the public base port of the node (default: 9000)
-T nodetype specify the node type (validator, explorer; default: validator)
-i shardid specify the shard id (valid only with explorer node; default: 1)
-a dbfile specify the db file to download (default:off)
-U FOLDER specify the upgrade folder to download binaries
-P enable public rpc end point (default:off)
-d download only (default: off)
-v print out the version of the node.sh
-V print out the version of the Harmony binary
-z run in staking mode
-y run in legacy, foundational-node mode (default)
-Y verify the signature of the downloaded binaries (default: off)
-m minpeer specify minpeers for bootstrap (default: 6)
-f blsfolder folder that stores the bls keys and corresponding passphrases (default: ./.hmy/blskeys)
-A enable archival node mode (default: off)
-B blacklist specify file containing blacklisted accounts as a newline delimited file (default: ./.hmy/blacklist.txt)
-r address start a pprof profiling server listening on the specified address
-I use statically linked Harmony binary (default: true)
-R tracefile enable p2p trace using tracefile (default: off)
-l limit broadcasting of invalid transactions (default: off)
-L log_level logging verbosity: 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail (default: $log_level)
examples:
# start node program with all key/passphrase under .hmy/blskeys
# first try to unlock account with .pass file. If pass file not exist or cannot decrypt, prompt to get passphrase.
${progname} -S
# start node program w/o accounts
${progname} -S -k mybls1.key,mybls2.key
ARGS will be passed to the PROCESS.
# download beacon chain (shard0) db snapshot
${progname} -i 0 -b
Ex:
${progname} -d validator
${progname} validator --help
${progname} validator --run explorer --run.shard=0
# just re-download the harmony binaries
${progname} -d
# start a non-validating node in shard 1
# you need to have a dummy BLSKEY/pass file using 'touch BLSKEY; touch blspass'
${progname} -S -k BLSKEY -p blspass -T explorer -i 1
ENDEND
}
# upgrade harmony binaries from specified repo
${progname} -1 -U upgrade
usage() {
color "31" "$@"
print_usage >&2
exit 64 # EX_USAGE
}
# start the node in a different port 9010
${progname} -n 9010
failed_verification() {
MSG=$(
cat <<-END
Failed to verify Harmony binary. Please erase downloads in the
staging directory and run this script again. Alternatively, you can use a
A prior version by specifying environment variable HARMONY_RELEASE
with the specific version, as desired. Example: HARMONY_RELEASE=v2.4.0
If you must wish to continue running an unverified binary, specific the
environment variable HARMONY_UNVERIFIED=1
END
)
color "31" "$MSG"
exit 1
}
do_verify() {
local file=$1
local binary="${file}-${arch}"
skip=${HARMONY_UNVERIFIED-0}
if [[ $skip == 1 ]]; then
return 0
fi
checkSum="shasum -a 256"
hash shasum 2>/dev/null || {
checkSum="sha256sum"
hash sha256sum 2>/dev/null || {
echo >&2 "SHA checksum utility not available. Either install one (shasum or sha256sum) or run with HARMONY_UNVERIFIED=1."
exit 1
}
}
hash gpg 2>/dev/null || {
echo >&2 "gpg is not available. Either install it or run with HARMONY_UNVERIFIED=1."
exit 1
}
# multi-bls: specify folder that contains bls keys
${progname} -S -f /home/xyz/myfolder
color "32" "Verifying binary integrity."
# multi-bls using default passphrase: place all keys under .hmy/blskeys
# supply passphrase file using -p option (single passphrase will be used for all bls keys)
${progname} -S -p blspass.txt
gpg --list-keys $HARMONY_SIGNING_KEY >/dev/null 2>&1 || curl --silent -L $HARMONY_PUB_KEY | gpg --import
(
cd "$wrapper_dir"
$checkSum -c "${binary}.sha256" || failed_verification
)
(
cd "$wrapper_dir"
gpg -u $HARMONY_SIGNING_KEY --verify "${binary}.sig" "$binary" || failed_verification
)
# disable interactive console for passphrase (prepare .pass file before running command)
${progname} -S -C
color "32;1" "Verified ${binary} has been signed by Harmony."
}
do_download() {
local file=$1
local binary="${file}-${arch}"
ENDEND
}
if [[ ! -x "${wrapper_dir}/${binary}" ]]; then
color "32" "Downloading ${binary} (${reason})"
usage() {
msg "$@"
print_usage >&2
exit 64 # EX_USAGE
curl -L "${DOWNLOAD_URL}/${harmony_rel}/${binary}" -o "${wrapper_dir}/${binary}"
curl --silent -L "${DOWNLOAD_URL}/${harmony_rel}/${binary}.sha256" -o "${wrapper_dir}/${binary}.sha256"
curl --silent -L "${DOWNLOAD_URL}/${harmony_rel}/${binary}.sig" -o "${wrapper_dir}/${binary}.sig"
chmod +x "${wrapper_dir}/${binary}"
else
color "37" "${binary} is up to date."
fi
cp -f "${wrapper_dir}/${binary}" "$file"
}
# =======
BUCKET=pub.harmony.one
OS=$(uname -s)
unset start_clean loop run_as_root blspass do_not_download download_only network node_type shard_id broadcast_invalid_tx
unset upgrade_rel public_rpc staking_mode pub_port blsfolder blacklist verify TRACEFILE minpeers max_bls_keys_per_node log_level
unset no_bls_pass_prompt
start_clean=false
loop=true
run_as_root=true
do_not_download=false
download_only=false
network=mainnet
node_type=validator
shard_id=-1
public_rpc=false
staking_mode=false
archival=false
blacklist=./.hmy/blacklist.txt
pprof=""
static=true
verify=false
minpeers=6
max_bls_keys_per_node=10
broadcast_invalid_tx=true
log_level=3
no_bls_pass_prompt=false
${BLSKEYFILES=}
${TRACEFILE=}
unset OPTIND OPTARG opt
unset OPTIND OPTARG opt download_only
OPTIND=1
while getopts :1cChk:sSp:dDN:T:i:U:PvVyzn:MAIB:r:Y:f:R:m:L:l opt
download_only=false
while getopts ":hdvV" opt
do
case "${opt}" in
'?') usage "unrecognized option -${OPTARG}";;
':') usage "missing argument for -${OPTARG}";;
c) start_clean=true;;
C) no_bls_pass_prompt=true;;
1) loop=false;;
h) print_usage; exit 0;;
k) BLSKEYFILES="${OPTARG}";;
s) setup_env; exit 0;;
S) run_as_root=false ;;
p) blspass="${OPTARG}";;
d) download_only=true;;
D) do_not_download=true;;
m) minpeers="${OPTARG}";;
f) blsfolder="${OPTARG}";;
N) network="${OPTARG}";;
n) pub_port="${OPTARG}";;
T) node_type="${OPTARG}";;
i) shard_id="${OPTARG}";;
I) static=true;;
U) upgrade_rel="${OPTARG}";;
P) public_rpc=true;;
B) blacklist="${OPTARG}";;
r) pprof="${OPTARG}";;
v) msg "version: $version"
v) color "32" "$progname version: $version"
exit 0 ;;
V) INSTALLED_VERSION=$(LD_LIBRARY_PATH=. ./harmony version 2>&1)
V) INSTALLED_VERSION=$(./harmony version 2>&1)
RUNNING_VERSION=$(curl -s --request POST 'http://127.0.0.1:9500/' --header 'Content-Type: application/json' --data-raw '{ "jsonrpc": "2.0", "method": "hmyv2_getNodeMetadata", "params": [], "id": 1}' | grep -Eo '"version":"[^"]*"' | cut -c11- | tr -d \")
echo "Binary Version: $INSTALLED_VERSION"
echo "Running Version: $RUNNING_VERSION"
exit 0 ;;
Y) verify=true;;
z) staking_mode=true;;
y) staking_mode=false;;
A) archival=true;;
R) TRACEFILE="${OPTARG}";;
l) broadcast_invalid_tx=false;;
L) log_level="${OPTARG}";;
M) msg "WARNING: deprecated flag -M: Multi BLS is always enabled, and it's safe to remove this flag.";;
*) err 70 "unhandled option -${OPTARG}";; # EX_SOFTWARE
*) color "31" "unhandled option -${OPTARG}";; # EX_SOFTWARE
esac
done
shift $((${OPTIND} - 1))
unset -v bootnodes REL network_type dns_zone syncdir
case "${node_type}" in
validator) ;;
explorer) archival=true;;
*)
usage ;;
esac
case "${network}" in
mainnet)
bootnodes=(
/ip4/100.26.90.187/tcp/9874/p2p/Qmdfjtk6hPoyrH1zVD9PEH4zfWLo38dP2mDvvKXfh3tnEv
/ip4/54.213.43.194/tcp/9874/p2p/QmZJJx6AdaoEkGLrYG4JeLCKeCKDjnFz2wfHNHxAqFSGA9
/ip4/13.113.101.219/tcp/12019/p2p/QmQayinFSgMMw5cSpDUiD9pQ2WeP6WNmGxpZ6ou3mdVFJX
/ip4/99.81.170.167/tcp/12019/p2p/QmRVbTpEYup8dSaURZfF6ByrMTSKa4UyUzJhSjahFzRqNj
)
REL=main_v2
network_type=mainnet
dns_zone=t.hmny.io
syncdir=mainnet.min
;;
testnet)
bootnodes=(
/ip4/54.86.126.90/tcp/9850/p2p/Qmdfjtk6hPoyrH1zVD9PEH4zfWLo38dP2mDvvKXfh3tnEv
/ip4/52.40.84.2/tcp/9850/p2p/QmbPVwrqWsTYXq1RxGWcxx9SWaTUCfoo1wA6wmdbduWe29
)
REL=testnet
network_type=testnet
dns_zone=b.hmny.io
syncdir=lrtn
;;
staking)
bootnodes=(
/ip4/54.86.126.90/tcp/9867/p2p/Qmdfjtk6hPoyrH1zVD9PEH4zfWLo38dP2mDvvKXfh3tnEv
/ip4/52.40.84.2/tcp/9867/p2p/QmbPVwrqWsTYXq1RxGWcxx9SWaTUCfoo1wA6wmdbduWe29
)
REL=pangaea
network_type=pangaea
dns_zone=os.hmny.io
syncdir=ostn
;;
partner)
bootnodes=(
/ip4/52.40.84.2/tcp/9800/p2p/QmbPVwrqWsTYXq1RxGWcxx9SWaTUCfoo1wA6wmdbduWe29
/ip4/54.86.126.90/tcp/9800/p2p/Qmdfjtk6hPoyrH1zVD9PEH4zfWLo38dP2mDvvKXfh3tnEv
)
REL=partner
network_type=partner
dns_zone=ps.hmny.io
syncdir=pstn
;;
stn|stress|stressnet)
bootnodes=(
/ip4/52.40.84.2/tcp/9842/p2p/QmbPVwrqWsTYXq1RxGWcxx9SWaTUCfoo1wA6wmdbduWe29
)
REL=stressnet
network_type=stressnet
dns_zone=stn.hmny.io
syncdir=stn
;;
*)
err 64 "${network}: invalid network"
;;
esac
case $# in
[1-9]*)
usage "extra arguments at the end ($*)"
;;
esac
# reset REL if upgrade_rel is set
if [ -n "$upgrade_rel" ]; then
REL="${upgrade_rel}"
shift $((OPTIND - 1))
if [ "$#" -lt 1 ]; then
usage "Missing PROCESS parameter"
fi
if [ "$OS" == "Darwin" ]; then
FOLDER=release/darwin-x86_64/$REL
fi
if [ "$OS" == "Linux" ]; then
FOLDER=release/linux-x86_64/$REL
if [ "$static" == "true" ]; then
FOLDER=${FOLDER}/static
fi
fi
extract_checksum() {
awk -v basename="${1}" '
{
s = $0;
}
# strip hash and following space; skip line if unsuccessful
sub(/^[0-9a-f]+ /, "", s) == 0 { next; }
# save hash
{ hash = substr($0, 1, length($0) - length(s) - 1); }
# strip executable indicator (space or asterisk); skip line if unsuccessful
sub(/^[* ]/, "", s) == 0 { next; }
# leave basename only
{ sub(/^.*\//, "", s); }
# if basename matches, print the hash and basename
s == basename { printf "%s %s\n", hash, basename; }
'
}
get_version
color "37" "Latest Harmony release is: $harmony_rel."
verify_checksum() {
local dir file checksum_file checksum_for_file
dir="${1}"
file="${2}"
checksum_file="${3}"
[ -f "${dir}/${checksum_file}" ] || return 0
checksum_for_file="${dir}/${checksum_file}::${file}"
extract_checksum "${file}" < "${dir}/${checksum_file}" > "${checksum_for_file}"
[ -s "${dir}/${checksum_for_file}" ] || return 0
if ! (cd "${dir}" && exec md5sum -c --status "${checksum_for_file}")
then
msg "checksum FAILED for ${file}"
return 1
fi
return 0
}
verify_signature() {
local dir file
dir="${1}"
file="${dir}/${2}"
sigfile="${dir}/${2}.sig"
readonly wrapper_dir="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")/staging/${harmony_rel}"
VALIDATOR="harmony"
BTCRELAY="hmy-btcrelay"
ETHRELAY="hmy-ethrelay"
mkdir -p "${wrapper_dir}"
result=$(openssl dgst -sha256 -verify "${outdir}/harmony_pubkey.pem" -signature "${sigfile}" "${file}" 2>&1)
echo ${result}
if [[ ${result} != "Verified OK" ]]; then
return 1
fi
return 0
}
arch=$(uname -m)
arch=${arch/x86_64/amd64}
arch=${arch/aarch64/arm64}
download_binaries() {
local outdir status
${do_not_download} && return 0
outdir="${1}"
mkdir -p "${outdir}"
for bin in $(cut -c35- "${outdir}/md5sum.txt"); do
status=0
curl -sSf http://${BUCKET}.s3.amazonaws.com/${FOLDER}/${bin} -o "${outdir}/${bin}" || status=$?
case "${status}" in
0) ;;
*)
msg "cannot download ${bin} (status ${status})"
return ${status}
;;
esac
if $verify; then
curl -sSf http://${BUCKET}.s3.amazonaws.com/${FOLDER}/${bin}.sig -o "${outdir}/${bin}.sig" || status=$?
case "${status}" in
0) ;;
*)
msg "cannot download ${bin}.sig (status ${status})"
return ${status}
;;
esac
verify_signature "${outdir}" "${bin}" || return $?
fi
verify_checksum "${outdir}" "${bin}" md5sum.txt || return $?
msg "downloaded ${bin}"
done
chmod +x "${outdir}/harmony" "${outdir}/node.sh"
(cd "${outdir}" && exec openssl sha256 $(cut -c35- md5sum.txt)) > "${outdir}/harmony-checksums.txt"
}
_curl_check_exist() {
local url=$1
local statuscode=$(curl -I --silent --output /dev/null --write-out "%{http_code}" $url)
if [ $statuscode -ne 200 ]; then
return 1
else
return 0
fi
}
_curl_download() {
local url=$1
local outdir=$2
local filename=$3
mkdir -p "${outdir}"
if _curl_check_exist $url; then
curl --progress-bar -Sf $url -o "${outdir}/$filename" || return $?
return 0
else
msg "failed to find/download $url"
return 1
fi
}
case "$1" in
validator|harmony)
readonly process=${VALIDATOR}
;;
btcrelay)
readonly process=${BTCRELAY}
;;
ethrelay)
readonly process=${ETHRELAY}
;;
*)
usage "Process $1 is not found"
;;
esac
any_new_binaries() {
local outdir
${do_not_download} && return 0
outdir="${1}"
mkdir -p "${outdir}"
if ${verify}; then
curl -L https://harmony.one/pubkey -o "${outdir}/harmony_pubkey.pem"
if ! grep -q "BEGIN\ PUBLIC\ KEY" "${outdir}/harmony_pubkey.pem"; then
msg "failed to downloaded harmony public signing key"
return 1
fi
fi
curl -sSf http://${BUCKET}.s3.amazonaws.com/${FOLDER}/md5sum.txt -o "${outdir}/md5sum.txt.new" || return $?
if diff "${outdir}/md5sum.txt.new" "${outdir}/md5sum.txt"
then
rm "${outdir}/md5sum.txt.new"
else
mv "${outdir}/md5sum.txt.new" "${outdir}/md5sum.txt"
return 1
fi
return 0
}
do_download "${process}"
do_verify "${process}"
if ${download_only}; then
if any_new_binaries staging
then
msg "binaries did not change in staging"
else
download_binaries staging || err 69 "download node software failed"
msg "downloaded files are in staging direectory"
fi
color "37" "Only download operation is requested, done."
exit 0
fi
if ${run_as_root}; then
check_root
fi
if any_new_binaries .
then
msg "binaries did not change"
else
download_binaries . || err 69 "initial node software update failed"
fi
NODE_PORT=${pub_port:-9000}
PUB_IP=
if [ "$OS" == "Linux" ]; then
if ${run_as_root}; then
setup_env
fi
fi
# find my public ip address
myip
check_pkg_management
unset -v BN_MA bn
for bn in "${bootnodes[@]}"
do
BN_MA="${BN_MA+"${BN_MA},"}${bn}"
done
if [[ "${start_clean}" == "true" && "${network_type}" != "mainnet" ]]
then
msg "cleaning up old database (-c)"
# set a 2s timeout, and set its default return value to Y (true)
read -t 2 -rp "Remove old database? (Y/n) " yesno
yesno=${yesno:-Y}
echo
if [[ "$yesno" == "y" || "$yesno" == "Y" ]]; then
unset -v backup_dir now
now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
mkdir -p backups; rm -rf backups/*
backup_dir=$(mktemp -d "backups/${now}.XXXXXX")
mv -f harmony_db_* .dht* "${backup_dir}/" 2>/dev/null || :
fi
# install unzip as dependency of rclone
if ! which unzip > /dev/null; then
$PKG_INSTALL unzip
fi
# do rclone sync
if ! which rclone > /dev/null; then
msg "installing rclone to fast sync db"
msg "curl https://rclone.org/install.sh | sudo bash"
curl https://rclone.org/install.sh | sudo bash
mkdir -p ~/.config/rclone
fi
if ! grep -q 'hmy' ~/.config/rclone/rclone.conf 2> /dev/null; then
msg "adding [hmy] profile to rclone.conf"
cat<<-EOT>>~/.config/rclone/rclone.conf
[hmy]
type = s3
provider = AWS
env_auth = false
region = us-west-1
acl = public-read
EOT
fi
msg "Syncing harmony_db_0"
rclone sync -P hmy://pub.harmony.one/$syncdir/harmony_db_0 harmony_db_0
fi
mkdir -p latest
unset -v check_update_pid
cleanup() {
local trap_sig kill_sig
trap_sig="${1:-EXIT}"
kill_sig="${trap_sig}"
case "${kill_sig}" in
0|EXIT|2|INT) kill_sig=TERM;;
esac
case "${check_update_pid+set}" in
set)
msg "terminating update checker (pid ${check_update_pid})"
kill -${kill_sig} "${check_update_pid}"
;;
esac
}
unset -v trap_sigs trap_sig
trap_sigs="EXIT HUP INT TERM"
trap_func() {
local trap_sig="${1-EXIT}"
case "${trap_sig}" in
0|EXIT) msg "exiting";;
*) msg "received SIG${trap_sig}";;
esac
trap - ${trap_sigs}
cleanup "${trap_sig}"
case "${trap_sig}" in
""|0|EXIT) ;;
*) kill -"${trap_sig}" "$$";;
esac
}
for trap_sig in ${trap_sigs}
do
trap "trap_func ${trap_sig}" ${trap_sig}
done
# Kill the given PID, ensuring that it is a child of this script ($$).
kill_child() {
local pid
pid="${1}"
case $(($(ps -oppid= -p"${pid}" || :) + 0)) in
$$) ;;
*) return 1;;
esac
msg "killing pid ${pid}"
kill "${pid}"
}
# Kill nodes that are direct child of this script (pid $$),
# i.e. run directly from main loop.
kill_node() {
local pids pid delay
msg "finding node processes that are our children"
pids=$(
ps axcwwo "pid=,ppid=,command=" |
awk -v me=$$ '$2 == me && $3 == "harmony" { print $1; }'
)
msg "found node processes: ${pids:-"<none>"}"
for pid in ${pids}
do
delay=0
while kill_child ${pid}
do
sleep ${delay}
delay=1
done
msg "pid ${pid} no longer running"
done
}
{
while ${loop}
do
msg "re-downloading binaries in 30~60m"
redl_sec=$( random 1800 1800 )
sleep $redl_sec
if any_new_binaries staging
then
msg "binaries did not change"
continue
fi
while ! download_binaries staging
do
msg "staging download failed; retrying in 10~30m"
retry_sec=$( random 600 1200 )
sleep $retry_sec
done
if diff staging/harmony-checksums.txt harmony-checksums.txt
then
msg "binaries did not change"
continue
fi
msg "binaries changed; moving from staging into main"
(cd staging; exec mv harmony-checksums.txt $(cut -c35- md5sum.txt) ..) || continue
msg "binaries updated, killing node to restart"
kill_node
done
} > harmony-update.out 2>&1 &
check_update_pid=$!
while :
do
msg "############### Running Harmony Process ###############"
args=(
--bootnodes "${BN_MA}"
--ip "${PUB_IP}"
--port "${NODE_PORT}"
--network_type="${network_type}"
--dns_zone="${dns_zone}"
--blacklist="${blacklist}"
--min_peers="${minpeers}"
--max_bls_keys_per_node="${max_bls_keys_per_node}"
--broadcast_invalid_tx="${broadcast_invalid_tx}"
--verbosity="${log_level}"
)
args+=(
--is_archival="${archival}"
)
if [ ! -z "$BLSKEYFILES" ]; then
args+=(
--blskey_file "${BLSKEYFILES}"
)
fi
if [ ! -z "$blsfolder" ]; then
args+=(
--blsfolder "${blsfolder}"
)
fi
if [ ! -z "$blspass" ]; then
args+=(
--blspass "file:${blspass}"
)
else
if $no_bls_pass_prompt; then
args+=(
--blspass no-prompt
)
fi
fi
if ${public_rpc}; then
args+=(
--public_rpc
)
else
args+=(
--public_rpc=false
)
fi
if [ ! -z "${pprof}" ]; then
args+=(
--pprof.addr "${pprof}"
)
fi
color "36" "Starting harmony $1 ${*:2}"
# backward compatible with older harmony node software
case "${node_type}" in
validator)
case "${shard_id}" in
?*)
args+=(
--shard_id="${shard_id}"
)
if [ ${staking_mode} == "false" ]; then
args+=(
--run.legacy
)
fi
;;
esac
;;
explorer)
args+=(
--node_type="${node_type}"
--shard_id="${shard_id}"
)
;;
esac
case "${TRACEFILE}" in
"") ;;
*) msg "WARN: enabled p2p tracefile: $TRACEFILE. Be aware of the file size."
export P2P_TRACEFILE=${TRACEFILE} ;;
esac
case "$OS" in
Darwin) ld_path_var=DYLD_FALLBACK_LIBRARY_PATH;;
*) ld_path_var=LD_LIBRARY_PATH;;
esac
env "${ld_path_var}=$(pwd)" ./harmony "${args[@]}" "${@}"
msg "node process finished with status $?"
${loop} || break
msg "restarting in 10s..."
sleep 10
done
exec -a "$0 ${process}" "./${process}" "${@:2}"
# vim: set expandtab:ts=3

Loading…
Cancel
Save