From f6757869ddcd497f7ffeaf9a6792d1e138e1f169 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Mon, 5 Oct 2026 20:41:40 +0000 Subject: [PATCH 1/3] HiveOS: rigs mine only until a Linux prover ships; IDENTITIES=auto by VRAM README: a second paragraph under the title says the package carries igneumd, igneum-miner and the two workers and no prover (make-hive-package.sh), so a HiveOS rig earns nothing from the 20% proving share until a Linux prover build is published; the rig installer on rig-install (3799604, packaging/linux/README.md) idles its prover unit in state setup for the same reason. A per-card table (8, 12, 16, 24, 32 GB) from the app's rule in provedefault.rs and the proving agent's measurements of 5 October 2026 (bench-log "proving v1": 13.9 GB prover alone on an empty shard, 28.3 GB on the full prototype shard, 15.6 GB and 16.75 GB mine-and-prove on one 5090, 30.0 GB full shard beside the miner), marked before the v1-shard row. IDENTITIES: the app's rule (detect.rs) is 8 vote keys for a card with 8 GiB or more, else 2. h-config.sh now defaults to IDENTITIES=auto and resolves it per card from nvidia-smi memory.total or /sys/class/drm/card/device/mem_info_vram_total (amdgpu), 8 when neither answers, writing IDENTITIES_GPU keys into igneum.conf beside the IDENTITIES=8 fallback; a number still overrides every card. h-run.sh reads IDENTITIES_GPU first, else IDENTITIES. The README and the h-config comment say the number. selftest.sh: IDENTITIES=auto with no GPU tools (8, no per-card keys), the default being auto, a stubbed nvidia-smi printing 6144 and 24576 (gpu0=2, gpu1=8), the numeric override, and h-run taking IDENTITIES_GPU1=3 over the fallback. bash packaging/hive/selftest.sh on this Mac: auto with no GPU tools: IDENTITIES=8, no per-card keys ok default (no IDENTITIES line) is auto ok auto with nvidia-smi 6144/24576: gpu0=2, gpu1=8 ok numeric override keeps IDENTITIES=4 ok == h-run.sh (fake GPUs: 2 NVIDIA, fake node, fake miner) dev fee lines in the main log: 4 DEV_FEE=0 reached the miner as --dev-fee 0 ok gpu0 took the IDENTITIES=8 fallback ok gpu1 took IDENTITIES_GPU1=3 over the fallback 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] == self-test passed (scripts and stats shape; Hive itself is untested) Co-Authored-By: Claude Fable 5.1 --- packaging/hive/README.md | 29 +++++++++++++++++++++--- packaging/hive/h-config.sh | 46 +++++++++++++++++++++++++++++++++----- packaging/hive/h-run.sh | 3 ++- packaging/hive/selftest.sh | 18 ++++++++++++++- 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/packaging/hive/README.md b/packaging/hive/README.md index 6676e1a61..e5072ded1 100644 --- a/packaging/hive/README.md +++ b/packaging/hive/README.md @@ -6,6 +6,26 @@ 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 rule (`app/igneum-app/src/provedefault.rs` on `proving-v1`: 20 GB mines and proves on +one card, 16 GB proves only with the miner paused, under 16 GB mines only) and from the proving agent's measurements +of 5 October 2026, before the v1-shard row (`docs/bench-log.md`, "proving v1": jobs `prover-cost-pc2-pv1b`, +`chain-pc2-pv1c`, `memsweep-pc2-pv1`, `memminer-pc2-pv1`, one RTX 5090): + +| Card | Once a Linux prover ships | Measured on 5 October 2026 | +|---|---|---| +| 8 GB | mines only | the prover alone peaks at 13.9 GB on an empty shard | +| 12 GB | mines only | the same 13.9 GB does not fit | +| 16 GB | proves only, with the miner paused | mine-and-prove peaked at 15.6 GB on empty shards and 16.75 GB with chained aggregation | +| 24 GB | mines and proves | 16.75 GB leaves 7 GB; the full prototype shard (28.3 GB with the card to itself) does not fit | +| 32 GB | mines and proves | the full prototype shard beside the miner peaked at 30.0 GB | + +The v1-budget shard (about 7 M cycles) is unmeasured and may move these lines. + ## Flight Sheet | Field | Value | @@ -16,7 +36,8 @@ 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 | +| 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 +58,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); 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`, 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), @@ -67,3 +88,5 @@ 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. +- 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 60f1d044c..3c724ae7d 100755 --- a/packaging/hive/h-config.sh +++ b/packaging/hive/h-config.sh @@ -8,7 +8,10 @@ # 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 @@ -29,7 +32,7 @@ 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="" +DEV_FEE=1; IDENTITIES=auto; WORKER=auto; VOTE=1; PEERS=""; EXTRA="" while read -r kv; do [[ -z "$kv" || "$kv" == \#* ]] && continue key="${kv%%=*}"; val="${kv#*=}" @@ -39,7 +42,40 @@ while read -r kv; do esac done < <(printf '%s\n' "$CUSTOM_USER_CONFIG" | tr ' ' '\n' | sed 's/^"//; s/"$//') [[ "$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" @@ -53,9 +89,9 @@ WALLET=$(printf '%s' "$wallet" | tr 'A-F' 'a-f') LABEL=$label DEV_FEE=$DEV_FEE IDENTITIES=$IDENTITIES -WORKER=$WORKER +${ident_block}WORKER=$WORKER VOTE=$VOTE PEERS=$PEERS EXTRA=$EXTRA CONF -echo "Igneum: config written to $CUSTOM_CONFIG_FILENAME (node $url, wallet ${wallet:0:8}..., dev fee ${DEV_FEE}%, $IDENTITIES identities per card)" +echo "Igneum: config written to $CUSTOM_CONFIG_FILENAME (node $url, wallet ${wallet:0:8}..., dev fee ${DEV_FEE}%, identities ${ident_summary:-$IDENTITIES per card})" diff --git a/packaging/hive/h-run.sh b/packaging/hive/h-run.sh index c936fe4b8..d07aa9ab9 100755 --- a/packaging/hive/h-run.sh +++ b/packaging/hive/h-run.sh @@ -59,7 +59,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 66b75de9b..40fcedfe5 100755 --- a/packaging/hive/selftest.sh +++ b/packaging/hive/selftest.sh @@ -49,6 +49,21 @@ 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" +# 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' 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,7 +71,8 @@ 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; } 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)" From 7be34b2f5dbc743a9460cfaf9f3f2abc6e088b6b Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Mon, 5 Oct 2026 20:46:03 +0000 Subject: [PATCH 2/3] HiveOS README: the per-card table from the S_p curve The "Once a Linux prover ships" column and the sentence above it now follow the proving agent's S_p curve (bench-log "proving v1" on proving-v1) and the app's default at 66e1199 (proving on at 24 GB or more, off below): 32 GB mines and proves the prototype shard (28.3 GB alone, 30.0 GB beside the miner, 2.5 GB spare); 24 GB proves the adopted v1 shard of 30,000 pgas (20.4 GB alone, about 22 GB beside the miner, approximate) from the fee switch at DAA 210,000 and nothing before it; 16 GB proves only empty shards alone (13.9 GB) and nothing beside the miner (15.7 GB), so in practice mines only; 12 GB proves nothing on SP1 6.8.1's GPU server; 8 GB mines only. The sources line stays; "before the v1-shard row" and the v1-budget caveat are gone, the curve measured it. README only; selftest.sh unchanged and still passing from f675786. Co-Authored-By: Claude Fable 5.1 --- packaging/hive/README.md | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/packaging/hive/README.md b/packaging/hive/README.md index e5072ded1..706f8844d 100644 --- a/packaging/hive/README.md +++ b/packaging/hive/README.md @@ -11,20 +11,17 @@ workers; no `igneum-prove-host`, no `igneum-prove-export`, no SP1 GPU server. So 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 rule (`app/igneum-app/src/provedefault.rs` on `proving-v1`: 20 GB mines and proves on -one card, 16 GB proves only with the miner paused, under 16 GB mines only) and from the proving agent's measurements -of 5 October 2026, before the v1-shard row (`docs/bench-log.md`, "proving v1": jobs `prover-cost-pc2-pv1b`, -`chain-pc2-pv1c`, `memsweep-pc2-pv1`, `memminer-pc2-pv1`, one RTX 5090): +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 alone peaks at 13.9 GB on an empty shard | -| 12 GB | mines only | the same 13.9 GB does not fit | -| 16 GB | proves only, with the miner paused | mine-and-prove peaked at 15.6 GB on empty shards and 16.75 GB with chained aggregation | -| 24 GB | mines and proves | 16.75 GB leaves 7 GB; the full prototype shard (28.3 GB with the card to itself) does not fit | -| 32 GB | mines and proves | the full prototype shard beside the miner peaked at 30.0 GB | - -The v1-budget shard (about 7 M cycles) is unmeasured and may move these lines. +| 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 From 6e8cf598066e824881ef8ea7e3491b92d2553db2 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Mon, 5 Oct 2026 23:35:03 +0000 Subject: [PATCH 3/3] HiveOS: the bundled node takes the override from the Flight Sheet (C41) 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= 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= 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 --- packaging/hive/README.md | 11 ++++++++--- packaging/hive/h-config.sh | 40 +++++++++++++++++++++++++++----------- packaging/hive/h-run.sh | 22 +++++++++++++++++++-- packaging/hive/selftest.sh | 27 ++++++++++++++++++++++++- 4 files changed, 83 insertions(+), 17 deletions(-) diff --git a/packaging/hive/README.md b/packaging/hive/README.md index 706f8844d..b59938a57 100644 --- a/packaging/hive/README.md +++ b/packaging/hive/README.md @@ -33,6 +33,7 @@ v1": jobs `memsweep-pc2-pv1`, `memminer-pc2-pv1` and the S_p curve, one RTX 5090 | 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 | +| 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`) | @@ -55,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); 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`, 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-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), @@ -68,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 @@ -85,5 +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 3c724ae7d..2b3743754 100755 --- a/packaging/hive/h-config.sh +++ b/packaging/hive/h-config.sh @@ -16,6 +16,11 @@ # 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" @@ -32,15 +37,26 @@ if ! [[ "$wallet" =~ ^0x[0-9a-fA-F]{40}$ ]]; then fi # defaults, then the user's KEY=VALUE lines -DEV_FEE=1; IDENTITIES=auto; 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" == "auto" ]] || IDENTITIES=auto @@ -81,6 +97,7 @@ 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 diff --git a/packaging/hive/selftest.sh b/packaging/hive/selftest.sh index 40fcedfe5..044442f4c 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' @@ -62,8 +70,14 @@ grep -q '^IDENTITIES_GPU0=2$' "$T/auto-nv.conf" && grep -q '^IDENTITIES_GPU1=8$' # 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' 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" +( 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 @@ -73,8 +87,19 @@ _lines=$(grep -c "dev fee off (--dev-fee 0)" "$T/log/igneum.log" || true); echo 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 -- "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)"