Packaging for proving v0: the Mac DMG carries igneum-prove-host and igneum-prove-export, the Windows payload carries the Linux host and exporter under wsl2/bin with the WSL2 scripts and the fixtures; the prover probes the shipped WSL2 binaries first and runs helpers by absolute path; push-inputs takes IGNEUM_NODE_SRC; the test script's --network-only mode

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
igneum-labs 2026-10-04 14:36:59 +00:00
parent 34f9cdea96
commit 3f23df38b7
5 changed files with 49 additions and 6 deletions

View file

@ -145,8 +145,11 @@ fn evm_rpc(shared: &Shared, method: &str, params: Value, timeout: Duration) -> R
fn find_tools(bin_dir: &Path) -> Result<Tools, String> {
let miner = bin_dir.join(if cfg!(windows) { "igneum-miner.exe" } else { "igneum-miner" });
if cfg!(windows) {
// the SP1 host runs inside WSL2 (Ubuntu-24.04): built there by setup-wsl.sh, or shipped as a Linux binary
let probe = Command::new("wsl").args(["-d", "Ubuntu-24.04", "--", "bash", "-lc", "for f in ~/igneum-prove/target/release/igneum-prove-host /opt/igneum/igneum-prove-host; do [ -x \"$f\" ] && { echo \"$f\"; break; }; done; command -v nvidia-smi >/dev/null && echo cuda"]).output();
// the SP1 host runs inside WSL2 (Ubuntu-24.04): the Linux binaries the payload ships under wsl2\bin\ (seen
// from Ubuntu as /mnt/<drive>/.../wsl2/bin), else one built there by setup-wsl.sh
let shipped = wsl_path(&bin_dir.join("wsl2").join("bin").join("igneum-prove-host"));
let script = format!("for f in '{shipped}' ~/igneum-prove/target/release/igneum-prove-host /opt/igneum/igneum-prove-host; do [ -x \"$f\" ] && {{ echo \"$f\"; break; }}; done; command -v nvidia-smi >/dev/null && echo cuda");
let probe = Command::new(crate::platform::tool("wsl")).args(["-d", "Ubuntu-24.04", "--", "bash", "-lc", &script]).output();
let text = probe.map(|o| String::from_utf8_lossy(&o.stdout).to_string()).unwrap_or_default();
let host = text.lines().find(|l| l.contains("igneum-prove-host")).map(|l| PathBuf::from(l.trim()));
let setup = bin_dir.join("wsl2").join("setup-wsl.sh");
@ -170,7 +173,7 @@ fn find_tools(bin_dir: &Path) -> Result<Tools, String> {
/// Runs the host or the exporter: directly, or through WSL on Windows. Returns (exit ok, output).
fn run_tool(t: &Tools, exe: &Path, args: &[String], env: &[(&str, &str)], limit: Duration) -> (bool, String) {
let mut cmd = if t.wsl {
let mut c = Command::new("wsl");
let mut c = Command::new(crate::platform::tool("wsl"));
let envs: String = env.iter().map(|(k, v)| format!("{k}={v} ")).collect();
let line = format!("{envs}{} {}", exe.display(), args.iter().map(|a| format!("'{a}'")).collect::<Vec<_>>().join(" "));
c.args(["-d", "Ubuntu-24.04", "--", "bash", "-lc", &line]);
@ -417,8 +420,8 @@ pub fn setup(shared: &Shared) -> Result<Value, String> {
return Err(format!("setup script missing: {}", script.display()));
}
let line = format!("bash {}", wsl_path(&script));
let mut c = Command::new("cmd");
c.args(["/c", "start", "", "wsl", "-d", "Ubuntu-24.04", "--", "bash", "-lc", &line]);
let mut c = Command::new(crate::platform::tool("cmd"));
c.args(["/c", "start", "", &crate::platform::tool("wsl").display().to_string(), "-d", "Ubuntu-24.04", "--", "bash", "-lc", &line]);
c.spawn().map_err(|e| e.to_string())?;
shared.event("proving", "WSL2 prover setup started in its own window");
Ok(json!({ "ok": true }))

View file

@ -28,6 +28,9 @@ NODE="${NODE:-$ROOT/vendor/igneum-node/target-integration/release/igneumd}"
MINER="${MINER:-$ROOT/vendor/igneum-node/target-integration/release/igneum-miner}"
WORKER="${WORKER:-}"
ENGINE="${ENGINE:-}"
# proving v0: the SP1 host and the exporter next to the node (CPU proving on a Mac; app/igneum-app/src/prover.rs)
PROVE_HOST="${PROVE_HOST:-$ROOT/proving/igneum-prove/target/release/igneum-prove-host}"
PROVE_EXPORT="${PROVE_EXPORT:-$ROOT/proving/igneum-prove/target/release/igneum-prove-export}"
REBUILD_WORKER="${REBUILD_WORKER:-1}"
ICONS="$ROOT/brand/icons"
BUILD="$HERE/build"
@ -96,6 +99,11 @@ cp "$ICONS/igneum.icns" "$APP/Contents/Resources/igneum.icns"
cp "$NODE" "$APP/Contents/Resources/bin/igneumd"
cp "$MINER" "$APP/Contents/Resources/bin/igneum-miner"
cp "$WORKER" "$APP/Contents/Resources/bin/igneum-bench"
if [ -f "$PROVE_HOST" ] && [ -f "$PROVE_EXPORT" ]; then
cp "$PROVE_HOST" "$APP/Contents/Resources/bin/igneum-prove-host"
cp "$PROVE_EXPORT" "$APP/Contents/Resources/bin/igneum-prove-export"
echo "prover: igneum-prove-host and igneum-prove-export from $(dirname "$PROVE_HOST")"
else echo "warning: no $PROVE_HOST / $PROVE_EXPORT (cd proving/igneum-prove && cargo build --release -p igneum-prove-host -p igneum-prove-export); the Proving tile will say the prover is missing"; fi
write_packaged_config "$APP/Contents/Resources/igneum-app.json"
chmod 755 "$APP/Contents/MacOS/"* "$APP/Contents/Resources/bin/"*

View file

@ -76,6 +76,19 @@ mkdir -p "$STAGE/app/windows/art" && cp "$ROOT/brand/icons/igneum.ico" "$STAGE/a
if [ -f "$ROOT/app/windows/dist/Igneum Miner.exe" ]; then cp "$ROOT/app/windows/dist/Igneum Miner.exe" "$STAGE/"; echo "window host: Igneum Miner.exe from app/windows/dist"; fi
cp "$HERE/stop-igneum.ps1" "$STAGE/stop-igneum.ps1"
# proving v0 (spec 7.7, app/igneum-app/src/prover.rs): the SP1 host runs inside WSL2 on a PC, so the payload ships the
# Linux x86_64 host and exporter (proving/igneum-prove cross-built with cargo-zigbuild, glibc 2.36, sp1 cuda feature;
# IGNEUM_PROVE_LINUX overrides the folder) under wsl2\bin\, the WSL2 setup scripts and the fixtures. The engine runs
# them as /mnt/<drive>/.../wsl2/bin/igneum-prove-host from Ubuntu-24.04; Set up runs wsl2\setup-wsl.sh.
PROVE_LINUX="${IGNEUM_PROVE_LINUX:-$ROOT/proving/igneum-prove/target-linux/x86_64-unknown-linux-gnu/release}"
mkdir -p "$STAGE/wsl2/bin" "$STAGE/wsl2/fixtures"
if [ -f "$PROVE_LINUX/igneum-prove-host" ] && [ -f "$PROVE_LINUX/igneum-prove-export" ]; then
cp "$PROVE_LINUX/igneum-prove-host" "$PROVE_LINUX/igneum-prove-export" "$STAGE/wsl2/bin/"
echo "prover (WSL2): igneum-prove-host $(stat -f %z "$PROVE_LINUX/igneum-prove-host") bytes, igneum-prove-export $(stat -f %z "$PROVE_LINUX/igneum-prove-export") bytes"
else echo "warning: no Linux igneum-prove-host/igneum-prove-export in $PROVE_LINUX (cargo zigbuild --target x86_64-unknown-linux-gnu.2.36 --features igneum-prove-host/cuda); the Proving tile will ask for the WSL2 setup, which builds them"; fi
cp "$ROOT"/proving/windows-wsl2/*.sh "$ROOT"/proving/windows-wsl2/*.ps1 "$ROOT"/proving/windows-wsl2/*.bat "$ROOT/proving/windows-wsl2/README.txt" "$STAGE/wsl2/"
cp "$ROOT"/proving/fixtures/*.json "$STAGE/wsl2/fixtures/"
# the packaged configuration: the download token stays out of the repo
TOKEN=""
[ -f "$TOKEN_FILE" ] && TOKEN="$(tr -d '[:space:]' < "$TOKEN_FILE")"
@ -83,8 +96,13 @@ MANIFEST=""
[ -n "$TOKEN" ] && MANIFEST="https://dl.igneum.network/dl/$TOKEN/igneum-app-latest.json"
[ -n "$MANIFEST" ] || echo "note: no $TOKEN_FILE; the update check is disabled in this build"
LOG_KEY="$(sed -n 's/^LOG_KEY="\(.*\)"/\1/p' "$ROOT/packaging/mac/packaged-config.sh")"
# the pinned consensus parameters (packaged-config.sh NODE_OVERRIDE_PARAMS, e.g. the difficulty v2 activation height)
NODE_OVERRIDE_PARAMS="$(sed -n "s/^NODE_OVERRIDE_PARAMS='\(.*\)'/\1/p" "$ROOT/packaging/mac/packaged-config.sh")"
OVERRIDE_LINE=""
[ -n "$NODE_OVERRIDE_PARAMS" ] && OVERRIDE_LINE=" \"node_override_params\": $NODE_OVERRIDE_PARAMS,"
cat > "$STAGE/igneum-app.json" <<JSON
{
$OVERRIDE_LINE
"update_manifest": "$MANIFEST",
"log_intake_url": "https://igneum-six.vercel.app/api/log",
"log_intake_key": "$LOG_KEY",

View file

@ -51,7 +51,8 @@ else echo "warning: no $NVRTC_DIR/igneum-worker-cuda.exe (run $NVRTC_DIR/build-w
[ -f "$CL_WORKER" ] && cp "$CL_WORKER" "$STAGE/" || echo "warning: no $CL_WORKER"
# the manifest: what is in the zip, from where, when
NODE_COMMIT="$(git -C "$ROOT/vendor/igneum-node-v4" rev-parse --short HEAD 2>/dev/null || git -C "$ROOT/vendor/igneum-node" rev-parse --short HEAD 2>/dev/null || echo unknown)"
# IGNEUM_NODE_SRC names the worktree the exes were built from (default devnet-v4), for the manifest's commit field
NODE_COMMIT="$(git -C "${IGNEUM_NODE_SRC:-$ROOT/vendor/igneum-node-v4}" rev-parse --short HEAD 2>/dev/null || git -C "$ROOT/vendor/igneum-node" rev-parse --short HEAD 2>/dev/null || echo unknown)"
REPO_COMMIT="$(git -C "$ROOT" rev-parse --short HEAD 2>/dev/null || echo unknown)"
{
echo '{'

View file

@ -12,6 +12,8 @@
// Never touches the live devnet (26610/26611, 26640/28640) or the fast-time simnet (29500+).
//
// node tools/proving-v0/run.mjs [--secs 1500] [--activation 60] [--empty] (--empty proves the newest empty segment instead)
// node tools/proving-v0/run.mjs --network-only --secs 3600 (just the 3 nodes and the voters, for the app's prover loop; node 1
// p2p 127.0.0.1:29811 is the peer to give the app)
import { spawn, spawnSync } from 'node:child_process';
import { mkdirSync, rmSync, writeFileSync, readFileSync, openSync, existsSync } from 'node:fs';
@ -33,6 +35,7 @@ const flag = (name, dflt) => { const i = args.indexOf(name); return i >= 0 && ar
const SECS = flag('--secs', 1500);
const ACTIVATION = flag('--activation', 60);
const EMPTY = args.includes('--empty');
const NETWORK_ONLY = args.includes('--network-only');
const started = [];
const t0 = Date.now();
const since = () => ((Date.now() - t0) / 1000).toFixed(1);
@ -119,6 +122,16 @@ try {
const status0 = await n0.eth('igneum_getProvingStatus');
log(`proving status n0: ${JSON.stringify(status0)}`);
step('status', { activationDaa: status0.activationDaa, verifier: status0.verifier });
if (NETWORK_ONLY) {
log(`network only: 3 nodes up for ${SECS} s; peer for the app: 127.0.0.1:${n1.p2pPort}; EVM RPC n0 ${n0.evm}`);
while (Date.now() - t0 < SECS * 1000) {
await sleep(15000);
const s = await n0.eth('igneum_getProvingStatus').catch(() => null);
if (s) log(`daa ${parseInt(s.tipDaa, 16)} active=${s.active} pool=${JSON.stringify(s.pool)} paidShards=${s.paidShards}`);
}
report.ok = true;
throw new Error('network-only run finished');
}
// 1. wait for the activation DAA (plus a margin: the sortition window needs dust blocks per key)
let daa = 0;