Merge remote-tracking branch 'origin/master' into ca3-coord

This commit is contained in:
igneum-labs 2026-10-06 18:17:32 +00:00
commit 534feaedd6
25 changed files with 495 additions and 223 deletions

View file

@ -91,6 +91,8 @@ jobs:
run: bash tools/ci/prover-socket-check.sh
- name: commit-string gate self-test (the empty-commit class of 6 October 2026; the gate itself runs in build-remote.sh, cross-remote.sh and cross-build.sh on every node binary)
run: bash tools/ci/commit-string-check.sh --self-test
- name: build server remote checkout self-test (the stale-overlay class of 6 October 2026)
run: bash infra/build-server/remote-run.sh --self-test
- name: no secret file names and no 64-hex secrets in the tree (self-test first, then the tree)
run: bash tools/ci/no-secrets-check.sh --self-test && bash tools/ci/no-secrets-check.sh
- name: faucet unit tests (validation, the daily limits, the signed transaction; keccak, RLP and secp256k1 vectors)

View file

@ -83,7 +83,17 @@ Also logged for context: the Mac's Linux cross-build with zig (`infra/cross/buil
| R6 | The box is never a node host for the live devnet and never holds a secret (no `~/.config/igneum` there). The Devnet 2 seed on it runs under its own unit with `--devnet --devnet-suffix=<n>` on 26611 (ufw already open) when that work starts. |
| R7 | CLAUDE.md line "nothing is built on a server" and "Windows builds go to the GitHub runner, Linux binaries come from infra/cross/build-linux.sh" are rewritten when R1 and R2 are adopted; until then the box is the measured option, not the rule. |
## 5. What the box does not do yet
## 5. Gotchas met on the first day
| Case | What happened | Fix |
|---|---|---|
| Stale overlay blocks the next checkout (PC 1 worker, 6 Oct 2026) | build-remote.sh rsyncs uncommitted files over the box's checkout; on the next commit `git checkout -B` refused with "local changes would be overwritten" | remote-run.sh `checkout` mode: `git checkout -- .` and `git clean -fd` (target dirs, sha stamps and ignored files kept) before the branch checkout, then the overlay; `remote-run.sh --self-test` reproduces the dirty tree and shows the mode landing on the new commit clean |
| An all-identical overlay listed only directories | the first run's touch pipeline got an empty file list and failed | files only are counted and re-stamped (lib.sh bs_overlay_dir) |
| bash 3.2 on the Mac treats an empty array as unbound under `set -u` | run-from-mac.sh died on `PASS[*]` | a string instead of an array |
| `grep -q` plus `pipefail` turned a strings hit into a miss | the commit-string gate failed a stamped igneumd on its first use (SIGPIPE on `strings`) | `grep -c` |
| Let's Encrypt saw NXDOMAIN for build.igneum.network | the deSEC record was minutes old; Ubuntu's Caddy then fell back to ZeroSSL and failed with HTTP 422 for ever | issuer pinned to Let's Encrypt; the retry got the certificate |
## 6. What the box does not do yet
| Gap | Why it matters | Next step |
|---|---|---|

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

View file

@ -111,10 +111,13 @@ bs_push_and_checkout() {
[ "$BS_TOP_REL" = . ] && remote_top="$BS_REMOTE_WT"
bs_log "push $BS_TOP HEAD $BS_SHA ($BS_BRANCH) -> $url"
GIT_SSH_COMMAND="$BS_SSH_CMD" git -C "$BS_TOP" push -q --force "$url" "HEAD:refs/heads/$BS_BRANCH" || bs_die "push to the mirror failed"
bs_ssh "set -e; mkdir -p '$BS_REMOTE_WT'
if [ ! -d '$remote_top/.git' ]; then rm -rf '$remote_top'; git clone -q --no-checkout '$BS_MIRROR' '$remote_top'; fi
cd '$remote_top'; git fetch -q origin '+refs/heads/*:refs/remotes/origin/*'; git checkout -q -B '$BS_BRANCH' '$BS_SHA'; git reset -q --hard '$BS_SHA'
git status --porcelain | head -3" || bs_die "remote checkout at $remote_top failed"
# the checkout runs as remote-run.sh's `checkout` mode: discard the previous overlay (tracked edits and untracked files,
# target dirs kept), then the branch at the commit. 6 October 2026, PC 1 worker's first use: the overlay of an earlier
# commit's uncommitted files stayed in the box's tree and `git checkout -B` refused with "local changes would be overwritten".
BR_MODE=checkout BR_CO_DIR="$remote_top" BR_CO_MIRROR="$BS_MIRROR" BR_CO_BRANCH="$BS_BRANCH" BR_CO_SHA="$BS_SHA" BR_CO_WT="$BS_REMOTE_WT" \
bash -c '
for v in BR_MODE BR_CO_DIR BR_CO_MIRROR BR_CO_BRANCH BR_CO_SHA BR_CO_WT; do printf "export %s=%q\n" "$v" "${!v}"; done
cat "$0"' "$(dirname "${BASH_SOURCE[0]}")/remote-run.sh" | bs_ssh 'bash -s' || bs_die "remote checkout at $remote_top failed"
BS_REMOTE_TOP="$remote_top"
}

View file

@ -17,8 +17,63 @@
# 2026): on success, on failure and on the slot give-up. UTC ISO 8601 Z times, numbers unquoted, unknown fields omitted,
# artefacts with bytes and sha256 only when the run succeeded (a failed build would list the previous build's files),
# the line kept under 4 KB.
# Modes (BR_MODE, default run): `checkout` resets the box's tree and checks the branch out at the commit (lib.sh
# bs_push_and_checkout: BR_CO_DIR, BR_CO_MIRROR, BR_CO_BRANCH, BR_CO_SHA, BR_CO_WT); `--self-test` (first argument) builds a
# scratch mirror and clone, dirties the clone the way a build's overlay does, moves the mirror one commit on, and shows the
# checkout mode lands on the new commit with a clean tree (the 6 October 2026 case: a stale overlay made `git checkout -B`
# refuse with "local changes would be overwritten").
set -uo pipefail
. /etc/profile.d/igneum-build.sh
[ -f /etc/profile.d/igneum-build.sh ] && . /etc/profile.d/igneum-build.sh
# discard the previous overlay (tracked edits and untracked files; target dirs, the sha stamps and anything ignored are kept),
# fetch, then the branch at the commit. Runs in BR_CO_DIR, clones it from BR_CO_MIRROR when it has no .git.
checkout_tree() {
local dir="$1" mirror="$2" branch="$3" sha="$4" wt="${5:-}"
set -e
[ -n "$wt" ] && mkdir -p "$wt"
if [ ! -d "$dir/.git" ]; then rm -rf "$dir"; git clone -q --no-checkout "$mirror" "$dir"; fi
cd "$dir"
git checkout -q -- . 2>/dev/null || true
git clean -qfd -e target -e 'target-*' -e '.build-remote-sha-*' -e '.cross-remote-sha-*' -e sccache
git fetch -q origin '+refs/heads/*:refs/remotes/origin/*'
git checkout -q -B "$branch" "$sha"
git reset -q --hard "$sha"
# what may remain untracked: target dirs, the sha stamps of build-remote.sh and cross-remote.sh (kept so a build after the
# checkout knows whether to clean kaspa-build-info), sccache; the first live run after this mode was added failed on a
# stamp it had itself kept (6 October 2026, 18:14 UTC: the self-test had no stamp file; it has one now)
local left; left=$(git status --porcelain | grep -vE '^\?\? (target|target-|sccache|\.build-remote-sha-|\.cross-remote-sha-)' | head -3 || true)
[ -z "$left" ] || { echo "checkout: tree not clean after reset at $dir: $left" >&2; return 1; }
set +e
}
if [ "${1:-}" = --self-test ]; then
t=$(mktemp -d); trap 'rm -rf "$t"' EXIT
git init -q --bare -b master "$t/mirror.git"
git init -q -b master "$t/src"; git -C "$t/src" -c user.name=t -c user.email=t@t commit -q --allow-empty -m one
echo a > "$t/src/a.txt"; git -C "$t/src" add a.txt; git -C "$t/src" -c user.name=t -c user.email=t@t commit -q -m two
git -C "$t/src" push -q "$t/mirror.git" master
sha1=$(git -C "$t/src" rev-parse HEAD)
checkout_tree "$t/box" "$t/mirror.git" master "$sha1" || { echo "self-test: first checkout failed"; exit 1; }
# the overlay of a build: a tracked file edited, an untracked file added, a target dir that must survive
echo edited > "$t/box/a.txt"; echo new > "$t/box/b.txt"; mkdir -p "$t/box/target/release"; echo bin > "$t/box/target/release/x"; echo "$sha1" > "$t/box/.build-remote-sha-target"
# the Mac moves on: a new commit that changes a.txt
echo a2 > "$t/src/a.txt"; git -C "$t/src" -c user.name=t -c user.email=t@t commit -qam three; git -C "$t/src" push -q "$t/mirror.git" master
sha2=$(git -C "$t/src" rev-parse HEAD)
if (cd "$t/box" && git fetch -q origin && git checkout -q -B master "$sha2" 2>/dev/null); then echo "self-test: the plain checkout did NOT refuse on the dirty tree (the case no longer reproduces; the reset is still right)"; else echo "self-test: the plain checkout refuses on the dirty tree, as on 6 October"; fi
checkout_tree "$t/box" "$t/mirror.git" master "$sha2" || { echo "self-test: checkout mode FAILED on the dirty tree"; exit 1; }
[ "$(git -C "$t/box" rev-parse HEAD)" = "$sha2" ] || { echo "self-test: wrong commit"; exit 1; }
[ "$(cat "$t/box/a.txt")" = a2 ] || { echo "self-test: tracked edit survived"; exit 1; }
[ ! -e "$t/box/b.txt" ] || { echo "self-test: untracked overlay file survived"; exit 1; }
[ -f "$t/box/target/release/x" ] || { echo "self-test: target dir was cleaned"; exit 1; }
[ -f "$t/box/.build-remote-sha-target" ] || { echo "self-test: the sha stamp was cleaned"; exit 1; }
echo "self-test: checkout mode lands on the new commit with a clean tree, target dir and sha stamp kept"; exit 0
fi
if [ "${BR_MODE:-run}" = checkout ]; then
: "${BR_CO_DIR:?}" "${BR_CO_MIRROR:?}" "${BR_CO_BRANCH:?}" "${BR_CO_SHA:?}"
checkout_tree "$BR_CO_DIR" "$BR_CO_MIRROR" "$BR_CO_BRANCH" "$BR_CO_SHA" "${BR_CO_WT:-}"; exit $?
fi
: "${BR_DIR:?}" "${BR_CMD:?}" "${BR_LABEL:?}" "${BR_TOOL:?}" "${BR_KIND:?}"
BR_HOST=$(hostname); BR_PID=$$; BR_T0=$(date +%s)
export BR_HOST BR_PID BR_T0

View file

@ -0,0 +1,62 @@
# Site capture on PC 1 (6 October 2026): screenshots of the installed Igneum Miner's own UI for igneum.network/miner.
# A read-only run job. It reads the installed app's URL file and GETs the four pages with Edge headless, which every
# Windows box has. Nothing is posted to the app: no quit, no pause, no resume, no settings change; the miners keep
# running; Edge runs as its own process on a scratch profile under the job folder and exits after each shot.
# Each PNG goes back as a raw file drop on the relay (under 4 MB each; x-igneum-key is the job's intake key, which
# may report but never execute). The Mac reads them with tools/relay.mjs and masks the rail foot and the machine id
# before anything reaches site/img. Every line that matters starts with RESULT.
$ErrorActionPreference = 'Continue'
function Say($t) { Write-Output "RESULT $t" }
$urlFile = @((Join-Path $env:IGNEUM_APP_DATA 'app\app.url'), (Join-Path $env:LOCALAPPDATA 'igneum\app\app.url')) | Where-Object { Test-Path $_ } | Select-Object -First 1
if (-not $urlFile) { Say 'no app.url found: the installed app is not running'; exit 2 }
$base = (Get-Content -LiteralPath $urlFile -Raw).Trim()
if (-not $base.EndsWith('/')) { $base += '/' }
Say 'app url read (the installed app; read only)'
$edge = @("${env:ProgramFiles(x86)}\Microsoft\Edge\Application\msedge.exe", "$env:ProgramFiles\Microsoft\Edge\Application\msedge.exe") | Where-Object { Test-Path $_ } | Select-Object -First 1
if (-not $edge) { Say 'msedge.exe not found'; exit 2 }
Say ("edge " + (Get-Item $edge).VersionInfo.ProductVersion)
try {
$state = Invoke-RestMethod -Uri ($base + 'api/state') -TimeoutSec 10
$cards = @($state.mining.cards)
Say ("state: app {0}, mining {1}, {2} card(s), {3:N1} MH/s total" -f $env:IGNEUM_APP_VERSION, $state.mining.state, $cards.Count, [double]$state.mining.hash_total)
foreach ($c in $cards) { Say ("card {0}: {1}, {2:N1} MH/s, {3} W, sweep {4}" -f $c.name, $c.state, [double]$c.hash_now, $c.power_w, $c.sweep_state) }
} catch { Say ("api/state not read: " + $_.Exception.Message) }
$out = Join-Path $env:IGNEUM_JOB_DIR 'shots'
New-Item -ItemType Directory -Force -Path $out | Out-Null
$profileDir = Join-Path $env:IGNEUM_JOB_DIR 'edge-profile'
$shots = @()
foreach ($theme in @('dark', 'light')) {
foreach ($page in @('mine', 'earnings', 'prove', 'settings')) { $shots += @{ name = "pc1-$page-$theme"; page = $page; w = 1440; h = 900; dark = ($theme -eq 'dark') } }
$shots += @{ name = "pc1-mine-phone-$theme"; page = 'mine'; w = 390; h = 844; dark = ($theme -eq 'dark') }
$shots += @{ name = "pc1-settings-phone-$theme"; page = 'settings'; w = 390; h = 844; dark = ($theme -eq 'dark') }
}
foreach ($s in $shots) {
$file = Join-Path $out ($s.name + '.png')
$edgeArgs = @('--headless=new', '--disable-gpu', '--hide-scrollbars', '--no-first-run', '--disable-extensions', '--disable-features=WebContentsForceDark',
"--user-data-dir=$profileDir", '--force-device-scale-factor=2', '--virtual-time-budget=10000', ('--window-size=' + $s.w + ',' + $s.h), "--screenshot=$file")
if ($s.dark) { $edgeArgs += '--force-dark-mode' }
$edgeArgs += ($base + '?page=' + $s.page)
$p = Start-Process -FilePath $edge -ArgumentList $edgeArgs -Wait -PassThru -NoNewWindow
if (Test-Path $file) { Say ("shot {0} {1} bytes" -f $s.name, (Get-Item $file).Length) } else { Say ("shot {0} FAILED, edge exit {1}" -f $s.name, $p.ExitCode) }
}
$relay = 'https://relay.igneum.network/api/relay?fn=drop'
$sent = 0
foreach ($png in Get-ChildItem $out -Filter '*.png') {
try {
$bytes = [IO.File]::ReadAllBytes($png.FullName)
if ($bytes.Length -gt 4000000) { Say ("not sent {0}: {1} bytes is over the raw cap" -f $png.Name, $bytes.Length); continue }
$hdr = @{ 'x-igneum-key' = $env:IGNEUM_INTAKE_KEY; 'x-file-name' = $png.Name; 'x-title' = ('site-capture ' + $png.Name); 'x-from' = 'pc1' }
$r = Invoke-RestMethod -Uri $relay -Method Post -Headers $hdr -Body $bytes -ContentType 'image/png' -TimeoutSec 120
Say ("sent {0} as relay item {1}" -f $png.Name, $r.id)
$sent++
} catch { Say ("not sent {0}: {1}" -f $png.Name, $_.Exception.Message) }
}
Say ("done: {0} of {1} shots on the relay" -f $sent, $shots.Count)
if ($sent -lt $shots.Count) { exit 1 }

View file

@ -1,5 +1,5 @@
// Igneum live devnet feed. GET /api/live returns what tools/observer wrote to Neon:
// {now, state, blocks (last 90 s, or ?window=N up to 300), miners (last 10 min), events (last 30), finality (checkpoints, newest lock),
// {now, state (incl. height = chain block number), blocks (last 90 s, or ?window=N up to 300), miners (last 10 min), events (last 30), finality (checkpoints, newest lock),
// proving (activation and 10-minute counts; every chain block carries shards: [{i, state, prover, lag, payout}])}.
// Five queries, all on indexed columns. Cached one second at the edge.
// LIVE_TABLE_PREFIX (default empty) reads a test observer's tables (fintest_live_*, provtest_live_*) instead of the devnet's.
@ -43,7 +43,8 @@ export default async function handler(req, res) {
const [head, blockRows, minerRows, checkpointRows, proofRows] = await Promise.all([
sql(`SELECT now() AS now,
(SELECT row_to_json(s) FROM ${T}live_state s WHERE s.id = 1) AS state,
(SELECT json_agg(e) FROM (SELECT ts, kind, text FROM ${T}live_events ORDER BY ts DESC LIMIT 30) e) AS events`),
(SELECT json_agg(e) FROM (SELECT ts, kind, text FROM ${T}live_events ORDER BY ts DESC LIMIT 30) e) AS events,
(SELECT max(number) FROM ${T}live_blocks WHERE number IS NOT NULL AND received_at > now() - interval '10 minutes') AS height`),
sql(`SELECT hash, blue_score, daa_score, timestamp_ms, parent_hashes, is_chain_block, vote_key_hash, received_at, color
FROM ${T}live_blocks
WHERE received_at > now() - ($1 || ' seconds')::interval
@ -78,6 +79,9 @@ export default async function handler(req, res) {
age_s: age_s === null ? null : Math.round(age_s * 10) / 10,
network: s ? s.network : null,
node_version: s ? s.node_version : null,
// 6 Oct 2026: height is the chain block number (the EVM block number of the newest chain block the observer planned),
// the same field /api/stats reports; block_count counts every DAG block the node holds (pruned nodes hold fewer)
height: num(head[0].height),
block_count: s ? num(s.block_count) : null,
header_count: s ? num(s.header_count) : null,
blue_score: s ? num(s.blue_score) : null,

View file

@ -255,7 +255,7 @@ const PRODUCT = {
full: 'Igneum Ember',
name: 'Ember',
app: 'Igneum Miner',
caption: 'Igneum Ember (the app is still labelled Igneum Miner until 0.3.6)',
caption: 'Igneum Ember (the app window still says Igneum Miner)',
};
function stampProduct(html, file) {
return html.replace(/<span data-product="([a-z]+)">[^<]*<\/span>/g, (m, k) => {

View file

@ -3,27 +3,27 @@
"files": {
"miner-hive": {
"alias": "/public/igneum-miner-hive.tar.gz",
"file": "igneum-hive-0.3.9.tar.gz",
"path": "/dl/public/igneum-hive-0.3.9.tar.gz",
"sha256": "7a58a30fd47c9ecb3d4aeaa0c0a464550f7e4b2b33eacf87512f1b72164c829e",
"size": 24179978,
"version": "0.3.9"
"file": "igneum-hive-0.3.14.tar.gz",
"path": "/dl/public/igneum-hive-0.3.14.tar.gz",
"sha256": "c4699f2487580dcf06b5c22a36a2eb8383a3307b6137699c76c45eefebdd4c88",
"size": 24659507,
"version": "0.3.14"
},
"miner-mac": {
"alias": "/public/igneum-miner-mac.dmg",
"file": "Igneum-Miner-0.3.10.dmg",
"path": "/dl/public/Igneum-Miner-0.3.10.dmg",
"sha256": "151687c5672553c571af7224a8e4228348135b8a313fc89e6641db7ae21c85b3",
"size": 41383375,
"version": "0.3.10"
"file": "Igneum-Miner-0.3.14.dmg",
"path": "/dl/public/Igneum-Miner-0.3.14.dmg",
"sha256": "e9e4c24db81a262a36b6bac11609ce6d24ed03220973da4142df935d41fc4e40",
"size": 41892337,
"version": "0.3.14"
},
"miner-windows": {
"alias": "/public/igneum-miner-windows.exe",
"file": "Igneum-Miner-Setup-0.3.10.exe",
"path": "/dl/public/Igneum-Miner-Setup-0.3.10.exe",
"sha256": "24e58849f2b517e8c5579455e8c9d8376ff7dd27052f458ef91913cbc48abc88",
"size": 49858273,
"version": "0.3.10"
"file": "Igneum-Miner-Setup-0.3.14.exe",
"path": "/dl/public/Igneum-Miner-Setup-0.3.14.exe",
"sha256": "08e75effc732f88bca11006b3b7cdf2bc533576f56819f79509fee47a8f5dd59",
"size": 45416619,
"version": "0.3.14"
},
"wallet-mac": {
"alias": "/public/igneum-wallet-mac.dmg",
@ -34,5 +34,5 @@
"version": "0.1.4"
}
},
"updated": "2026-10-05T21:52:34Z"
"updated": "2026-10-06T17:48:20Z"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
site/img/miner-phone.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
site/img/miner-prove.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

File diff suppressed because one or more lines are too long

View file

@ -1,5 +1,5 @@
{
"updated": "2026-10-05",
"updated": "2026-10-06",
"stage": "phase-3",
"phases": [
{
@ -50,6 +50,86 @@
}
],
"log": [
{
"date": "2026-10-06",
"text": "00:4xZ, the empty `/api/state` reply",
"short": "00:4xZ, the empty `/api/state` reply"
},
{
"date": "2026-10-06",
"text": "07:12Z to 07:17Z, the host's chain mode with --save-shards records and --prev, on the Apple M5 Max's CPU",
"short": "07:12Z to 07:17Z, the host's chain mode with --save-shards records…"
},
{
"date": "2026-10-06",
"text": "07:52Z to 08:24Z, the segment-aligned prover beside the miner on PC 2's RTX 5090",
"short": "07:52Z to 08:24Z, the segment-aligned prover beside the miner on PC…"
},
{
"date": "2026-10-06",
"text": "08:26Z to 08:35Z, the fast-time harness on the fresh-record rule",
"short": "08:26Z to 08:35Z, the fast-time harness on the fresh-record rule"
},
{
"date": "2026-10-06",
"text": "12:25 to 13:20Z, the finality route: why 26 fresh nodes lost the seed every checkpoint",
"short": "12:25 to 13:20Z, the finality route: why 26 fresh nodes lost the…"
},
{
"date": "2026-10-05",
"text": "The 9070 XT on the eGPU: why 17.9 MH/s, and what moved",
"short": "The 9070 XT on the eGPU"
},
{
"date": "2026-10-05",
"text": "Ember Tune: the two-knob efficiency tune, the fleet prior, and what PC 1 could measure tonight",
"short": "Ember Tune: the two-knob efficiency tune, the fleet prior"
},
{
"date": "2026-10-05",
"text": "Read width of the lottery hash: 4, 16 and 64-byte loads, a per-load mix, a written scratch; three cards",
"short": "Read width of the lottery hash"
},
{
"date": "2026-10-05",
"text": "The hot table on the M5 Max: a second table sized to GPU cache beside the 1 GiB dataset",
"short": "The hot table on the M5 Max"
},
{
"date": "2026-10-05",
"text": "Mixer x4 and the cache growth rule: the class v3 dataset construction, with the x8 candidate",
"short": "Mixer x4 and the cache growth rule"
},
{
"date": "2026-10-05",
"text": "The SP1 CPU prover on PC 1 beside the miners, and the backend survey: no zkVM proves on AMD",
"short": "The SP1 CPU prover on PC 1 beside the miners, and the backend survey"
},
{
"date": "2026-10-05",
"text": "Proving v1: segment records, the chain rule, the unproven rule; what was measured tonight",
"short": "Proving v1: segment records, the chain rule"
},
{
"date": "2026-10-05",
"text": "Dp4a-class throughput on the M5 Max: the dot4 emulation against the ALU chain",
"short": "Dp4a-class throughput on the M5 Max"
},
{
"date": "2026-10-05",
"text": "Layer 3 scratch soundness",
"short": "Layer 3 scratch soundness"
},
{
"date": "2026-10-05",
"text": "Epoch length as an era parameter : the Apple M5 Max's compile-ahead per program",
"short": "Epoch length as an era parameter"
},
{
"date": "2026-10-05",
"text": "Aggregation cost on the RTX 5090: what a per-block aggregation spends and what each lever gives",
"short": "Aggregation cost on the RTX 5090"
},
{
"date": "2026-10-05",
"text": "The C4 fix: certificate-driven reorg",
@ -85,146 +165,6 @@
"text": "Live devnet: the first shards proven, verified and paid",
"short": "Live devnet: the first shards proven, verified and paid"
},
{
"date": "2026-10-04",
"text": "Ledger M30: the block and transaction floods grew the node by 256 MiB per epoch roll, fixed by sharing the PoW cache across the epochs of a day",
"short": "Ledger M30: the block and transaction floods grew the node by 256…"
},
{
"date": "2026-10-04",
"text": "Round-4 consensus items F23, F24, G12, X18 and M31: unit tests and fast-time 3-node runs against the control",
"short": "Round-4 consensus items F23, F24, G12, X18 and M31"
},
{
"date": "2026-10-04",
"text": "The software dev fee measured on a test network: 9 fee blocks in 785, the chain and the miners' counters agree",
"short": "The software dev fee measured on a test network"
},
{
"date": "2026-10-04",
"text": "Miner fault guards and the app watchdog measured against a fake worker",
"short": "Miner fault guards and the app watchdog measured against a fake worker"
},
{
"date": "2026-10-04",
"text": "Miner performance: variant racing",
"short": "Miner performance"
},
{
"date": "2026-10-04",
"text": "Finality rule v3: the frozen weight table and the certificate fold , simulator, unit tests, fast-time 3-node network with 300-ms links",
"short": "Finality rule v3"
},
{
"date": "2026-10-04",
"text": "First machine in the United States: a Windows laptop on an Intel integrated GPU, synced and voting",
"short": "First machine in the United States: a laptop on an integrated GPU, synced and voting"
},
{
"date": "2026-10-04",
"text": "Shard proving on the RTX 5090: a full shard compressed in 10.9 s, a two-shard block aggregated in 2.2 s, all verified",
"short": "Shard layer on the RTX 5090: a full shard proven in 10.9 s, a block aggregated in 2.2 s"
},
{
"date": "2026-10-04",
"text": "Cloud devnet: 12 igneumd nodes in 5 locations, inter-region latency, two Singapore partitions, hash-rate steps",
"short": "Cloud devnet: 12 igneumd nodes in 5 locations, inter-region latency"
},
{
"date": "2026-10-04",
"text": "Correction: the 78-minute observer gap was the Apple M5 Max hibernating",
"short": "Correction: the 78-minute observer gap was the Apple M5 Max hibernating"
},
{
"date": "2026-10-04",
"text": "Difficulty v2 rollout rehearsal on the 12-node the cloud provider network, binaries for the devnet, the devnet plan",
"short": "Difficulty v2 rollout rehearsal on the 12-node the cloud provider…"
},
{
"date": "2026-10-04",
"text": "Difficulty rule v2 activated on the live devnet at DAA 33,000 by height switch, no fresh chain",
"short": "Difficulty rule v2 switched on the live devnet by height, no fresh chain"
},
{
"date": "2026-10-04",
"text": "First outside machine on the devnet: an Apple silicon laptop through the Igneum Miner app",
"short": "First outside machine: a friend's Mac mining through the app"
},
{
"date": "2026-10-04",
"text": "One-click Windows workers: what the Apple M5 Max could measure",
"short": "One-click Windows workers"
},
{
"date": "2026-10-04",
"text": "The gfx1036 worker fault and what the Apple M5 Max could and could not reproduce",
"short": "The gfx1036 worker fault and what the Apple M5 Max could and could…"
},
{
"date": "2026-10-04",
"text": "Difficulty rule v2: the live oscillation, its cause, the DAG replay, the fix behind a height switch",
"short": "Difficulty rule v2"
},
{
"date": "2026-10-04",
"text": "The observer stored nothing for 78 minutes, then 7,022 blocks in two minutes",
"short": "The observer stored nothing for 78 minutes, then 7,022 blocks in two…"
},
{
"date": "2026-10-04",
"text": "PC 2 at the 14:20 boundary: a worker stuck on the previous epoch",
"short": "PC 2 at the 14:20 boundary: a worker stuck on the previous epoch"
},
{
"date": "2026-10-04",
"text": "The gfx1036 worker fault and what the Mac could and could not reproduce",
"short": "The gfx1036 worker fault and what the Mac could and could not reproduce"
},
{
"date": "2026-10-04",
"text": "A node 60 s behind the clock is silently dead",
"short": "A node 60 s behind the clock is silently dead"
},
{
"date": "2026-10-04",
"text": "First machine on the Igneum Miner app: PC 2's RTX 5090 at 118 MH/s, via Setup.exe",
"short": "First machine on the one-click app: a 5090 at 118 MH/s"
},
{
"date": "2026-10-04",
"text": "First finality lock on the live devnet: checkpoint 242 at 77.4% of all weight, two hours after genesis",
"short": "First live finality lock: 77.4% of weight, 17 voters"
},
{
"date": "2026-10-04",
"text": "Proving: devnet v4 shards on the Apple M5 Max CPU, loaded machine",
"short": "Proving: devnet v4 shards on the Apple M5 Max CPU, loaded machine"
},
{
"date": "2026-10-04",
"text": "One-click Windows workers: what the Mac could measure",
"short": "One-click Windows workers"
},
{
"date": "2026-10-04",
"text": "First hourly program swap on the live devnet: compile-ahead, no pause, two cards",
"short": "First live hourly swap: no pause on Mac, NVIDIA or AMD"
},
{
"date": "2026-10-04",
"text": "Proving v0 on the RTX 5090: first GPU proof of an Igneum block",
"short": "First GPU proof of an Igneum block: 1.4 s on an RTX 5090"
},
{
"date": "2026-10-04",
"text": "Devnet v4 cut-over: generator v2, 2/3 floor, three nodes and a seed on a fresh chain",
"short": "Devnet v4 live: generator v2, two-thirds floor, fresh chain"
},
{
"date": "2026-10-04",
"text": "Generator version 2 adopted: exact load count, fresh-source loads, program acceptance; every vector re-cut, three workers re-checked, 20,000-program census, devnet-v4 binaries rebuilt",
"short": "Generator v2 adopted: every hash does 128 distinct reads"
},
{
"date": "2026-10-04",
"text": "Sim/economy: mining versus proving under stress, agent-based",
@ -246,9 +186,69 @@
"short": "Devnet v4: nine branches merged into one node"
},
{
"date": "2026-10-03",
"text": "RTX 5090, memory-hard dataset",
"short": "RTX 5090 on the memory-hard dataset"
"date": "2026-10-04",
"text": "Generator version 2 adopted: exact load count, fresh-source loads, program acceptance; every vector re-cut, three workers re-checked, 20,000-program census, devnet-v4 binaries rebuilt",
"short": "Generator v2 adopted: every hash does 128 distinct reads"
},
{
"date": "2026-10-04",
"text": "Proving v0 on the RTX 5090: first GPU proof of an Igneum block",
"short": "First GPU proof of an Igneum block: 1.4 s on an RTX 5090"
},
{
"date": "2026-10-04",
"text": "Devnet v4 cut-over: generator v2, 2/3 floor, three nodes and a seed on a fresh chain",
"short": "Devnet v4 live: generator v2, two-thirds floor, fresh chain"
},
{
"date": "2026-10-04",
"text": "First hourly program swap on the live devnet: compile-ahead, no pause, two cards",
"short": "First live hourly swap: no pause on Mac, NVIDIA or AMD"
},
{
"date": "2026-10-04",
"text": "Proving: devnet v4 shards on the Apple M5 Max CPU, loaded machine",
"short": "Proving: devnet v4 shards on the Apple M5 Max CPU, loaded machine"
},
{
"date": "2026-10-04",
"text": "First finality lock on the live devnet: checkpoint 242 at 77.4% of all weight, two hours after genesis",
"short": "First live finality lock: 77.4% of weight, 17 voters"
},
{
"date": "2026-10-04",
"text": "A node 60 s behind the clock is silently dead",
"short": "A node 60 s behind the clock is silently dead"
},
{
"date": "2026-10-04",
"text": "First machine on the Igneum Miner app: PC 2's RTX 5090 at 118 MH/s, via Setup.exe",
"short": "First machine on the one-click app: a 5090 at 118 MH/s"
},
{
"date": "2026-10-04",
"text": "PC 2 at the 14:20 boundary: a worker stuck on the previous epoch",
"short": "PC 2 at the 14:20 boundary: a worker stuck on the previous epoch"
},
{
"date": "2026-10-04",
"text": "Ledger M30: the block and transaction floods grew the node by 256 MiB per epoch roll, fixed by sharing the PoW cache across the epochs of a day",
"short": "Ledger M30: the block and transaction floods grew the node by 256…"
},
{
"date": "2026-10-04",
"text": "Round-4 consensus items F23, F24, G12, X18 and M31: unit tests and fast-time 3-node runs against the control",
"short": "Round-4 consensus items F23, F24, G12, X18 and M31"
},
{
"date": "2026-10-04",
"text": "The software dev fee measured on a test network: 9 fee blocks in 785, the chain and the miners' counters agree",
"short": "The software dev fee measured on a test network"
},
{
"date": "2026-10-04",
"text": "Miner fault guards and the app watchdog measured against a fake worker",
"short": "Miner fault guards and the app watchdog measured against a fake worker"
}
]
}

View file

@ -236,7 +236,7 @@ main{padding-bottom:var(--sec)}
<div class="card" aria-label="Block DAG, finality and proving, live">
<div class="viz-head">
<div class="eyebrow"><span class="dot" style="margin-right:8px"></span>blocks, finality, proving</div>
<div class="viz-stats mono"><span>on screen <b id="c-screen">0</b></span><span>chain <b id="c-chain">0</b></span><span>identities <b id="c-idents">0</b></span><span>last lock <b id="c-locked">none</b></span><span>proven <b id="c-proven">n/a</b></span></div>
<div class="viz-stats mono"><span>on screen <b id="c-screen">0</b></span><span>chain <b id="c-chain">0</b></span><span>identities <b id="c-idents">0</b></span><span>last lock <b id="c-locked">none</b></span><span>proven <b id="c-proven">pending</b></span></div>
</div>
<canvas id="dag" aria-hidden="true"></canvas>
<div class="legend">
@ -402,7 +402,10 @@ main{padding-bottom:var(--sec)}
blocks.forEach(function(b){if(b.ts>vis){on++;if(b.chain){chain++;if(b.shards.length){planned++;if(b.proven)proven++;}}}});
$('c-screen').textContent=on;$('c-chain').textContent=chain;$('c-idents').textContent=idents;
var f=fin;$('c-locked').textContent=f&&f.latest_locked_index?('#'+f.latest_locked_index+(f.checkpoints&&f.checkpoints.length?', '+lockAge(f):'')):(f&&f.supported?'none yet':'n/a');
$('c-proven').textContent=prov&&prov.supported&&prov.active?(proven+'/'+planned):(prov&&prov.supported?'not active':'n/a');
// 6 Oct 2026: proofs land a median of minutes behind the tip, so the on-screen window (proven+'/'+planned) read 0 for ever; the
// counter now reads the observer's 10-minute truth: chain blocks with every shard paid, of the chain blocks planned in 10 min
var pe=$('c-proven');if(prov&&prov.supported&&prov.active){pe.textContent=(prov.blocks_fully_proven_10m||0)+'/'+(prov.blocks_10m||0)+' in 10 min';pe.title=(prov.shards_paid_10m||0)+' shards paid in the last 10 minutes'+(prov.median_proof_lag_s?', landing a median '+Math.round(prov.median_proof_lag_s)+' s behind the tip':'')+'; '+(prov.paid_shards_total!==null&&prov.paid_shards_total!==undefined?Number(prov.paid_shards_total).toLocaleString('en-GB')+' paid on the chain so far':'');}
else{pe.textContent=prov&&prov.supported?'not active':'no proving layer';pe.title='';}
if(!running&&!document.hidden)kick();
}
function lockAge(f){var cps=f.checkpoints||[],lk=null;for(var i=cps.length-1;i>=0;i--)if(cps[i].state==='locked'){lk=cps[i];break;}

View file

@ -4,13 +4,13 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>The Igneum miner app</title>
<meta name="description" content="One click: install, start, the card mines, and every NVIDIA card from 8 GB proves. Auto GPU detection on NVIDIA, AMD and Apple silicon, a wallet made for you, hourly program swaps with no pause, signed updates, a visible 1% software fee you can switch off.">
<meta name="description" content="One click: install, start, the card mines, and every NVIDIA card from 8 GB proves. Four pages: Mine, Earnings, Prove, Settings. Every card is one row with its rate, watts and pounds a day at your electricity price. Ember Tune measured on an RTX 5090: 84 W saved for 0.15% of rate. A visible 1% software fee you can switch off.">
<link rel="canonical" href="https://igneum.network/miner">
<meta name="theme-color" content="#0C0C0E">
<meta property="og:type" content="website">
<meta property="og:site_name" content="Igneum">
<meta property="og:title" content="The Igneum miner app">
<meta property="og:description" content="One click: install, start, the card mines, and every NVIDIA card from 8 GB proves. Auto GPU detection on NVIDIA, AMD and Apple silicon, a wallet made for you, hourly program swaps with no pause, signed updates, a visible 1% software fee you can switch off.">
<meta property="og:description" content="One click: install, start, the card mines, and every NVIDIA card from 8 GB proves. Four pages: Mine, Earnings, Prove, Settings. Every card is one row with its rate, watts and pounds a day at your electricity price. Ember Tune measured on an RTX 5090: 84 W saved for 0.15% of rate. A visible 1% software fee you can switch off.">
<meta property="og:url" content="https://igneum.network/miner">
<meta property="og:image" content="https://igneum.network/og.png?v=3">
<meta property="og:image:width" content="1200">
@ -18,7 +18,7 @@
<meta property="og:image:alt" content="Igneum. Mined by GPUs. Proven by fire.">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="The Igneum miner app">
<meta name="twitter:description" content="One click: install, start, the card mines, and every NVIDIA card from 8 GB proves. Auto GPU detection, a wallet made for you, hourly program swaps with no pause, signed updates, a visible 1% software fee you can switch off.">
<meta name="twitter:description" content="One click: install, start, the card mines, and every NVIDIA card from 8 GB proves. Four pages: Mine, Earnings, Prove, Settings. Every card is one row: rate, watts, pounds a day at your electricity price, a Tune button. A visible 1% software fee you can switch off.">
<meta name="twitter:image" content="https://igneum.network/og.png?v=3">
<meta name="twitter:image:alt" content="Igneum. Mined by GPUs. Proven by fire.">
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Crect width='1024' height='1024' fill='%230C0C0E'/%3E%3Cg transform='translate(166.95 166.95) scale(6.901)'%3E%3Cpolygon points='50,4 74,34 67,58 80,54 61,96 39,96 20,54 33,58 26,34' fill='%23F2541B'/%3E%3Cpolygon points='50,42 59,58 50,82 41,58' fill='%230C0C0E'/%3E%3C/g%3E%3C/svg%3E" type="image/svg+xml">
@ -153,6 +153,18 @@ section+section{padding-top:0;scroll-margin-top:var(--sm)}
.frame .bar b{margin-left:auto;font:500 11px/1 var(--f-mono);letter-spacing:.12em;color:var(--ash);text-transform:uppercase}
.frame img{display:block;width:100%;height:auto}
.frame figcaption{padding:10px 14px;font-size:13px;color:var(--ash);border-top:1px solid var(--line)}
/* the page-by-page section: three desktop shots in a grid, then the light desktop beside the phone */
.shots{display:grid;gap:var(--gap);grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr));margin-top:28px}
.shots .shot::before{inset:20% -4% -6% -4%}
.shots-row{display:grid;gap:var(--gap);grid-template-columns:1fr;align-items:start;margin-top:var(--gap)}
@media (min-width:900px){.shots-row{grid-template-columns:minmax(0,2.3fr) minmax(0,1fr)}}
.frame.phone{max-width:320px;margin:0 auto}
.frame.light{background:#F2F0EB;border-color:#D9D6CF}
.frame.light .bar{background:#E9E6DF;border-color:#D9D6CF}
.frame.light .bar i{background:#CFCBC2}
.frame.light figcaption{background:#0C0C0E}
.row-tbl{margin-top:28px}
.row-tbl td:first-child{white-space:nowrap;font-weight:600}
/* the three steps */
.steps{display:grid;gap:var(--gap-tile);grid-template-columns:repeat(3,minmax(0,1fr));position:relative}
@ -250,7 +262,7 @@ pre b{color:var(--molten);font-weight:500}
<div class="hero-copy">
<div class="eyebrow ember"><span data-product="full">Igneum Ember</span> · one click</div>
<h1>Install. Start. The card mines. Every NVIDIA card from 8 GB proves; 12 GB and up mine and prove.</h1>
<p class="lead"><span data-product="name">Ember</span> finds your GPU, makes a wallet for you and runs the node, the miner and the prover as one app. Every hour it compiles the next program while the current one mines, so the card never stops.</p>
<p class="lead"><span data-product="name">Ember</span> finds your GPU, makes a wallet for you and runs the node, the miner and the prover as one app. Four pages: Mine, Earnings, Prove, Settings. Every card is one row: its rate, its watts, pounds a day at your electricity price, a Tune button. Every hour it compiles the next program while the current one mines, so the card never stops.</p>
<div class="cta">
<a href="#get" class="btn primary">Downloads: public testnet</a>
<a href="#features" class="btn">Every feature</a>
@ -262,8 +274,8 @@ pre b{color:var(--molten);font-weight:500}
<div class="shot reveal">
<figure class="frame" style="margin:0">
<div class="bar"><i></i><i></i><i></i><b><span data-product="app">Igneum Miner</span></b></div>
<img src="/img/miner-dashboard.webp" width="2360" height="1540" alt="The miner dashboard: hash rate, blocks found, node synced, a countdown to the next program, the block chart, the Apple M5 Max card mining, node and finality panels" fetchpriority="high" decoding="async">
<figcaption><span data-product="caption">Igneum Ember (the app is still labelled Igneum Miner until 0.3.6)</span> on an Apple M5 Max, live devnet, 5 Oct 2026.</figcaption>
<img src="/img/miner-dashboard.webp" width="2880" height="1800" alt="The Mine page of Igneum Miner 0.3.14: the Start mining button, the live total in MH/s and blocks, the card row for an Apple M5 Max with its state word, Tune button and switch, the tune line, the Tuning card with Efficiency, Balanced and Maximum, the node as one line, and the activity strip" fetchpriority="high" decoding="async">
<figcaption><span data-product="caption">Igneum Ember (the app window still says Igneum Miner)</span> 0.3.14, Mine page, on an Apple M5 Max, paused, live devnet, 6 Oct 2026.</figcaption>
</figure>
</div>
</div>
@ -295,6 +307,68 @@ pre b{color:var(--molten);font-weight:500}
</div>
</section>
<section id="app">
<div class="wrap">
<div class="sec-head reveal">
<h2>Four pages. Every card is one row.</h2>
<p>Mine, Earnings, Prove, Settings, shipped in 0.3.14 on 6 October 2026. The screenshots are the live app on this team's Apple M5 Max, paused. Apple silicon reports no draw, so its row carries no watts and no pounds; an NVIDIA or AMD card's row does.</p>
</div>
<div class="tbl row-tbl reveal"><table>
<thead><tr><th>On the row</th><th>What it says</th><th>When it is not shown</th></tr></thead>
<tbody>
<tr><td>State word</td><td>mining, paused, tuning: step 7 of 9, waiting for the node, restarting in 4 s, off with the reason. A card never shows 0 MH/s without a word.</td><td>Always shown.</td></tr>
<tr><td>Rate</td><td>122 MH/s, live.</td><td>Blank with the state word when the card is not mining.</td></tr>
<tr><td>Power</td><td>290 W with 0.42 MH/W under it.</td><td>A card that reports no draw: Apple silicon, an integrated GPU. The row says so once.</td></tr>
<tr><td>Pounds a day</td><td>Watts × 24 ÷ 1,000 × your pence per kWh. The price is yours, set once in Settings.</td><td>"Set a price" until you set one; hidden with no draw.</td></tr>
<tr><td>Temperature</td><td>61 °C. Amber from 86 °C, ember from 92 °C.</td><td>When the card reports none.</td></tr>
<tr><td>Tune and the switch</td><td>Tune starts an Ember Tune on this card; Stop during a run. The switch turns the card on or off. Tune all queues every card, one at a time.</td><td>Tune is hidden for a card with no control and no measurement.</td></tr>
<tr><td>The tune line</td><td>"Not tuned yet: starts after 2 min of steady mining", "Tuning: step 7 of 9 · about 4 min left", "Tuned 2 h ago · 1,854 MHz at 100% · next check Sunday", or "Measured 27 MH/s as it runs" where the system sets the clocks.</td><td>No line for a card with no control and no measurement.</td></tr>
<tr><td>Under the chevron</td><td>The power cap slider, identities, pin or unpin, memory temperature, clocks, device facts, the last tune's table.</td><td>Closed by default.</td></tr>
</tbody>
</table></div>
<p class="pt reveal" style="margin-top:16px">Under the rows: the Tuning card (Efficiency, Balanced, Maximum, and about how many pounds a day at that goal), then the node as one line: synced, peers, blocks, read N s ago. Details opens the chain numbers in place.</p>
<div class="shots">
<div class="shot reveal">
<figure class="frame" style="margin:0">
<div class="bar"><i></i><i></i><i></i><b>Earnings</b></div>
<img src="/img/miner-earnings.webp" width="2880" height="1800" alt="The Earnings page: pounds earned with the devnet reason, IGN from proofs, blocks lifetime and this run, electricity at your price, the dev fee switch, the rewards address with Copy, Change address and Show my key" loading="lazy" decoding="async">
<figcaption>Money first. £ earned reads 0.00 on devnet and says why. The dev fee switch lives here. Change address and Show my key ask in place, no dialogs.</figcaption>
</figure>
</div>
<div class="shot reveal">
<figure class="frame" style="margin:0">
<div class="bar"><i></i><i></i><i></i><b>Prove</b></div>
<img src="/img/miner-prove.webp" width="2880" height="1800" alt="The Prove page: the Prove on this machine switch, one sentence per card on what it can prove, one line of counts, and Details" loading="lazy" decoding="async">
<figcaption>One switch, one sentence per card, one line of counts: assigned, proven, paid, IGN. Details holds the verifier, the program id and the segments.</figcaption>
</figure>
</div>
<div class="shot reveal">
<figure class="frame" style="margin:0">
<div class="bar"><i></i><i></i><i></i><b>Settings</b></div>
<img src="/img/miner-settings.webp" width="2880" height="1800" alt="The Settings page: Tuning with the goal, Ember Tune, Power control, Hill climb and the electricity price; This machine with start at login, remote jobs, the name and appearance; the update card" loading="lazy" decoding="async">
<figcaption>Plain rows, one sentence each: Tuning, This machine, one update card, Logs, Advanced. The electricity price every £ figure uses is set here.</figcaption>
</figure>
</div>
</div>
<div class="shots-row">
<div class="shot reveal">
<figure class="frame light" style="margin:0">
<div class="bar"><i></i><i></i><i></i><b>Light</b></div>
<img src="/img/miner-dashboard-light.webp" width="2880" height="1800" alt="The Mine page in light mode" loading="lazy" decoding="async">
<figcaption>Light and dark follow the system. Settings lets you pick one.</figcaption>
</figure>
</div>
<div class="shot reveal">
<figure class="frame phone" style="margin:0 auto">
<div class="bar"><i></i><i></i><i></i><b>390 px</b></div>
<img src="/img/miner-phone.webp" width="780" height="1688" alt="The Mine page in a 390 pixel wide window: the big button, the totals, the card row stacked, a bottom tab bar with Mine, Earnings, Prove, Settings and Logs" loading="lazy" decoding="async">
<figcaption>Under 720 px the rail becomes a bottom tab bar.</figcaption>
</figure>
</div>
</div>
</div>
</section>
<section id="features">
<div class="wrap">
<div class="sec-head reveal">
@ -308,7 +382,7 @@ pre b{color:var(--molten);font-weight:500}
<div class="feat"><b>The card mines; an NVIDIA card proves</b><p>One button starts the node, waits for sync, starts one miner per card and, on an NVIDIA card, the prover: every NVIDIA card from 8 GB proves; 12 GB and up mine and prove; 24 GB on the stock server (eleven rented cards, RTX 3060 to RTX 5090, 6 October 2026, docs/analysis/prover-tiers-real-cards.md); the patched server for the smaller cards is not yet in the shipped app. AMD and Apple cards mine; a prover for them lands when a zkVM ships one. Quit stops them in order.</p></div>
<div class="feat"><b>Finds your GPU by itself</b><p>NVIDIA through the driver, AMD and Intel through OpenCL, Apple silicon through Metal. Real card names, one worker per card.</p></div>
<div class="feat"><b>A wallet made for you</b><p>A payout key made on your machine and locked to your user, with a backup step before mining starts. Or paste an address you already hold.</p></div>
<div class="feat"><b>Earnings in IGN</b><p>Every block this machine finds pays one address in IGN. The dashboard counts them per run, per hour and for life. The <a href="/wallet" style="color:var(--ember)">wallet</a> shows the balance.</p></div>
<div class="feat"><b>Earnings, money first</b><p>Every block this machine finds pays one address in IGN. The Earnings page counts blocks this run and for life, IGN from proofs, and the electricity cost at your price. £ earned stays 0.00 on devnet and says why; a market price fills it in when one exists (coming). The <a href="/wallet" style="color:var(--ember)">wallet</a> shows the balance.</p></div>
<div class="feat"><b>Windows, macOS, Linux</b><p>An installer on Windows, a disk image on macOS, a package on Linux. No toolchain, no driver work: the GPU workers are prebuilt.</p></div>
<div class="feat"><b>HiveOS package</b><p>A custom miner for farms: the Linux miner, node and both GPU workers with the four Hive hooks. Hive itself is untested: report what breaks.</p></div>
<div class="feat"><b>First outside machine</b><p>An Apple silicon laptop, no instructions beyond the five steps: 33 accepted blocks in 7 minutes, 0 rejected, 21.0 MH/s average.</p><a class="src" href="/bench#4-october-2026-first-outside-machine-on-the-devnet-an-apple-silicon-laptop-through-the-igneum-miner-app">log · 4 Oct 2026</a></div>
@ -319,7 +393,7 @@ pre b{color:var(--molten);font-weight:500}
<div class="group reveal" id="client">
<div class="g-head"><div class="eyebrow ember">02 · One client</div><h3>Hashing and proving, switched by the client</h3><p>The lottery and the proving are kept apart on purpose. The client runs both and the miner sees one balance.</p></div>
<div class="feats">
<div class="feat"><b>Hashing and proving in one client</b><p>Proving is a switch. On, the client proves the shards the chain assigns to this machine's keys, submits the record to its own node and goes back to hashing. The tile shows assigned, proving, submitted, paid.</p></div>
<div class="feat"><b>Hashing and proving in one client</b><p>Proving is a switch. On, the client proves the shards the chain assigns to this machine's keys, submits the record to its own node and goes back to hashing. The Prove page shows one sentence per card on what it can prove and one line of counts: assigned, proven, paid, IGN.</p></div>
<div class="feat"><b>Several identities per card</b><p>Identities take turns on the card and each one votes and pays separately. 8 suits a big card, 2 a small one, 1 an integrated GPU.</p></div>
<div class="feat"><b>Hourly program, no pause</b><p>The node announces the next seed early. The worker compiles the next program in the background and swaps at the boundary while the current one mines.</p><a class="src" href="/bench#4-october-2026-first-hourly-program-swap-on-the-live-devnet-compile-ahead-no-pause-two-cards">log · 4 Oct 2026</a></div>
<div class="feat wide">
@ -353,7 +427,20 @@ pre b{color:var(--molten);font-weight:500}
<div class="feat"><b>Variant racing every hour</b><p>At every hourly prepare the worker compiles the program in several shapes (unroll, load path, register budget, threads per group), times each for 2 seconds and keeps the fastest for the hour. Base keeps its place unless beaten.</p><a class="src" href="/bench#4-october-2026-miner-performance-variant-racing-metal-worker-on-the-m5-max-the-rtx-5090-job-is-ready-not-run">log · 4 Oct 2026</a></div>
<div class="feat"><b>Measured on Apple silicon</b><p>On the M5 Max, 256-thread groups ran 17.3% and 21.2% faster than base on two programs, under load from other work. The NVIDIA race is built and has not yet run on a GPU.</p><a class="src" href="/bench#4-october-2026-miner-performance-variant-racing-metal-worker-on-the-m5-max-the-rtx-5090-job-is-ready-not-run">log · 4 Oct 2026, ratios under contention</a></div>
<div class="feat"><b>Fleet tuning manifest</b><p>Every race is one record in the app log. The fleet's best variant per card model goes back out inside the signed update manifest, so a card starts from the known best and keeps racing.</p></div>
<div class="feat"><b>Ember Tune</b><p>Hash per watt, the number miners compare. Out of the box the app steps every card's power limit and core clock on the live kernel, 60 seconds a step, and keeps the point with the best MH per watt within 1% of the card's top rate. The memory clock is never touched; a step with a rejected hash, a hot GPU or a dragged memory clock is reverted and marked. Every result feeds a fleet prior per card model that the next card of that model starts from. Built and unit-tested; the first measured tune is owed.</p></div>
<div class="feat"><b>Ember Tune</b><p>Tunes every card for hashes per watt: once after install, then every 7 days, and after a driver or program change. The app steps the power limit and the core clock on the live kernel, 60 seconds a step, and keeps the point with the best MH per watt within 1% of the card's top rate. The memory clock is never touched; a step with a rejected hash, a hot GPU or a dragged memory clock is reverted and marked. Every result feeds a fleet prior per card model that the next card of that model starts from. One goal for all cards: Efficiency, Balanced or Maximum, with about how many pounds a day at that goal.</p><a class="src" href="/bench">log · 6 Oct 2026, Ember run 6</a></div>
<div class="feat"><b>Power control: one approval, then no prompts</b><p>Setting an NVIDIA power or clock limit needs administrator rights on Windows. The app asks once, when you turn Power control on, and registers a helper task; every cap after that is set through the task with no prompt. Off, NVIDIA cards are measured only. AMD cards are set through the app's own helper with no prompt at all.</p><a class="src" href="/bench">log · 6 Oct 2026, the task re-pointed and two caps set with no prompt</a></div>
<div class="feat wide">
<b>Ember Tune measured, PC 1, 6 Oct 2026</b>
<div class="tbl" style="margin-top:8px"><table>
<thead><tr><th>Card</th><th>Untuned</th><th>Tuned</th><th>Saved</th></tr></thead>
<tbody>
<tr><td>RTX 5090</td><td class="num">311.0 W<br>127.9 MH/s<br>0.411 MH/W</td><td class="num">226.8 W at 1,854 MHz, cap 100%<br>127.71 MH/s (0.15% less)<br>0.563 MH/W</td><td class="num">84 W<br>£0.56 a day at 28p/kWh</td></tr>
<tr><td>RTX 4070</td><td class="num">106.0 W<br>28.72 MH/s<br>0.271 MH/W</td><td class="num">75.6 W at 1,863 MHz, cap 50%<br>28.78 MH/s (none lost)<br>0.381 MH/W</td><td class="num">30 W<br>£0.20 a day at 28p/kWh</td></tr>
</tbody>
</table></div>
<p style="font-size:13px;color:var(--ash);margin-top:8px">The chosen clocks are the floor of the ladder, not the optimum: the next cut's ladder goes lower. The pounds are arithmetic from the saved watts at 28p per kWh; the app uses your price. The RX 9070 XT's run aborted at step 1 on a rule that asked a card reporting offsets for watts, fixed the same hour; its row is owed.</p>
<a class="src" href="/bench">log · 6 Oct 2026, Ember run 6 on PC 1 (job ember-tune-pc1-6, 0.3.13 + kit 6, elevated, one click)</a>
</div>
<div class="feat"><b>Latency work</b><p>A block built on a stale tip earns less. The miner is moving from polling to a template subscription and shorter jobs, so a new tip reaches the card in milliseconds. In progress, no number published yet.</p></div>
<div class="feat"><b>Remote signed jobs, opt in</b><p>Our own fleet only. A switch, "Allow remote jobs from Igneum (signed)", with the key's fingerprint beside it. Off aborts the running job and stops polling. Jobs run at most once each and only on the machines they name.</p></div>
</div>
@ -404,7 +491,7 @@ pre b{color:var(--molten);font-weight:500}
<tbody>
<tr><td><b>1 · Race the compiler every hour</b></td><td>For each new program, five to ten kernel variants are compiled, benched for two seconds each, and the winner is kept for the hour.</td><td>Measured on the Mac's Metal worker: the winning variant +17.3% on the genesis seed and +21.2% on the hourly seed over the base compile, under load from other work. The RTX 5090 race is prepared and not yet run. <a href="/bench#4-october-2026-miner-performance-variant-racing-metal-worker-on-the-m5-max-the-rtx-5090-job-is-ready-not-run">Log, 4 Oct 2026</a></td></tr>
<tr><td><b>2 · Auto-tune that learns from the fleet</b></td><td>Apps report the race per card and program class, and every finished Ember Tune. The best settings come back down through the signed update manifest as defaults, so the miner gets faster and more efficient for everyone as the fleet grows.</td><td>Shipped. The fleet is still small, so no fleet table yet; the priors table on <a href="/miners#priors">/miners</a> fills as machines report.</td></tr>
<tr><td><b>3 · Hash per watt, not hash</b></td><td>Ember Tune: two knobs per card (power limit, core clock), the memory clock held, the point with the best MH per watt within 1% of the top rate kept and pinned. Miners pay for electricity; that is the number they compare.</td><td>Built for NVIDIA (through the driver, with Power control on) and AMD (through the app's own helper, no administrator rights), measure only on Apple silicon. Unit-tested on every rule; the first tune measured on a card is the owed number.</td></tr>
<tr><td><b>3 · Hash per watt, not hash</b></td><td>Ember Tune: two knobs per card (power limit, core clock), the memory clock held, the point with the best MH per watt within 1% of the top rate kept and pinned. Miners pay for electricity; that is the number they compare.</td><td>Measured on PC 1, 6 Oct 2026: an RTX 5090 from 311.0 W to 226.8 W for 0.15% of its rate (0.411 to 0.563 MH/W); an RTX 4070 from 106.0 W to 75.6 W for none (0.271 to 0.381 MH/W). The chosen clocks are the ladder's floor, not the optimum. AMD through the app's own helper, no prompt; Apple silicon measures only. The <a href="#tuning">table above</a>.</td></tr>
<tr><td><b>4 · Template latency</b></td><td>Solo against the local node, a new template within 50 ms of a new tip, because a late block on a BlockDAG goes red and earns nothing.</td><td>Approximate, from the 0.3.6 release plan and not yet in the engineering log: switched p50 46 to 52 ms on a three-node CPU run, 5 Oct 2026. Ships in 0.3.6.</td></tr>
<tr><td><b>5 · Never lose a second</b></td><td>Zero-loss hourly program swaps, fault guards, automatic restart, a CPU re-check of every found hash, per-worker health.</td><td>Shipped. Swap 0.01 ms on Metal and 0.00 ms on CUDA with 0 rejected blocks; recoveries in the <a href="#reliability">table above</a>. <a href="/bench#4-october-2026-first-hourly-program-swap-on-the-live-devnet-compile-ahead-no-pause-two-cards">Log, 4 Oct 2026</a></td></tr>
<tr><td><b>6 · Prove it in public</b></td><td>The bench table per card, fed from the job channel. We claim fastest only when the table says so.</td><td>Live at <a href="/miners">/miners</a>, one row per card, generator version and miner version, each with its log entry.</td></tr>
@ -426,7 +513,7 @@ pre b{color:var(--molten);font-weight:500}
<div class="tbl"><table style="min-width:0">
<thead><tr><th>Where</th><th>Off with</th></tr></thead>
<tbody>
<tr><td>The app, Settings</td><td>the switch beside the rewards address</td></tr>
<tr><td>The app, Earnings</td><td>the Dev fee switch under the money rows</td></tr>
<tr><td>The command line</td><td class="mono">--dev-fee 0</td></tr>
<tr><td>HiveOS, extra config</td><td class="mono">DEV_FEE=0</td></tr>
</tbody>
@ -435,8 +522,8 @@ pre b{color:var(--molten);font-weight:500}
</div>
<div style="display:flex;flex-direction:column;gap:14px">
<div class="card" style="display:flex;flex-direction:column;gap:10px">
<div class="eyebrow">Settings, as the app shows it</div>
<div class="switch"><span class="track"></span><span>Dev fee 1% (1 block in 100)</span></div>
<div class="eyebrow">Earnings, as the app shows it</div>
<div class="switch"><span class="track"></span><span>Dev fee: 1 block in 100 pays the miner software's author</span></div>
<p style="font-size:14px;color:var(--ash)">The miner software's fee, the same way every GPU miner takes one. The protocol takes none. This switch turns it off.</p>
</div>
<div class="card" style="display:flex;flex-direction:column;gap:10px">
@ -459,16 +546,16 @@ pre b{color:var(--molten);font-weight:500}
<p data-devnet-notice style="margin-top:6px;font-weight:600;color:var(--molten)">Devnet: coins have no value and the chain may be reset.</p>
</div>
<div class="cta reveal" style="align-items:center">
<a data-dl="miner-windows" href="https://dl.igneum.network/public/igneum-miner-windows.exe" class="btn primary"><svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor" aria-hidden="true"><path d="M3 5.5l7.5-1v7H3zM11.5 4.3L21 3v8.5h-9.5zM3 12.5h7.5v7L3 18.5zM11.5 12.5H21V21l-9.5-1.3z"/></svg>Windows <span data-dl-meta="miner-windows" style="font-weight:400;opacity:.85">v0.3.13 · 45.4 MB</span></a>
<a data-dl="miner-mac" href="https://dl.igneum.network/public/igneum-miner-mac.dmg" class="btn primary"><svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor" aria-hidden="true"><path d="M16.4 12.6c0-2.3 1.9-3.4 2-3.5-1.1-1.6-2.8-1.8-3.4-1.8-1.4-.1-2.8.8-3.5.8-.7 0-1.8-.8-3-.8-1.5 0-3 .9-3.8 2.3-1.6 2.8-.4 7 1.2 9.3.8 1.1 1.7 2.4 2.9 2.3 1.2 0 1.6-.7 3-.7s1.8.7 3 .7c1.3 0 2-1.1 2.8-2.3.9-1.3 1.2-2.6 1.3-2.6-.1 0-2.5-.9-2.5-3.7zM14.1 5.8c.6-.8 1.1-1.9.9-3-.9 0-2 .6-2.7 1.4-.6.7-1.1 1.8-1 2.9 1.1.1 2.1-.5 2.8-1.3z"/></svg>macOS <span data-dl-meta="miner-mac" style="font-weight:400;opacity:.85">v0.3.13 · 41.9 MB</span></a>
<a data-dl="miner-hive" href="https://dl.igneum.network/public/igneum-miner-hive.tar.gz" class="btn"><svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor" aria-hidden="true"><path d="M12 2c-2.4 0-4 1.9-4 4.6 0 1.2.2 2 0 2.8-.6 1.4-2.1 2.9-2.6 4.9-.3 1.1-.1 2 .3 2.6-.6.4-1.3 1-1.1 1.7.3 1 2.1 1.2 3.2 1.8.7.4 1.5.6 2.1.1.6.2 1.3.3 2.1.3s1.5-.1 2.1-.3c.6.5 1.4.3 2.1-.1 1.1-.6 2.9-.8 3.2-1.8.2-.7-.5-1.3-1.1-1.7.4-.6.6-1.5.3-2.6-.5-2-2-3.5-2.6-4.9-.2-.8 0-1.6 0-2.8C16 3.9 14.4 2 12 2zm-1.4 4.2c.5 0 .8.5.8 1.2s-.3 1.2-.8 1.2-.8-.5-.8-1.2.3-1.2.8-1.2zm2.8 0c.5 0 .8.5.8 1.2s-.3 1.2-.8 1.2-.8-.5-.8-1.2.3-1.2.8-1.2zM12 9.3c.9 0 1.9.5 1.9 1s-1 1.2-1.9 1.2-1.9-.7-1.9-1.2 1-1 1.9-1zm0 3.4c2.2 0 3.6 2.6 3.6 4.4 0 1.5-1.6 2.3-3.6 2.3s-3.6-.8-3.6-2.3c0-1.8 1.4-4.4 3.6-4.4z"/></svg>Linux <span data-dl-meta="miner-hive" style="font-weight:400;opacity:.85">v0.3.13 · 24.6 MB</span></a>
<a data-dl="miner-hive" href="https://dl.igneum.network/public/igneum-miner-hive.tar.gz" class="btn"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round" aria-hidden="true"><path d="M12 2.5l8.2 4.75v9.5L12 21.5l-8.2-4.75v-9.5z"/><path d="M12 7.5l4.3 2.5v5L12 17.5l-4.3-2.5v-5z"/></svg>HiveOS <span data-dl-meta="miner-hive" style="font-weight:400;opacity:.85">v0.3.13 · 24.6 MB</span></a>
<a data-dl="miner-windows" href="https://dl.igneum.network/public/igneum-miner-windows.exe" class="btn primary"><svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor" aria-hidden="true"><path d="M3 5.5l7.5-1v7H3zM11.5 4.3L21 3v8.5h-9.5zM3 12.5h7.5v7L3 18.5zM11.5 12.5H21V21l-9.5-1.3z"/></svg>Windows <span data-dl-meta="miner-windows" style="font-weight:400;opacity:.85">v0.3.14 · 45.4 MB</span></a>
<a data-dl="miner-mac" href="https://dl.igneum.network/public/igneum-miner-mac.dmg" class="btn primary"><svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor" aria-hidden="true"><path d="M16.4 12.6c0-2.3 1.9-3.4 2-3.5-1.1-1.6-2.8-1.8-3.4-1.8-1.4-.1-2.8.8-3.5.8-.7 0-1.8-.8-3-.8-1.5 0-3 .9-3.8 2.3-1.6 2.8-.4 7 1.2 9.3.8 1.1 1.7 2.4 2.9 2.3 1.2 0 1.6-.7 3-.7s1.8.7 3 .7c1.3 0 2-1.1 2.8-2.3.9-1.3 1.2-2.6 1.3-2.6-.1 0-2.5-.9-2.5-3.7zM14.1 5.8c.6-.8 1.1-1.9.9-3-.9 0-2 .6-2.7 1.4-.6.7-1.1 1.8-1 2.9 1.1.1 2.1-.5 2.8-1.3z"/></svg>macOS <span data-dl-meta="miner-mac" style="font-weight:400;opacity:.85">v0.3.14 · 41.9 MB</span></a>
<a data-dl="miner-hive" href="https://dl.igneum.network/public/igneum-miner-hive.tar.gz" class="btn"><svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor" aria-hidden="true"><path d="M12 2c-2.4 0-4 1.9-4 4.6 0 1.2.2 2 0 2.8-.6 1.4-2.1 2.9-2.6 4.9-.3 1.1-.1 2 .3 2.6-.6.4-1.3 1-1.1 1.7.3 1 2.1 1.2 3.2 1.8.7.4 1.5.6 2.1.1.6.2 1.3.3 2.1.3s1.5-.1 2.1-.3c.6.5 1.4.3 2.1-.1 1.1-.6 2.9-.8 3.2-1.8.2-.7-.5-1.3-1.1-1.7.4-.6.6-1.5.3-2.6-.5-2-2-3.5-2.6-4.9-.2-.8 0-1.6 0-2.8C16 3.9 14.4 2 12 2zm-1.4 4.2c.5 0 .8.5.8 1.2s-.3 1.2-.8 1.2-.8-.5-.8-1.2.3-1.2.8-1.2zm2.8 0c.5 0 .8.5.8 1.2s-.3 1.2-.8 1.2-.8-.5-.8-1.2.3-1.2.8-1.2zM12 9.3c.9 0 1.9.5 1.9 1s-1 1.2-1.9 1.2-1.9-.7-1.9-1.2 1-1 1.9-1zm0 3.4c2.2 0 3.6 2.6 3.6 4.4 0 1.5-1.6 2.3-3.6 2.3s-3.6-.8-3.6-2.3c0-1.8 1.4-4.4 3.6-4.4z"/></svg>Linux <span data-dl-meta="miner-hive" style="font-weight:400;opacity:.85">v0.3.14 · 24.7 MB</span></a>
<a data-dl="miner-hive" href="https://dl.igneum.network/public/igneum-miner-hive.tar.gz" class="btn"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round" aria-hidden="true"><path d="M12 2.5l8.2 4.75v9.5L12 21.5l-8.2-4.75v-9.5z"/><path d="M12 7.5l4.3 2.5v5L12 17.5l-4.3-2.5v-5z"/></svg>HiveOS <span data-dl-meta="miner-hive" style="font-weight:400;opacity:.85">v0.3.14 · 24.7 MB</span></a>
</div>
<div class="card reveal" id="hive" style="margin-top:28px;overflow-wrap:anywhere;word-break:break-word;min-width:0">
<div class="eyebrow">HiveOS · Flight Sheet</div>
<h3 style="margin:8px 0 10px">Install on a Hive rig</h3>
<p style="font-size:15px;color:var(--ink-2)">Miner: <b>Custom</b>. Installation URL: <code data-dl-url="miner-hive">https://dl.igneum.network/dl/public/igneum-hive-0.3.13.tar.gz</code>. Miner name <code>igneum</code>, wallet and worker <code>0x&lt;your 40-hex payout address&gt;.%WORKER_NAME%</code>, pool URL <code>grpc://&lt;your node&gt;:26610</code> or <code>local</code> for the bundled node, extra config <code>DEV_FEE=1 IDENTITIES=8 WORKER=auto VOTE=1</code>. The Linux button above is the same archive: the Linux miner, node and both GPU workers. Hive itself is untested so far. Report what breaks.</p>
<p style="font-size:13px;color:var(--ash);margin-top:8px;overflow-wrap:anywhere">sha256 <span class="mono" data-dl-sha="miner-hive" style="word-break:break-all">65ea42600236c7024844d85fc401ef2c4650e671d92061c8db6415038bac9530</span></p>
<p style="font-size:15px;color:var(--ink-2)">Miner: <b>Custom</b>. Installation URL: <code data-dl-url="miner-hive">https://dl.igneum.network/dl/public/igneum-hive-0.3.14.tar.gz</code>. Miner name <code>igneum</code>, wallet and worker <code>0x&lt;your 40-hex payout address&gt;.%WORKER_NAME%</code>, pool URL <code>grpc://&lt;your node&gt;:26610</code> or <code>local</code> for the bundled node, extra config <code>DEV_FEE=1 IDENTITIES=8 WORKER=auto VOTE=1</code>. The Linux button above is the same archive: the Linux miner, node and both GPU workers. Hive itself is untested so far. Report what breaks.</p>
<p style="font-size:13px;color:var(--ash);margin-top:8px;overflow-wrap:anywhere">sha256 <span class="mono" data-dl-sha="miner-hive" style="word-break:break-all">c4699f2487580dcf06b5c22a36a2eb8383a3307b6137699c76c45eefebdd4c88</span></p>
</div>
<p class="pt reveal" style="margin-top:20px">Testnet coin for testing: <a href="/faucet" style="color:var(--ember)">the faucet</a> sends 10 IGN per address per day. Any 4 GB card at launch. The dataset starts at 2 GB and grows (the proposed schedule, fixed at the testnet genesis: 2 GB, doubling at years 4, 12 and 28), so a 4 GB card mines for about four years, approximate. Updates arrive signed; the app installs them itself. The <a href="/wallet" style="color:var(--ember)">wallet</a> reads this machine's node when the miner is installed.</p>
<a href="/litepaper#miners" class="lp reveal">Read more in the litepaper</a>