From f4152ed9eb6963dc53b6700ca162a2ca0c41706a Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Thu, 8 Oct 2026 21:02:39 +0000 Subject: [PATCH] build-remote --ship: the x86-64-v3 certified baseline (zero AVX-512), the box-side ISA gate, the C date pin The founder's order of 8 Oct 2026: a shipped Linux pair with no AVX-512 instruction, read back by the kit ISA check. The 2,018 zmm lines of a 7cfa422a igneumd were not libc (glibc is dynamic under zig; its memcpy family lives in the host's libc.so.6) but blake3 1.8.3's AVX-512 assembly, cpuid-dispatched, attributed to __libc_memalign by a stripped symbol table. blake3's no_avx512 feature only turns the dispatch off; the assembly stays linked. So a ship build of a node tree adds `-p kaspa-hashes --features blake3/pure` (the member that depends on blake3 directly), which compiles none of it. --cpu (default seed/linux x86-64-v3, hive/rig x86-64: a rig's Celeron or Pentium has no AVX2) goes in as a --config target rustflags entry: cargo merges it with the box's own -fuse-ld=lld, the flag reads back in the logged command, and cargo-zigbuild 0.23.4 reads the same entry and hands zig -mcpu=x86_64_v3 for every C and C++ file. At v2 and v3 rocksdb's build.rs compiles its pclmul crc32c on the sse4.2 feature but adds -mpclmul only on a pclmulqdq feature no level sets, so CFLAGS carry -mpclmul (zig takes a -m feature after its -mcpu). The ISA gate: every ship artefact is disassembled on the box right after the build (the Mac has no ELF objdump), the pattern of tools/ci/kit-isa-check.sh (zmm, opmask, EVEX-only mnemonics), and one line fails the run with rc 98 before the sha marker. The C date pin (GOV-03): mimalloc's banner compiles __DATE__ and __TIME__; the cc crate hands C compiles to sccache, whose server runs them with its own environment, so the exported SOURCE_DATE_EPOCH never reached clang and build-1, build-8 and build-9 gave three igneumd shas differing only by that string. The ship path now defines __DATE__ and __TIME__ on the command line from the commit's author time (UTC), which both sccache and zig's cache key on. Measured on 7cfa422a, seed class, build-8 and build-9: igneumd 6502b3c7d58a16df and igneum-miner b4748308e0887982 byte-identical on both boxes, 0 AVX-512 lines each, GLIBC_2.34 needed, the commit string and IGNEUM_POW_FINGERPRINT=cbc5bd0aa10585c8 read back, the banner date Oct 8 2026 18:44:40 (the commit's), igneumd --version prints 2.0.1. Co-Authored-By: Claude Fable 5.1 --- tools/build-remote.sh | 72 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/tools/build-remote.sh b/tools/build-remote.sh index 52fea5df8..f50bf5839 100755 --- a/tools/build-remote.sh +++ b/tools/build-remote.sh @@ -24,6 +24,25 @@ # A plain build is native glibc 2.39: the box, the fleet's # Ubuntu 24.04 hosts, never a seed or a rig (7 Oct 2026: # a seed took 14 restarts on a 2.39 binary). +# tools/build-remote.sh --ship seed [--cpu x86-64-v3|x86-64] the ISA of what ships (the founder's certified baseline, +# 8 Oct 2026): --cpu sets `-C target-cpu=` for the Rust +# code (a --config rustflags entry, merged with the box's +# own, so the flag reads back in the logged command) and +# cargo-zigbuild passes the same level to zig as -mcpu for +# the C/C++ code (mimalloc, rocksdb, zstd, secp256k1); +# default by class: seed/linux x86-64-v3 (AVX2, no +# AVX-512), hive/rig x86-64 (a rig's Celeron or Pentium +# has no AVX2). A node build also gets blake3's `pure` +# feature (`-p kaspa-hashes --features blake3/pure`): the +# 2,018 zmm instructions of a 7cfa422a igneumd were ALL +# blake3's AVX-512 assembly (cpuid-dispatched, not libc: +# glibc is dynamic under zig, its memcpy family lives in +# the host's libc.so.6), and blake3 1.8.3's `no_avx512` +# only disables the dispatch, the assembly stays linked; +# `pure` compiles none of it. Every ship artefact is then +# disassembled ON THE BOX (the ISA gate, the same pattern +# as tools/ci/kit-isa-check.sh: zmm, opmask, EVEX-only +# mnemonics) and the build fails on any AVX-512 line. # tools/build-remote.sh --priority gate -- test ... a RELEASE GATE (the app gate, the canary cut, the pre-push # self-tests): nice 0, the full core set, a slot ahead of # queued suites and benches @@ -75,10 +94,11 @@ BS_TOOL=build-remote # flight cannot reach the running copy (7 Oct 2026: build-remote.sh was edited mid-run and died on shifted bytes after a 4-min build) # JOBS empty = the box decides: 90 alone, 45 beside another slot holder (remote-run.sh, main's ruling 6 Oct 2026) -JOBS="${JOBS:-}"; OUT=""; ARTEFACTS=""; TARGET_DIR="target"; FETCH=1; CARGO_ARGS=(); SELFTEST=0; FULL=0; SHIP=0; SHIP_CLASS="${SHIP_CLASS:-seed}"; PRIORITY="${PRIORITY:-normal}"; PLAN=0; BOX="${BOX:-}"; GLIBC="${GLIBC:-}" +JOBS="${JOBS:-}"; OUT=""; ARTEFACTS=""; TARGET_DIR="target"; FETCH=1; CARGO_ARGS=(); SELFTEST=0; FULL=0; SHIP=0; SHIP_CLASS="${SHIP_CLASS:-seed}"; PRIORITY="${PRIORITY:-normal}"; PLAN=0; BOX="${BOX:-}"; GLIBC="${GLIBC:-}"; SHIP_CPU="${SHIP_CPU:-}" while [ $# -gt 0 ]; do case "$1" in --jobs) JOBS="$2"; shift 2 ;; + --cpu) SHIP_CPU="$2"; shift 2 ;; --out) OUT="$2"; shift 2 ;; --artefacts) ARTEFACTS="$2"; ARTEFACTS_SET=1; shift 2 ;; --target-dir) TARGET_DIR="$2"; shift 2 ;; @@ -175,8 +195,15 @@ SHIP_TARGET=x86_64-unknown-linux-gnu if [ "$SHIP" = 1 ]; then [ -n "$GLIBC" ] || GLIBC=$("$HERE/ci/glibc-ceiling-check.sh" --ceiling-of "$SHIP_CLASS") || bs_die "unknown ship class $SHIP_CLASS" [ "$GLIBC" != native ] || bs_die "--ship native is a plain build: drop --ship" + # the ISA level of what ships (the founder's certified baseline, 8 Oct 2026): seed/linux x86-64-v3; hive/rig x86-64, a rig's + # Celeron or Pentium has no AVX2 and a v3 igneum-miner would die at its first ymm instruction (the plug, tune, play rule) + [ -n "$SHIP_CPU" ] || case "$SHIP_CLASS" in hive|rig) SHIP_CPU=x86-64 ;; *) SHIP_CPU=x86-64-v3 ;; esac + case "$SHIP_CPU" in x86-64|x86-64-v2|x86-64-v3) ;; *) bs_die "--cpu takes x86-64, x86-64-v2 or x86-64-v3 (never v4 or a model name: the ISA gate refuses AVX-512), not '$SHIP_CPU'" ;; esac TARGET_SUB="$SHIP_TARGET/release" else TARGET_SUB="release"; fi +# the AVX-512 pattern of the ISA gate: the same as tools/ci/kit-isa-check.sh (the CI steward's kit check, master 6193967a): +# a zmm register, an EVEX opmask or {z}, an EVEX-only mnemonic +ISA_PAT='%?zmm[0-9]|\{%?k[1-7]\}|\{z\}|\bvpternlog|\bvpcompress|\bvpexpand|\bvpconflict|\bvplzcnt|\bvpermt2|\bvpermi2|\bvprol|\bvpror|\bvrndscale|\bvscalef|\bvfixupimm|\bvrange|\bvreduce|\bvgetexp|\bvgetmant|\bvpmovm2|\bvpmov[a-z]*2m\b|\bk(mov|and|or|xor|unpck|not|test|ortest|add|shift)[a-z]*\b|\bvscatter|\bvpbroadcastm|\bvcvtt?[a-z]*2usi|\bvdbpsadbw|\bvpmadd52' # defaults per crate case "$BS_KIND:$BS_CRATE_REL" in node:*) @@ -195,6 +222,16 @@ case "${CARGO_ARGS[0]}" in build) ;; *) [ -n "${ARTEFACTS_SET:-}" ] || { FETCH=0 if [ "$SHIP" = 1 ]; then [ "${CARGO_ARGS[0]}" = build ] || bs_die "--ship is for cargo build" CARGO_ARGS=(zigbuild "${CARGO_ARGS[@]:1}" --target "$SHIP_TARGET.$GLIBC") + # the ISA level, as a --config rustflags entry: cargo MERGES it with the box's own target rustflags (-fuse-ld=lld stays; a + # RUSTFLAGS variable would replace them), the flag reads back in the logged command, and cargo-zigbuild 0.23.4 reads the + # same entry (its cli_config.rs) and hands zig `-mcpu=` for every C and C++ file + CARGO_ARGS+=(--config "target.$SHIP_TARGET.rustflags=[\"-C\",\"target-cpu=$SHIP_CPU\"]") + # a node build: blake3 without its AVX-512 assembly (the only AVX-512 in a 7cfa422a igneumd and igneum-miner, 2,018 zmm lines each, + # cpuid-dispatched; `no_avx512` keeps the assembly linked, `pure` compiles none of it). kaspa-hashes is the workspace member + # that depends on blake3 directly, which is what cargo's `/` syntax needs; it is in both binaries' graphs already + if [ "$BS_KIND" = node ] && grep -qs '^blake3' "$BS_CRATE/crypto/hashes/Cargo.toml"; then + CARGO_ARGS+=(-p kaspa-hashes --features blake3/pure) + fi BR_TARGET_SHIP="$SHIP_TARGET.$GLIBC" fi [ -n "$OUT" ] || OUT="$BS_CRATE/target-remote" @@ -222,7 +259,33 @@ pre="" if [ "$BS_KIND" = node ] && { [ "${CARGO_ARGS[0]}" = build ] || [ "${CARGO_ARGS[0]}" = zigbuild ]; }; then pre="[ \"\$(cat '.build-remote-sha-$TARGET_DIR' 2>/dev/null)\" = '$BS_SHA' ] || CARGO_TARGET_DIR='$TARGET_DIR' cargo clean -q --release -p kaspa-build-info 2>/dev/null; " fi -cmd="$(bs_repro_env)${pre}CARGO_TARGET_DIR='$TARGET_DIR' cargo $(printf '%q ' "${CARGO_ARGS[@]}")${JOBS:+-j $JOBS} 2>&1 | tee -a '$BS_REMOTE_WT/.build-remote.log'; rc=\${PIPESTATUS[0]}; [ \$rc = 0 ] && echo '$BS_SHA' > '.build-remote-sha-$TARGET_DIR'; ( exit \$rc )" # a subshell exit: the runner reads \$? and still prints its RESULT line +# the ISA gate of anything that ships (the founder's certified baseline, 8 Oct 2026): every artefact is disassembled ON THE BOX +# (the Mac has no ELF objdump) right after the build and a single AVX-512 line (ISA_PAT above) fails the run with rc 98 before +# the sha marker is written; the count per artefact is printed as "build-remote: isa : AVX-512 lines" +isa=""; cflags="" +# at a level with SSE4.2 (v2, v3) librocksdb-sys's build.rs reads sse4.2 in CARGO_CFG_TARGET_FEATURE and compiles rocksdb's +# pclmul crc32c, but adds -mpclmul only on a `pclmulqdq` feature, which no x86-64 level sets: zig at -mcpu=x86_64_v3 then +# refuses crc32c.cc ("needs target feature pclmul", 8 Oct 2026 21:43 BST on build-8). The flag goes in through the cc +# crate's CFLAGS (zig takes a -m feature after its -mcpu: tested on build-8); rocksdb picks the pclmul path by cpuid at run time +# The C date pin (GOV-03, 8 Oct 2026 22:0x BST): mimalloc's banner compiles __DATE__ and __TIME__ (options.c), and the cc crate +# hands every C and C++ compile to sccache because RUSTC_WRAPPER names it; sccache's SERVER runs the compile with the server's +# own environment, so the SOURCE_DATE_EPOCH the command exports never reaches clang (measured on build-8: through sccache the +# object carries the wall clock, direct it carries the commit time), and neither sccache's key nor zig's own C cache carries the +# epoch, so a stale object survives a new epoch. The pin is on the COMMAND LINE instead: __DATE__ and __TIME__ defined from the +# commit's author time in UTC (the same second bs_repro_env exports), which both caches key on. One tree, any box: one object. +utc_fmt() { date -u -r "$1" "$2" 2>/dev/null || date -u -d "@$1" "$2"; } # BSD date on the Mac, GNU date elsewhere +if [ "$SHIP" = 1 ]; then + cval=""; case "$SHIP_CPU" in x86-64-v2|x86-64-v3) cval="-mpclmul" ;; esac + sde=$(bs_sde "$BS_TOP"); cdate=$(utc_fmt "$sde" '+%b %e %Y'); ctime=$(utc_fmt "$sde" '+%H:%M:%S') + cval="${cval:+$cval }-Wno-builtin-macro-redefined '-D__DATE__=\"$cdate\"' '-D__TIME__=\"$ctime\"'" + # CC_SHELL_ESCAPED_FLAGS: the cc crate splits the value as a shell would, so the quoted date (two spaces inside) stays one argument + cflags="export CC_SHELL_ESCAPED_FLAGS=1 CFLAGS_x86_64_unknown_linux_gnu=$(printf '%q' "$cval") CXXFLAGS_x86_64_unknown_linux_gnu=$(printf '%q' "$cval"); " + bs_log "ship C flags: $cval (the commit's date and time, UTC, as __DATE__ and __TIME__; -mpclmul at v2 and v3)" +fi +if [ "$SHIP" = 1 ] && [ -n "$ARTEFACTS" ]; then + isa="[ \$rc = 0 ] && for a in $ARTEFACTS; do [ -f \"\$a\" ] || continue; n=\$(objdump -d --no-show-raw-insn \"\$a\" 2>/dev/null | grep -cE '$ISA_PAT' || true); echo \"build-remote: isa \$(basename \"\$a\"): \$n AVX-512 lines (target-cpu $SHIP_CPU, glibc $GLIBC; the gate needs 0)\"; [ \"\$n\" = 0 ] || { echo \"build-remote: ISA GATE RED: \$a carries AVX-512 (zmm, opmask or an EVEX-only mnemonic)\" >&2; rc=98; }; done; " +fi +cmd="$(bs_repro_env)${cflags}${pre}CARGO_TARGET_DIR='$TARGET_DIR' cargo $(printf '%q ' "${CARGO_ARGS[@]}")${JOBS:+-j $JOBS} 2>&1 | tee -a '$BS_REMOTE_WT/.build-remote.log'; rc=\${PIPESTATUS[0]}; ${isa}[ \$rc = 0 ] && echo '$BS_SHA' > '.build-remote-sha-$TARGET_DIR'; ( exit \$rc )" # a subshell exit: the runner reads \$? and still prints its RESULT line label="$BS_WT/$BS_CRATE_REL cargo ${CARGO_ARGS[*]}" BR_KIND=$(bs_kind build-remote "$( [ "${CARGO_ARGS[0]}" = zigbuild ] && echo build || echo "${CARGO_ARGS[0]}")"); BR_COMMAND="cargo ${CARGO_ARGS[*]}"; BR_TARGET="${BR_TARGET_SHIP:-x86_64-unknown-linux-gnu}" [ "$SCHED_CLASS" = bench ] && BR_KIND=bench @@ -238,9 +301,10 @@ bs_remote_run "$BS_REMOTE_CRATE" "$label" "$cmd" 2>&1 | tee "/tmp/build-remote-$ rc=${PIPESTATUS[0]} set -e secs=$(( $(date +%s) - t0 )) -result=$(grep -m1 '^build-remote: RESULT' "/tmp/build-remote-$$.log" || true); rm -f "/tmp/build-remote-$$.log" -if [ "$rc" != 0 ]; then bs_die "remote cargo failed (rc $rc) after $(bs_fmt_secs "$secs"); $result"; fi +result=$(grep -m1 '^build-remote: RESULT' "/tmp/build-remote-$$.log" || true); isa_lines=$(grep '^build-remote: isa ' "/tmp/build-remote-$$.log" | sed 's/^build-remote: isa //' | tr '\n' ';' || true); rm -f "/tmp/build-remote-$$.log" +if [ "$rc" != 0 ]; then bs_die "remote cargo failed (rc $rc) after $(bs_fmt_secs "$secs"); $result${isa_lines:+; isa: $isa_lines}"; fi bs_log "remote cargo ${CARGO_ARGS[0]} done in $(bs_fmt_secs "$secs") wall from the Mac; ${result#build-remote: RESULT }" +[ "$SHIP" = 1 ] && bs_log "ship ISA gate on the box: ${isa_lines:-no artefact scanned} (class $SHIP_CLASS, target-cpu $SHIP_CPU for Rust and zig, blake3 pure on a node build, C date pinned to the commit)" if [ "$FETCH" = 1 ] && [ -n "$ARTEFACTS" ]; then mkdir -p "$OUT"