igneum/tools/digest-read.sh

42 lines
3.3 KiB
Bash
Executable file

#!/usr/bin/env bash
# Reads a node's "Consensus params digest" (the shipper and main, 7 October 2026 21:4x BST, for the manifest guard): either from a
# PINNED BINARY started bare (an empty datadir, no override file, no peers, the way the canary reads it: the digest line is printed
# at start, the process is ended) or from a RUNNING node's log or journal (the network's CURRENT digest; the hub dn3-g1 for Devnet 3).
#
# tools/digest-read.sh binary <igneumd> [--net-flags "--devnet --devnet-suffix=3"] [--secs 15] prints the 64-hex digest
# tools/digest-read.sh log <file or 'journal:<unit>'> [--host user@box] the newest digest line in it
# tools/digest-read.sh --self-test the line parser on fixtures
# Exit 1 with a line on stderr when no digest is read. The ports are loopback and private to the run (26899/26898/26897), the
# datadir a private temp folder removed after. Never run on a seed: it is a bare start, not a node.
set -uo pipefail
DIGEST_RE='Consensus params digest: ([0-9a-f]{64})'
parse() { grep -oE "$DIGEST_RE" | tail -1 | awk '{print $4}'; }
case "${1:-}" in
binary)
bin="${2:?igneumd}"; shift 2; flags="--devnet --devnet-suffix=3"; secs=15
while [ $# -gt 0 ]; do case "$1" in --net-flags) flags="$2"; shift 2 ;; --secs) secs="$2"; shift 2 ;; *) echo "digest-read: unknown $1" >&2; exit 2 ;; esac; done
[ -x "$bin" ] || { echo "digest-read: $bin is not executable" >&2; exit 1; }
d=$(mktemp -d); trap 'rm -rf "$d"' EXIT
# shellcheck disable=SC2086
"$bin" $flags --appdir="$d/a" --nologfiles --listen=127.0.0.1:26899 --rpclisten=127.0.0.1:26898 --evm-rpclisten=127.0.0.1:26897 --outpeers=0 --nodnsseed --disable-upnp > "$d/a.log" 2>&1 &
p=$!; for i in $(seq 1 "$((secs * 2))"); do grep -qE "$DIGEST_RE" "$d/a.log" 2>/dev/null && break; sleep 0.5; done
kill -TERM "$p" 2>/dev/null; wait "$p" 2>/dev/null
dg=$(parse < "$d/a.log"); [ -n "$dg" ] || { echo "digest-read: no digest line from $bin in $secs s (tail: $(tail -c 200 "$d/a.log" | tr '\n' ' '))" >&2; exit 1; }
echo "$dg" ;;
log)
src="${2:?file or journal:<unit>}"; shift 2; host=""
while [ $# -gt 0 ]; do case "$1" in --host) host="$2"; shift 2 ;; *) echo "digest-read: unknown $1" >&2; exit 2 ;; esac; done
case "$src" in
journal:*) cmd="journalctl -u ${src#journal:} --no-pager -o cat | grep -oE '$DIGEST_RE' | tail -1" ;;
*) cmd="grep -aoE '$DIGEST_RE' '$src' | tail -1" ;;
esac
if [ -n "$host" ]; then line=$(ssh -i "$HOME/.ssh/igneum_ed25519" -o BatchMode=yes -o ConnectTimeout=8 "$host" "$cmd" 2>/dev/null); else line=$(bash -c "$cmd" 2>/dev/null); fi
dg=$(printf '%s\n' "$line" | parse); [ -n "$dg" ] || { echo "digest-read: no digest line in $src${host:+ on $host}" >&2; exit 1; }
echo "$dg" ;;
--self-test)
a=$(printf '2026-10-07 x [INFO] Consensus params digest: %s\nmore\n' "$(printf 'ab%.0s' $(seq 1 32))" | parse)
[ "$a" = "$(printf 'ab%.0s' $(seq 1 32))" ] || { echo "digest-read self-test: FAIL: parse"; exit 1; }
b=$(printf 'no digest here\n' | parse); [ -z "$b" ] || { echo "digest-read self-test: FAIL: parsed a digest from nothing"; exit 1; }
echo "digest-read self-test: the digest line parses, an absent line reads empty" ;;
*) sed -n '2,10p' "$0" | sed 's/^# \{0,1\}//'; exit 2 ;;
esac