partition.sh adapted to private-network mode: the cut sits on the region's gateway (INPUT, OUTPUT and FORWARD against the far gateways' public IPs over 26611 and the DNAT ports 27001:27099), since a per-node port-26611 rule leaves the DNAT links up. It now records the locks per side at cut, during, at heal and after convergence, the first lock after the heal from the journals, and the heal time as each minority node's first chain removal of 5+ blocks (the sink-count criterion is tip churn on a healthy network). hop.sh and partition.sh hold the Mac awake with caffeinate; analyze.py gains a 10-s hop series (difficulty, block count, 1- and 2-min rates, threads) and an overshoot table; collect.sh writes hop-series.tsv and hop.md and gzips the journals. Results 2026-10-04: partition 1 (window still filling) reorg 431/496 on the minority, 2 on the majority, healed in 10 and 14 s; partition 2 (locks active): minority locked nothing during the cut, majority locked every interval at 66.8% to 84.5% of total, 0 conflicting locks over 107 indices, healed in 11 and 15 s, first lock after heal 13 s. Hash-rate steps x1.42, x0.70, x0.75, x1.32: difficulty overshoots x1.67, x0.66, x0.53, x1.60, settle 751 s, never in 900 s, 241 s, 646 s. Failures stated in summary.md: the Mac hibernated during the hop (phase 2 ran 94 min), the first partition could not see locks, the script's heal and first-lock figures were artefacts (fixed), and another agent's v2 rollout restarted every node during the second heal. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
55 lines
2.8 KiB
Bash
Executable file
55 lines
2.8 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
|
|
# A schedule of sleeps pauses when the Mac sleeps (4 Oct 2026: the hop's 15-min 4-thread phase ran 94 min because the
|
|
# laptop hibernated on a flat battery). On macOS re-run under caffeinate -i, which holds the machine awake while this runs.
|
|
if [ "$(uname)" = Darwin ] && [ -z "${IGNEUM_CAFFEINATED:-}" ] && command -v caffeinate >/dev/null 2>&1; then
|
|
IGNEUM_CAFFEINATED=1 exec caffeinate -i "$0" "$@"
|
|
fi
|
|
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"
|