infra/cloud-devnet: hcloud (doctl variant) create, builder-VM provision from a git-archive source tarball, systemd units for igneumd --devnet-suffix with a sparse --addpeer mesh and a CPU trickle miner per node, stdlib wRPC client, experiments (latency, partition, hop, collect, observer hookup), README with the command sequence and the Hetzner API prices of 3 Oct 2026. infra/gpu-bench: RunPod image recipes (CUDA 12.8, ROCm), bundle, run.sh (vectors gate, 10-min raw, sweep, inline shortcut ratio, nvcc/NVRTC/OpenCL recompile timings, results row, intake upload), bench-log template. infra/seed-nodes: create-seed (persistent IPv4, firewall), provision on the VM, health check, addPeer from the Mac over grpcurl, seeds.txt; igneum-seed-1 created at 188.245.5.161 (Hetzner cx23, fsn1). docs/plans/cloud-devnet.md and docs/plans/seed-nodes.md. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
50 lines
2.4 KiB
Bash
Executable file
50 lines
2.4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Experiment 1c: hash-rate steps for the difficulty controller (spec 02 section 2.3; the dual-lane rule is on the
|
|
# `difficulty` worktree, NODE_SRC=vendor/igneum-node-diff when building; on master it exercises Kaspa's sampled DAA).
|
|
# ./experiments/hop.sh "<schedule>"
|
|
# schedule = phases separated by ";", phase = <selector>:<threads>:<seconds>
|
|
# selector: all | half (odd indices) | odd | even | region:<name> | <from>-<to> (indices)
|
|
# threads: miner threads on the selected nodes (0 stops the miner); unselected nodes keep their setting
|
|
# Default schedule (about 75 min): steady, 4x step up on half the nodes, back down, one region off, back:
|
|
# all:1:900;half:4:900;all:1:900;region:hel1:0:600;all:1:900
|
|
# Every phase change is logged to results/<date>/hop.log (ts_ms, selector, threads); collect.sh and analyze.py hop
|
|
# line the difficulty samples up against it.
|
|
. "$(dirname "$0")/../lib/common.sh"
|
|
require_nodes
|
|
schedule="${1:-all:1:900;half:4:900;all:1:900;region:hel1:0:600;all:1:900}"
|
|
out="$(results_dir_for)"; logf="$out/hop.log"
|
|
|
|
select_nodes() {
|
|
case "$1" in
|
|
all) node_names ;;
|
|
half|odd) awk -F'\t' '$2 % 2 == 1 { print $1 }' "$NODES_FILE" ;;
|
|
even) awk -F'\t' '$2 % 2 == 0 { print $1 }' "$NODES_FILE" ;;
|
|
region:*) nodes_in_region "${1#region:}" ;;
|
|
*-*) awk -F'\t' -v a="${1%-*}" -v b="${1#*-}" '$2 >= a && $2 <= b { print $1 }' "$NODES_FILE" ;;
|
|
*) die "bad selector $1" ;;
|
|
esac
|
|
}
|
|
|
|
set_threads() { # node threads
|
|
local ip; ip=$(node_ip "$1")
|
|
if [ "$2" = 0 ]; then
|
|
nssh "$ip" "systemctl stop igneum-miner"
|
|
else
|
|
nssh "$ip" "sed -i 's/^MINER_THREADS=.*/MINER_THREADS=$2/' /etc/igneum/node.env && systemctl restart igneum-miner"
|
|
fi
|
|
}
|
|
|
|
log "schedule: $schedule"
|
|
IFS=';' read -r -a phases <<< "$schedule"
|
|
for ph in "${phases[@]}"; do
|
|
sel="${ph%%:*}"; rest="${ph#*:}"
|
|
if [ "$sel" = region ]; then sel="region:${rest%%:*}"; rest="${rest#*:}"; fi
|
|
threads="${rest%%:*}"; secs="${rest#*:}"
|
|
nodes=$(select_nodes "$sel")
|
|
log "phase: $sel -> $threads thread(s) for $secs s ($(printf '%s\n' "$nodes" | wc -l | tr -d ' ') nodes)"
|
|
for n in $nodes; do set_threads "$n" "$threads" & done; wait
|
|
printf '%s\t%s\t%s\t%s\n' "$(date +%s)000" "$sel" "$threads" "$secs" >> "$logf"
|
|
sleep "$secs"
|
|
done
|
|
printf '%s\tend\t-\t-\n' "$(date +%s)000" >> "$logf"
|
|
log "done; phases in $logf. Pull the samples with ./experiments/collect.sh and read results/<date>/hop.md"
|