ghost-node/scripts/starter.sh

388 lines
14 KiB
Bash
Raw Permalink Normal View History

#!/bin/bash
set -Ee
CHECK_KEYS=false
INSERT_KEYS=false
UNIT_FILE=false
SKIP_BUILD=false
SET_ENVIRONMENT=false
EXECUTABLE_PATH="/usr/bin/"
SPECIFICATION_PATH="/etc/ghost/"
NODE_PATH="/var/lib/ghost"
SPECIFICATION_NAME="casper"
TARGET="release"
CURRENT_PATH=$(pwd)
CURRENT_SCRIPT=$(realpath "$0")
SCRIPT_FOLDER=$(dirname "$CURRENT_SCRIPT")
PROJECT_FOLDER=("$SCRIPT_FOLDER/..")
final() {
cd $CURRENT_PATH
if [[ $1 -eq 1 ]]; then
echo "[-] error occured during execution"
else
echo "[+] execution finished"
fi
exit $1
}
prompt() {
while true; do
printf "$1 [y/N]: "
read yn
case $yn in
[Yy]* ) return 0;;
* ) return 1;;
esac
done
}
sanity_check() {
secret_seed=$(ghost key inspect --scheme="$1" "$2" | grep "Secret seed" | awk '{ print $3 }')
account_id=$(ghost key inspect --scheme="$1" "$2" | grep "Account ID" | awk '{ print $3 }')
echo "[+] inspected account id for $3: $account_id"
num_keys=$(grep $account_id "$PROJECT_FOLDER/service/ghosties" | wc -l)
num_types=$(grep $account_id "$PROJECT_FOLDER/service/ghosties" | grep $3 | wc -l)
if [ ! $num_keys = 1 ] || [ ! $num_types = 1 ]; then
echo "[-] inspected account id not found on 'ghosties' file or wrong key type"
exit 1
fi
}
extract_seed() {
name_with_spaces=$(echo $1 | tr '-' ' ')
read -p "[?] path to the file with $name_with_spaces: (default: /etc/ghost/$1) " seed_path
seed_path="${seed_path:-/etc/ghost/$1}"
if [ ! -f $seed_path ]; then
echo "[-] path to $name_with_spaces is not valid"
fi
seed=$(cat $seed_path)
echo $seed
}
help() {
echo -e "Ghost Node Build automation tool. Helper for Ghost Node environment preparation.\n"
echo -e "With no OPTION nothing will happen, possible OPTION:\n"
echo -e "-i, --set-environment\n\tSet up rust environment."
echo -e "-u, --unit-file\n\tCreation of systemd unit file."
echo -e "-m, --make-global\n\tStore compiled ghost executable and chain specification globally."
echo -e "-a, --set-arguments\n\tPrepare CLI arguments for running ghost node."
echo -e "-k, --check-keys\n\tCheck if your keys are already included in 'ghosties' file."
echo -e "-r, --insert-keys\n\tInsert session keys to the keystore via JSON RPC."
echo -e "-r, --release\n\tCompile node with '--release' flag."
echo -e "-p, --profile\n\tCompile node with '--profile [PROFILE]' flag."
echo -e "-f, --features\n\tCompilation features '--features=\"FEATURE1,FEATURE2\"'"
echo -e "-e, --executable-path\n\tPath to executable ('/usr/lib/' is default)."
echo -e "-c, --specification-path\n\tPath to specification ('/etc/ghost' is default)."
echo -e "-n, --specification-name\n\tSpecification name to be used ('casper' is default)."
echo -e "-h, --help\n\tPrints help information."
}
trap 'final "$?"' EXIT
clear
echo " ____ _ _ _ _ _"
echo " / ___| |__ ___ ___| |_ | \ | | ___ __| | ___"
echo "| | _| '_ \ / _ \/ __| __| | \| |/ _ \ / _' |/ _ \\"
echo "| |_| | | | | (_) \__ \ |_ | |\ | (_) | (_| | __/"
echo " \____|_| |_|\___/|___/\__| |_| \_|\___/ \__,_|\___|"
echo -e "\nCreated by st1nky (stinky@ghostchain.io)"
echo -e "Repository: https://git.ghostchain.io/ghostchain/ghost-node"
echo -e "Usage: local-builder.sh [OPTION]\n"
while [ $# -gt 0 ]; do
case "$1" in
--set-environment|-i)
SET_ENVIRONMENT=true
;;
--unit-file|-u)
UNIT_FILE=true
;;
--make-global|-m)
MAKE_GLOBAL=true
;;
--set-arguments|-a)
ARGUMENTS=true
;;
--check-keys|-k)
CHECK_KEYS=true
;;
--insert-keys|-k)
INSERT_KEYS=true
;;
--release|-r)
RELEASE="--release"
TARGET="release"
;;
--profile*|-p*)
if [[ "$1" != *=* ]]; then shift; fi
RELEASE="--profile=${1#*=}"
TARGET="${1#*=}"
;;
--feature*|-f*)
if [[ "$1" != *=* ]]; then shift; fi
FEATURES="--features=${1#*=}"
;;
--executable-path*|-e*)
if [[ "$1" != *=* ]]; then shift; fi
EXECUTABLE_PATH=$(echo ${1#*=}/ | tr -s /)
;;
--specification-path*|-c*)
if [[ "$1" != *=* ]]; then shift; fi
SPECIFICATION_PATH=$(echo ${1#*=}/ | tr -s /)
;;
--specification-name*|-n*) if [[ "$1" != *=* ]]; then shift; fi
SPECIFICATION_NAME="${1#*=}"
;;
--help|-h)
help
exit 0
;;
*)
help
exit 1
;;
esac
shift
done
if [[ $SET_ENVIRONMENT = true ]]; then
echo -e "\n"
echo "WARNING!!! THIS IS HIGHLY EXPERIMENTAL FLAG, USE IT ONLY ON YOUR"
echo "OWN RISK! NOT EVERY SYSTEM CHECKED AND PROVED TO BE WORKING AS"
echo "EXPECTED! FOR THOSE WHO FOUND BUG OR SOME INCONSISTENCY FEEL"
echo "FREE TO FILL ISSUE ON https://git.ghostchain.io/ghostchain/ghost-node/issues"
echo -e "\n"
if prompt "[?] are you brave enough?"; then
echo "[+] you were warned, I hope you know what you're doing"
else
echo "[-] aborting environment setup"
exit 1
fi
if command -v rustc >/dev/null 2>&1; then
echo "[+] rust already installed"
else
os_name=$(uname -s)
cd $HOME
if [ "$os_name" = "Darwin" ]; then
echo "[+] detected MacOS. installing dependencies via homebrew"
if command -v brew >/dev/null 2>&1; then
echo "[+] already installed: $(brew --version)"
else
if prompt "[?] do you want to install homebrew?"; then
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
else
echo "[-] cannot continue without homebrew"
exit 1
fi
fi
brew update
if prompt "[?] install git, cmake, openssl and protobuf?"; then
brew install git cmake openssl protobuf
else
echo "[!] assuming git, cmake, openssl and protobuf are present"
fi
elif [ "$os_name" == "Linux" ]; then
distro=$(cat /etc/*-release | tr '[:upper:]' '[:lower:]' | grep -Poi '(debian|ubuntu|arch|fedora|opensuse)' | uniq | head -n 1)
echo $distro
if [ "$distro" = "ubuntu" ]; then
echo "[+] ubuntu detected, using apt to install dependencies"
sudo apt update
sudo apt install --assume-yes git make clang curl libssl-dev protobuf-compiler
elif [ "$distro" = "debian" ]; then
echo "[+] debian detected, using apt to install dependencies"
sudo apt update
sudo apt install --assume-yes git make clang curl libssl-dev llvm libudev-dev protobuf-compiler
elif [ "$distro" = "arch" ]; then
echo "[+] arch linux detected, using pacman to install dependencies"
sudo pacman -Syu --needed --no-confirm curl git clang make protobuf
elif [ "$distro" = "fedora" ]; then
echo "[+] fedora detected, using dnf to install dependencies"
sudo dnf update --assumeyes
sudo dnf install --assumeyes clang curl git openssl-devel make protobuf-compiler perl
elif [ "$distro" = "opensuse" ]; then
echo "[+] openSUSE detected, using zypper to install dependencies"
sudo zypper install --no-confirm clang gcc gcc-c++ curl git openssl-devel llvm-devel libudev-devel make awk protobuf-devel
else
if prompt "[?] unknown linux distribution, unable to install dependencies. continue anyway?"; then
echo "[+] proceeding with unknown linux distribution"
else
echo "[-] aborting with uknown distribution"
exit 1
fi
fi
else
echo "[-] unknown operating system"
exit 1
fi
fi
if prompt "[?] setup the rust environment (e.g. WASM support)?"; then
rustup default stable
rustup update
rustup target add wasm32-unknown-unknown
rustup component add rust-src
fi
fi
if [[ ! -z $RELEASE ]]; then
if prompt "[?] 'cargo build $RELEASE $FEATURES' is what you want?"; then
cd $PROJECT_FOLDER
echo "[+] Starting build in 3 seconds..."
sleep 3
cargo build $RELEASE $FEATURES
fi
fi
if [[ $MAKE_GLOBAL = true ]]; then
cd $PROJECT_FOLDER
sudo cp target/$TARGET/ghost $EXECUTABLE_PATH
cp service/chain-specs/$SPECIFICATION_NAME.json $SPECIFICATION_PATH
echo "[+] ghost executable copied in '$EXECUTABLE_PATH' from '$TARGET'"
echo "[+] specification '$SPECIFICATION_NAME.json' copied to '$SPECIFICATION_PATH'"
fi
if [ $UNIT_FILE = true ]; then
cd $SCRIPT_FOLDER
read -p "[?] name for the unit file (default: ghost-node.service) " unit_name
if [ -z $unit_name ]; then
unit_name="ghost-node"
fi
unit_name=$(echo "$unit_name" | sed -e "s/.service//g")
unit_name="$unit_name.service"
user_name="ghost"
if id $user_name > /dev/null 2>&1; then
echo "[+] user ghost found, continue for the user ghost"
else
echo "[!] user ghost not found"
if prompt "[?] do you want to create ghost user? (NOT RECOMMENDED: current $(whoami))"; then
sudo useradd --system --create-home $user_name
if [ ! -d $NODE_PATH ]; then
echo "[+] create folder for the node at '$NODE_PATH'"
sudo mkdir $NODE_PATH
fi
else
user_name=$(whoami)
fi
sudo chown $user_name $NODE_PATH
echo "[+] write permission to '$NODE_PATH'"
fi
cp packaging/template.service /tmp/$unit_name
sed -i -e "s/User=ghost/User=$user_name/g" /tmp/$unit_name
sudo cp packaging/template.service /etc/systemd/system/$unit_name
sudo systemctl daemon-reload
if prompt "[?] do you want to start the $unit_name?"; then
sudo systemctl restart $unit_name
fi
if prompt "[?] do you want to enable the $unit_name?"; then
sudo systemctl enable $unit_name
fi
fi
if [[ $ARGUMENTS = true ]]; then
echo "[+] setting-up default CLI arguments"
CLI_ARGS=()
read -p "[?] specify p2p protocol TCP port (default: 30333): " port
CLI_ARGS+=("--port=${port:-30333}")
read -p "[?] specify JSON-RPC server TCP port: (default: 9945): " rpc_port
CLI_ARGS+=("--rpc-port=${rpc_port:-9945}")
read -p "[?] specify the chain specification (default: /etc/ghost/casper.json): " chain
CLI_ARGS+=("--chain=${chain:-/etc/ghost/casper.json}")
read -p "[?] specify node's secret key file for p2p networking (default: /etc/ghost/node-key): " node_key
CLI_ARGS+=("--node-key-file=${node_key:-/etc/ghost/node-key}")
read -p "[?] specify name for the node (default: RANDOM_NAME): " node_name
if [[ ! -z $node_name ]]; then
CLI_ARGS+=("--name='$node_name'")
fi
CLI_ARGS+=("--validator")
if prompt "[?] disable validator mode?"; then
unset CLI_ARGS[-1]
fi
if prompt "[?] enable prometheus?"; then
read -p "[?] specify prometheus exporter TCP port: (default: 9615)" prometheus_port
CLI_ARGS+=("--prometheus-port=${prometheus_port:-9615}")
else
CLI_ARGS+=("--no-prometheus")
fi
read -p "[?] list of bootnodes if any: " bootnodes
if [ ! -z $bootnodes ]; then
CLI_ARGS+=("--bootnodes=$bootnodes")
fi
# default for now
CLI_ARGS+=("--base-path=$NODE_PATH")
CLI_ARGS+=("--state-pruning=archive")
CLI_ARGS+=("--blocks-pruning=archive")
CLI_ARGS+=("--rpc-methods=auto")
CLI_ARGS+=("--no-telemetry")
CLI_ARGS+=("--no-private-ip")
CLI_ARGS+=("--no-mdns")
CLI_ARGS+=("--no-hardware-benchmarks")
echo "GHOST_CLI_ARGS=\"$(IFS=' '; echo "${CLI_ARGS[*]}")\"" > /tmp/ghost
sudo cp /tmp/ghost /etc/default/ghost
rm /tmp/ghost
echo "[+] new CLI arguments stored in '/etc/default/ghost'"
cat /etc/default/ghost
fi
if [ $CHECK_KEYS = true ]; then
seed=$(extract_seed "wallet-key")
sanity_check "sr25519" $seed "wallet"
echo "[+] local wallet key found in 'ghosties' with correct key type"
echo
seed=$(extract_seed "stash-key")
sanity_check "sr25519" $seed "stash"
echo "[+] local stash key from found in 'ghosties' with correct key type"
echo
seed=$(extract_seed "session-key")
if [ $INSERT_KEYS = true ]; then
read -p "[?] JSON RPC endpoint to the node: (default: localhost:9945) " rpc_endpoint
rpc_endpoint="${rpc_endpoint:-localhost:9945}"
fi
for type in $(echo audi babe gran slow); do
echo "[+] parsing session key for [$type]"
scheme="sr25519"
if [ $type = "gran" ]; then
scheme="ed25519"
fi
sanity_check $scheme "$seed//$type" $type
echo "[+] inspected account id found in 'ghosties' file with correct key type"
if [ $INSERT_KEYS = true ]; then
echo "[+] trying to make an 'author_insertKey' RPC call to $rpc_endpoint..."
curl --location $rpc_endpoint \
--header "Content-Type: application/json" \
--data '{ "id":1, "jsonrpc":"2.0", "method":"author_insertKey", "params": ["'"$type"'", "'"$secret_seed"'", "'"$account_id"'"] }'
fi
echo
done
fi