The finding (release-0.3.11.md section 5): h-run.sh started the rig's node with --devnet --appdir
--rpclisten --listen and the peers and no --override-params-file, so a HiveOS rig in local mode ran
on genesis parameters, printed the no-override digest and was refused by every devnet peer; no
package ever carried the override.
h-config.sh: OVERRIDE=<json object> in the Flight Sheet's extra config, read as a whole line (JSON
may carry spaces; single or double quotes around it are stripped), refused unless it is {...},
written to igneum.conf single-quoted (sq helper; EXTRA gets the same quoting, the same class: a
value with shell characters sourced unquoted). Still sourceable (return, never exit).
h-run.sh, local branch: writes data/override-params.json from OVERRIDE when set and passes
--override-params-file=<that path> to igneumd; when empty, a WARNING in the main log that the node
runs on genesis parameters and devnet peers will refuse it. After the node answers, the switch
lines and the "Consensus params digest" line from node.log are copied into the main log as
"node: ..." so the operator can compare the digest with the downloads page.
README: the Flight Sheet table gains the OVERRIDE row with the four-field devnet object as the
example (nine fields after the 0.3.11 switch; the downloads page carries the live one), the rule
"set OVERRIDE from the downloads page when it changes", the sentence that a rig without it is
refused, the digest check in the requirements, and the gap entry. No "every override publish
needs a package republish" sentence exists in packaging/hive/README.md on this branch or master,
so nothing was replaced; the new rule stands alone.
selftest.sh: a fake igneumd that records its argv and prints the real digest line; OVERRIDE
single-quoted on its own line beside other keys round-trips through the conf; OVERRIDE=notjson
refused; empty OVERRIDE named in the summary; the main h-run run checks the file, the flag on the
node and the digest and switch lines in the main log; a second short run without OVERRIDE checks
the warning and the absence of the flag. bash packaging/hive/selftest.sh on this Mac:
== h-config.sh OVERRIDE
OVERRIDE (single-quoted, own line) sourced back intact beside the other keys ok
OVERRIDE that is not {...} refused ok
no OVERRIDE: empty in the conf and named in the summary ok
== h-run.sh (fake GPUs: 2 NVIDIA, fake node, fake miner)
data/override-params.json written from OVERRIDE ok
the node got --override-params-file ok
the node's digest and switch lines reached the main log ok
NVIDIA cards got the cuda worker ok
exit 42 restarted the miner and re-exported the pack ok
== h-stats.sh (sourced)
stats JSON ok: hs [118500.0, 118500.0] temp [61, 58] ar [24, 0] bus [1, 2]
== h-run.sh without OVERRIDE (the warning)
no OVERRIDE: warning in the main log, no flag on the node ok
== self-test passed (scripts and stats shape; Hive itself is untested)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
105 lines
6.1 KiB
Bash
Executable file
105 lines
6.1 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Igneum Miner for HiveOS: starts the bundled node when asked, exports the hourly program pack, then one igneum-miner
|
|
# per GPU with the matching worker (igneum-worker-cuda on NVIDIA, igneum-worker-opencl on AMD). Each miner mines
|
|
# against the node for its own payout address; the software dev fee (1 template in 100) is the miner's default and
|
|
# DEV_FEE=0 in the Flight Sheet's extra config turns it off. Per-GPU logs: $CUSTOM_LOG_BASENAME.gpu<N>.log; the main
|
|
# log is their merged tail. Run by Hive with the working directory at the miner folder.
|
|
cd "$(dirname "$0")" || exit 1
|
|
HERE="$(pwd)"
|
|
[[ -z "$CUSTOM_LOG_BASENAME" || -z "$CUSTOM_CONFIG_FILENAME" ]] && . "$HERE/h-manifest.conf"
|
|
[[ -z "$CUSTOM_LOG_BASENAME" ]] && echo "No CUSTOM_LOG_BASENAME is set" && exit 1
|
|
[[ -f "$CUSTOM_CONFIG_FILENAME" ]] || { echo "No config at $CUSTOM_CONFIG_FILENAME (apply the Flight Sheet first)"; exit 1; }
|
|
. "$CUSTOM_CONFIG_FILENAME"
|
|
BIN="${IGNEUM_BIN:-$HERE/bin}"
|
|
mkdir -p "$(dirname "$CUSTOM_LOG_BASENAME")" "$HERE/packs" "$HERE/data"
|
|
date +%s > "$CUSTOM_LOG_BASENAME.started"
|
|
MAIN="$CUSTOM_LOG_BASENAME.log"
|
|
: > "$MAIN"
|
|
say() { printf '%s %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$*" | tee -a "$MAIN"; }
|
|
echo $$ > "$CUSTOM_LOG_BASENAME.pid"
|
|
pids=()
|
|
cleanup() { say "stopping"; for p in "${pids[@]}"; do kill "$p" 2>/dev/null; done; pkill -TERM -P $$ 2>/dev/null; sleep 2; for p in "${pids[@]}"; do kill -9 "$p" 2>/dev/null; done; pkill -KILL -P $$ 2>/dev/null; exit 0; }
|
|
trap cleanup INT TERM
|
|
|
|
# 1. the node
|
|
if [[ "$NODE_URL" == "local" ]]; then
|
|
NODE_URL="grpc://127.0.0.1:26610"
|
|
peers=()
|
|
if [[ -n "$PEERS" ]]; then IFS=',' read -r -a plist <<< "$PEERS"; for p in "${plist[@]}"; do peers+=("--addpeer=$p"); done
|
|
else peers+=("--addpeer=188.245.5.161:26611"); fi # the public devnet seed (app/igneum-app/src/config.rs)
|
|
# the consensus override (OVERRIDE in the Flight Sheet's extra config, written to igneum.conf by h-config.sh): the
|
|
# devnet's activation heights. A node without it runs on genesis parameters, prints another digest in the p2p
|
|
# handshake and is refused by every devnet peer (release 0.3.11, section 5, C41).
|
|
override=()
|
|
if [[ -n "${OVERRIDE:-}" ]]; then
|
|
printf '%s\n' "$OVERRIDE" > "$HERE/data/override-params.json"
|
|
override=("--override-params-file=$HERE/data/override-params.json")
|
|
say "consensus override from the Flight Sheet: $OVERRIDE"
|
|
else
|
|
say "WARNING: no OVERRIDE in the Flight Sheet; the node runs on genesis parameters and every devnet peer will refuse it. Set OVERRIDE from the downloads page."
|
|
fi
|
|
say "starting the bundled node (devnet, data $HERE/data, peers ${peers[*]#--addpeer=})"
|
|
"$BIN/igneumd" --devnet "--appdir=$HERE/data" --rpclisten=127.0.0.1:26610 --listen=0.0.0.0:26611 "${peers[@]}" \
|
|
${override[@]+"${override[@]}"} --nodnsseed --disable-upnp --nologfiles --yes >> "$CUSTOM_LOG_BASENAME.node.log" 2>&1 &
|
|
pids+=($!)
|
|
fi
|
|
say "node $NODE_URL; waiting for it to answer"
|
|
for _ in $(seq 1 60); do
|
|
"$BIN/igneum-miner" watch 1 "$NODE_URL" >/dev/null 2>&1 && break
|
|
sleep 2
|
|
done
|
|
if [[ -f "$CUSTOM_LOG_BASENAME.node.log" ]]; then
|
|
# the switch lines and the digest the node printed at start, so the operator can compare the digest with the one
|
|
# on the downloads page (another digest = refused by every peer)
|
|
n=0
|
|
while IFS= read -r l; do say "node: $l"; n=$((n + 1)); done < <(grep -E 'override params file|from the override file|Consensus params digest' "$CUSTOM_LOG_BASENAME.node.log" | head -12)
|
|
[[ $n == 0 ]] && say "node: no digest line yet in $CUSTOM_LOG_BASENAME.node.log (an older node, or not started); check it by hand"
|
|
fi
|
|
|
|
# 2. the GPUs: Hive's gpu-detect when present, else the driver tools
|
|
nv=0; amd=0
|
|
if command -v gpu-detect >/dev/null 2>&1; then nv=$(gpu-detect NVIDIA 2>/dev/null || echo 0); amd=$(gpu-detect AMD 2>/dev/null || echo 0)
|
|
else
|
|
command -v nvidia-smi >/dev/null 2>&1 && nv=$(nvidia-smi -L 2>/dev/null | grep -c '^GPU')
|
|
[[ -d /sys/bus/pci/drivers/amdgpu ]] && amd=$(ls /sys/bus/pci/drivers/amdgpu 2>/dev/null | grep -c '^0000:')
|
|
fi
|
|
nv=${nv:-0}; amd=${amd:-0}
|
|
say "GPUs: $nv NVIDIA, $amd AMD (worker setting: $WORKER)"
|
|
[[ "$nv" == "0" && "$amd" == "0" ]] && say "no GPU found; nothing to mine with" && sleep 30 && exit 1
|
|
|
|
# 3. the hourly program pack from the node (the workers read it with --pack; the miner writes the next one to packs/prepare)
|
|
export_pack() { rm -rf "$HERE/packs/devnet"; "$BIN/igneum-miner" export-pack "$NODE_URL" "$HERE/packs/devnet" >> "$MAIN" 2>&1; }
|
|
export_pack || say "pack export failed; the miners retry"
|
|
|
|
# 4. one miner per GPU, restarted on exit (exit 42 = the program changed and the worker cannot prepare: re-export the pack)
|
|
run_gpu() {
|
|
local idx="$1" worker="$2" dev="$3" tag="$4"
|
|
local log="$CUSTOM_LOG_BASENAME.gpu$idx.log"
|
|
local args=(mine "$NODE_URL" 1 100000000 "$LABEL-gpu$idx" --worker "$BIN/$worker" --worker-args "--device $dev --pack packs/devnet"
|
|
--prepare-packs packs/prepare --exit-on-seed-change --evm-address "$WALLET" --payout-label "$LABEL-gpu$idx" --status-secs 30)
|
|
local identv="IDENTITIES_GPU$idx" ident="$IDENTITIES"; [[ -n "${!identv:-}" ]] && ident="${!identv}" # per-card from h-config.sh, else the fallback
|
|
[[ "$ident" -gt 1 ]] && args+=(--identities "$ident")
|
|
[[ "$VOTE" == "0" ]] && args+=(--no-vote)
|
|
[[ "$DEV_FEE" != "1" ]] && args+=(--dev-fee "$DEV_FEE")
|
|
[[ -n "$EXTRA" ]] && args+=($EXTRA)
|
|
while :; do
|
|
echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) gpu$idx ($tag $dev): igneum-miner ${args[*]}" >> "$log"
|
|
"$BIN/igneum-miner" "${args[@]}" >> "$log" 2>&1
|
|
rc=$?
|
|
if [[ $rc == 42 ]]; then export_pack; else sleep 5; fi
|
|
done
|
|
}
|
|
idx=0
|
|
if [[ "$nv" -gt 0 && "$WORKER" != "opencl" ]]; then
|
|
for ((d = 0; d < nv; d++)); do run_gpu "$idx" igneum-worker-cuda "$d" nvidia & pids+=($!); idx=$((idx + 1)); done
|
|
fi
|
|
if [[ "$amd" -gt 0 && "$WORKER" != "cuda" ]]; then
|
|
for ((d = 0; d < amd; d++)); do run_gpu "$idx" igneum-worker-opencl "$d" amd & pids+=($!); idx=$((idx + 1)); done
|
|
fi
|
|
say "$idx miner(s) started; dev fee ${DEV_FEE}% (the miner prints its own dev fee line below)"
|
|
|
|
# 5. the main log: every GPU's lines, merged
|
|
sleep 1
|
|
tail -q -n +1 -F "$CUSTOM_LOG_BASENAME".gpu*.log 2>/dev/null | tee -a "$MAIN" &
|
|
pids+=($!)
|
|
wait
|