#!/usr/bin/env zsh # initialize variables DAEMON=bitcoin NETWORK=mainnet FEATURES=default DB_FOLDER=/electrs NODENAME=$(hostname|cut -d . -f1) LOCATION=$(hostname|cut -d . -f2) USAGE="Usage: $0 (mainnet|testnet|signet|liquid|liquidtestnet) [popular-scripts]" # load rust if necessary if [ -e "${HOME}/.cargo/env" ];then source "${HOME}/.cargo/env" export PATH="${HOME}/.cargo/bin:${PATH}" fi # which OS? case "$(uname -s)" in FreeBSD) OS=FreeBSD NPROC=$(sysctl -n hw.ncpu) export CC=/usr/local/bin/clang17 export CXX=/usr/local/bin/clang++17 export CPP=/usr/local/bin/clang-cpp17 export RUSTFLAGS="-C linker=clang17" ;; Darwin) OS=Darwin NPROC=$(sysctl -n hw.ncpu) ;; Linux) OS=Linux NPROC=$(grep -c proc /proc/cpuinfo) ;; *) OS=Unknown NPROC=4 ;; esac # which network? case "${1}" in mainnet) THREADS=$((NPROC / 3)) CRONJOB_TIMING="20 4 * * *" ;; testnet) NETWORK=testnet THREADS=$((NPROC / 6)) CRONJOB_TIMING="2 4 * * *" ;; testnet4) NETWORK=testnet4 THREADS=$((NPROC / 6)) CRONJOB_TIMING="17 4 * * *" ;; signet) NETWORK=signet THREADS=$((NPROC / 6)) CRONJOB_TIMING="9 4 * * *" ;; liquid) DAEMON=elements NETWORK=liquid FEATURES=liquid THREADS=$((NPROC / 6)) CRONJOB_TIMING="12 4 * * *" ;; liquidtestnet) DAEMON=elements NETWORK=liquidtestnet FEATURES=liquid THREADS=$((NPROC / 6)) CRONJOB_TIMING="17 4 * * *" ;; *) echo "${USAGE}" exit 1 ;; esac # Run the popular address txt file generator before each run POPULAR_SCRIPTS_FOLDER="${HOME}/popular-scripts/${NETWORK}" POPULAR_SCRIPTS_FILE_RAW="${POPULAR_SCRIPTS_FOLDER}/popular-scripts-raw.txt" POPULAR_SCRIPTS_FILE="${POPULAR_SCRIPTS_FOLDER}/popular-scripts.txt" # This function runs the job for generating the popular scripts text file for the precache arg generate_popular_scripts() { mkdir -p "${POPULAR_SCRIPTS_FOLDER}" ## Use nproc * 4 threads to generate the txt file (lots of iowait, so 2x~4x core count is ok) ## Only pick up addresses with 101 history events or more ## (Without lowering MIN_HISTORY_ITEMS_TO_CACHE this is the lowest we can go) ## It prints out progress to STDERR echo "[*] Generating popular-scripts using ${THREADS} threads..." cd "${HOME}/electrs" HIGH_USAGE_THRESHOLD=101 \ JOB_THREAD_COUNT=${THREADS} \ nice cargo run \ --release \ --bin popular-scripts \ --features "${FEATURES}" \ -- \ --network "${NETWORK}" \ --db-dir "${DB_FOLDER}" \ > "${POPULAR_SCRIPTS_FILE_RAW}" ## Only overwrite the existing file if the popular-scripts cargo run succeeded if [ "$?" = "0" ];then ## Sorted and deduplicated just in case echo "Sorting popular scripts for final results..." sort "${POPULAR_SCRIPTS_FILE_RAW}" | uniq > "${POPULAR_SCRIPTS_FILE}" fi rm "${POPULAR_SCRIPTS_FILE_RAW}" } # This function is for inserting the cronjob for generating the popular scripts CRONJOB_CMD="\"${HOME}/electrs/start\" \"${NETWORK}\" popular-scripts" echo "${CRONJOB_TIMING} ${CRONJOB_CMD}" case "${2}" in popular-scripts) echo "[*] Only generate popular-scripts, then exit" generate_popular_scripts exit 0 ;; version) echo "[*] Only print versions, then exit" cargo run --bin electrs --release -- --version cargo run --bin popular-scripts --release -- --version exit 0 ;; "") # If the 2nd arg isn't passed, just run the normal electrs script as-is ;; *) echo "${USAGE}" exit 1 ;; esac # run in loop in case of crash until false do # reset CWD cd "${HOME}/electrs" # disable making electrs.core files ulimit -c 0 # prepare run-time variables UTXOS_LIMIT=500 ELECTRUM_TXS_LIMIT=500 MAIN_LOOP_DELAY=500 DAEMON_CONF="${HOME}/${DAEMON}.conf" HTTP_SOCKET_FILE="${HOME}/socket/esplora-${DAEMON}-${NETWORK}" RPC_SOCKET_FILE="${HOME}/socket/electrum-${DAEMON}-${NETWORK}" # get RPC credentials from bitcoin.conf or elements.conf directly echo "[*] Getting RPC credentials from ${DAEMON_CONF}" RPC_USER=$(grep 'rpcuser=' "${DAEMON_CONF}"|cut -d = -f2|head -1) RPC_PASS=$(grep 'rpcpassword=' "${DAEMON_CONF}"|cut -d = -f2|head -1) # override limits based on hostname if [ "${NODENAME}" = "node201" ];then UTXOS_LIMIT=9000 ELECTRUM_TXS_LIMIT=9000 MAIN_LOOP_DELAY=14000 fi if [ "${NODENAME}" = "node202" ] && [ "${LOCATION}" = "va1" ];then UTXOS_LIMIT=9000 ELECTRUM_TXS_LIMIT=9000 fi if [ "${NODENAME}" = "node203" ] && [ "${LOCATION}" = "va1" ];then UTXOS_LIMIT=9000 ELECTRUM_TXS_LIMIT=9000 fi if [ "${NODENAME}" = "node204" ] && [ "${LOCATION}" = "va1" ];then UTXOS_LIMIT=9000 ELECTRUM_TXS_LIMIT=9000 fi if [ "${NODENAME}" = "node205" ] && [ "${LOCATION}" = "va1" ];then UTXOS_LIMIT=9000 ELECTRUM_TXS_LIMIT=9000 fi if [ "${NODENAME}" = "node206" ] && [ "${LOCATION}" = "va1" ];then UTXOS_LIMIT=9000 ELECTRUM_TXS_LIMIT=9000 fi if [ "${NODENAME}" = "node213" ];then UTXOS_LIMIT=9000 ELECTRUM_TXS_LIMIT=9000 fi if [ "${NODENAME}" = "node214" ];then UTXOS_LIMIT=9000 ELECTRUM_TXS_LIMIT=9000 fi if [ "${NETWORK}" = "testnet4" ];then UTXOS_LIMIT=9000 ELECTRUM_TXS_LIMIT=9000 fi if [ "${LOCATION}" = "fmt" ];then UTXOS_LIMIT=9000 ELECTRUM_TXS_LIMIT=9000 fi if [ ! -e "${POPULAR_SCRIPTS_FILE}" ];then generate_popular_scripts fi # Run the electrs process (Note: db-dir is used in both commands) cargo run \ --release \ --bin electrs \ --features "${FEATURES}" \ -- \ --network "${NETWORK}" \ --daemon-dir "${HOME}" \ --db-dir "${DB_FOLDER}" \ --main-loop-delay "${MAIN_LOOP_DELAY}" \ --rpc-socket-file "${RPC_SOCKET_FILE}" \ --http-socket-file "${HTTP_SOCKET_FILE}" \ --precache-scripts "${POPULAR_SCRIPTS_FILE}" \ --precache-threads "${THREADS}" \ --cookie "${RPC_USER}:${RPC_PASS}" \ --cors '*' \ --address-search \ --utxos-limit "${UTXOS_LIMIT}" \ --electrum-txs-limit "${ELECTRUM_TXS_LIMIT}" \ -vv sleep 1 done