diff --git a/packaging/hive/README.md b/packaging/hive/README.md index 6676e1a6..b59938a5 100644 --- a/packaging/hive/README.md +++ b/packaging/hive/README.md @@ -6,6 +6,23 @@ the two GPU workers (`igneum-worker-cuda` for NVIDIA, `igneum-worker-opencl` for scripts were self-tested with stub binaries (`selftest.sh`) and the binaries were cross-compiled on a Mac; the first real run on a Hive rig is still to come. Report what breaks. +**A HiveOS rig mines only.** The package (`make-hive-package.sh`) carries `igneumd`, `igneum-miner` and the two +workers; no `igneum-prove-host`, no `igneum-prove-export`, no SP1 GPU server. So a rig on this package earns from the +80% lottery share and nothing from the 20% proving share until a Linux prover build is published. The Ubuntu rig +installer (`packaging/linux/README.md`, branch `rig-install`, commit dd632c1) carries a prover unit that idles in state +`setup` for the same reason; its per-card table is the fuller version of the one below. What each card could do once +the prover ships, from the app's default (`app/igneum-app/src/provedefault.rs` at 440fd59 on `proving-v1`: proving on +at 24 GB or more, off below) and from the proving agent's S_p curve of 5 October 2026 (`docs/bench-log.md`, "proving +v1": jobs `memsweep-pc2-pv1`, `memminer-pc2-pv1` and the S_p curve, one RTX 5090, SP1 6.8.1's GPU server): + +| Card | Once a Linux prover ships | Measured on 5 October 2026 | +|---|---|---| +| 8 GB | mines only | the prover's floor is 13.9 GB for an empty shard | +| 12 GB | mines only; proves nothing on this SP1 build | the same 13.9 GB floor | +| 16 GB | in practice mines only: proves empty shards alone, nothing beside the miner | 13.9 GB alone; 15.7 GB beside the miner leaves nothing for the display | +| 24 GB | proves the adopted v1 shard (30,000 pgas) from the fee switch at DAA 210,000, nothing before it | 20.4 GB alone, about 22 GB beside the miner (approximate, not measured on a 24 GB card); the prototype shard at 28.3 GB does not fit | +| 32 GB | mines and proves, prototype shard included | 28.3 GB alone, 30.0 GB beside the miner, 2.5 GB spare | + ## Flight Sheet | Field | Value | @@ -16,7 +33,9 @@ run on a Hive rig is still to come. Report what breaks. | Wallet and worker template | `0x<40 hex>.%WORKER_NAME%`: the payout address is an EVM address you hold the key for; the part after the dot labels this rig's keys | | Pool URL | `grpc://:26610` (your own igneumd, solo mining), or `local` to run the bundled node on the rig | | Pass | empty | -| Extra config arguments | `DEV_FEE=1 IDENTITIES=8 WORKER=auto VOTE=1` (one per line also works); `PEERS=a:26611,b:26611` for the bundled node; `EXTRA="..."` for more miner flags | +| OVERRIDE | the devnet's consensus override as one JSON object on its own line, needed with `local`: `OVERRIDE={"difficulty_v2_activation_daa":33000,"proving_v0_activation_daa":84100,"fees_v1_activation_daa":210000,"finality_v3_activation_daa":135200}` is the four-field object 0.3.10 shipped; after the 0.3.11 switch it has nine fields, and the downloads page carries the live one. Set OVERRIDE from the downloads page when it changes. **A rig without it is refused**: its node runs on genesis parameters, prints another digest, and every devnet peer drops it (`h-run.sh` warns in the main log) | +| Extra config arguments | `DEV_FEE=1 IDENTITIES=auto WORKER=auto VOTE=1` (one per line also works); `PEERS=a:26611,b:26611` for the bundled node; `EXTRA="..."` for more miner flags | +| IDENTITIES | vote keys per card: 8 for a card with 8 GB or more, else 2 (`IDENTITIES=auto` applies that rule, per card, from `nvidia-smi` or the amdgpu sysfs; 8 when neither answers; a number overrides it for every card). The rule is the app's (`app/igneum-app/src/detect.rs`) | Solo mining: there is no pool. Each card mines block templates from the node and the block reward pays the wallet in the template (80% of each block to its finder, 20% to the proving pool; the protocol takes no fee for anyone). @@ -37,8 +56,8 @@ The protocol carries no fee: this is the software's, and any other miner client | Hook | What | |---|---| -| `h-config.sh` | writes `igneum.conf` from the Flight Sheet (node URL, wallet, label, DEV_FEE, IDENTITIES, WORKER, VOTE, PEERS, EXTRA); refuses a wallet that is not 0x + 40 hex | -| `h-run.sh` | starts the bundled node when the URL is `local`, waits for the node, exports the hourly program pack (`igneum-miner export-pack`), then one `igneum-miner` per GPU with its worker; restarts a miner that exits (exit 42 = program change without prepare support: the pack is re-exported first); per-GPU logs `.gpu.log`, merged into the main log | +| `h-config.sh` | writes `igneum.conf` from the Flight Sheet (node URL, wallet, label, DEV_FEE, IDENTITIES, WORKER, VOTE, PEERS, EXTRA, OVERRIDE); refuses an OVERRIDE that is not `{...}`; resolves `IDENTITIES=auto` to `IDENTITIES_GPU` keys by VRAM; refuses a wallet that is not 0x + 40 hex | +| `h-run.sh` | starts the bundled node when the URL is `local` (writes `data/override-params.json` from OVERRIDE and passes `--override-params-file`; warns when OVERRIDE is empty; copies the node's switch lines and its `Consensus params digest` line into the main log), waits for the node, exports the hourly program pack (`igneum-miner export-pack`), then one `igneum-miner` per GPU with its worker (`--identities` from `IDENTITIES_GPU`, else `IDENTITIES`); restarts a miner that exits (exit 42 = program change without prepare support: the pack is re-exported first); per-GPU logs `.gpu.log`, merged into the main log | | `h-stats.sh` | per-GPU hash rate from each miner's last `STATUS` line (`now=`), accepted and rejected totals, dev-fee block count, temperatures and fans from Hive's `gpu-stats` (else `nvidia-smi`), uptime, version | Stats JSON (what Hive reads from `$stats`): `hs` (kH/s per GPU), `hs_units` (`khs`), `temp`, `fan`, `uptime` (s), @@ -50,7 +69,9 @@ Stats JSON (what Hive reads from `$stats`): `hs` (kH/s per GPU), `hs_units` (`kh on the library path). The worker compiles the hourly program at run time with NVRTC; without the library it says so and the miner retries. Hive images ship the driver; whether `libnvrtc.so.12` is present depends on the image, untested. - AMD: an OpenCL ICD (`libOpenCL.so.1` from ROCm or amdgpu-pro). The OpenCL worker compiles the program through the ICD. -- The bundled node (`local`) keeps its chain data under the miner folder (`data/`); a devnet chain is small today. +- The bundled node (`local`) keeps its chain data under the miner folder (`data/`); a devnet chain is small today. It + needs OVERRIDE (the Flight Sheet table): compare the `node: Consensus params digest:` line in the main log with the + digest on the downloads page; a different one means the override is stale and the node is refused. - Ports: the bundled node listens on 26611 (p2p) and answers RPC on 127.0.0.1:26610 only. ## Building the package @@ -67,3 +88,7 @@ Stats JSON (what Hive reads from `$stats`): `hs` (kH/s per GPU), `hs_units` (`kh - GPU order: the CUDA device index is assumed to follow `nvidia-smi` order and Hive's `gpu-stats` arrays (NVIDIA first); a mixed NVIDIA and AMD rig may show temperatures against the wrong card. - Each card runs its own `igneum-miner` and node connection; the node's template RPC serves them all. +- Before this change no package carried the override: `h-run.sh` started the node without `--override-params-file`, so + a `local` rig was refused by every devnet peer (release 0.3.11, section 5, C41). Still untested on a rig. +- No prover in the package (the second paragraph above): the rig earns nothing from the proving share until a Linux + prover build ships. diff --git a/packaging/hive/h-config.sh b/packaging/hive/h-config.sh index 60f1d044..2b374375 100755 --- a/packaging/hive/h-config.sh +++ b/packaging/hive/h-config.sh @@ -8,11 +8,19 @@ # CUSTOM_USER_CONFIG extra lines, KEY=VALUE, one per line or separated by spaces: # DEV_FEE=1 the miner software's dev fee in whole percent (1 block template in 100 to the dev # address); DEV_FEE=0 turns it off. The protocol itself takes no fee. -# IDENTITIES=8 vote keys per card (8 for a big card, 2 for a small one) +# IDENTITIES=auto vote keys per card: 8 for a card with 8 GB or more, else 2 (IDENTITIES=auto +# applies that rule per card from nvidia-smi or the amdgpu sysfs, 8 when neither +# answers; the app's rule, app/igneum-app/src/detect.rs). A number overrides it +# for every card. # WORKER=auto auto | cuda | opencl (the GPU worker; auto = cuda on NVIDIA, opencl on AMD) # VOTE=1 sign finality checkpoints (0 = mine without voting) # PEERS=a:26611,b:26611 peers for the bundled node when CUSTOM_URL=local # EXTRA="..." appended to every igneum-miner command line +# OVERRIDE={...} the devnet's consensus override, one JSON object on its own line (single or +# double quotes around it are fine in the Hive UI); the bundled node (CUSTOM_URL=local) +# starts with --override-params-file from it. Without it the node runs on genesis +# parameters and every devnet peer refuses it. Copy the live object from the +# downloads page whenever it changes. # Hive sources h-manifest.conf before this hook; the fallback is for a run outside Hive (selftest.sh) [[ -z "$CUSTOM_CONFIG_FILENAME" ]] && . "$(dirname "${BASH_SOURCE[0]}")/h-manifest.conf" @@ -29,22 +37,67 @@ if ! [[ "$wallet" =~ ^0x[0-9a-fA-F]{40}$ ]]; then fi # defaults, then the user's KEY=VALUE lines -DEV_FEE=1; IDENTITIES=8; WORKER=auto; VOTE=1; PEERS=""; EXTRA="" -while read -r kv; do - [[ -z "$kv" || "$kv" == \#* ]] && continue - key="${kv%%=*}"; val="${kv#*=}" - case "$key" in - DEV_FEE|IDENTITIES|WORKER|VOTE|PEERS|EXTRA) printf -v "$key" '%s' "$val" ;; - *) echo "Igneum: unknown setting '$key' ignored" ;; - esac -done < <(printf '%s\n' "$CUSTOM_USER_CONFIG" | tr ' ' '\n' | sed 's/^"//; s/"$//') +DEV_FEE=1; IDENTITIES=auto; WORKER=auto; VOTE=1; PEERS=""; EXTRA=""; OVERRIDE="" +while IFS= read -r line; do + [[ -z "$line" || "$line" == \#* ]] && continue + if [[ "$line" == OVERRIDE=* ]]; then # the whole line: JSON may carry spaces; quotes around it are stripped + val="${line#OVERRIDE=}"; val="${val#\'}"; val="${val%\'}"; val="${val#\"}"; val="${val%\"}" + OVERRIDE="$val"; continue + fi + while read -r kv; do + [[ -z "$kv" ]] && continue + key="${kv%%=*}"; val="${kv#*=}" + case "$key" in + DEV_FEE|IDENTITIES|WORKER|VOTE|PEERS|EXTRA) printf -v "$key" '%s' "$val" ;; + *) echo "Igneum: unknown setting '$key' ignored" ;; + esac + done < <(printf '%s\n' "$line" | tr ' ' '\n' | sed 's/^"//; s/"$//') +done < <(printf '%s\n' "$CUSTOM_USER_CONFIG") +if [[ -n "$OVERRIDE" && ! "$OVERRIDE" =~ ^\{.*\}$ ]]; then + echo -e "${YELLOW:-}Igneum: OVERRIDE must be one JSON object, {\"...\":N,...} from the downloads page; got '${OVERRIDE:0:40}'${NOCOLOR:-}" + return 1 +fi [[ "$DEV_FEE" =~ ^[0-9]+$ ]] || DEV_FEE=1 -[[ "$IDENTITIES" =~ ^[0-9]+$ ]] || IDENTITIES=8 +[[ "$IDENTITIES" =~ ^[0-9]+$ || "$IDENTITIES" == "auto" ]] || IDENTITIES=auto + +# IDENTITIES=auto: 8 for a card with 8 GiB (8192 MiB) or more, else 2, per card, in the order h-run.sh numbers them +# (NVIDIA first unless WORKER=opencl, then AMD unless WORKER=cuda). VRAM from nvidia-smi (MiB per line) and from +# /sys/class/drm/card/device/mem_info_vram_total (bytes, amdgpu). A card whose VRAM cannot be read gets 8. +ident_block="" # IDENTITIES_GPU=... lines, one per card, newline-terminated +ident_summary="" +if [[ "$IDENTITIES" == "auto" ]]; then + vrams=() + if [[ "$WORKER" != "opencl" ]] && command -v nvidia-smi >/dev/null 2>&1; then + nvq=(nvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits) + command -v timeout >/dev/null 2>&1 && nvq=(timeout 20 "${nvq[@]}") + while read -r mib; do + mib="${mib//[[:space:]]/}" + [[ "$mib" =~ ^[0-9]+$ ]] && vrams+=("$mib") || vrams+=("") + done < <("${nvq[@]}" 2>/dev/null) + fi + if [[ "$WORKER" != "cuda" ]]; then + for d in "${IGNEUM_DRM_ROOT:-/sys/class/drm}"/card*; do + [[ "$(basename "$d")" =~ ^card[0-9]+$ && -r "$d/device/mem_info_vram_total" ]] || continue + bytes="$(cat "$d/device/mem_info_vram_total" 2>/dev/null)" + [[ "$bytes" =~ ^[0-9]+$ ]] && vrams+=("$((bytes / 1048576))") || vrams+=("") + done + fi + n=0 + for mib in ${vrams[@]+"${vrams[@]}"}; do + if [[ -z "$mib" || "$mib" -ge 8192 ]]; then ident=8; else ident=2; fi + ident_block+="IDENTITIES_GPU$n=$ident"$'\n' + ident_summary+="gpu$n ${mib:-?}MiB:$ident " + n=$((n + 1)) + done + IDENTITIES=8 # the fallback h-run.sh uses for a card h-config.sh could not see + [[ $n == 0 ]] && ident_summary="no VRAM readable, 8 per card" +fi url="$CUSTOM_URL" [[ "$url" == "local" ]] && url="local" [[ "$url" != "local" && "$url" != grpc://* ]] && url="grpc://$url" +sq() { local v="${1//\'/\'\\\'\'}"; printf "'%s'" "$v"; } # single-quoted for sourcing: JSON and flags carry shell characters mkdir -p "$(dirname "$CUSTOM_CONFIG_FILENAME")" cat > "$CUSTOM_CONFIG_FILENAME" < "$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[@]}" \ - --nodnsseed --disable-upnp --nologfiles --yes >> "$CUSTOM_LOG_BASENAME.node.log" 2>&1 & + ${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" @@ -37,6 +48,13 @@ 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 @@ -59,7 +77,8 @@ run_gpu() { 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) - [[ "$IDENTITIES" -gt 1 ]] && args+=(--identities "$IDENTITIES") + 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) diff --git a/packaging/hive/selftest.sh b/packaging/hive/selftest.sh index 66b75de9..044442f4 100755 --- a/packaging/hive/selftest.sh +++ b/packaging/hive/selftest.sh @@ -35,6 +35,14 @@ case "$1" in esac FAKE chmod +x "$M/bin/igneum-miner" +cat > "$M/bin/igneumd" <<'FAKE' +#!/usr/bin/env bash +echo "fake igneumd $*" +for a in "$@"; do case "$a" in --override-params-file=*) echo "Finality rule v3 from the override file: active from checkpoint DAA score 135200" ;; esac; done +echo "Consensus params digest: 0139ab9dc2992d449ec787d8f021974933631eb55740ab4b6ce9d5c226e72888 (exchanged in the p2p handshake; a peer with another digest is refused)" +sleep 600 +FAKE +chmod +x "$M/bin/igneumd" mkdir -p "$T/bin" printf '#!/bin/sh\n[ "$1" = NVIDIA ] && echo 2 || echo 0\n' > "$T/bin/gpu-detect" cat > "$T/bin/gpu-stats" <<'GS' @@ -49,6 +57,27 @@ export CUSTOM_CONFIG_FILENAME="$M/igneum.conf" CUSTOM_LOG_BASENAME="$T/log/igneu ( . "$M/h-config.sh" ) || { echo "h-config.sh failed"; exit 1; } grep -q '^WALLET=0xabcd000000000000000000000000000000000001$' "$M/igneum.conf" && grep -q '^DEV_FEE=0$' "$M/igneum.conf" && grep -q '^LABEL=rig7$' "$M/igneum.conf" && grep -q '^IDENTITIES=4$' "$M/igneum.conf" && echo " conf ok: $(tr '\n' ' ' < "$M/igneum.conf" | cut -c1-160)" ( CUSTOM_TEMPLATE="notanaddress" . "$M/h-config.sh" >/dev/null 2>&1 ) && { echo "h-config.sh accepted a bad wallet"; exit 1; } || echo " bad wallet refused ok" +echo "== h-config.sh IDENTITIES=auto" +# no GPU tool on the PATH (gpu-detect is not a VRAM source) and no amdgpu sysfs: every card falls back to 8 +( CUSTOM_USER_CONFIG="IDENTITIES=auto" IGNEUM_DRM_ROOT="$T/no-drm" CUSTOM_CONFIG_FILENAME="$T/auto-none.conf" . "$M/h-config.sh" >/dev/null ) || { echo "h-config.sh failed on IDENTITIES=auto"; exit 1; } +grep -q '^IDENTITIES=8$' "$T/auto-none.conf" && ! grep -q '^IDENTITIES_GPU' "$T/auto-none.conf" && echo " auto with no GPU tools: IDENTITIES=8, no per-card keys ok" || { echo "FAIL: auto without tools"; cat "$T/auto-none.conf"; exit 1; } +# the default is auto: no IDENTITIES line at all gives the same +( CUSTOM_USER_CONFIG="" IGNEUM_DRM_ROOT="$T/no-drm" CUSTOM_CONFIG_FILENAME="$T/auto-default.conf" . "$M/h-config.sh" >/dev/null ) && grep -q '^IDENTITIES=8$' "$T/auto-default.conf" && echo " default (no IDENTITIES line) is auto ok" || { echo "FAIL: default not auto"; exit 1; } +# a stubbed nvidia-smi: 6 GB and 24 GB cards resolve to 2 and 8, in nvidia-smi order +printf '#!/bin/sh\nprintf "6144\\n24576\\n"\n' > "$T/bin/nvidia-smi"; chmod +x "$T/bin/nvidia-smi" +( CUSTOM_USER_CONFIG="IDENTITIES=auto" IGNEUM_DRM_ROOT="$T/no-drm" CUSTOM_CONFIG_FILENAME="$T/auto-nv.conf" . "$M/h-config.sh" >/dev/null ) || { echo "h-config.sh failed on stubbed nvidia-smi"; exit 1; } +grep -q '^IDENTITIES_GPU0=2$' "$T/auto-nv.conf" && grep -q '^IDENTITIES_GPU1=8$' "$T/auto-nv.conf" && grep -q '^IDENTITIES=8$' "$T/auto-nv.conf" && grep -q '^WORKER=auto$' "$T/auto-nv.conf" && echo " auto with nvidia-smi 6144/24576: gpu0=2, gpu1=8 ok" || { echo "FAIL: auto by VRAM"; cat "$T/auto-nv.conf"; exit 1; } +# a number still overrides every card +( CUSTOM_USER_CONFIG="IDENTITIES=4" CUSTOM_CONFIG_FILENAME="$T/auto-num.conf" . "$M/h-config.sh" >/dev/null ) && grep -q '^IDENTITIES=4$' "$T/auto-num.conf" && ! grep -q '^IDENTITIES_GPU' "$T/auto-num.conf" && echo " numeric override keeps IDENTITIES=4 ok" || { echo "FAIL: numeric override"; exit 1; } +rm -f "$T/bin/nvidia-smi" +echo "== h-config.sh OVERRIDE" +OV='{"difficulty_v2_activation_daa":33000,"proving_v0_activation_daa":84100,"fees_v1_activation_daa":210000,"finality_v3_activation_daa":135200}' +( CUSTOM_USER_CONFIG="DEV_FEE=0 VOTE=1"$'\n'"OVERRIDE='$OV'"$'\n'"IDENTITIES=4" CUSTOM_CONFIG_FILENAME="$T/ov.conf" . "$M/h-config.sh" >/dev/null ) || { echo "h-config.sh failed on OVERRIDE"; exit 1; } +( . "$T/ov.conf"; [[ "$OVERRIDE" == "$OV" && "$DEV_FEE" == 0 && "$IDENTITIES" == 4 ]] ) && echo " OVERRIDE (single-quoted, own line) sourced back intact beside the other keys ok" || { echo "FAIL: OVERRIDE round trip"; cat "$T/ov.conf"; exit 1; } +( CUSTOM_USER_CONFIG="OVERRIDE=notjson" CUSTOM_CONFIG_FILENAME="$T/ov-bad.conf" . "$M/h-config.sh" >/dev/null 2>&1 ) && { echo "FAIL: OVERRIDE=notjson accepted"; exit 1; } || echo " OVERRIDE that is not {...} refused ok" +( CUSTOM_USER_CONFIG="" CUSTOM_CONFIG_FILENAME="$T/ov-none.conf" . "$M/h-config.sh" | grep -q "override NONE" ) && grep -q "^OVERRIDE=''$" "$T/ov-none.conf" && echo " no OVERRIDE: empty in the conf and named in the summary ok" || { echo "FAIL: empty OVERRIDE"; exit 1; } +# h-run.sh reads IDENTITIES_GPU first: write a conf with gpu1=3 and check the second miner's argv +( CUSTOM_USER_CONFIG=$'DEV_FEE=0\nIDENTITIES=auto\n'"OVERRIDE=$OV" IGNEUM_DRM_ROOT="$T/no-drm" CUSTOM_CONFIG_FILENAME="$M/igneum.conf" . "$M/h-config.sh" >/dev/null ) && printf 'IDENTITIES_GPU1=3\n' >> "$M/igneum.conf" echo "== h-run.sh (fake GPUs: 2 NVIDIA, fake node, fake miner)" ( cd "$M" && CUSTOM_CONFIG_FILENAME="$M/igneum.conf" CUSTOM_LOG_BASENAME="$T/log/igneum" ./h-run.sh > "$T/log/run.out" 2>&1 ) & disown @@ -56,9 +85,21 @@ sleep 8 ls "$T/log" | sed 's/^/ /' _lines=$(grep -c "dev fee off (--dev-fee 0)" "$T/log/igneum.log" || true); echo " dev fee lines in the main log: $_lines"; [[ "$_lines" -ge 2 ]] || { echo "FAIL: expected the two miners' dev fee lines in the main log"; cat "$T/log/run.out"; exit 1; } grep -q -- "--dev-fee 0" "$M/argv.log" && echo " DEV_FEE=0 reached the miner as --dev-fee 0 ok" || { echo "FAIL: --dev-fee 0 missing"; exit 1; } -grep -q -- "--identities 4" "$M/argv.log" && echo " IDENTITIES=4 reached the miner ok" || { echo "FAIL: --identities 4 missing"; exit 1; } +grep -q -- "rig7-gpu0 .*--identities 8" "$M/argv.log" && echo " gpu0 took the IDENTITIES=8 fallback ok" || { echo "FAIL: --identities 8 missing on gpu0"; cat "$M/argv.log"; exit 1; } +grep -q -- "rig7-gpu1 .*--identities 3" "$M/argv.log" && echo " gpu1 took IDENTITIES_GPU1=3 over the fallback ok" || { echo "FAIL: --identities 3 missing on gpu1"; cat "$M/argv.log"; exit 1; } +[[ "$(cat "$M/data/override-params.json")" == "$OV" ]] && echo " data/override-params.json written from OVERRIDE ok" || { echo "FAIL: override file"; exit 1; } +grep -q -- "--override-params-file=$M/data/override-params.json" "$T/log/igneum.node.log" && echo " the node got --override-params-file ok" || { echo "FAIL: node flag"; cat "$T/log/igneum.node.log"; exit 1; } +grep -q "node: Consensus params digest: 0139ab9d" "$T/log/igneum.log" && grep -q "node: Finality rule v3 from the override file" "$T/log/igneum.log" && echo " the node's digest and switch lines reached the main log ok" || { echo "FAIL: digest relay"; cat "$T/log/igneum.log"; exit 1; } grep -q "igneum-worker-cuda" "$M/argv.log" && echo " NVIDIA cards got the cuda worker ok" || { echo "FAIL: cuda worker missing"; exit 1; } [[ -f "$M/exited42" && $(grep -c "^mine" "$M/argv.log") -ge 3 ]] && echo " exit 42 restarted the miner and re-exported the pack ok" || { echo "FAIL: no restart after exit 42"; exit 1; } echo "== h-stats.sh (sourced)" ( . "$M/h-stats.sh"; echo " khs=$khs"; echo " stats=$stats"; python3 -c "import json,sys; s=json.loads(sys.argv[1]); assert s['hs_units']=='khs' and len(s['hs'])==2 and s['ar'][0]>0 and s['algo']=='igneum' and len(s['temp'])==2, s; print(' stats JSON ok: hs', s['hs'], 'temp', s['temp'], 'ar', s['ar'], 'bus', s['bus_numbers'])" "$stats" ) +echo "== h-run.sh without OVERRIDE (the warning)" +( CUSTOM_USER_CONFIG=$'DEV_FEE=0' IGNEUM_DRM_ROOT="$T/no-drm" CUSTOM_CONFIG_FILENAME="$T/noov.conf" . "$M/h-config.sh" >/dev/null ) +mkdir -p "$T/log2" +( cd "$M" && CUSTOM_CONFIG_FILENAME="$T/noov.conf" CUSTOM_LOG_BASENAME="$T/log2/igneum" ./h-run.sh > "$T/log2/run.out" 2>&1 ) & +disown +sleep 4 +grep -q "WARNING: no OVERRIDE in the Flight Sheet" "$T/log2/igneum.log" && ! grep -q -- "--override-params-file" "$T/log2/igneum.node.log" && echo " no OVERRIDE: warning in the main log, no flag on the node ok" || { echo "FAIL: missing warning"; cat "$T/log2/igneum.log"; exit 1; } +_p2="$(cat "$T/log2/igneum.pid" 2>/dev/null)"; [[ -n "$_p2" ]] && kill -TERM "$_p2" 2>/dev/null; sleep 1 echo "== self-test passed (scripts and stats shape; Hive itself is untested)"