Observer: additive live_blocks.color (pending by default). Every chain block's
mergeset marks its blues blue and its reds red, from the notification's verbose
data or getBlock for chain blocks learned via virtualChainChanged; a reorg puts
the removed chain blocks' mergesets back to pending. API serves color. Page:
blue side blocks filled in the miner's hue at 70% with the ring, pending the
faint outline, red a dark outline with a strike; tooltip and legend name the
state.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
GitHub Actions workflow (.github/workflows/ci.yml) on push and pull_request with three jobs on the free runners:
igneum-pow `cargo test --release` and the igneum-census build; the two Python simulators' --quick modes under a
120-second timeout; the site build, an internal link check of site/*.html (tools/ci/link-check.mjs) and a gh-free
identity grep of the public export list (tools/ci/identity-check.sh over tools/ci/forbidden-strings.txt: machine
names, LAN and overlay addresses, home paths, local time zones, the log-intake key pattern; never a key or a name).
The node fork is too big for CI today and the workflow says so.
sim/finality_v2.py --quick is now a genuine smoke run (one day or hour per scenario, one partition and one eclipse
setting): 149 s at nice 19 on a loaded Mac, was 745 s. sim/difficulty/sim.py gains --quick (up50 and warmup-hard,
kaspa and igneum controllers, 36 s). One bench-log time-zone label reworded so the identity grep passes.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
igneum-common.ps1 uses igneum-worker-cuda.exe (with nvrtc64_*_0.dll next to it) and igneum-worker-opencl.exe when they
are in the folder, passes the exported pack with --pack, and only surveys the toolchain (Find-Toolchain) when a worker
is missing or FORCE_BUILD=1; the dashboard and the status block name the path per card; a prebuilt worker that is not
ready after 150 s falls back to the build path once when a toolchain exists; 90 s of seed mismatch errors re-export
the pack and restart the vendor; WORKER_ARCH overrides the NVRTC target. make-package.sh ships the two exes, the two
NVRTC DLLs, the licence texts, THIRD-PARTY.md and TEST.md (what the first RTX 5090 run should print and what to send
back). README.txt, the bats, proto-cuda/README.md (nvrtc/ section), WINDOWS-MINER.md and the bench log updated with
what the Mac measured.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
host.c --serve --pack <dir> serves a pack read at run time (packfile.h), whatever pack the exe was built against: the
first pair is built and self-tested like a prepared one (pairBuffers, pairSelfTest), prepared pairs are self-tested
too, the ready line says path prebuilt-generic. cl_dynamic.h (IGNEUM_CL_DYNAMIC) opens OpenCL.dll with LoadLibrary and
fills a function pointer per entry point, so the mingw build links no import library. test-generic.sh checks the mode
through Apple OpenCL with the packs of the CUDA emulation test: PASS (192 found, prepare and swap, 15 sampled hashes
equal igneum-pow hash-bound), built against a different placeholder pack than it served.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
proto-cuda/nvrtc/worker.cpp serves igneum-miner's worker protocol with nothing installed but the NVIDIA driver:
nvcuda.dll and the redistributable nvrtc64_120_0.dll are opened with LoadLibrary (cuda_api.h), the pack's kernel.cu
and kernel_bound.cu are handed to NVRTC byte for byte up to the host launch wrappers with program.h and memhard.h as
named headers, every pack is self-tested against its vectors.h (cache head, last line, FNV-1a 64, dataset head, last
word, 64 samples, 96 vector lanes) before it serves a job, prepare runs on a thread for the hourly swap, and a job on
seeds without a pair makes the worker find the miner's pack by seeds.txt and build it. packfile.h (C99) reads a pack
directory. fetch-redist.sh verifies and stages the NVIDIA 12.8.93 redistributables and the Khronos headers
(THIRD-PARTY.md records URLs, hashes and the EULA clause); build-windows.sh cross-compiles with mingw (static,
KERNEL32 + Universal CRT only). emu/: the two libraries as host functions, the pack kernels on host threads, the NVRTC
source compared with the pack files; test.sh PASS on the Mac (two real packs, swap, self-heal, 17 sampled hashes equal
igneum-pow hash-bound). Not run here: the real NVRTC compile and driver load (RTX 5090 PC).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
One lane per miner ranked by share, overflow in an others lane with a count.
Lane labels in a left gutter in the miner's colour (3-character tag on phones).
No per-block labels: short id on the chain tip, the lock, and on hover or tap
with a canvas tooltip (id, blue, DAA, parents, chain or side). Same-lane
overlaps nudged in a fixed sequence. Chain as one path, side blocks linked to
their first parent only, clamped cubics so no edge becomes a tall loop. Block
size and time scale step down together at density. One rAF loop, DPR aware,
paused when hidden or scrolled out. Final band and lock marker. Before and
after screenshots in docs/design/live-dag.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A lock needs two thirds of all 30-day weight signing; finality pauses
whenever less than two thirds is connected and signing, the chain runs
on proof of work meanwhile and the node reports it. Spec 3.3, 3.3.1,
3.7, 3.9, 3.10 Q3 row, 3.11 rewritten with the new arithmetic (safety
one third in every view, liveness two thirds connected, the per-view
window bound stated as 3.7 item 9); O-3.15 decided, O-3.16 closed,
O-3.18 and O-3.19 narrowed. Simulator: --floor, the +local partition
mode, scenario L; A to L re-run at the 2/3 floor over five seeds with
the 0.85 deltas in results_v2.md. Litepaper finality sentences and the
'does not claim' item. Ledger F2, F9, F16, F18 restated, F21 added
(the window bound and the post-heal finality fork from the devnet).
Bench-log: node build and tests, simulator deltas, three-node six-voter
runs of 6A, 6B and 6A with a long heal on ports 29200 and up.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
igneum-pow 0.2.0: generator v2 draws exactly 16 load slots from instructions 1..63, a
load's source from the registers written earlier and not read by a load since, the other
48 ops from the ten non-load weights; accept.rs is spec 01 section 1.4.6 (static: no
stale load source, every register injected; dynamic: 64 units on the seed-keyed
closed-form dataset, no constant bit, no lane-constant site, under 164 saturated, bias
within 136 of 1024, distinct addresses above 245,760); a rejected candidate is replaced
by the next attempt of the seed (seed || k_le32), 32 a consensus fault. Packs carry the
generator version, attempt and program id. Version 1 kept as generate_v1 for the census.
Packs: igneum-genesis, igneum-hourly, igneum-genesis-mh regenerated by igneum-pow export;
new igneum-devnet-v4-epoch0 (devnet genesis hash, day bytes 20730). Checks: Rust 39 of
39 tests; Metal natively via the Swift port (export cross-check 3 of 3 warps, identical
programs and vectors on five seeds incl. three with attempt 1, fuzz 2,000 of 2,000);
CUDA emu 4 of 4 packs; OpenCL emu 2 packs x 2 configurations; Apple OpenCL 4 of 4 packs
at 27.9 Mhash/s. Census 20,000: 5.225 percent rejected, accepted distinct mean 127.887.
Spec 01 0.2 (1.4.2, 1.4.3, 1.4.6, 1.11, 1.15, 1.16, 1.17), igneum-pow README, the CUDA,
OpenCL and Metal test notes, bench-log entry, ledger M5 and M6 Fixed.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The first stage run built v4 on igneum-seed-1 in 60 min 49 s and then failed on `igneumd --version | head -1` under
pipefail, because the devnet-v4 igneumd prints its version and exits 1. The post-build steps now write to files and
test them; the tarball is unpacked once per src.stamp so a rerun is incremental; `stage-v4.sh <seed> resume` reruns
the build script on the tree already on the VM and then waits and installs.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Windows combined package 0.2.0 (proto-cuda/windows-app): v4 exes from target-integration, peers = seed then Mac,
fresh appdir devnet-v4, one miner and one worker per card with --identities 8, --evm-address (PAYOUT_EVM or derived
per vendor from the PC name), voting on (VOTE=0 opts out), --prepare-packs for the hot swap with --exit-on-seed-change
as the fallback, --yes on the node, STATUS regex tolerant of the v4 now= segment, version in the dashboard header.
Mac app 0.2.0 (packaging/mac): v4 binaries, Metal worker rebuilt for macOS 11, data folder devnet-v4, EVM payout,
identities in one process, synced= flag honoured. Seed (infra/seed-nodes): stage-v4.sh builds v4 on the VM as a
niced, memory-capped transient service and installs a disabled igneumd-v4 unit with a fresh data dir; switch-v4.sh
swaps the units (--back reverses); health.sh reports active-v4. Runbook: docs/plans/cutover-2026-10-04.md.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Spec 2.3: rule 1 measures every chain step on a sanitised clock stored per header
(c(b) = max(c(p) + clamp(t(b) - c(p), -20 T, +20 T), t(b) - 60 T), step min(c(b) - c(p),
20 T)); rule 4 bounds the output to [2^128, MAX_DIFFICULTY_TARGET]; the timestamp rules
are Igneum's own, 10 s ahead of the clock and 10 s behind the selected parent beside the
unchanged past-median rule; new parameter rows, the bounds paragraph rewritten (the old
"next honest block cancels it" was the attack), the attack and test-network results added.
sim/difficulty/sim.py: class Igneum carries the same clock, lag bound and floor, so the
rule as simulated is the rule as coded (attacks.py's igneum-san is now identical to it).
docs/analysis/difficulty-2026-10-03.md section 11: the attack, the three parts, before and
after tables (simulator seeds 7 to 9, base-profile regression within 10% on the 3-seed
means, pool hopping unchanged, the two 15-minute 3-node forger runs), unit tests, limits.
docs/bench-log.md: the 4 October entry. docs/fud-ledger.md: M23, status Fixed.
Node side: vendor/igneum-node branch difficulty, commit 52eacad9.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- spec 3.10: C5/3.8 (min_daa = weight window, window-filling report), Q4 (drawn aggregator at
once, fallback for anyone), S1 (draw by weight), 3.9 (finality_reason) rows for fin-fixes da1eb889
- fork-divergence: four rows for the fin-fixes files and the merge note against the difficulty
branch (hot swap is already in master)
- bench-log: unit tests and the scenario 2 and 5 re-runs before (master) and after (fin-fixes)
- fud-ledger: F17 and F1 status lines
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simulator harness over sim/difficulty/sim.py with multi-miner attribution and in-rule timestamp forging, a 3-node CPU test network (ports 27700+), results and bench-log entry. Timestamp stretching inside Kaspa's rules drops the Igneum block rate 34 to 88% (the per-step clamp cancels forged and honest pairs to zero time); proposed 10 s timestamp bounds plus a sanitised running clock in the chain steps (+0.7% to +1.1% drift at 50% in the simulator). Block flood underflows the 192-bit work after 4,142 blocks; a 2^128 target floor proposed. Rule not changed.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
tools/finality-attacks: run.mjs drives a private igneum-devnet-800 network (ports 27800+,
/tmp/igneum-fin-attacks, skip_proof_of_work) with the test-only hostile flags of igneum-miner
(vmine, --equivocate, --sybil, --drop-votes, --pulse, fin-rpc-attack; worktree fin-attacks on
master c6d47547..2a00ff55). Seven scenarios in priority order 3,2,1,6,4,8,5 with a spec 03
criterion and a measured result each; README carries the catalogue, what needs a finality-aware
p2p probe, and a proposed diff for every FAIL.
Results (six voters): S3 dishonest aggregators PASS (35/35/35 locks, 0 conflicts, 1,018 ms);
S2 Sybil dust: weights PASS, aggregator sortition FAIL (per key, ledger F17); S1 equivocation
PASS (2/2/2 stripped, 0 conflicts); S6A 3/3 partition FAIL (floor is time-bounded, one side
crossed 56.7% at 84 s of a 90 s split, T* = 2F/13R, 9.2 days for a 50/50 split at mainnet
scale); S6B 4/2 PASS; S4 vote-dropping producer PASS (0 ms added); S8 malformed votes over
RPC PASS (9 cases, no crash); S5 pulse: no retarget amplification (ratio 0.999) PASS,
lock-alone FAIL (a 20 s burst locked checkpoints 1 to 10 alone on a young window, ledger F1,
spec 3.8 not implemented). S7 eclipse not run.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
No per-job growth in any worker or in the miner's memory. The STATUS rates are cumulative averages
(a fast first interval decays by construction), and the miner's Seeder walks the selected chain from
the sink to the epoch start on every memo miss (one getBlock per block, up to 3,600), a gap between
jobs that grew 0.10 s to 0.33 s across epoch 2 on the PC and reset at the epoch boundary while the
difficulty held. Reproduced on the Metal worker (churn on, off, on). One versus eight workers at two
fixed difficulties: 4% and 1% constant cost, no decay. Fix as a unified diff, not applied.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
sim/economy/sim.py: 1,000 operators choosing MINE, PROVE, HYBRID or OFF per card class with their own clients; sortition by weight with the 10-s window then open claiming, external jobs with the 90/10 split, backlog rule, difficulty clamps, GBM price. Scenarios a to f, 5 seeds: no backlog, no window miss, hash floor 0.74 of pre-event. Traffic sensitivity finds the shortage oscillation only above the proving fleet's capacity (100 to 300 shards per block); at 100 the sortition window (10 s to 20 s) is the lever that removes it. docs/analysis/economy-2026-10-04.md holds the model, assumptions, results, worst case and the proposal (window = p90 shard time plus a swap, 25 s at today's targets; B_p tied to the live fleet), not applied.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adversarial robustness and conformance tests of the execution layer against a
throwaway 3-node simnet on ports 27600+. Six scenarios, each a runnable command
with a design-derived pass criterion and a measured result: malformed/boundary
txs, nonce games across parallel blocks, RPC fuzz, pgas exhaustion, reorgs under
execution, and developer-registry abuse. 98 checks, 0 failures, 0 node panics.
Two findings filed in the bench-log entry: the mempool admits txs with gas_limit
above B_e (low), and an over-pgas-budget tx is executed natively in full before
being skipped for no fee (medium, griefing).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Safety: X = 1/3 of total weight while honest votes reach every honest node within 41 min of median time; 4/30 = 13.3% across a longer partition, because only the 17/30 floor binds then (2 x 17/30 - 1). Liveness: Y = 17/30 connected and signing, T = P (1 - Y/(2(1 - Y))) + 107 s, 107 s at 2/3, 43 min at 17/30; below the floor finality pauses and the node reports it. Two certificates at one index: no verified lock is ever withdrawn, operators resolve (replaces the 3.5 re-evaluation). Seeds: uncertified checkpoint allowed (O-4.3 decided). Scenarios H (equivocator across a 50/50 split: conflicts at 12 to 16 min with 20%, none at 13%), I (40/40/20), J (signing stops 1, 6, 24 h), K (bought keys worth 20% and 40% against 30% hash), five seeds each. 3.10 rows for the gaps; open items O-3.15 to O-3.19.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
docs/evidence.md and site/evidence.html: 28 public claims with one of five status labels (7 designed, 3 implemented, 18 tested by the team, 0 reproduced externally, 0 reviewed independently), version or commit, the reproducible test, the result with date and machine, and independent verification (none yet for every row). Evidence link in the homepage nav and the generated pages' nav.
docs/benchmarks/proving-e2e.md: replaces the 20-second shard gate with three fixed workloads, job-received-to-accepted-proof latency, cost per proof, the eligible card list with mining and proving reported separately, the verbatim acceptance standard and the three-unrelated-operator protocol.
docs/plans/funding.md: cost, what is funded (founder's means, the client's 1% fee once there is mining), what waits on revenue, what pauses.
docs/analysis/security-budget.md: emission through six halvings at three price inputs, miners and provers separate from burns, the USD 1M floor and the year it is crossed.
docs/design/payment-routes.md: Mermaid flowchart and table of every flow, with operator, app, team and protocol revenue labelled.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
proving/igneum-prove: core (port of igneum-exec at fb33069 as the block statement), program (SP1 v6.8.1 guest),
host (execute, core, compressed; ProofSystem trait with the stub and the SP1 implementation), export (cuts a block
out of igneum_exportSegments and checks every state root against the node's). Fixtures block-78-increment and
block-56-transfers from the 3-node simnet. proving/windows-wsl2: SETUP-PROVER.bat, setup-wsl.sh, PROVE-BLOCK.bat,
make-package.sh. docs/plans/proving-v0.md: the devnet v4 shard plan, what tonight's proof shows and does not, the
morning acceptance line. Mac CPU baseline (block 78: 626 k cycles, core 22.0 s and 7.3 MB, compressed 55.7 s and
1.27 MB, both verified) appended to docs/bench-log.md, left uncommitted because that file carries another agent's
pending changes.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Measured at 375, 768, 1280 and 1680 with headless Chrome. One token set in
all four stylesheets: container 1200 px with a clamp(16px,4vw,32px) gutter,
section rhythm clamp(56px,8vw,96px), cards clamp(18px,3vw,28px) padding and
18 px radius, tiles 18 by 20 px padding and 14 px radius, 24 px card gap and
12 px tile gap, headings h1 clamp(32,5.5vw,56) h2 clamp(28,4.2vw,44) h3
clamp(18,2vw,22), tile values clamp(20,2.2vw,26).
Home: the live strip spans the full hero width with economics-spec tiles;
stat strip and economics tiles share one spec; journey phases and log take
the tile and card boxes; inline padding-top overrides removed, consecutive
dark sections share one gap; every nav anchor lands the heading 11 px under
the sticky bar at every width (padded sections subtract their own padding).
Live: head, strip, cards and gaps on the tokens; four tiles a row, two on
phones; network name no longer clips. Litepaper: real gutter instead of a
fixed 16 px, cover, layout, tables, figures, pull quotes and stat tiles on
the tokens, pager stacks on phones. Engineering log: same tokens, long code
tokens wrap so phones no longer scroll sideways, duplicate h1 hidden.
Copy shortened so no label orphans at any width: stat strip labels, the
economics tiles, the strip tile labels, the litepaper stat tiles, the
mining-program eyebrow. The light-client card block is untouched.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
igneum-seed-1 (Hetzner cx23, fsn1, 188.245.5.161:26611): built on the VM in 1,530 s, synced to the live devnet
(12,204 blocks, same sink as the live node) through a non-mining relay igneumd on the Mac (the live node's addPeer
RPC is refused in safe mode); the live node and the Windows PC learned the seed's address by peer exchange and dialled
it. seeds.txt written. Hetzner prices corrected to USD (pricing API currency) in the plans, READMEs and scripts;
current-generation types per location (cx23 EU, cpx22 sin, cpx21 US) in the cloud-devnet config.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Mac: bundle renamed Igneum Miner.app (network.igneum.miner, 0.1.0, LSMinimumSystemVersion 11.0, igneum.icns),
Terminal title Igneum Miner, seed line in the first-run text, branded DMG (volume icon, background, icon slots via
dmgbuild), dist/Igneum-Miner-0.1.0.dmg at 16.2 MB, tested synced against the live node on 27400/27401.
Windows: packaging/windows with windres .rc files and embed-resources.sh (relink commands for the next cross-build),
Igneum-Miner.iss (Program Files, Start Menu group, firewall rule, uninstall stops the processes, licence, seed line),
BUILD-INSTALLER.bat and build-installer.ps1 for the project lead's PC (winget Inno Setup 6, rcedit fallback for the exe icon).
Icons: brand/icons/make-icons.py makes igneum.icns, igneum.ico, the Inno wizard art and the DMG background.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
site/verify/core.js recomputes every header hash (keyed BLAKE2b, the
node's field order), checks the parent links from the previous locked
checkpoint, hashes each voter's G1 key to its vote_key_hash, verifies the
BLS aggregate over "igneum-vote-v1/" || chain_id || 0 || index_le64 ||
checkpoint under the vote tag with the bitmap's keys, and applies Q3
(2/3 of active, 17/30 of total). verify.js drives it from /api/checkpoint
with @noble/hashes 2.4.0 and @noble/curves 2.4.0 pinned from jsdelivr and
fills the homepage card; the badge says LIVE only after a pass in the tab.
site/api/checkpoint.mjs ships the data: certificate bytes, voter table
with public keys, header chain. tools/observer stores every certificate a
block carries (new table live_certificates, voter table read at the lock,
selected-chain headers back to the previous lock, one-off backfill of the
newest lock on start) and keeps header nonces exact; the FinalityLock
write no longer fails on a missing votes_seen.
Tested on the igneum-devnet-7 test network: checkpoint 95 verifies in
Chrome in 103 ms; a flipped signature bit, a dropped voter, an altered key,
an altered header and a removed header all fail with the reason named.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
tools/harness runs the standard consensus-attack catalogue against a private
test network of our own igneumd nodes (127.0.0.1 ports 27200+, /tmp/igneum-harness,
never the live devnet or the PC node), with a pass criterion per scenario from the
spec and a measured result each. Built on the node fork's own crates
(igneum-harness-sim on kaspa_utils::sim as simpa does; igneum-p2p-probe for the
wire). Scenarios: 1 withholding, 2 timestamp edges and drift, 3 partition and heal,
4 eclipse, 5 malformed and boundary inputs on every p2p and RPC surface, 6 resource
exhaustion, 7 fast-miner flood. Finality and difficulty-controller scenarios are
stubs with their criteria written.
bench-log: one dated entry, a row per scenario (criterion, measured, pass or fail).
First run: 19 of 20 measured rows pass. Findings recorded in the entry: scenario 5
reproduces ledger M15 on HEAD (bogus past-day or DAA headers build a 256 MiB cache
before rejection; the r3-fixes branch removes it); scenario 1 at 45% hash with
burst withholding shows a selfish-mining blue-share gain (50.7% of blues), the one
failing row.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>