#!/usr/bin/env bash set -euo pipefail log_info(){ echo "[INFO] $(date -Iseconds) $*"; } log_warn(){ echo "[WARN] $(date -Iseconds) $*" >&2; } log_error(){ echo "[ERROR] $(date -Iseconds) $*" >&2; } die(){ log_error "$*"; exit 1; } need(){ command -v "$1" >/dev/null 2>&1 || die "Missing required tool: $1"; } confirm_gate() { : "${DRY_RUN:=1}" : "${REQUIRE_CONFIRM:=1}" : "${CONFIRM_PHRASE:=I UNDERSTAND THIS WILL BROADCAST A BITCOIN TX}" [[ "$DRY_RUN" == "0" ]] || die "DRY_RUN=$DRY_RUN (set DRY_RUN=0)." if [[ "$REQUIRE_CONFIRM" == "1" ]]; then echo "Type to confirm:" echo " $CONFIRM_PHRASE" read -r input [[ "$input" == "$CONFIRM_PHRASE" ]] || die "Confirmation phrase mismatch." fi } json_escape() { local s="$1" s="${s//\\/\\\\}"; s="${s//\"/\\\"}"; s="${s//$'\n'/\\n}" printf "%s" "$s" } read_root_hex() { : "${ROOT_HEX:=}" : "${ROOT_FILE:=}" if [[ -n "$ROOT_HEX" ]]; then echo "${ROOT_HEX#0x}" return 0 fi [[ -n "$ROOT_FILE" ]] || die "Set ROOT_HEX or ROOT_FILE." [[ -f "$ROOT_FILE" ]] || die "ROOT_FILE not found: $ROOT_FILE" rh="$(grep '^root_hex=' "$ROOT_FILE" | head -n1 | cut -d= -f2)" [[ -n "$rh" ]] || die "Could not parse root_hex from ROOT_FILE." echo "${rh#0x}" } net_flag() { : "${BTC_NETWORK:=testnet}" case "$BTC_NETWORK" in mainnet) echo "" ;; testnet) echo "-testnet" ;; signet) echo "-signet" ;; *) die "BTC_NETWORK must be mainnet|testnet|signet" ;; esac } ascii_to_hex() { # portable: use xxd echo -n "$1" | xxd -p -c 256 | tr -d '\n' }