diff --git a/tools/fleet/box-dn3.sh b/tools/fleet/box-dn3.sh new file mode 100644 index 000000000..040d97805 --- /dev/null +++ b/tools/fleet/box-dn3.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# A Devnet 3 box (7 October 2026, the founder's clock: a fresh chain from genesis on 0.3.22, network igneum-devnet-3, every activation at 0, +# NO override file). Modelled on box-dn2.sh. The node runs with NET_ARGS (default "--devnet --devnet-suffix=3": own handshake magic, +# own data directory $F/$APPDIR; a live-devnet or Devnet 2 peer refuses it at the handshake), peered with SEED (comma list); one miner on +# card 0 with the box's vote key; PROVER=1 adds the segment prover loop (CHAIN_NAME igneum-devnet-3). NODE_BIN names the igneumd. +# FRESH=1 wipes $F/$APPDIR (a new genesis); UNSYNCED=1 adds --enable-unsynced-mining (the genesis boxes: a fresh chain's nodes start +# unsynced and must mine anyway). RPC_PORT, P2P_PORT, EVM_PORT: other ports on a box whose live node holds 26610/26611/26790 +# (a standing box running a second node for Devnet 3: 36610/36611/36790). Nothing here touches the live devnet's node or miner. +set -uo pipefail +mkdir -p /root/fleet/pids; echo $$ > /root/fleet/pids/loop.pid # 15:3xZ 8 Oct 2026: kills by pid file only (main): loop.pid, node.pid, miner.pid under /root/fleet/pids +F=/root/fleet; OUT=$F/out; mkdir -p $F/in $OUT $F/$APPDIR $F/mine/packs; exec >> $OUT/dn3.log 2>&1 +stamp() { date -u +%Y-%m-%dT%H:%M:%SZ; } +LABEL="${LABEL:-dn3}"; WALLET="${WALLET:-0x1919191919191919191919191919191919191919}"; SEED="${SEED:-}"; NODE_BIN="${NODE_BIN:-$F/in/igneumd-0322}" +APPDIR="${APPDIR:-dn3}"; PACK="${PACK:-dn3}"; CHAIN_NAME="${CHAIN_NAME:-igneum-devnet-3}" # 15:4xZ 8 Oct 2026: devnet-4 takes APPDIR=dn4 PACK=dn4 CHAIN_NAME=igneum-devnet-4 NET_ARGS="--devnet --devnet-suffix=4" +PROVER="${PROVER:-0}"; UNSYNCED="${UNSYNCED:-}"; RPC_PORT="${RPC_PORT:-26610}"; P2P_PORT="${P2P_PORT:-26611}"; EVM_PORT="${EVM_PORT:-26790}"; JSON_PORT="${JSON_PORT:-$((RPC_PORT+2080))}"; MINE="${MINE:-1}" +NET_ARGS="${NET_ARGS:---devnet --devnet-suffix=3}"; P2P_LISTEN="${P2P_LISTEN:-0.0.0.0:$P2P_PORT}"; MINER_ONLY="${MINER_ONLY:-0}"; ANNOUNCE="${ANNOUNCE:-}"; export -n MINER_ONLY # 21:3xZ 7 Oct 2026: never in the loop's environment (the puller restarts from it; MINER_ONLY=1 there would leave the node down at the next move) # MINER_ONLY=1: the node stays, only the miner loop restarts (with --announce ip:port when ANNOUNCE is set: the peer directory) +JSONF="--rpclisten-json=127.0.0.1:$JSON_PORT"; case " $NET_ARGS ${EXTRA_ARGS:-} " in *rpclisten-json*) JSONF="";; esac # 13:3xZ 8 Oct: the pool boxes already carry it in NET_ARGS (dn3-pool-b: "cannot be used multiple times") +MINER_BIN="${MINER_BIN:-$F/in/igneum-miner-0322}" # the 0.3.22 miner (sub-version 3 draw); the hive package's 0.3.20 miner is the live devnet's and never mines Devnet 3 (16:5xZ: every block BlockInvalid) +[ -x "$NODE_BIN" ] || { echo "RESULT dn3_failed $(stamp) no node binary at $NODE_BIN"; exit 2; } +[ "${MINE:-1}" = 1 ] && { [ -x "$MINER_BIN" ] || { echo "RESULT dn3_failed $(stamp) no 0.3.22 miner at $MINER_BIN"; exit 2; }; } +# the pack-id gate (main through the shipper, 7 Oct 2026 17:0xZ): BEFORE the miner starts, the worker's pack and the node's engine must come +# from the same igneum-pow pin. Tonight's shape (the shipper, 17:05Z): BY CONSTRUCTION, the pack the worker hashes is EXPORTED on this box by the +# paired 0.3.22 miner (MINER_BIN's sha equals PAIR_MINER_SHA16, default 07246920fd9fe895 = igneum-pow 017e7037, the node's pin), never a copied kit; +# a different miner sha or a pre-shipped pack directory is UNREADABLE and holds the miner. The id-equality read over RPC (a785001687d8688a against +# the kit's id) replaces it from the next cut when the node lane names the method (NODE_ID_CMD / PACK_ID_CMD). +pack_gate() { + local msha want; msha=$(sha256sum "$MINER_BIN" | cut -c1-16); want="${PAIR_MINER_SHA16:-07246920fd9fe895 c29f33bbbd284a12 dfdc6883aa79a76f fb147dd1754cbfc0 cfa9f5ca382e0efc} $(cat $F/in/pair-miners.txt 2>/dev/null | tr '\n' ' ')" # 8 Oct 2026 09:4xZ: the list is also a FILE the puller appends every move's miner sha to (the 10:05 move: 18 miners refused for a sha only in a hand-edited default) # the two paired 0.3.22 miners (hands / node-lane builds, both igneum-pow 017e7037) + if [ -n "${NODE_ID_CMD:-}" ] && [ -n "${PACK_ID_CMD:-}" ]; then + local pid nid; pid=$(eval "$PACK_ID_CMD" 2>/dev/null); nid=$(eval "$NODE_ID_CMD" 2>/dev/null) + [ -n "$pid" ] && [ -n "$nid" ] || { echo "RESULT dn3_pack_gate $(stamp) UNREADABLE pack_id=${pid:-none} node_id=${nid:-none}"; return 1; } + [ "$pid" = "$nid" ] || { echo "RESULT dn3_pack_gate $(stamp) REFUSED pack_id=$pid node_id=$nid"; return 1; } + echo "RESULT dn3_pack_gate $(stamp) PASS by id pack_id=$pid node_id=$nid"; return 0 + fi + case " $want " in *" $msha "*) ;; *) echo "RESULT dn3_pack_gate $(stamp) UNREADABLE miner=$msha is not a paired miner ($want); a pre-shipped kit or another miner"; return 1;; esac + [ -e $F/mine/packs/$PACK ] && { echo "RESULT dn3_pack_gate $(stamp) UNREADABLE packs/$PACK already present before this export (a copied kit?)"; return 1; } + echo "RESULT dn3_pack_gate $(stamp) PASS by construction (miner $msha = pair, pack exported here by it, generator v4 sub-version 3)"; return 0 +} +echo "RESULT dn3_start $(stamp) label=$LABEL node=$(sha256sum $NODE_BIN | cut -c1-16) miner=$(sha256sum $MINER_BIN 2>/dev/null | cut -c1-16) seed=${SEED:-none} prover=$PROVER mine=$MINE net=\"$NET_ARGS\" ports=$RPC_PORT/$P2P_PORT/$EVM_PORT" +command -v curl >/dev/null || { apt-get update -qq >/dev/null 2>&1; apt-get install -y -qq curl ca-certificates python3 >/dev/null 2>&1; } +if [ ! -x /opt/igneum/pkg/bin/igneum-miner ]; then + read -r PKG_PATH PKG_SHA PKG_VER <<< "$(curl -fsSL -m 30 https://dl.igneum.network/dl/public/igneum-downloads.json | python3 -c 'import sys,json; d=json.load(sys.stdin)["files"]["miner-hive"]; print(d["path"], d["sha256"], d["version"])')" + curl -fsSL -o $F/pkg.tgz "https://dl.igneum.network$PKG_PATH" && echo "$PKG_SHA $F/pkg.tgz" | sha256sum -c - >/dev/null && mkdir -p /opt/igneum/pkg && tar -C /opt/igneum/pkg --strip-components=1 -xzf $F/pkg.tgz || { echo "RESULT dn3_failed package"; exit 2; } +fi +B=/opt/igneum/pkg/bin +# the Devnet 3 node and its miner only (anchored on the dn3 appdir and this RPC port), never the live node beside it +# kills by pid file only (founder 8 Oct 2026, by construction: pkill and killall are shimmed to exit 97 on every box) +pidkill() { local P; P=$(cat "$F/pids/$1.pid" 2>/dev/null); [ -n "$P" ] && kill -0 "$P" 2>/dev/null && { kill -TERM "$P" 2>/dev/null; sleep 2; kill -0 "$P" 2>/dev/null && kill -9 "$P" 2>/dev/null; }; return 0; } +[ "$MINER_ONLY" = 1 ] || pidkill node; pidkill miner; sleep 2 +[ "${FRESH:-0}" = 1 ] && { rm -rf $F/$APPDIR; mkdir -p $F/$APPDIR; [ -s $F/$APPDIR-node.log ] && mv $F/$APPDIR-node.log $F/$APPDIR-node.prev.log; echo "RESULT dn3_fresh $(stamp) appdir wiped for the genesis"; } +PEER=""; for sd in ${SEED//,/ }; do PEER="$PEER --addpeer=$sd"; done +UNS=""; [ "$UNSYNCED" = 1 ] && UNS="--enable-unsynced-mining" +if [ "$MINER_ONLY" != 1 ]; then +echo "=== dn3 node start $(stamp) $(sha256sum $NODE_BIN | cut -c1-16)" >> $F/$APPDIR-node.log +IGNEUM_PROOF_PROGRAM_IDS="${PROGRAM_IDS:-}" IGNEUM_PROOF_VERIFIER="${HOST_VERIFIER:-}" setsid nohup $NODE_BIN $NET_ARGS --appdir=$F/$APPDIR --rpclisten=0.0.0.0:$RPC_PORT --evm-rpclisten=127.0.0.1:$EVM_PORT $JSONF --listen=$P2P_LISTEN $PEER $UNS --unsaferpc --nodnsseed --disable-upnp --nologfiles --yes > $F/$APPDIR-node.log 2>&1 & + echo $! > $F/pids/node.pid +sleep 10 +echo "RESULT dn3_node $(stamp) pid=$(pgrep -f '[/]root/fleet/in/igneumd-[0-9a-f]+ .* --appdir=/root/fleet/$APPDIR ' | head -1) version=$(grep -oE 'igneumd/[0-9]+\.[0-9]+\.[0-9]+-[0-9a-f]+' $F/$APPDIR-node.log | tail -1) digest=$(grep -o 'digest: [0-9a-f]*' $F/$APPDIR-node.log | tail -1 | awk '{print substr($2,1,16)}') network=$(grep -oiE 'igneum-devnet-[0-9][^ ,]*' $F/$APPDIR-node.log | head -1) genesis=$(grep -oiE 'genesis[^\n]{0,120}' $F/$APPDIR-node.log | grep -oE '[0-9a-f]{64}' | head -1 | cut -c1-16)" +for i in $(seq 1 30); do w="$($B/igneum-miner watch 1 grpc://127.0.0.1:$RPC_PORT 2>/dev/null | grep -o 'blocks=[0-9]*.*synced=[a-z]*' | tail -1)"; [ -n "$w" ] && break; sleep 5; done +echo "RESULT dn3_watch $(stamp) $(printf '%s' "$w" | sed -E 's/difficulty=[0-9.]* sink=[0-9a-f]* //')" +fi +rm -rf $F/mine/packs/$PACK.prev; [ -e $F/mine/packs/$PACK ] && mv $F/mine/packs/$PACK $F/mine/packs/$PACK.prev # the previous run's export, moved aside so the gate sees a clean slot +if [ "$MINE" = 1 ] && ! pack_gate; then echo "RESULT dn3_miner_refused $(stamp) the pack-id gate refused the place; node runs, miner off"; MINE=0; fi +if [ "$MINE" = 1 ]; then + cd $F/mine && rm -rf packs/$PACK && $MINER_BIN export-pack grpc://127.0.0.1:$RPC_PORT packs/$PACK > $OUT/dn3-export-pack.log 2>&1 + ( echo $BASHPID > $F/pids/miner-loop.pid; while :; do $MINER_BIN mine grpc://127.0.0.1:$RPC_PORT 1 100000000 "$LABEL" --exec-rpc http://127.0.0.1:$EVM_PORT --worker $WORKER_BIN --worker-args "--device 0 --pack packs/$PACK" --prepare-packs packs/$PACK-prepare --exit-on-seed-change ${ANNOUNCE:+--announce $ANNOUNCE} --evm-address "$WALLET" --payout-label "$LABEL" --status-secs 30 >> $OUT/dn3-miner.log 2>&1 & echo $! > $F/pids/miner.pid; wait $(cat $F/pids/miner.pid); sleep 5; done ) /dev/null 2>&1 & + echo "RESULT dn3_miner_started $(stamp) miner=$(sha256sum $MINER_BIN | cut -c1-16) announce=${ANNOUNCE:-none}" + # the engine's program id as the paired miner prints it ("class v4 program id <16 hex>", the node lane 17:0xZ): a785001687d8688a on sub-version 3, + # 1a4230699a6b9c60 is the 0.3.20 kit (known-failed); logged as the gate's id line, refused on the known-failed value + # the worker form prints no id (the node lane, main.rs 1471): a second one-thread CPU miner beside the worker for 20 s prints "class v4 program id <16 hex>" + timeout 60 $MINER_BIN mine grpc://127.0.0.1:$RPC_PORT 1 20 idread --engine igneum-pow --no-vote --stall-secs 0 > $OUT/dn3-idread.log 2>&1 > $OUT/dn3-prover-launch.log 2>&1 & + echo "RESULT dn3_prover_started $(stamp)" +fi diff --git a/tools/fleet/box-ember.sh b/tools/fleet/box-ember.sh index e278c4497..db5f1bfae 100755 --- a/tools/fleet/box-ember.sh +++ b/tools/fleet/box-ember.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +. /root/fleet/in/pidkill.sh # kills by pid only (founder 8 Oct 2026) # Ember Tune's two-knob ladder on a rented NVIDIA card (docs/plans/ember-tune.md, branch ember-tune): the miner runs # throughout; the power ladder 100, 90, 80, 70, 60, 50% of the default limit at the unlocked clock (clamped at the # card's reported minimum), then the clock ladder 90, 80, 70, 60% of the maximum graphics clock at the power the @@ -15,7 +16,7 @@ stamp() { date -u +%Y-%m-%dT%H:%M:%SZ; } say() { echo "$(stamp) $*"; } q() { nvidia-smi --query-gpu="$1" --format=csv,noheader,nounits -i 0 2>/dev/null | head -1 | tr -d ' '; } NAME="$(q name)"; DRV="$(q driver_version)"; PDEF="$(q power.default_limit)"; PMIN="$(q power.min_limit)"; PMAX="$(q power.max_limit)"; CMAX="$(q clocks.max.graphics)" -pkill -x sp1-gpu-server 2>/dev/null; rm -f /tmp/sp1-cuda-*.sock +. /root/fleet/in/pidkill.sh; kill_sock_owner 'sp1-cuda-[0-9]*\.sock' echo "RESULT start $(stamp) card=$NAME driver=$DRV power_default_w=$PDEF min_w=$PMIN max_w=$PMAX clock_max_mhz=$CMAX" # can we set anything? nvidia-smi -i 0 -pl "$PDEF" >/dev/null 2>&1 && PL_OK=1 || PL_OK=0 @@ -27,7 +28,7 @@ rm -rf packs/devnet; $B/igneum-miner export-pack grpc://127.0.0.1:26610 packs/de nohup $B/igneum-miner mine grpc://127.0.0.1:26610 1 100000000 "$LABEL" --worker $B/igneum-worker-cuda --worker-args "--device 0 --pack packs/devnet" \ --prepare-packs packs/prepare --exit-on-seed-change --evm-address "$WALLET" --payout-label "$LABEL" --status-secs 10 > $OUT/ember-miner.log 2>&1 & MPID=$!; cd $F -cleanup() { nvidia-smi -i 0 -rgc >/dev/null 2>&1; [ "$PL_OK" = 1 ] && nvidia-smi -i 0 -pl "$PDEF" >/dev/null 2>&1; kill $MPID 2>/dev/null; pkill -f '[/]opt/igneum/pkg/bin/igneum-worker-cuda' 2>/dev/null; } +cleanup() { nvidia-smi -i 0 -rgc >/dev/null 2>&1; [ "$PL_OK" = 1 ] && nvidia-smi -i 0 -pl "$PDEF" >/dev/null 2>&1; kill_children $MPID; kill $MPID 2>/dev/null; } trap cleanup EXIT say "miner warming 90 s"; sleep 90 STEPS=$OUT/ember-steps.jsonl; : > $STEPS @@ -38,7 +39,7 @@ step() { #