From e695b721090668e56d287999a6ed31c2684c65b9 Mon Sep 17 00:00:00 2001 From: Robert Martin-Legene <robert@nic.ar> Date: Tue, 27 Apr 2021 15:52:03 +0000 Subject: [PATCH] Introducing command: bfa --- bin/bfa | 384 ++++++++++++++++++++++++++++++++++++++++++++++++++ bin/bfalog.sh | 8 +- 2 files changed, 385 insertions(+), 7 deletions(-) create mode 100755 bin/bfa mode change 100755 => 120000 bin/bfalog.sh diff --git a/bin/bfa b/bin/bfa new file mode 100755 index 0000000..d8043a9 --- /dev/null +++ b/bin/bfa @@ -0,0 +1,384 @@ +#!/bin/bash +# Robert Martin-Legene <robert@nic.ar> + +if [ -z "${BFAHOME}" ]; then echo "\$BFAHOME not set. Did you source bfa/bin/env ?" >&2; exit 1; fi +source ${BFAHOME}/bin/libbfa.sh || exit 1 + +declare -A commands help + +function register_subcommand +{ + declare -g commands help + commands[$1]=$2 + help[$1]=$3 +} + +function _usage() +{ + local after='' + for c in $( echo ${!commands[*]} | sort ) + do + after="${after}|$c" + done + echo "Usage: $(basename $0) {${after:1}}" >&2 + for c in $( echo ${!commands[*]} | sort ) + do + printf '%-15s %s\n' "$c" "${help[$c]}" >&2 + done + trap - ERR + exit 1 +} + +function _max +{ + test "$1" -lt "$2" && echo "$2" + echo "$1" +} + +function pidsfromsigfiles +{ + local pids= + local file + for file in \ + ${BFANETWORKDIR}/bootnode.pid \ + ${BFANETWORKDIR}/start-bootnode-loop.pid \ + ${BFANODEDIR}/monitor.pid \ + ${BFANODEDIR}/start-monitor-loop.pid \ + ${BFANODEDIR}/geth.pid \ + ${BFANODEDIR}/start-geth-loop.pid + do + test -r "$file" || continue + local pid=$(< "$file") + if ! [[ "$pid" =~ ^[0-9]+$ ]] + then + rm -f "$file" + continue + fi + if ! kill -0 "$pid" >/dev/null 2>/dev/null + then + rm -f "$file" + continue + fi + pids="$pids $pid" + done + echo "${pids# }" +} + +function sendsig +{ + local signal=$1 + shift + local pids="$*" + test -n "$pids" || return + ps -p ${pids// /,} + echo "Sending ${signal} signal to pid $pids." + kill "$signal" $pids || true +} + +register_subcommand 'kill' 'killbfastuff' 'Kill BFA background processes (no questions asked).' +function killbfastuff +{ + local pids=$(pidsfromsigfiles) + if [ -z "$pids" ] + then + echo "Nothing to send signals to." >&2 + exit 2 + fi + sendsig -KILL $pids +} + +register_subcommand 'stop' 'graceful' 'Ask the BFA background processes to end gracefully.' +function graceful +{ + local max=10 + local pids=$(pidsfromsigfiles) + while : + do + max=$((max - 1)) + test "$max" -eq 0 && break + if [ -z "$pids" ] + then + echo "Nothing to send signals to." >&2 + break + fi + sendsig -TERM $pids + sleep 0.4 + pids=$(pidsfromsigfiles) + done + test -z "$pids" || echo "This/these pids is/are still running: $f" +} + +register_subcommand 'initdb' 'initdb' 'Stop geth and reset the node to block zero (genesis).' +function initdb +{ + killbfastuff + yes | geth --cache 0 --datadir ${BFANODEDIR} removedb + geth --networkid ${BFANETWORKID} --cache 0 --datadir ${BFANODEDIR} init ${BFANETWORKDIR}/genesis.json +} + +register_subcommand 'exportdb' 'exportdb' 'Export blockchain in chunks of 1 million blocks per file.' +function exportdb +{ + local delta=1000000 + graceful + local maxblocks=$(bfageth --exec 'eth.blockNumber' console 2> /dev/null) + # 0 is genesis.. shouldn't dump that + local toblock + local blockstart=1 + while [ "$blockstart" -lt "$maxblocks" ] + do + toblock=$(( blockstart + delta - 1 )) + test "$toblock" -gt "$maxblocks" && + toblock=$maxblocks + local filename + printf -v filename 'bfa2018.blocks.%09d-%09d.export.gz' "$blockstart" "$toblock" + if [ ! -e "$filename" ] + then + echo "Dumping blocks# $blockstart to $toblock to the file named $filename" + bfageth export "$filename" "$blockstart" "$toblock" + fi + blockstart=$(( toblock + 1 )) + done +} + +register_subcommand 'importdb' 'importdb' 'Import blocks safely from previous block exports.' +function importdb +{ + local dumpurl="https://s3.wasabisys.com/bfa/blockdumps" + local delta=1000000 + graceful + local toblock + local blockstart=1 + while : + do + toblock=$(( blockstart + delta - 1 )) + printf -v filename 'bfa2018.blocks.%09d-%09d.export.gz' "$blockstart" "$toblock" + curl --fail "${dumpurl}/${filename}" || break + blockstart=$(( toblock + 1 )) + done + geth --networkid ${BFANETWORKID} --datadir "${BFANODEDIR}" --syncmode "full" --gcmode "archive" import <( + n=1 + while gzip -dc "bfa2018-1Mblocksstartingat${n}.block.export.gz" 2>/dev/null + do + n=$(( n + 1000000 )) + done + true + ) +} + +register_subcommand 'syncmode' 'admin_syncmode' 'Set initial synchronization mode.' +function admin_syncmode +{ + echo "Synchronization modes can only be set for the initial " + echo "synchronization. Later follow-up block synchronization " + echo "operations will always be \"full\" and can not be changed." + echo "Available synchronization modes:" + echo " full : verify all blocks and all transactions (most secure)" + echo " fast : verify all blocks but not all transactions (faster than full, but less certain)" + echo " light: Makes this node into a light node which downloads almost" + echo " nothing, but relies on fast and full nodes in the network" + echo " to answer it's requests. This is the fastest and uses least" + echo " local resources, but outsources all trust to another node." + echo " Possibly still an untested-by-BFA feature." + echo "Default mode is fast, because for many, it is a healthy compromise" + echo "between speed and paranoia. You can change the setting, according to" + echo "your needs." + + mode=$( cat ${BFANODEDIR}/syncmode 2>/dev/null || true ) + mode=${mode:-fast} + echo "Your current mode is set to ${mode}" + killed=0 + orgmode=$mode + mode= + + echo + while [ -z "${mode}" ] + do + read -p "Which mode do you wish? : " mode + modefilter "$mode" + if [[ "$mode" =~ ^full$|^fast$|^light$ ]] + then + : + else + echo "Unsupported synchronization mode." >&2 + exit 1 + fi + done + echo "Remembering your choice." + echo $mode > ${BFANODEDIR}/syncmode + if [ "$orgmode" = "fast" ] && [ "$mode" = "full" ] + then + echo "You increased your paranoia level. The proper thing to do now," + echo "would be to delete your version of what you synchronized with" + echo "fast mode, and revalidate everything in the entire blockchain." + echo "This probably takes quite a long time and also requires downloading" + echo "all blocks from the entire blockchain again." + yesno n "Do you wish to delete all downloaded blocks and resynchronize?" + if [ "$REPLY" = "y" ] + then + if [ -r "${BFANODEDIR}/geth.pid" ] + then + pid=$( cat ${BFANODEDIR}/geth.pid ) + kill -0 $pid 2>/dev/null && + echo "Killing running geth." && + killed=1 + while ! kill $pid 2>/dev/null + do + sleep 1 + done + fi + initdb + test $killed -eq 1 && + echo && + echo "The startup.sh should restart your geth shortly." + fi + else + echo "No further action taken." + fi +} + +register_subcommand 'bootnode' 'admin_bootnode' 'Enable/disable the local bootnode.' +function admin_bootnode +{ + keyfile=${BFANETWORKDIR}/bootnode/key + echo "Only very few wants to actually run a boot node." + echo "If you have a keyfile for a bootnode, then you will" + echo "automatically start one, when restarting your system." + if [ -f $keyfile ] + then + echo "You are set up to run a boot node." + echo "Deleting your bootnode keyfile disables your bootnode." + yesno n "Do you want to delete your bootnode keyfile?" + if [ "$REPLY" = "y" ] + then + rm $keyfile + fi + pidfile=${BFANETWORKDIR}/bootnode/pid + if [ -r $pidfile ] + then + pid=`cat $pidfile` + kill -0 $pid && + echo "Terminating your bootnode." && + kill `cat $pidfile` || + true + fi + else + echo "You are not set up to run a boot node." + yesno n "Do you want to create a keyfile for a bootnode?" + if [ "$REPLY" = "y" ] + then + bootnode -genkey $keyfile + fi + echo "You can now start your bootnode by running start.sh" + fi +} + +register_subcommand 'account' 'bfaaccount' 'Account manipulation.' +function bfaaccount +{ + case "$1" in + 'create') + exec create_account + ;; + *) + echo "Usage: $0 account create" >&2 + echo ' create' 'Create an extra account locally on the node.' >&2 + exit 1 + ;; + esac +} + +function create_account +{ + local num=0 + local filename + for filename in ${BFANODEDIR}/keystore/* + do + test -f "$filename" && + num=$(( num + 1 )) + done + if [ "$num" -gt 0 ] + then + local plural="" + if [ "$num" -ne 1 ] + then + plural="s" + fi + yesno n "You already have ${num} account${plural}. Do you wish to create an extra?" + if [ "$REPLY" = "n" ] + then + return + fi + fi + geth --cache 0 --datadir ${BFANODEDIR} --password /dev/null account new +} + +register_subcommand 'truncatelog' 'truncatelog' \ + 'Truncate the log file. You may want to stop the background processes first.' +function truncatelog +{ + true > ${BFANODEDIR}/log +} + +register_subcommand 'bfageth' 'bfageth' 'Start geth for BFA.' +function bfageth +{ + exec geth --config ${BFANETWORKDIR}/conf.bfa2018.local+full+archive "$@" +} + +function bfaadmin +{ + case "$1" in + 'bootnode') + admin_bootnode + ;; + 'syncmode') + admin_syncmode + ;; + 'account') + create_account + ;; + *) + echo Usage: `basename $0` "{bootnode|syncmode|account}" + trap '' ERR + exit 1 + esac +} + +register_subcommand 'tail' 'bfatail' 'tail -f on the logfile.' +function bfatail +{ + exec tail -n 100 -F ${BFANODEDIR}/log + exit 1 +} + +register_subcommand 'log' 'bfalog' 'Open the logfile with less(1).' +function bfalog +{ + exec less ${BFANODEDIR}/log + exit 1 +} + +function main +{ + case "$(basename $0)" in + 'bfa') + local cmd + cmd=$1 + shift || _usage + test -n "$cmd" && test -n "${commands[$cmd]}" || _usage + eval ${commands[$cmd]} "$*" + ;; + 'admin.sh') + bfaadmin "$*" + ;; + 'bfalog.sh') + bfatail + ;; + 'bfageth') + bfageth "$*" + exit 1 + esac +} + +main "$*" diff --git a/bin/bfalog.sh b/bin/bfalog.sh deleted file mode 100755 index e387b0d..0000000 --- a/bin/bfalog.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -# Robert Martin-Legene <robert@nic.ar> - -if [ -z "${BFAHOME}" ]; then echo "\$BFAHOME not set. Did you source bfa/bin/env ?" >&2; exit 1; fi -source ${BFAHOME}/bin/libbfa.sh || exit 1 - -exec tail -n 100 -F ${BFANODEDIR}/log diff --git a/bin/bfalog.sh b/bin/bfalog.sh new file mode 120000 index 0000000..ff9e6d8 --- /dev/null +++ b/bin/bfalog.sh @@ -0,0 +1 @@ +bfa \ No newline at end of file -- GitLab