From 442833d89afe38e45981fb315a45e9e063a2da1a Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Thu, 8 Oct 2026 14:55:58 +0000 Subject: [PATCH] Release manifest and the proving economics: site/release-manifest.json served at /release.json (network and chain id, source commits and fingerprints, mining class and dataset, finality rule v3, proof program ids, verifier off per P21, fees, versions per platform, the proving view, generated date); /build, /economics, /miner, /evidence and the litepaper read it at build through data-rm spans and a gate check holds the pages to it; /light, /receipt and the light client say two thirds of total weight; 4463 marked historical in older docs; dated log entries labelled historical; the evidence page's sixth label (activated) and the reference-repository wording; /economics gains "Who pays for proving": three incomes apart, the burned base fee stated, the measured 24-hour payout, the halving walk computed from emission.mjs at build, per card per hour, the two routes priced, no price Co-Authored-By: Claude Fable 5.1 --- docs/build/build.md | 7 +- docs/design/developer-adoption.md | 2 +- docs/design/execution-layer.md | 2 +- docs/design/phone-app.md | 2 +- docs/evidence.md | 13 +- docs/fork-divergence.md | 2 +- docs/plans/explorer.md | 2 +- docs/provenance.md | 2 +- docs/spec/07-execution.md | 2 +- site/bench.html | 36 ++--- site/build.html | 2 +- site/build.mjs | 47 +++++- site/economics.html | 38 ++++- site/evidence.html | 60 +++---- site/lc/core.js | 4 +- site/lc/verify-receipt.js | 2 +- site/light.html | 2 +- site/litepaper.html | 2 +- site/miner.html | 1 + site/provenance.html | 2 +- site/receipt.html | 2 +- site/release-manifest.json | 243 ++++++++++++++++++++++++++++ site/vercel.json | 4 + tools/ci/checks.txt | 1 + tools/ci/link-check.mjs | 5 +- tools/ci/pre-push.sh | 1 + tools/ci/release-manifest-check.mjs | 50 ++++++ 27 files changed, 456 insertions(+), 80 deletions(-) create mode 100644 site/release-manifest.json create mode 100644 tools/ci/release-manifest-check.mjs diff --git a/docs/build/build.md b/docs/build/build.md index 0a96b7fba..64f153607 100644 --- a/docs/build/build.md +++ b/docs/build/build.md @@ -16,11 +16,12 @@ This file is the source of [igneum.network/build](https://igneum.network/build). | | Devnet 3 | Testnet | Mainnet | |---|---|---|---| -| Chain id | 4464 (`0x1170`) since its class v5 floor on 8 October 2026; 4463 below it | 4462 (`0x116e`) | 4461 (`0x116d`) | -| Network id | `igneum-devnet-3` | `igneum-testnet-1` | not started | -| RPC | `https://rpc.devnet.igneum.network` (a node you run serves `http://127.0.0.1:26790`) | `https://rpc.testnet.igneum.network` (answers; nothing mines there yet, so a transaction waits) | none | +| Chain id | {{rm:network.chain_id}} (`{{rm:network.chain_id_hex}}`) since its class v5 floor on 8 October 2026; 4463 below it | 4462 (`0x116e`) | 4461 (`0x116d`) | +| Network id | `{{rm:network.id}}` | `igneum-testnet-1` | not started | +| RPC | `{{rm:network.rpc}}` (a node you run serves `http://127.0.0.1:26790`) | `https://rpc.testnet.igneum.network` (answers; nothing mines there yet, so a transaction waits) | none | | Coins | no value, resets without notice | no value, resets with notice | not started | | Symbol, decimals | IGN, 18 | IGN, 18 | IGN, 18 | +| Machine-readable | [/release.json](/release.json): the chain id, the source commits and fingerprints, the mining class, the finality rule, the proof program ids, the fee schedule and the current version per platform, with a generated date | | | Devnet 3 is where you build today. It is a developer network: it resets without notice and its coins have no value. Its public RPC takes the read methods, `eth_sendRawTransaction` and a wRPC websocket at `/ws`, at 20 requests a second per address. The public testnet exists, its RPC answers, and no blocks are being produced on it until it opens. Mainnet has no date. Devnet 3 answered 4463 until its class v5 floor at DAA 68,400 on 8 October 2026 and 4464 from it; read it with `eth_chainId` rather than fixing it, since a transaction signed for the wrong id is refused. diff --git a/docs/design/developer-adoption.md b/docs/design/developer-adoption.md index 0acd30303..1d5ebc41e 100644 --- a/docs/design/developer-adoption.md +++ b/docs/design/developer-adoption.md @@ -182,7 +182,7 @@ What a builder expects on day one, what Igneum has, and the order to build the r | Item | Expected | Igneum has | Lacks | Order | |---|---|---|---|---| -| EVM | Cancun, same bytecode | Cancun opcodes, precompiles 0x01 to 0x09, revm 43; chain ids 4461 / 4462 / 4463; viem 2.57 drove deploy, write, read and fee estimation through stock paths | EIP-7702, 0x0a, blobs (by design); the documented differences table of spec 7.1 must be in the developer docs | Docs: 1 | +| EVM | Cancun, same bytecode | Cancun opcodes, precompiles 0x01 to 0x09, revm 43; chain ids 4461 / 4462 / 4463 (historical: Devnet 3 answers chain id 4464 since its class v5 floor at DAA 68,400 on 8 October 2026, 4463 below it; the current id is in /release.json); viem 2.57 drove deploy, write, read and fee estimation through stock paths | EIP-7702, 0x0a, blobs (by design); the documented differences table of spec 7.1 must be in the developer docs | Docs: 1 | | RPC | Full `eth_*`, `debug_*`, `trace_*`, subscriptions | 25 `eth_*` methods, `igneum_getTransactionStatus`, `igneum_getSegment`, `igneum_getBudgets`, `igneum_estimateGas` (both dimensions); HTTP JSON-RPC 2.0 with batches, port 26790 | `eth_getProof`, `eth_subscribe`, `debug_traceTransaction`, `trace_block`, `eth_getUncle*`, `IgneumInfo` (design 10.3 item 7); `pending`, `safe`, `finalized` all resolve to the executed tip | 2 (debug and subscribe are what Blockscout and Foundry's debugger need) | | RPC providers | A public endpoint, then third parties | None public. The devnet is the team's three nodes and a seed | A public devnet RPC with a rate limit; chain-id registration on ethereum-lists/chains before the public testnet (design 8.1) | 3 | | Tooling templates | Hardhat and Foundry work | Designed: templates "ship with the devnet" with the three things to tell a developer (design 8.3) | The templates themselves; a `vm.warp` note (past timestamps rejected) | 1 | diff --git a/docs/design/execution-layer.md b/docs/design/execution-layer.md index f0466d162..3c5034cf9 100644 --- a/docs/design/execution-layer.md +++ b/docs/design/execution-layer.md @@ -461,7 +461,7 @@ Rule change, 4 October 2026 (findings F-exec-A and F-exec-B of the attack suite, | Miner address | Low 20 bytes of the header's `vote_key_hash` (`evm::miner_evm_address`) | The body has no `miner` field yet. A miner that wants to spend its rewards passes `--vote-key-hash 0x000000000000000000000000
` to `igneum-miner`. After the finality branch merges, `vote_key_hash` is the hash of a BLS key, so this rule must give way to the body's `miner` field (10.4) | | Units | 1 sompi = 1e10 wei; 1 IGN = 1e18 wei | Subsidies come from `igneum::block_subsidy` in 8-decimal sompi; the EVM is 18-decimal. The open "8 or 18 decimals" decision is unchanged; this is the fixed scaling at the bridge named there | | Rewards | 80% of every blue block's subsidy to its miner, 20% to the proving pool escrow `0x...0220`, both credited in the segment that merges the block; reds unpaid | Design 4.4, with the pool held in a keyless account until proof records exist | -| Simnet | Devnet block rate and depths (1 BPS, k 18, mergeset 180, merge depth 3,600) with proof of work skipped; chain id 4463 shared with the devnet | A CPU test network of the devnet DAG shape | +| Simnet | Devnet block rate and depths (1 BPS, k 18, mergeset 180, merge depth 3,600) with proof of work skipped; chain id 4463 shared with the devnet (historical: Devnet 3 answers chain id 4464 since its class v5 floor at DAA 68,400 on 8 October 2026, 4463 below it; the current id is in /release.json) | A CPU test network of the devnet DAG shape | | Mempool hold | A transaction stays in every template until a block carrying it is added to the DAG (any block, this node's or a peer's: the executor subscribes to consensus `BlockAdded`); then it is held for 30 s or until the executor removes it (executed) or offers it again (a chain block skipped it); a transaction skipped twice is dropped | Kaspa's own rule (`mining/src/manager.rs`, `handle_new_block_transactions`). Replaced the 4-second hand-out cooldown on 5 October 2026 (fork `tx-gossip`, `pool.rs IN_BLOCK_HOLD`, `service.rs listen_block_added`): the cooldown made a sender mineable 1 s in 5 and inclusion came in 50-s bursts (bench-log, 5 October 2026 afternoon); with the hold a transaction is offered to every template until a block has it | | Reorgs | Post-segment states for the last 64 chain blocks; deeper reorgs replay from genesis | Observed depth on the test network: 1 to 3 with Poisson-paced miners. A fixed per-template hold had made the three stub miners mine in lockstep rounds, and with equal work per block the GHOSTDAG hash tie-break then kept two equal-work chains alive from genesis (flips 48 deep every few seconds); `igneum-miner --hold-ms` is exponential now | | Block tags | `pending`, `safe` and `finalized` all resolve to the executed tip | The virtual's segment is not executed eagerly and no certified checkpoint exists on this branch; the RPC does not pretend otherwise | diff --git a/docs/design/phone-app.md b/docs/design/phone-app.md index 0a3ad7018..05306ace5 100644 --- a/docs/design/phone-app.md +++ b/docs/design/phone-app.md @@ -44,7 +44,7 @@ Full-header mode (spec 10.4 item 6, the lottery verified on the phone) is not in | Key storage | iOS Secure Enclave through the Keychain with device-only, biometric-gated access; Android Keystore with StrongBox when the device has it, else TEE-backed. The signing key for an EVM transaction is secp256k1, which the enclaves do not sign natively, so the private key is wrapped by an enclave key and unwrapped into memory only for the duration of one signature (approximate: the common pattern on both platforms) | Designed | | Seed | BIP-39, 24 words, generated on device; shown once, confirmed by re-entering words in random positions (spec 8.5 item 1's rule for the desktop app, applied here); optional second confirmation after 24 hours | Designed | | Derivation | BIP-44 path `m/44'/coin'/0'/0/n` with Igneum's SLIP-44 coin type; the coin type is unregistered (Open, P1 below) and the app uses Ethereum's 60 until it is, so a seed restored into any Ethereum wallet shows the same addresses | Designed, Open | -| Address | 20-byte EVM address, chain id 4461 / 4462 / 4463 (spec 7.4), EIP-155 signatures, transaction types 0, 1, 2 (design document, execution layer, 1.1) | Designed | +| Address | 20-byte EVM address, chain id 4461 / 4462 / 4463 (spec 7.4) (historical: Devnet 3 answers chain id 4464 since its class v5 floor at DAA 68,400 on 8 October 2026, 4463 below it; the current id is in /release.json), EIP-155 signatures, transaction types 0, 1, 2 (design document, execution layer, 1.1) | Designed | | Gas | One gas limit and one price, as the node quotes them with proving gas folded in (spec 7.1, "quoted gas price"); the app shows the quote and never lets a user set a limit below the estimate | Designed | | Status line | Every transaction shows executed, proven, locked as `igneum_getTransactionStatus` reports them, with the app's own verification state beside it: "locked" is shown only when the engine has verified the certificate that covers the block | Designed | | Backup | None by the project. The app offers no cloud backup of the seed and refuses the platform's automatic keychain sync for the wallet entries; the user writes the words down | Designed (spec 8.5 item 3) | diff --git a/docs/evidence.md b/docs/evidence.md index a1da5c0d7..6c63753f0 100644 --- a/docs/evidence.md +++ b/docs/evidence.md @@ -2,12 +2,13 @@ 4 October 2026. One row per claim the homepage (`site/index.html`) and the litepaper (`site/litepaper.html`) make. Every number here is copied from `docs/bench-log.md`, which names the machine, the date and the command, or from the result files it names; nothing is restated from memory. Where a bench-log figure is approximate, this table says so. -## The five labels +## The six labels | Label | Meaning | |---|---| | designed | A decision in the design document or the specification. No code carries it, or the code is a stub | | implemented | Code exists in this repository with test vectors, and the vectors pass. Not run as a measurement of the claim | +| activated | The code is live on a named chain by its activation height, and a node's own line says so. Not yet a measurement of the claim | | tested by the team | The claim was measured or exercised by the project's own people and agents on a named machine, and the result is in the bench log | | reproduced externally | Somebody outside the project ran the published command on their own hardware and got the published result | | reviewed independently | Somebody outside the project, paid or not, read the code or the rule and published their finding | @@ -18,8 +19,9 @@ Four rules for reading the table: 2. A status applies to the exact version in the row. An audit of one version never covers a newer one; when the version changes, the status falls back to "tested by the team" until the new version is reproduced or reviewed again. 3. "Tested by the team" on one machine is one machine. The rows say which. Discrete AMD, Intel and a 2019-class CPU core have not run anything. 4. The 12-node cloud network of 4 October 2026 (`infra/cloud-devnet`, cloud VMs in five locations) is the project's own. Rows that cite it are tested by the team, not reproduced externally. +5. The labels stay distinct and a claim never moves up a label without the artefact that label names (the table "What would move a row"). The public reference repository exists now (the specifications, the `igneum-pow` crate, the simulators and the test material, at git.igneum.network); the full node, the miner and the proving code open later, so a row that cites them is tested by the team until they do. -Versions in the table: `igneum-pow` is the Rust crate at `igneum-pow/Cargo.toml`, version 0.2.0 since 4 October 2026 (generator version 2; 0.1.0 rows are marked). "Repo" commits are this repository's. "Fork" commits are `vendor/igneum-node` and its worktrees (`-v4`, `-diff`, `-exec`, `-harness`, `-fin-fixes`), which are not in this repository's history; the row names the fork commit or branch as the bench log does. The first devnet is devnet v4 (genesis 10:05 BST, 4 October 2026, branch `devnet-v4`). Devnet 3 (`igneum-devnet-3`, chain id 4463, release 0.3.22) made its first block at 17:06 UTC on 7 October 2026 with every upgrade on from block zero (class v4 sub-version 3, the era VDF, difficulty v2, finality v3, proving v0 and v1, the ladder at rung 0, calibrated fees) and locked its first checkpoint at 19:02 UTC; rows that name the live devnet without a chain are the first devnet's, and Devnet 3 readings are marked. The spec is `docs/spec/` version 0.1. +Versions in the table: `igneum-pow` is the Rust crate at `igneum-pow/Cargo.toml`, version 0.2.0 since 4 October 2026 (generator version 2; 0.1.0 rows are marked). "Repo" commits are this repository's. "Fork" commits are `vendor/igneum-node` and its worktrees (`-v4`, `-diff`, `-exec`, `-harness`, `-fin-fixes`), which are not in this repository's history; the row names the fork commit or branch as the bench log does. The first devnet is devnet v4 (genesis 10:05 BST, 4 October 2026, branch `devnet-v4`). Devnet 3 (`igneum-devnet-3`, chain id 4463 from genesis and {{rm:network.chain_id}} since its class v5 floor at DAA 68,400; node {{rm:source.node.commit}} on {{rm:source.node.branch}}, igneum-pow {{rm:source.pow.commit}}, {{rm:read_at_short}}; the current state is the [release manifest](/release.json), filled at build time) made its first block at 17:06 UTC on 7 October 2026 with every upgrade on from block zero (class v4 sub-version 3, the era VDF, difficulty v2, finality v3, proving v0 and v1, the ladder at rung 0, calibrated fees) and locked its first checkpoint at 19:02 UTC; rows that name the live devnet without a chain are the first devnet's, and Devnet 3 readings are marked. The spec is `docs/spec/` version 0.1. ## The table @@ -38,7 +40,7 @@ Versions in the table: `igneum-pow` is the Rust crate at `igneum-pow/Cargo.toml` | 11 | Hashrate that arrived today has almost no vote: ten days of the whole network's hashrate to reach a third of the weight, twenty for two thirds; 51% never reaches two thirds while honest miners stay | Litepaper Finality; homepage firsts | tested by the team | repo `bbb264a`; `sim/finality_v2.py` | Scenario B of `sim/finality_v2.py`, seeds 7 and 11 | share(t) = (t/30) x a/(1+a) holds to 0.04 points; a renter equal to the whole honest network (a = 1) crosses 1/3 on day 20 and never reaches 2/3; a = 9 crosses 1/3 on day 11.1 and 2/3 on day 22.2. The ten-day figure is a = infinity, honest miners gone. 3 October 2026, Apple M5 Max. A model with 1,000 Pareto keys and no DAG; the live devnet's window is two hours old, so the claim has no live measurement yet | none yet | | 12 | The difficulty rule recovers from a hashrate step within minutes, where Kaspa's sampled rule never settles. A step inside an epoch set the rule oscillating on the live devnet on 4 October 2026; rule v2 removes it in the simulator and on a test network and is built but not yet rolled out | Spec 2.3; litepaper Speed (implied); bench page | tested by the team | repo `e9328c6`, `abb5a5d` (attacks), `67bf226` (rule v2); fork `difficulty` branch (timestamp fix) and `devnet-v4` `a21ff239` (`difficulty_v2_activation_daa`, `REF_WINDOW_V2 = 600`); `sim/difficulty/sim.py --live` | The live record `sim/difficulty/records/live-2026-10-04.csv` (8,090 headers, `pull_live.py`) and the hash-rate record beside it; `sim/difficulty/sim.py` on the synthetic set and the DAG replay; `sim/difficulty/attacks/attacks.py`; `sim/difficulty/testnet_v2.py` (3 nodes, activation at DAA 900); `cargo test --release -p kaspa-consensus --lib difficulty` (15 pass); bench-log "difficulty controller", "difficulty rule under attack", "timestamp attack fixed", "difficulty rule v2" | Live devnet v4, 4 October 2026 (UTC): a second RTX 5090 joining 7 minutes into an epoch (about 152 to 280 MH/s) hardened the difficulty 70M to 144M in 90 s and then swung by about a third for 40 minutes around the true level of 139M while the epoch-long reference lane carried the join; that card leaving for 4 minutes eased 116M to 67M and back to 106M; the epoch boundary with both PCs restarting took 152M to 77M in 3 minutes, after which the rule held within 1.3% per minute with no flips. Cause: the reference lane covered the whole epoch, so a mid-epoch step polluted it for the hour and the 25% trigger flipped on the short lane's noise. The DAG replay reproduces the record (std of log difficulty 0.115 against 0.134, 4.3 peaks against 4). Rule v2 (reference window 600 DAA) on the replay: std 0.026, 0 flips, mean 142.6M against 139M true; on a 3-node test network the v2 nodes eased a leave with no peak and held a rejoin within 3% after 60 s, and a node without the activation height forked off at it as designed. Rule v2 rolled onto the 12-node cloud network on 4 October (all nodes crossed the height on one chain; a hash-rate step then settled in 160 to 270 s with no swing) and activates on the devnet at DAA 33,000 the same evening. Timestamp forging (ledger M23) fixed the same day: a 50% forger drifts the rate under 1.1% where the 3 October rule gave it a 9.9x difficulty. Simulator, settled seconds: x50 step 62 to 66 (Kaspa 1,542), /50 step 657 to 753 (Kaspa 12,296). Apple M5 Max under load 7 to 442; the DAG model is fitted on one scale; the pool hopper's 0.7-point excess over Kaspa's rule stays open | none yet | | 13 | Every node executes the ordered transactions natively and reaches the same state root | Litepaper Proving ("Every node executes ... natively"), Building ("runs on Igneum unchanged") | tested by the team | repo `f5f8c80`, `8dae48b`; fork `devnet-v4` `dc749905`; revm 43.0.3 | `node tools/evm-smoke/smoke.mjs` against a 3-node `igneumd`; `igneum-exec-diff seq.json`; bench-log "execution layer devnet v3" and "devnet-v4 integration" | Simnet, 3 October 2026: 87 of 87 viem checks, state roots identical on 3 nodes at four heights, 57 executed and 19 skipped transactions agree with plain revm, 0 mismatches. Merged node on real proof of work, 4 October 2026: 84 of 85 checks (the miss needs parallel blocks the network did not produce in 36 s), 59 transfers in 10 chain blocks, state roots identical on 3 nodes, `igneum-exec-diff` 0 mismatches over 59 transactions; the live devnet v4 runs this execution layer. Apple M5 Max. The prover is a stub; state is rebuilt from genesis at start; no EVM transaction relay between nodes | none yet | -| 14 | Ethereum bytecode runs unchanged, with the documented differences of spec 7.1 | Homepage Build card; litepaper Building | tested by the team | as row 13; fixes `F-exec-A`, `F-exec-B` (spec 7.5) | `tools/evm-smoke/smoke.mjs`: deploy via viem, `increment`, `hashLoop`, `eth_estimateGas`, `eth_getLogs`; `tools/exec-attacks` scenarios 1 and 3; bench-log "execution layer attack fixes" | Deployment, calls, reverts, logs and gas estimates behave as viem expects; chain id 4463; the prototype pgas table gives 0.0095 to 0.028 pgas per gas, below the design's band before calibration, 3 October 2026. 4 October 2026: a transaction that would cross the block's proving budget is refused by the mempool and, if forced in, aborted and charged with its nonce advanced (25 of 25 checks; 30 of 30 malformed cases). Apple M5 Max. The `Prover` precompile, proof records and the shard planner are not in the node | none yet | +| 14 | Ethereum bytecode runs unchanged, with the documented differences of spec 7.1 | Homepage Build card; litepaper Building | tested by the team | as row 13; fixes `F-exec-A`, `F-exec-B` (spec 7.5) | `tools/evm-smoke/smoke.mjs`: deploy via viem, `increment`, `hashLoop`, `eth_estimateGas`, `eth_getLogs`; `tools/exec-attacks` scenarios 1 and 3; bench-log "execution layer attack fixes" | Deployment, calls, reverts, logs and gas estimates behave as viem expects; chain id 4463 at that version (4464 since the class v5 floor, 8 October 2026); the prototype pgas table gives 0.0095 to 0.028 pgas per gas, below the design's band before calibration, 3 October 2026. 4 October 2026: a transaction that would cross the block's proving budget is refused by the mempool and, if forced in, aborted and charged with its nonce advanced (25 of 25 checks; 30 of 30 malformed cases). Apple M5 Max. The `Prover` precompile, proof records and the shard planner are not in the node | none yet | | 15 | Every block is proven, with the proof landing within about a minute at launch | Homepage stats ("~60 s to a proof"); litepaper Proving; roadmap phase 3 gate | implemented | repo `d7e1f89` (GPU proof), `e01a3cc`, `292e800`, `eedd136` (`proving/igneum-prove`: shard cutter, MPT witnesses, shard and aggregator guests); SP1 6.8.1; spec 7.2, 7.6 | `proving/windows-wsl2` (SETUP-PROVER, PROVE-BLOCK) on the RTX 5090; `igneum-prove-host --mode block` on `proving/fixtures/`; bench-log "proving v0 on the RTX 5090" and "proving: devnet v4 shards" | First GPU proof of an Igneum block, 4 October 2026, RTX 5090 (WSL2, SP1 cuda, mining paused): fixture `block-78-increment` (2 transactions), core proof 1.4 s (7.3 MB, verify 0.221 s), compressed proof 2.7 s (1.27 MB, verify 0.038 s), post-state and receipts roots identical to the node's; 15.7x and 20.6x faster than a loaded M5 Max CPU. The same day on that CPU (load 38 to 47): a three-shard block proved shard by shard and aggregated by recursion, 19 min (1,139 s) end to end, 245 to 337 s per compressed shard proof, every proof verified. What is not there: no proof is produced, carried or checked on the chain (the devnet prover is a stub that signs claims), the proving pool pays nobody (row 21), the block proven is far below one shard, and the 60-second figure remains a design target; the pass mark is the standard in `docs/benchmarks/proving-e2e.md`. Second RTX 5090 run, 4 October 2026 evening (job run-20261004-173115): a full shard at the provisional S_p (6.75 M pgas, 60.8 M cycles) executed in 1.63 s, core proof 8.3 s (18.1 MB), compressed proof 10.9 s (1.27 MB, verify 0.040 s); a two-shard block (13.5 M pgas) proved shard by shard (11.7 s and 10.0 s) and aggregated in 2.2 s, 24 s of GPU stages end to end, every proof verified, six tampered witnesses rejected. The two host defects (an abort after the upload, an idle wait that turned out to be an unbuffered 18 MB proof save through the WSL2 file bridge, 24 minutes) are fixed (ledger P20) 5 October 2026, live devnet with real transactions (bench-log "real transactions, the first non-empty shard proven and paid"): block 72704 shard 0, 29 transfers, 5,800 pgas, proven on PC 2 in 34 s, verified on the Mac in 0.297 s and paid 1.7623 IGN, 53 s after the chain block executed; of about 1,400 blocks in the 20-minute window 36 were proven (the one prover takes the newest shard assigned to it), so "every block" is not yet true; a second content shard (72803, all copies skipped) failed the native-execution veto on the exporter's block structure, fixed with fixtures the same day, the node side pending the 0.3.9 rollout 5 October 2026, evening (bench-log "proving v1"): the aggregated segment record, the chain rule and the unproven rule are implemented behind `proving_v1_activation_daa` (branch proving-v1, not on the devnet before 0.3.11); on the RTX 5090 a chain of 8 consecutive live blocks proved and aggregated by recursion in 135.6 s with the miner on the card (17 s a block, one proof of 1,272,909 bytes attesting all 8, verified in 0.04 s); the 3-node fast-time harness paid a segment record 1.0 s after submission and refused a late one after its deadline (21 checks); the devnet itself, with one prover, carried proofs for 2.4% of blocks over 30 minutes at a block-to-record latency p50 44 s, p99 52 s. The "within about a minute" holds per proven block; "every block" needs 18 mining 5090s or 6 proving-only cards at empty blocks on the measured rates, and the mandatory rule stays off until the share is one | none yet | | 16 | A 12 GB card proves one shard in about 20 s (WITHDRAWN 5 October 2026: a 24 GB card proves a full shard at the adopted size in 4.3 s; 32 GB mines and proves) | Litepaper Proving ("The proving budget"); roadmap gate 2 | designed | spec 5.1 (Target), 7.6 (`S_p` provisional, 7,500,000 pgas = `B_p` / 4) | `PROVE-SHARD.bat` on the RTX 5090 (pending); the end-to-end standard in `docs/benchmarks/proving-e2e.md`; bench-log "proving: devnet v4 shards" | Measured on a 32 GB card, not yet on a 12 GB card. A shard at the provisional `S_p` is 60.8 M SP1 cycles on the prototype pgas table (9 cycles per pgas, 44 per EVM gas; the modexp entry about 100x its SP1 cost); on an RTX 5090 (4 October 2026 evening, job run-20261004-173115) it executed in 1.63 s and its compressed proof took 10.9 s, verified in 0.040 s, so the 32 GB card is inside the 20 s target with margin. Whether a 12 GB card proves it at all, and in what time, is the next measurement (an RTX 3060 and an RTX 5060 Ti 16 GB are on order). A per-shard time can be met by shrinking the shard, so the project does not use it as a pass mark 5 October 2026, evening (bench-log "proving v1", the S_p curve): measured on the RTX 5090 with SP1 6.8.1's GPU prover, the card to itself, 1-s nvidia-smi samples: an empty shard 13,874 MiB and 2.2 s; a full shard at the ADOPTED v1 budget (30,000 pgas, 4.7 M cycles) 20,434 MiB and 4.3 s; the full prototype shard (6.75 M pgas, 60 M cycles) 28,307 MiB and 10.8 s; beside the miner 15,670 and 30,039 MiB. No environment knob of SP1 moves the 13.9 GB floor and the GPU server has no options of its own, so on this build a 12 GB card proves nothing, a 16 GB card only empty shards, a 24 GB card the adopted full shard alone and beside the miner (22,210 MiB and 13.2 s, measured on the 32 GB card: the 5090's allocation pattern, not yet a run on a 24 GB card) and a 32 GB card the prototype shard beside the miner with 2.5 GB spare. The litepaper line now says so; the 12 GB gate returns when a prover build with a smaller floor is measured on a 12 GB card | none yet | | 17 | The chip resistance claim, served as the class v6 close words it: Class v6 adopts the 64-register window and retains it across every rotation. Current modelling places the strongest specialised designs assessed against the GPU tier at about 2.3x to 3.3x energy-efficiency advantage a node ahead (2.0x to 2.9x on the GPU's own node), a bracket that is approximate and provisional until the placed gated core rows land. The long-program and select-tree proposals were rejected. Economic resistance depends on development cost, deployment economics and productive hardware lifetime; family transitions receive an obsolescence benefit only where a loss of competitiveness is demonstrated; programmable multi-epoch designs are included in the assessment. Beside it: class v4 is live from the first block on the testnet and the mainnet; class v5 makes the dataset the chain's state so a stateless or stale chip is wrong on every item; the hot-set cache is bounded at 1.067x at the ceiling and the weak-day FPGA at 12 percent on 15 days a century, both routed to the next class; datacentre silicon does not change the question; the three statements (energy resistance, economic resistance, response capability) are served separate, with the harness and the scoring rule linked | the home page's chip line, the litepaper's chip section (/litepaper#chip-model), the miner page's line | the GPU side tested by the team (the RTX 5080 and RTX 5090 clock-lock passes under class v4, every card, the verifier, the two attack-pass bounds, the H100); the chip core synthesised on ASAP7 and scaled to N3, claimed; the chip's memory modelled; the node column claimed scaling; the economic surface modelled, first cut, conditional; the rotation schedule measured per boundary; class v5 designed; the Antminer X5 an observed comparison, not a ceiling; the X9 a withdrawn pre-order, never benchmarked | `docs/design/class-v6-rotating-family.md` section 10 (10.0 to 10.0h, the close and its two accepted external reviews, 8 October 2026); `docs/design/class-v5-stored-state.md` sections 0, 13 and 14 and `docs/design/class-v5-harness/` (branch class-v5); `docs/design/class-rotation-four-layers.md`; `docs/analysis/chip-model-v3.md` 5 and 6; `docs/analysis/latency-shadow-2026-10-06.md`; `docs/analysis/attack-pass/f8-uniform.md`, `f4-weakday.md`, `docs/analysis/ca3-v4-uniform.md`; the H100 row of 7 October; `docs/plans/cryptanalysis/in-house-pass.md` (the internal adversarial pass) | the scoring rule in the close (the minimum over workloads of the maximum over free adversarial designs of the GPU's joules per hash over the adversary's, under the 10 percent GPU-cost budget at the lock, the verifier limit, cross-vendor correctness and hardware accessibility); the card rows by the benchmark package; the class v5 harness and the family harness; the attack-pass harnesses `tools/attack/f8-uniform` and the F4 census; the verifier by `igneum-pow bench` | 136 MH/s at 350 W (5090, bench) and 290 W (app); the class v4 efficiency passes (bench log "7 to 8 October 2026, the class v4 efficiency passes: the core clock lock on the RTX 5090 and the RTX 5080", measured): the 5090 at 136.84 MH/s and 475.5 W unlocked, 134.98 at 316.3 W at a 1,400 MHz core lock, the best points class v4 at 1,200 MHz (133.80 MH/s, 305.1 W, 0.439 MH/W) and class v3 at 1,300 MHz (134.62, 223.3 W, 0.603), the premium 145 W unlocked and 82 W at the best points, the knee 1,300 MHz; the RTX 5080 (8 October 2026, the dock card of the three-card Windows rig) at 71.41 MH/s and 253.1 W unlocked under class v4 against 71.28 at 169.7 W under class v3, the best points class v4 at 1,100 MHz (71.20 MH/s, 146.6 W, 0.486 MH/W) and class v3 at 1,000 MHz (71.11, 103.7 W, 0.686), the premium 83.4 W unlocked and 41 W at the best points, the knee between 1,000 and 900 MHz; per tier: a 5080 owner on class v4 locked near 1,100 MHz pays 147 W instead of 253 for 0.3 percent less rate, MH per watt up 72 percent, the lever Ember Tune's core-clock knob in 0.3.24; 27 MH/s at 21 W (M5 Max); 249 MH/s (H100 SXM) at 98 percent of its read ceiling, 1.78x hash, 1.15x MH/W, a third per rented dollar; 2.33 ms per warp; the GPU side of the close: the RTX 5080 at its 1,100 MHz lock 2.06 microjoules per hash and the RTX 5090 at its 1,300 MHz lock 2.33 (class v4, 8 October 2026); the modelled bracket about 2.3x to 3.3x a node ahead and 2.0x to 2.9x node for node (approximate, provisional; the clock-gated base core k about 0.37 at N3, the gated window adding about 0.13; the first placed core 64 percent above synthesis), the placed gated row expected near 2.6x to 3.1x and 2.3x to 2.7x and served when it lands; the shadow's premium on a 5090 81.8 W at its knee (class v4 at the 1,200 MHz lock 133.80 MH/s at 305.1 W; class v3 at 1,300 MHz 134.62 at 223.3 W; 7 October 2026); 1.067x at the ceiling; 12 percent on 15 days a century; 10.85 ms at rung 3; 6 to 8 October 2026, the M5 Max, the desk rigs' RTX 5090, RTX 5080, RX 9070 XT and RTX 4070, rented pods, a rented H100 SXM, igneum-build-1 Bitmain's Antminer X9 (RandomX; 1,000 KH/s, 2,472 W, 2.47 J per KH, USD 5,600; pre-orders 26 December 2025) was withdrawn in mid-May 2026 with buyers refunded before any unit shipped, no independent benchmark, commodity Sophgo SG2044 server SoCs with an AES accelerator, no tapeout: it is a precedent on the served pages, not a chip core against the model (attack pass AP-F5-1, 7 October 2026; the close's 10.0f, 8 October 2026). Withdrawn from the served pages on 8 October 2026 and not restated: the 2.1x and 3.4x launch line, the 5x to 9x class v3 baseline, the ladder's 2.8x row, the USD 100 M pay-back row, any chip-arrival probability, the lifetime claim and the USD 300 M and 340 M lines. | none yet; the next test is the internal adversarial pass (three lanes new to the hash code, outsider inputs only, reports published whole), whose floor reading is in (measured, 8 October 2026; ledger AP-F8-1 and AP-F8-6): nine of nine hot sets refused; the diffuse era-stride excess, bounded under 0.1 percent of a hash's reads per site, is not caught by the floor and is the next class's test, and no outside review has run yet | @@ -103,6 +105,8 @@ Versions in the table: `igneum-pow` is the Rust crate at `igneum-pow/Cargo.toml` | Row | Before | After | Why | |---|---|---|---| | 17 | the 5090's efficiency pass | the RTX 5080's clock-lock pass beside it (71.41 MH/s at 253.1 W unlocked, 71.20 at 146.6 W at 1,100 MHz, the premium 83.4 W to 41 W) and the per-tier reading | the bench log's efficiency-passes entry | +| versions | chain id 4463, release 0.3.22 | the chain id at genesis and since the floor, the node, pow and app versions read from the release manifest at build time (/release.json) | an accepted external review: no status page hand-carries a number | +| labels | five labels | six: "activated" between implemented and tested by the team; the reference-repository wording corrected (specs, pow crate, simulators and test material public; node, miner and proving later) | the same review | | 17 | the 2.1x to 3.4x launch line, the 5x to 9x baseline, the 2.8x rung, the USD 100 M pay-back row | the class v6 close's served sentence with the bracket (about 2.3x to 3.3x a node ahead, 2.0x to 2.9x node for node, approximate and provisional until the placed gated core row), the three statements separate, the harness and scoring-rule links, every number labelled | two accepted external reviews of the close (`docs/design/class-v6-rotating-family.md` 10.0f and 10.0g); the lifetime claim and the USD 300 M and 340 M lines withdrawn before they were served | ## What would move a row @@ -111,6 +115,7 @@ Versions in the table: `igneum-pow` is the Rust crate at `igneum-pow/Cargo.toml` |---|---|---| | designed | implemented | Code in this repository with test vectors that pass | | implemented | tested by the team | A bench-log entry with the machine, the date, the command and the number | -| tested by the team | reproduced externally | The repository public (at the public testnet), the command published, and a third party's run with the same result, linked from the row | +| implemented | activated | A node's own start line on a named chain naming the rule and its activation height | +| tested by the team | reproduced externally | The code the row names public in the reference repository (the specifications, the pow crate, the simulators and the test material are; the full node, the miner and the proving code open later), the command published, and a third party's run with the same result, linked from the row | | reproduced externally | reviewed independently | A named reviewer's published finding on that version. Funding for review is `docs/plans/funding.md` | | any | the row's status falls back | A new version of the code or rule the row names | diff --git a/docs/fork-divergence.md b/docs/fork-divergence.md index 76bc20c19..fabc2352f 100644 --- a/docs/fork-divergence.md +++ b/docs/fork-divergence.md @@ -115,7 +115,7 @@ Implements `docs/design/execution-layer.md` D1 to D10 and section 8.2 on a 3-nod | File (vendor/igneum-node-exec/) | What changed | Why | Risk | Upstream-merge note | |---|---|---|---|---| -| `consensus/core/src/evm.rs` (new), `consensus/core/src/lib.rs`, `consensus/core/Cargo.toml` (sha3) | `EvmTransaction = Vec` (raw EIP-2718 bytes), `evm_tx_hash` (keccak256), `evm_chain_id` (4461 / 4462 / 4463, simnet shares the devnet id), `miner_evm_address` (low 20 bytes of `vote_key_hash`), `BLOCK_EXECUTION_GAS_LIMIT` 30 M, `MAX_EVM_BODY_BYTES` 1 MiB, the `EvmTemplateSource` trait | Design D1, D8, 8.1; the devnet rule for the `miner` address until the body carries a 20-byte field | Low | Pure addition. | +| `consensus/core/src/evm.rs` (new), `consensus/core/src/lib.rs`, `consensus/core/Cargo.toml` (sha3) | `EvmTransaction = Vec` (raw EIP-2718 bytes), `evm_tx_hash` (keccak256), `evm_chain_id` (4461 / 4462 / 4463, simnet shares the devnet id) (historical: Devnet 3 answers chain id 4464 since its class v5 floor at DAA 68,400 on 8 October 2026, 4463 below it; the current id is in /release.json), `miner_evm_address` (low 20 bytes of `vote_key_hash`), `BLOCK_EXECUTION_GAS_LIMIT` 30 M, `MAX_EVM_BODY_BYTES` 1 MiB, the `EvmTemplateSource` trait | Design D1, D8, 8.1; the devnet rule for the `miner` address until the body carries a 20-byte field | Low | Pure addition. | | `consensus/core/src/block.rs` | `Block` and `MutableBlock` gain `evm_transactions` (`Arc>` / `Vec`); `Block::new` keeps its signature (empty EVM list), `with_evm_transactions`, `from_arcs_with_evm`; `MutableBlock::set_evm_transactions` recomputes the merkle root and re-finalizes the header | Design D1: EVM transactions in the body | Medium by spread: every `Block {..}` literal in the tree had to name the field (six sites) | Upstream additions of `Block` literals will fail to compile until the field is added; the compiler finds them. | | `consensus/core/src/merkle.rs` | `calc_block_hash_merkle_root(utxo_txs, evm_txs)`: leaves are Kaspa's transaction hashes followed by keccak256 of each raw EVM transaction | Design D7: `hash_merkle_root` is reused as the body commitment and now covers the EVM transactions. With no EVM transactions the root equals Kaspa's, so no genesis hash moved | Low | Pure addition; `calc_hash_merkle_root` is untouched. | | `consensus/src/model/stores/block_transactions.rs` | Stored body is `BlockBody(utxo_txs, evm_txs)`; `get_evm`, `insert_batch` and `insert` take both | One store, one write per body | Low | Database format changed: a node from before this branch must resync. `insert` has one more argument; upstream call sites conflict trivially. | diff --git a/docs/plans/explorer.md b/docs/plans/explorer.md index 53fd65530..e4a650aa8 100644 --- a/docs/plans/explorer.md +++ b/docs/plans/explorer.md @@ -28,7 +28,7 @@ Blockscout indexes through standard JSON-RPC. Its documented requirements (docs. Cost of one instance on Hetzner (the price list the seeds are on, `docs/plans/seed-nodes.md`: cx23 2 vCPU 4 GB at USD 6.49 net a month; larger types not priced here): Blockscout's own AWS example is 4 vCPU 16 GB plus a 2 vCPU 8 GB database. The matching Hetzner shape is one box in the 8 GB to 16 GB class plus Postgres on the same box for a devnet, a second box for the database when the chain carries real traffic. Price it from the Hetzner API when the box is ordered; the figure here is approximate: USD 15 to 40 a month for the single box, under USD 80 for two. Plus an Igneum node on the same box or next to it (Blockscout wants a local, unlimited RPC; the public `rpc.testnet.igneum.network` is rate limited to 20 req/s, `docs/plans/testnet-go.md`). -What it costs in work, in hours not weeks: the two missing `eth_` methods (small, same shape as their by-number siblings); a decision on tracing (the `debug_` namespace with revm inspectors, design 8.2, is the larger piece and is not needed to run Blockscout without internal transactions); Blockscout's env file and a Docker compose on the box; the chain's entry in its config (chain id 4463 devnet, 4462 testnet, 4461 mainnet, design 8.1); contract verification through Sourcify or Blockscout's own verifier microservice. +What it costs in work, in hours not weeks: the two missing `eth_` methods (small, same shape as their by-number siblings); a decision on tracing (the `debug_` namespace with revm inspectors, design 8.2, is the larger piece and is not needed to run Blockscout without internal transactions); Blockscout's env file and a Docker compose on the box; the chain's entry in its config (chain id 4463 devnet, 4462 testnet, 4461 mainnet (historical: Devnet 3 answers chain id 4464 since its class v5 floor at DAA 68,400 on 8 October 2026, 4463 below it; the current id is in /release.json), design 8.1); contract verification through Sourcify or Blockscout's own verifier microservice. ## 3. What Igneum needs that must be ours diff --git a/docs/provenance.md b/docs/provenance.md index 788320fd3..2b8fda547 100644 --- a/docs/provenance.md +++ b/docs/provenance.md @@ -21,7 +21,7 @@ How to read the licence column. "Verified" means the LICENSE file or the crate's | BLS12-381 | Curve by Barreto, Lynn and Scott; blst by Supranational. Licence approximate: Apache-2.0. https://github.com/supranational/blst (not yet cloned) | Unchanged, credited. The header carries the BLAKE2b hash of a G1 compressed public key (48 bytes); every voter signs every 30-s checkpoint; signatures aggregate | Finality rule v2 needs one aggregate signature per checkpoint from thousands of keys | Spec section 3.1 (W1) and 2.4; `sim/results_v2.md` for the rule itself. Signature cost not yet measured | | Hashing in the node | rusty-kaspa `crypto/hashes`, ISC, verified. Crates linked by the fork, licences read from the local cargo registry: blake2b_simd 1.0.2 (MIT), blake3 1.8.3 (CC0-1.0 or Apache-2.0), sha2 0.10.8 (MIT or Apache-2.0), keccak 0.1.6 (Apache-2.0 or MIT); sha3 0.10.8 not in the local registry, approximate: MIT or Apache-2.0 | Unchanged, credited. BLAKE2b with domain separation for block, transaction and PoW pre-hashes (`BlockHash`, `TransactionHash`, ...), BLAKE3 keyed for the sequencing-commitment and payload hashers, SHA-256 for ECDSA signing hashes, cSHAKE256 (Keccak) in the kHeavyHash stub that stays as the default engine and for pruning-proof block levels | The chain's hash for everything except the lottery is the one the forked commit uses (spec 0.6), so nothing unverified enters consensus | `hash_override_nonce_time` gained one field (fork-divergence row 1); every header-hash test vector was regenerated and the four genesis hashes re-derived | | Address format | Bitcoin BIP 173 character set (bech32, Pieter Wuille and Greg Maxwell; BIP licence approximate: BSD-2-Clause) with the CashAddr polymod checksum of Bitcoin Cash (the source cites bch.info), as implemented in rusty-kaspa `crypto/addresses/src/bech32.rs`, ISC, verified | Prefixes only: `igneum`, `igneumtest`, `igneumsim`, `igneumdev` (Kaspa: `kaspa`, `kaspatest`, `kaspasim`, `kaspadev`). The script public key behind an address is unchanged | No Igneum address string may parse as a Kaspa address on any network | Fork-divergence row 9; test vectors in `addresses` and `txscript` regenerated and passing | -| The EVM | Ethereum (Yellow Paper and ethereum/execution-specs, CC0 approximate). Cancun opcode set, precompiles 0x01 to 0x09 | Semantics on a DAG: `block.number` is selected-chain height, `block.timestamp` is non-decreasing by a max rule, `prevrandao` is the VDF epoch seed, chain ids 4461, 4462, 4463; 0x0a absent; gas has a second dimension | Blocks on a DAG have no single parent and no header state root; proving cost is a second resource; the random beacon must be unbiasable | Spec section 7.1 (normative table); devnet measurement R9 for timestamp drift; `ethereum/tests` replay in the differential plan | +| The EVM | Ethereum (Yellow Paper and ethereum/execution-specs, CC0 approximate). Cancun opcode set, precompiles 0x01 to 0x09 | Semantics on a DAG: `block.number` is selected-chain height, `block.timestamp` is non-decreasing by a max rule, `prevrandao` is the VDF epoch seed, chain ids 4461, 4462, 4463 (historical: Devnet 3 answers chain id 4464 since its class v5 floor at DAA 68,400 on 8 October 2026, 4463 below it; the current id is in /release.json); 0x0a absent; gas has a second dimension | Blocks on a DAG have no single parent and no header state root; proving cost is a second resource; the random beacon must be unbiasable | Spec section 7.1 (normative table); devnet measurement R9 for timestamp drift; `ethereum/tests` replay in the differential plan | | kHeavyHash (kept as a stub) | Kaspa, rusty-kaspa `crypto/hashes/src/pow_hashers.rs` and `consensus/pow/src/matrix.rs`, ISC, verified | Kept untouched as `HeavyHashEngine`, the default engine when the `igneum-pow` feature is off, and the block-level source for pruning proofs until seeds are threaded through | Lets the devnet run and lets upstream pow changes merge cleanly | Fork-divergence rows 14 and 15; open item in the same file (pruning-proof block levels) | ## What is new in Igneum diff --git a/docs/spec/07-execution.md b/docs/spec/07-execution.md index 7ac8c99ce..3ee48cf76 100644 --- a/docs/spec/07-execution.md +++ b/docs/spec/07-execution.md @@ -57,7 +57,7 @@ Nothing in consensus changes for any of this: the segment claim already commits | Parameter | Value | Label | |---|---|---| -| Chain id | 4461 / 4462 / 4463 (mainnet / testnet / devnet) | Designed | +| Chain id | 4461 / 4462 / 4463 (mainnet / testnet / the shared devnet); Devnet 3 answers 4464 since its class v5 floor at DAA 68,400 (8 October 2026) and 4463 below it, the id a function of the block's DAA score | Designed; the Devnet 3 value measured (the current id is in /release.json) | | BLOCKHASH reach | 256 chain blocks | Designed (Ethereum's) | | PREVRANDAO source | 10-minute epoch VDF output, keccak256 with the chain height | Designed | | Opcode set, precompiles | Cancun; 0x01 to 0x09 | Designed | diff --git a/site/bench.html b/site/bench.html index 2747a3845..25f36fa25 100644 --- a/site/bench.html +++ b/site/bench.html @@ -246,20 +246,20 @@ table{min-width:560px}

Igneum bench log

Append-only. Every number here was measured on the machine named, on the date given.

-

2026-10-03 proto-metal / igneum-bench, first run

+

2026-10-03 proto-metal / igneum-bench, first run

Historical record of 2026-10-03: the code and the chain as they stood that day. The chain's current state is the release manifest.

Machine: Apple M5 Max, 40 GPU cores, 64 GB unified memory, macOS Darwin 25.6.0, Swift 5.8.1, Metal 4. Build: swiftc -O -o igneum-bench main.swift -framework Metal. Source: proto-metal/main.swift. Setup: 1 GiB dataset (2^28 uint32), 64 instructions x 8 iterations, threadgroup 32 (threadExecutionWidth 32), 4 timed batches x 2^22 nonces after one warm-up batch. Verification: 3 warps per program, CPU interpreter vs GPU.

SeedLoads/hashCompile msMhash/sGB/s usefulCPU verify ms/warpVerify
igneum-genesis10449.6 (cold)45.218.80.015PASS
igneum-genesis/epoch110420.348.420.10.019PASS
igneum-second-seed10446.6 (cold)35.514.80.016PASS
igneum-second-seed/epoch114418.735.420.40.017PASS
igneum-hourly12852.0 (cold)36.618.70.021PASS
igneum-hourly/epoch112821.637.519.20.017PASS
igneum-hourly/epoch212023.736.617.60.016PASS

Dataset size sweep (seed igneum-genesis): 4 MiB 569 Mhash/s, 64 MiB 183, 256 MiB 94, 512 MiB 69, 1 GiB 44. Dataset fill 1 GiB: 2.34 ms GPU time (427 GB/s) warm, 5.57 ms on first run of a process. Result: 21 warps, 672 hashes, zero mismatches. OVERALL PASS. Reading: memory bound at 1 GiB (12.8x drop from cache-resident), limited by random access rather than bandwidth, CPU verify roughly 250x under the 10 ms gate with a cheap dataset element. Apple silicon only. Details in proto-metal/README.md.

-

2026-10-03 proto-cuda / program pack export (Apple M5 Max side only; RTX 5090 run pending)

+

2026-10-03 proto-cuda / program pack export (Apple M5 Max side only; RTX 5090 run pending)

Historical record of 2026-10-03: the code and the chain as they stood that day. The chain's current state is the release manifest.

Machine: the same Apple M5 Max. No CUDA toolchain exists on it, so nothing below is an NVIDIA measurement. Added --export-pack <dir> to proto-metal/main.swift. It writes, per seed, the CUDA kernel (kernel.cu), C headers (program.h, vectors.h), JSON twins, and the Metal source, into proto-cuda/packs/<seed>/. Vectors: 3 warps (base nonces 0, 4096, 1000000), 96 x 64-bit outputs from the CPU interpreter, plus dataset words 0..15 and word [MASK]. The exporter runs the Metal kernel for the same warps and refuses to write unless all 96 match.

PackLoads/hashOp mixCPU interpreter vs Metal GPU (3 warps)CUDA text in CPU emulation (clang, 32 threads/warp)
igneum-genesis104load=13 xor=13 sub=7 shfl=6 add=5 mulhi=5 mad=4 rotr=4 mul=3 rotl=3 or=1PASS 3/3PASS: dataset self-test, 3/3 warps standalone, warps 0 and 4096 in batch at 1 and 2 warps/block
igneum-hourly128load=16 add=8 xor=7 mad=5 mul=5 mulhi=5 shfl=5 rotl=4 or=3 rotr=3 sub=3PASS 3/3PASS: dataset self-test, 3/3 warps standalone, warps 0 and 4096 in batch at 1 warp/block

Sweep sizes 4, 64, 256, 512 MiB in the emulation: dataset self-test PASS at each (vectors only apply at 1 GiB). The regular Metal bench was re-run after the change: igneum-genesis 44.8 Mhash/s and igneum-hourly 36.3 Mhash/s at 1 GiB with 2 x 2^20 batches, PASS 3/3 warps each (consistent with the first-run table above, not a new figure). Harness: proto-cuda/host.cu, build.sh, build.bat, README.md, CHECKLIST.md, emu/. Pending: build and run on the project's RTX 5090 (CUDA 12.8 or newer, -arch=sm_120). No NVIDIA hash rate exists yet. Emulation rates are not recorded because they measure the Apple M5 Max's CPU, not a GPU.

-

2026-10-03 sim/finality_sim.py, sustained-mining finality vote weight (model, not hardware)

+

2026-10-03 sim/finality_sim.py, sustained-mining finality vote weight (model, not hardware)

Historical record of 2026-10-03: the code and the chain as they stood that day. The chain's current state is the release manifest.

Model: 1 day steps, 86,400 Poisson blocks/day, 1,000 Pareto honest keys (top key 17%), perfect retarget, every block blue, no latency, no VRF noise. Seed 7, seed 11 agrees. Rule: weight = 30-day sum of counted blocks, counted = min(actual, 2 x yesterday + f). Lock at 2/3 of total. Floors f in {1, 10, 100, 1000}. A: weight tracks hashrate at steady state (corr 1.00000); full weight from zero history on day 41 (f=1) to 32 (f=1000). B: 60% renter on one key takes 59.9% of rewards on day 1, crosses 1/3 of weight on day 20 to 26, 50% on day 27 to 34, never 2/3. 75% renter reaches 2/3 on day 29 to 34, day 27 with the cap removed. C: splitting defeats the cap. 10,000 fresh keys at f=1 move the 50% crossing from day 34 to 27 (no-cap figure 26); at f=10 they match no-cap exactly. The 30-day trickle buys 2 more days for 11.6% of the network. D: honest doubling is under-weighted 28 to 31 days; old miners lock alone for 20 to 23 days. E: 30% churn leaves 71% live, lock never lost. Threshold is 1/3: 35% stalls 1 day, 50% stalls 10 to 11 days. Active-24h total removes every stall. F: 51% patient owner holds 51.0% weight from day 45, vetoes from day 7 to 20, never locks alone. 67% owner locks alone from day 34 to 44. Recommend: f=1, cap 2x, window 30 (the window is the defence, the cap is worth 1 to 8 days), total = all keys with weight in the window. Details in sim/results.md.

-

2026-10-03 proto-metal hardening tests (correctness and soundness of the lottery hash, Metal only)

+

2026-10-03 proto-metal hardening tests (correctness and soundness of the lottery hash, Metal only)

Historical record of 2026-10-03: the code and the chain as they stood that day. The chain's current state is the release manifest.

Machine: the same Apple M5 Max. Added --fuzz, --edge, --stats, --determinism, --memcheck, --inline-dataset to proto-metal/main.swift. Full tables and commands in proto-metal/TESTS.md. Fuzz: 10,200 random programs (200 + 10,000, cold compiles 13.6 to 48.5 ms), 4 random full-range warps each, dataset drawn from 64 MiB / 256 MiB / 1 GiB: 40,800 warps, 1,305,600 hashes, 0 mismatches, 0 compile failures, 0 static mask failures, generator contract (rotl 1..31, mask in {1,2,4,8,16}, src != dst) held on every instruction. 196 s for the 10,000 run. Edge: 14 hand-built cases (rotr by register 0 / 32 / -32 / 31 / 63, rotl 1 and 31, mulhi max operands, shfl masks 1..16, loads at index 0 and MASK via in-range and out-of-range registers, add/sub/mul/mad wraparound, zero loads, 64 loads) with operand values proven by a traced interpreter: 14/14 PASS, 128/128 lanes each. rotl by 0 (never generated) agreed too, recorded as informational only. Stats (3 seeds, 2^20 nonces each): bit frequency max deviation 2.90 sigma over 192 bit positions; avalanche 16,000 flips mean 31.99 to 32.04 (expect 32), std 3.98 to 4.01 (expect 4), every output bit flips with probability 0.490 to 0.508; chi-square on four 16-bit windows all within 2.3 sigma; 0 duplicates. Looks uniform. Not a security proof. Determinism: 5 runs and 3 compiles (one forced cold, 30 ms) of 2^20 hashes gave fingerprint 933787e8cfefccb7 every time; dataset fill deterministic (0b1a77899ee60493 twice) and 4,096 sampled words incl. 0 and MASK match the CPU closed form. Memcheck: every dataset[ in the MSL is dataset[rN & MASK] (13/13 at 3 sizes), CUDA twin 13/13 plus one guarded fill write; 4 MiB run with nonces up to 0xffffffff completed and 4 wrapping warps matched the CPU; 416/416 load indices exceeded MASK before masking. Bench re-run after the changes: igneum-genesis 44.56 Mhash/s, epoch1 47.74 Mhash/s at 1 GiB, PASS 3/3 warps each (within 2 percent of the first-run table). --export-pack igneum-genesis re-run is byte-identical to the existing pack. SHORTCUT MEASURED: --inline-dataset replaces every load with the six-op closed form ds_elem and never reads memory: 4,888 Mhash/s wall (6,274 GPU time) vs 44.6 honest at 1 GiB, about 110x, and about 9x the cache-resident honest rate. With a closed-form dataset the hash is not memory-hard; an expensive dataset derivation is required, not optional. Not demonstrated: cryptographic strength, weak-program frequency and rejection, NVIDIA/AMD bit-exactness (CUDA run still pending), CPU verify gate with an expensive dataset element. Next three tests for the cryptographer are listed in TESTS.md section 8.

3 October 2026, RTX 5090 first run (an RTX 5090 on Windows, CUDA 12.8 runtime, driver 13.4, Visual Studio 2026 with the 14.30 toolset selected via vcvarsall -vcvars_ver=14.30)

@@ -272,23 +272,23 @@ table{min-width:560px}

Second program igneum-hourly (128 loads per hash): 96/96 vectors PASS, 185.3 Mhash/s at 1 GiB, 23.7 G random loads/s.

Reading: the 5090 carries 96 MiB of L2. At 4 and 64 MiB the dataset sits inside it and the program runs about 5.8x faster than at 1 GiB. Past the L2 the rate settles at about 23.7 G random loads/s for both programs regardless of loads per hash (104 vs 128 loads gives 228 vs 185 Mhash/s, proportional), so the program is random-access bound once the dataset exceeds on-chip cache. Each 4-byte random load moves a 32-byte sector, so DRAM traffic is roughly 760 GB/s, approximate, against a quoted peak near 1.8 TB/s for this card. Design consequence: the dataset must stay well above any plausible on-chip cache, which the 2 GB genesis size and the growth schedule provide; a chip would need gigabytes of on-chip memory to escape the random-access limit. Still prototype numbers: dataset derivation remains closed-form until the 256 MB cache construction lands.

-

2026-10-03 sim/finality_v2.py, finality rule V2 with latency, partitions and eclipses (model, not hardware)

+

2026-10-03 sim/finality_v2.py, finality rule V2 with latency, partitions and eclipses (model, not hardware)

Historical record of 2026-10-03: the code and the chain as they stood that day. The chain's current state is the release manifest.

Model: 30-s slots, Poisson(30) blocks/slot, 1,000 Pareto honest keys in 3 regions (45/35/20), 2-s inter-region delay (0.5 and 5 swept), uptime 97% (99.5% for pools over 1%), warm 30-day start for B to G. Seed 7, seed 11 agrees on B and E. Run time 5 min. Details in sim/results_v2.md. Rule: weight = flat 30-day blue blocks, dust 100, checkpoint per 30 blocks, lock at 2/3 of ACTIVE (participation over 240 checkpoints) vs TOTAL weight. A: weight = hashrate (corr 1.00000), full weight day 30, all keys over dust by day 20, lock median 2.5 s / p99 4.6 s at 2 s delay, 14 s max at 5 s, 0 stalls in 60 days except 17 at genesis. B: share(t) = (t/30) x a/(1+a) holds to 0.04 points; 1/3 crossed at day 20.0 / 15.0 / 12.5 / 11.1 and 2/3 at never / 30.0 / 25.0 / 22.2 for a = 1 / 2 / 4 / 9; dust hands a 9x renter 1.3 extra points. C: silent set that keeps mining: active recovers in 0 / 13 / 20 / 29 / 38 min at 34 / 40 / 45 / 50 / 55%; total never (silent weight never ages out). D: churn: active 2 min (35%) and 31 min (50%); total 41 h and 10.1 days. E: active FAILS the partition test: 50/50 honest split, no attacker, both sides lock after 60 min (30 with DAA retarget), 60/40 after 121 min; first-lock time = presence x (1 - 1.5 s)/s slots, confirmed. Total: 0 conflicts in every honest partition. 34% attacker breaks every variant at 50/50 (67% per side). F: delayed eclipse of a 20% pool is harmless (participation 0 after 2 h, back in 2 h, 0 conflicts); a 34% attacker poisoning that pool finalises a private fork in 49 min under active, never under total. Floor hybrid: active denominator never below 0.85 x total (lock needs 56.7% of total) gives 0 conflicts in every partition and eclipse, recovers in 0 / 13 min at 34 / 40% silent and 2 min at 35% churn; costs 4.1 days at 50% churn and liveness ends near 42% silent. Floor 0.80 does not stop the eclipse (54% > 53.3%). Recommend: active/cert + floor 0.85, presence 240, dust 100, quorum 2/3, grace at least 3x worst delay. Not modelled: real GHOSTDAG merge and post-heal fork choice, DAA lag, VRF aggregators, certificate revocation.

-

2026-10-03 proto-metal memory-hard dataset (cache + 8 dependent reads), Metal only; CUDA pack emulated

+

2026-10-03 proto-metal memory-hard dataset (cache + 8 dependent reads), Metal only; CUDA pack emulated

Historical record of 2026-10-03: the code and the chain as they stood that day. The chain's current state is the release manifest.

Machine: the same Apple M5 Max (one performance core for the CPU figures). Construction, every table and the commands are in proto-metal/MEMHARD.md. Default dataset is now memory-hard; --closed-form keeps the original for comparison. Construction: 256 MiB cache = 2^22 lines of 64 B in 2^16 chains of 64 ChaCha12 blocks with feed-forward (in_j = prev ^ (sigma || K[8] || seg || j || tag)); item t = 16 words, 8 rounds of (seed-parameterised ARX-multiply mixer, read cache line s[0] & (2^22-1), xor) plus a final mixer; dataset[w] = item(w >> 4)[w & 15]. Hash kernel unchanged. Cache fill: 2.0 ms GPU (0.6 to 2.1 across runs), 185 ms one CPU core (Swift), 162 ms C++ host reference. Dataset build 1 GiB: 20.6 ms GPU (29.4 first in process), 814 M items/s, 6.5 G cache-line reads/s. GPU cache == CPU cache on all 2^26 words every run (FNV-1a 64 48c4f5bf24166b2e for day 2026-10-03). Shortcut ratio, seed igneum-genesis, 1 GiB: honest 45.2 Mhash/s in both constructions. Inline kernel (never reads the dataset): closed form 5,014 Mhash/s (111x FASTER than honest); memory-hard 9.49 Mhash/s (0.21 of honest, 4.8x SLOWER). At a 256 MiB dataset: honest 94.8, inline 9.48 (0.10). CPU verify per 32-lane warp (holds only the cache, derives every word on demand, 32 lanes interleaved): 0.649 / 0.631 / 0.701 ms for igneum-genesis, /epoch1, /epoch2 (104, 104, 112 loads; 3,328 to 3,584 items); 0.801 ms igneum-second-seed (104 loads); 1.205 ms igneum-second-seed/epoch1 (144 loads, 4,608 items). Cold single warps 1.16 to 2.11 ms. Closed form was 0.017 ms. 10 ms GATE MET, margin about 8x steady. Levers (implemented, measured, OFF by default; default generator unchanged): (a) --load-weight 17: 72 to 80 loads/hash, CPU 0.457 to 0.512 ms/warp, GPU 55.0 to 73.4 Mhash/s. (b) --wide-frac 50 (warp-coalesced 128 B loads): CPU 0.233 to 0.489 ms/warp, GPU 56.1 to 135.2 Mhash/s and useful bandwidth up to 56 GB/s, so (b) erodes the random-access bound. (a)+(b): CPU 0.223 to 0.276, GPU 106 to 139. Recommendation: no lever; (a) is the fallback if a slower verifier ever threatens the gate; (b) not recommended. Tests re-run on the new dataset: fuzz 200/200 (800 warps, 25,600 hashes, 0 mismatches, CPU interpreter 1.23 s), edge 14/14, determinism PASS (fingerprint 62a4f0eb018df273), memcheck PASS, stats PASS (3 seeds, no obvious bias). 3 warps x 3 seeds bit-exact in the bench run. CUDA: new pack proto-cuda/packs/igneum-genesis-mh (kernel.cu with cache-fill and build kernels, memhard.h shared by device and host, vectors incl. cache head/last/FNV and 64 sampled words). host.cu handles both modes; old packs unchanged (closed-form export re-run is byte-identical in kernel.cu and program.metal). clang emulation (emu/emu.sh igneum-genesis-mh): cache check PASS (all words, FNV == Mac), dataset self-test PASS at 1 GiB, 3/3 vectors standalone and 2/2 in batch at 2 warps/block. RTX 5090 and AMD runs of this pack PENDING; no NVIDIA figure for the memory-hard dataset exists. Not demonstrated: cross-vendor results for the new dataset; the shortcut ratio on a discrete GPU; time-memory trade-offs between the two measured points; cryptographic strength of the mixer and the chained cache; distinct-lines-per-hash census.

-

2026-10-03 rusty-kaspa base build and 3-node devnet on the Apple M5 Max (consensus-engineer, pre-fork proof)

+

2026-10-03 rusty-kaspa base build and 3-node devnet on the Apple M5 Max (consensus-engineer, pre-fork proof)

Historical record of 2026-10-03: the code and the chain as they stood that day. The chain's current state is the release manifest.

Machine: Apple M5 Max (18 CPU cores), 64 GB, macOS 26.6.2. Toolchain: Homebrew rust 1.69.0 was too old (repo needs 1.91.0), so rustup 1.29.1 was installed non-interactively and gives rustc 1.99.0 and cargo 1.99.0; protobuf 36.2 added via brew install protobuf (protoc was missing); Apple clang 14.0.3 already present. Nothing else was needed. Source: vendor/rusty-kaspa at commit 01b532e8b553523216471682649693af92f0fd16 (v2.1.0, 2026-09-22). cargo build --release --bin kaspad: 2 min 36 s cold, binary 35,405,104 bytes (34 MB), 131 compiler warnings, zero errors. Devnet: three kaspad --devnet --nodnsseed --disable-upnp --enable-unsynced-mining --yes --loglevel=info nodes, separate --appdir, P2P 16611/16621/16631, gRPC 16610/16620/16630, nodes 2 and 3 --connect to node 1 (node 3 to node 2 never came up because both started at once, so the topology was a star through node 1). Network params: 10 BPS (100 ms blocks), GHOSTDAG k 124, merge depth 36,000 blocks, finality depth 432,000, pruning depth 1,080,000, DAA window 661 samples x 40 blocks, genesis bits 0x1e21bc1c (about 248,663 hashes per block). Miner: kaspad ships none, so a 150-line CPU miner on kaspa-pow::State (real kHeavyHash, 16 threads, 300 ms template refresh) submitted to node 1 only: 27.2 MH/s sustained, 5,718 blocks in 180 s, 0 rejected. Blocks per second over the 180 s run: 31.76 on all three nodes (1,691 to 7,409 blocks each). Two phases: 56 to 62 blocks/s while difficulty sat at genesis (first 6,000 blocks, min window 150 samples), then the DAA raised difficulty to 1.12 M at block 6,018 and the rate fell to 14 to 15 blocks/s, still converging toward the 10 BPS target when the run ended. Propagation: block counts, DAA scores and sink hash were identical on all three nodes at 18 of 19 ten-second samples; the one miss was node 2 trailing by a single block for one sample. Tips stayed at 1 because a single serial miner never produced parallel blocks, so GHOSTDAG k was not exercised; a second miner is the next step for that. Earlier 30 s warm-up run: 1,690 blocks, 56.3 blocks/s on all three nodes, 28.1 MH/s. Fork points mapped with line numbers in docs/fork-map.md (hash, coinbase, DAA, header, depth constants, BPS and k). All nodes stopped at the end. Miner source kept outside the repo (scratchpad); re-create from testing/integration/src/common/utils.rs:271 if needed.

3 October 2026, RTX 5090, memory-hard dataset (pack igneum-genesis-mh)

CheckResult
256 MiB cache, GPU vs host, all 67,108,864 wordsPASS, FNV-1a 48c4f5bf24166b2e matches the Apple M5 Max
Cache fill0.67 ms GPU, 223 ms one host thread
Dataset build from the cache, 1 GiB13.4 ms, 1,253 M items/s
Vectors, 3 warps, standalone and in batch96/96 PASS
Hash rate at 1 GiB228.95 Mhash/s, 95.2 GB/s useful, 23.8 G random loads/s

Reading: the memory-hard construction is now bit-exact across Apple Metal, NVIDIA CUDA and the CPU reference, cache and dataset included. Hash rate is unchanged from the closed-form dataset on both vendors, as expected, since the hash kernel only loads; what changed is that computing items on the fly is now slower than loading them (4.8x slower measured on Apple, not yet measured on NVIDIA). Still unmeasured: the inline shortcut ratio on NVIDIA, and AMD on any dataset.

-

2026-10-03 proto-vdf, Wesolowski VDF between the certified checkpoint and the program seed (epoch 10 min, era 1 h)

+

2026-10-03 proto-vdf, Wesolowski VDF between the certified checkpoint and the program seed (epoch 10 min, era 1 h)

Historical record of 2026-10-03: the code and the chain as they stood that day. The chain's current state is the release manifest.

Machine: Apple M5 Max (18 logical cores), rustc 1.69.0, GMP 6.3.0 via rug 1.19. Source proto-vdf/, details in proto-vdf/README.md. Single core sequential squaring unless stated. Rates: class group 1024-bit prime discriminant (production choice, chiavdf construction, NUDUPL/NUCOMP ported from vendor/chiavdf) 163,000 sq/s; class group 2048-bit 83,500 sq/s; RSA-2048 trusted-setup stand-in (public trapdoor, timing only) 1,257,000 sq/s. T for 10 min / 60 min on this core: class 1024: 98.0 M / 588 M; class 2048: 50.1 M / 301 M; RSA-2048: 754 M / 4.53 G. Full 10-min runs: RSA T=756,516,411 eval 607.1 s (1,246,000 sq/s), prove 9.0 s on 12 threads (71.2 s on 1), verify 0.88 ms, proof 512 bytes. Class 1024 T=97,126,043 eval 585.4 s (165,900 sq/s, the RSA run sharing the chip ended midway), prove 9.1 s on 12 threads (56.8 s on 1), verify 4.47 ms, proof 516 bytes. Prover costs 12 to 13 percent of eval single-threaded (12-bit digits, at most 65,536 checkpoints, 17 MB) and parallelises over residue classes; verify is two 256-bit exponentiations, 4.5 ms class 1024 (12.6 ms including deriving D from the checkpoint hash), 1.4 ms RSA. Seed pipeline: epoch_seed(checkpoint) -> (seed, proof) and verify_epoch_seed; the same checkpoint hash gave the same seed and identical proof bytes in two separate processes at T=1,000,000; wrong checkpoint, flipped seed bit and T+1 all rejected. Attacker speed: delay must only exceed the 2 s publish-or-lose window; margin is 300x at the epoch and 1,800x at the era, so a 2x (or 10x, or 100x) faster evaluator leaves grinding impossible. Requirement: the checkpoint hash must commit to full block hashes incl. nonce. Grinding model (3,600 blocks/epoch, advantage uniform 0 to 15%, keep top quartile, one block burned per withheld candidate), gain per epoch in blocks, no delay vs with delay: s=0.1 +0.40 vs 0; s=0.2 +1.66 vs 0; s=0.3 +3.62 (+0.32%, 13.5:1 on burned blocks) vs 0; s=0.4 +6.06 vs 0. Monte Carlo over 2,000,000 epochs agrees to 0.03 blocks. Correctness: NUDUPL, NUCOMP and the Lehmer partial xgcd agree with Cohen 5.4.7 / plain duplication / plain-division xgcd on 15,000 random cases; block prover equals the naive O(T) prover at T = 37, 5,000 and 100,000 in both groups; 216 associativity triples; 3 tamper cases rejected per size. Recommend: class group 1024-bit D from the checkpoint hash, epoch T = 600 x r_ref and era T = 3,600 x r_ref with r_ref the fastest honest single-core rate measured on the devnet (98 M and 588 M on this Mac), fixed at genesis, 20 min lead time for the epoch seed and 2 h for the era draw, 256-bit Fiat-Shamir prime. Open: external review of classgroup.rs against chiavdf, reference core choice, fallback rule for a node without the seed at epoch start, carry D in the proof.

-

2026-10-03 igneum-pow: Rust crate bit-exact with proto-metal (consensus-engineer)

+

2026-10-03 igneum-pow: Rust crate bit-exact with proto-metal (consensus-engineer)

Historical record of 2026-10-03: the code and the chain as they stood that day. The chain's current state is the release manifest.

Machine: Apple M5 Max, one performance core, rustc 1.99.0 (rustup), release build with LTO. Crate at igneum-pow/ (seed, generator, memhard, verify, emit; CLI bench, export, hash), standard library only, serde_json as a dev-dependency for the pack tests. Agreement with the Swift through proto-cuda/packs/: program.json instruction by instruction for igneum-genesis, igneum-genesis-mh and igneum-hourly (3 x 64 match); mixer rot/mul/rc match; cache head, last line and FNV-1a 64 48c4f5bf24166b2e match; dataset head, [MASK] and 64 sampled words match in all three packs; hash vectors 96/96 for igneum-genesis-mh (memory-hard) and 96/96 each for the two closed-form packs. 23 tests, all pass. Emitted sources: kernel.cu, program.metal, kernel.cl and program.h byte-identical for all three packs, memhard.h and memhard.metal byte-identical for igneum-genesis-mh; igneum-pow export then diff -r against the packs differs only in the provenance string of vectors.json/vectors.h. Found: proto-cuda/packs/igneum-genesis-mh/program.json is not valid JSON (main.swift line 1291 writes jhex(cacheLineMask) inside the "item" string). The Rust emitter writes the mask bare and the test normalises that line; fix pending in the Swift. Cache fill, 256 MiB on one core: 175 to 181 ms in Rust (5 runs) against 184.5 to 190.6 ms Swift and 161.5 ms C++ host reference. CPU verify per 32-lane warp, avg of 20, 1 GiB dataset: igneum-genesis 0.441 ms (Swift 0.649), /epoch1 0.411 (0.631), /epoch2 0.488 (0.701), igneum-second-seed 0.482 (0.801), igneum-second-seed/epoch1 at 144 loads and 4,608 items 0.579 (1.205). Cold single warps 0.41 to 0.87 ms (Swift 1.16 to 2.11). Closed form 0.002 ms (Swift 0.017). Reading: Rust is 1.4x to 2.1x faster than the Swift verifier per warp with the same algorithm (register-major lanes, 32-lane interleaved item derivation); 10 ms gate margin about 17x steady, 11x on the worst cold warp. Cache fill is within 5 percent of the Swift and 10 percent slower than clang C++. API for the fork: Epoch::memory_hard(seed, day) once per epoch (fills the cache), then epoch.hash(nonce), epoch.hash_warp(base), epoch.verify_block(nonce, target); emit::export_pack(&epoch, day, source) for miner programs. seed::seed_words_from_bytes is the boundary for the VDF output. Not done: no GPU run from Rust; the 256-bit target mapping stays in the fork; the seed is still a string.

3 October 2026, proto-opencl: OpenCL path built and proven without AMD silicon (Apple OpenCL 1.2, pocl, CPU emulator)

@@ -327,7 +327,7 @@ table{min-width:560px}

3 October 2026, execution layer devnet v3: revm over the selected chain, 3-node simnet, viem smoke test (execution-engineer)

Machine: the same Apple M5 Max (18 cores), shared with two other agents' builds (load 15 to 55). Branch execution-layer in vendor/igneum-node-exec, worktree of vendor/igneum-node from d62708a8; revm 43.0.3, alloy-primitives 1.7.3, alloy-consensus 2.5.0, alloy-trie 0.9.8, axum 0.8.9; viem 2.57.2, solc 0.8.37 (tools/evm-smoke). Release build CARGO_TARGET_DIR=target cargo build --release -p kaspad -p igneum-miner --features igneum-pow: first full build with the new crates about 20 min under nice -n 10 -j 10 on the loaded machine; incremental igneumd rebuilds 35 s to 4 min. Test network: 3 igneumd --simnet nodes (devnet block rate and depths, proof of work skipped, chain id 4463) on gRPC 26700/26710/26720, p2p 26701/26711/26721, eth RPC 26790/26791/26792, appdirs /tmp/igneum-exec-test; 3 single-thread igneum-miner --engine stub --hold-ms 2500 (exponential hold, mean 2.5 s per miner). Rate: 130 blocks in 120 s = 1.08 blocks/s; 68 chain blocks; selected-chain reorgs 22 in 120 s, depth 1 (17) and 2 (5), identical on the 3 nodes. Earlier run with a fixed 900 ms hold: 3 blocks/s in lockstep rounds and 80 to 92 reorgs in 60 s with flips 45 to 69 deep (equal-work chains kept alive by the hash tie-break); every flip was unwound correctly (state roots identical on 3 nodes at block 32 after 65-deep flips), the fix is Poisson pacing in the miner. Smoke test (node tools/evm-smoke/smoke.mjs, stock viem paths): 87 checks passed, 0 failed, 36 s wall, tip at chain block 78. eth_chainId 0x116f, net_version 4463. Miner 1 (EVM address = low 20 bytes of its vote key hash) held 91.28 IGN at chain block 53 from 80% subsidy shares of 36.59 IGN per blue block (3,168,808,781 sompi x 1e10 x 0.8, launch-ramp day 0 is not applied on simnet's genesis timestamp); proving pool escrow 92.55 IGN at the end. Funding: 3 transfers of 5 IGN, eth_estimateGas 25,380 (21,000 plus the pgas fold and the 15% margin), all status 1, balances exact. 50 transfers between 3 accounts (each sender's transactions to one node, no p2p relay of EVM transactions): all 50 executed in 16 s wall across chain blocks 58 (17), 61 (20), 62 (13); 57 executed transactions in 7 chain blocks over the run, max 20 per chain block; 19 skipped copies (the same miner re-including transactions handed out before its earlier template landed, every one skipped by the nonce rule with no fee and no receipt). Balances of the 3 accounts matched the receipt accounting to the wei (value plus gas_used x effectiveGasPrice plus burnedProvingFee). Transfer receipt: gasUsed 21,000, pgasUsed 200, effectiveGasPrice 2 gwei (base 1 gwei, tip 1 gwei), burnedProvingFee 200 gwei (200 pgas x 1 gwei), minerTip 16,800 gwei (80% of 21,000 gwei), developerShares [burned 4,200 gwei] (unregistered, 20%). Contract call increment(5): gasUsed 45,354, pgasUsed 1,288, minerTip 36,283.2 gwei (80%), developer share 9,070.8 gwei (20%) credited to the payee the constructor registered (balance delta equal). Deployment via viem deployContract: gasUsed 185,948, pgasUsed 1,438, registry creatorOf = deployer and payeeOf = constructor argument (executor CREATE rule plus register). eth_estimateGas reports the revert of increment(0); eth_call hashLoop(50) returns; eth_estimateGas hashLoop(200) = 98,900 with the fold; eth_getLogs finds the event. Measured pgas/gas: 0.0095 transfer, 0.028 storage write with event, 0.0077 deployment, 0.0099 averaged (prototype table, below the design's 0.1 to 10 band as expected before calibration). Duplicates in parallel blocks: one identical copy sent to nodes 1 and 2 was included twice (chain blocks 63 and 64, blocks c09c9329... and 3f401bd2...), executed once, the second skipped NonceTooLow { expected: 18, got: 17 }; a conflicting same-nonce pair (different values, one copy per node) executed exactly once (B1), the loser never reached a block because its node's pool dropped it once the nonce had passed (igneum_getTransactionStatus: includedIn [], executed false). Execution time per chain block (node 1, igneum.executionMicros, includes the full-recompute state root): 50, 71, 93, 57, 41, 46, 50 us for the 7 chain blocks with 3, 17, 20, 13, 2, 1, 1 transactions; 71 empty chain blocks averaged 11 us; the same chain block on the 3 nodes: 50 / 192 / 85 us (block 56) and 50 / 88 / 46 us (block 78). State roots as outputs: genesis (registry only) 7e37a9fb19b154d32daf5bf30a50d339a75029fbc9eec9ea20e95439dba5a311; chain block 56 (3 funding transfers) 68cacfd393b00ead784a69b10d57a3e2dd57858029df107b529487a49f393b50; chain block 78 5b18b3a58f6c1d21b22caad4a1dbd9ee8a6394a02db2220255e556a9d4f90878; identical hash and root on all 3 nodes at heights 0, 56, 74 and 78; the root advanced at every block with transactions. Base fees stayed at the 1 gwei floor (segments far below the 15 M gas target). Differential (igneum-exec-diff seq.json, plain revm without inspector, pgas or split, balances adjusted by the exported Igneum-only flows): segments 0 to 78, 57 executed transactions compared (status, gas used, logs), 19 skipped copies confirmed rejected by plain revm at their positions, 10 accounts compared (balance, nonce, code hash), 0 mismatches. cargo test -p igneum-evm-types: 3 passed. Not done: on-disk state and incremental trie (state rebuilt from genesis at start), header fields utxo_commitment and accepted_id_merkle_root kept (proofs_root is an RPC placeholder), body miner field and proofs section, pgas calibration, proving layer, eager virtual execution, eth_getProof/subscribe/debug, EVM transaction relay between nodes, the finality merge (plan in the design document, section 10.4). Test network stopped at the end of the run.

-

2026-10-03, consensus attack harness (consensus-engineer), catalogue run on the ordering-layer node

+

2026-10-03, consensus attack harness (consensus-engineer), catalogue run on the ordering-layer node

Historical record of 2026-10-03: the code and the chain as they stood that day. The chain's current state is the release manifest.

Machine: Apple M5 Max, 64 GB, load 61.19 55.26 50.53. Private test network of igneumd (release, skip_proof_of_work devnet) on 127.0.0.1 ports 27200+, data /tmp/igneum-harness; the live devnet and the RTX 5090 node were not touched. Harness: tools/harness/, node fork worktree vendor/igneum-node-harness.

ScenarioCriterion (spec)MeasuredPass
5 malformed and boundary inputs on every p2p message and RPC method the fork touchesrejected without a crash or a cache build (spec 02 2.4; fork-divergence header and RPC rows; ledger M15)63 cases (46 RPC, 17 p2p): node stayed up on every case; all malformed inputs rejected or disconnected. 5 cases (rpc:timestamp-zero, rpc:timestamp-past-3-days, rpc:daa-score-bogus, p2p:ts-past-day, p2p:daa-bogus) built a 256 MiB cache = ledger M15 reproduced on HEAD d62708a8, which the r3-fixes branch drives to 0 (bench-log M15 entry). Other unexpected cache builds: 0. Over-length vote_key_hash (vkh-33-bytes) and an unknown JSON field were normalized and accepted rather than rejected (minor, no safety impact).pass
2 timestamp boundaries (live)rejected at ts <= past median, accepted at pmt+1; accepted below now+132 s, rejected above (spec 02 section 2.3)past: pmt-1=rejected, pmt=rejected, pmt+1=accepted, pmt+2=accepted; future flip between +132.00 s and +132.01 spass
2 timestamp stretch drift (sim)controller response to a 33% miner stretching timestamps inside the rules is measured (blocks per second drift against an honest run)honest 0.9952 b/s (difficulty x1.016); ahead 131 s: 1.0222 b/s (+2.7%, x0.96); oscillate: 1.0422 b/s (+4.7%, x0.923); over 6000 virtual spass
1 withhold a=0.1 release every 5attacker blue share <= 0.1 + 2 sigma (0.014) over 1927 bluesblue share 5.4% (104 blue, 81 red of 186 made); honest reorgs depth:count 1:2 2:5 3:2 4:2 5:2 8:2, max 8pass
1 withhold a=0.1 release every 20attacker blue share <= 0.1 + 2 sigma (0.014) over 1858 bluesblue share 1.2% (23 blue, 157 red of 186 made); honest reorgs depth:count 1:1 2:1 5:1, max 5pass
1 withhold a=0.25 release every 5attacker blue share <= 0.25 + 2 sigma (0.020) over 1942 bluesblue share 22.0% (428 blue, 42 red of 474 made); honest reorgs depth:count 1:11 2:11 3:6 4:17 5:6 6:9 7:5 8:6 9:2 10:1, max 10pass
1 withhold a=0.25 release every 20attacker blue share <= 0.25 + 2 sigma (0.021) over 1693 bluesblue share 12.6% (214 blue, 266 red of 489 made); honest reorgs depth:count 1:3 3:3 4:1 5:1 6:1 7:1 8:2 11:2 13:1 14:2 16:1 25:1 30:1, max 30pass
1 withhold a=0.33 release every 5attacker blue share <= 0.33 + 2 sigma (0.021) over 2039 bluesblue share 31.5% (643 blue, 17 red of 663 made); honest reorgs depth:count 1:15 2:18 3:21 4:21 5:15 6:14 7:10 8:5 12:1 13:1, max 13pass
1 withhold a=0.33 release every 20attacker blue share <= 0.33 + 2 sigma (0.024) over 1561 bluesblue share 27.4% (428 blue, 212 red of 640 made); honest reorgs depth:count 2:2 3:1 4:1 5:1 6:1 7:1 8:2 12:1 13:1 15:1 19:1 22:1 23:3 25:2 26:1 28:2 29:1 32:2 33:1, max 33pass
1 withhold a=0.45 release every 5attacker blue share <= 0.45 + 2 sigma (0.022) over 2002 bluesblue share 44.2% (885 blue, 0 red of 886 made); honest reorgs depth:count 1:24 2:27 3:23 4:29 5:22 6:16 7:7 8:8 9:2 13:2 14:1 15:1, max 15pass
1 withhold a=0.45 release every 20attacker blue share <= 0.45 + 2 sigma (0.024) over 1657 bluesblue share 50.7% (840 blue, 40 red of 886 made); honest reorgs depth:count 3:1 8:2 9:1 11:3 12:1 13:1 15:1 16:5 17:2 18:2 19:3 20:3 21:1 22:4 23:3 25:3 26:2 28:1 29:1 31:1 32:2 36:1, max 36FAIL
3 partition 120 sone chain after the merge-depth rule; reorg depth and time to heal recordedone chain: true (blue scores within 3 at the end); healed in 10 s; losing-side reorg at heal 41 chain blocks (per node 41/41/0/2); rejects nonepass
3 partition 600 sone chain after the merge-depth rule; reorg depth and time to heal recordedone chain: true (blue scores within 4 at the end); healed in 10 s; losing-side reorg at heal 234 chain blocks (per node 0/0/233/234); rejects nonepass
3 partition 1800 sone chain after the merge-depth rule; reorg depth and time to heal recordedone chain: true (blue scores within 4 at the end); healed in 10 s; losing-side reorg at heal 920 chain blocks (per node 0/0/920/920); rejects nonepass
3 partition 3700 s (beyond merge depth)one chain after the merge-depth rule; reorg depth and time to heal recordedone chain: true (blue scores within 4 at the end); healed in 10 s; losing-side reorg at heal 2160 chain blocks (per node 0/5/2160/2159); rejects MissingParents:1; MissingParents:1; MissingParents:5; MissingParents:5pass
6 resource exhaustion (50x template, submit and mempool floods from one peer)honest template p95 < 200 ms and both nodes under baseline RSS + 512 MB, alive, one sinkhonest template p95 worst 3.7 ms across loads (baseline 33.2 ms); template 500ps 500/s, submit 50ps 50/s, mempool 500ps 500/s; RSS growth template +4MB, submit +11MB, mempool +14MB; alive true; same sink truepass
4 eclipse 600 svictim rejoins the honest chain on reconnection within the merge-depth bound; reorg depth recordedvictim rejoined 10 s after reconnection (blue-score gap to honest 3 at the end); victim reorg depth 149 chain blocks; adversary built 242 blocks that never entered the honest chainpass
4 eclipse 1800 svictim rejoins the honest chain on reconnection within the merge-depth bound; reorg depth recordedvictim rejoined 10 s after reconnection (blue-score gap to honest 0 at the end); victim reorg depth 447 chain blocks; adversary built 497 blocks that never entered the honest chainpass
7 fast-miner flood, controller trajectory (sim, Kaspa sampled DAA on HEAD)trajectory recorded for the difficulty branch (bits, blocks per second, settle times)50x joins at 600 s: peak 25.27 blocks/s, difficulty x28.4, within 25% of 1 BPS after never s; leaves at 1200 s: trough 0 blocks/s, back within 25% after never spass
7 fast-miner flood, live (50 blocks/s from one peer)node stays responsive: honest template p95 < 200 ms, both nodes alive, same sinkflood accepted 721 blocks in 60 s (12.0/s); honest template p50/p95/max 0.4/0.8/1.3 ms under flood (baseline 0.4/0.8/1.2); rss a 303->333 MB, b 305->332 MB; alive true; same sink truepass
1b withhold vs finality weight (finality branch)spec 03: a withholder gains no vote weight beyond its hash share; under the 56.7% total floor, 0 conflicting locks (the design document, ledger F18)stub: run s1 withhold against a node built with the finality-v2 branch, with miner --vote keys, and read getFinalityWeights and getFinalityCheckpoints; assert blue-weight share within noise and no conflicting lock. Needs the finality branch merged into the harness worktree.stub
3b partition vs finality lock (finality branch)spec 03.5 and ledger F16: after a partition heals, no certified lock is revoked (an exchange relies on "locked" being final); the F16 decision (Kaspa halt vs re-evaluate) is exercisedstub: run s3 partition with voting miners on both sides; record every FinalityLock notification and assert no locked checkpoint changes hash after the heal. Needs the finality branch.stub
4b eclipse vs finality presence window (finality branch)spec 03.3 F2 and ledger F2: a 2-hour presence window does not let an eclipsed victim be fed a locked side chain; the victim rejoins without accepting a revoked lockstub: run s4 eclipse with voting miners; assert the victim never reports a lock on the adversary chain that the honest chain does not also certify. Needs the finality branch.stub
2b difficulty controller under timestamp stretch (difficulty branch)docs/analysis/difficulty-2026-10-03.md: the igneum-dual rule holds the block rate under a timestamp-stretching miner better than Kaspa sampled DAA; forged timestamps move a lane by at most a few percent (spec 02 section 2.3)stub: run s2 Part B with {"difficulty_rule":"igneum-dual"} in the override file against the difficulty branch, compare the drift to the kaspa-sampled baseline this branch measured. Needs the difficulty branch (vendor/igneum-node-diff) merged into the harness worktree.stub
7b fast-miner flood on the dual-lane controller (difficulty branch)docs/analysis/difficulty-2026-10-03.md: on the igneum-dual rule the 50x step settles within about 62 s and the step-down within about 11 minutes, against Kaspa sampled DAA never settling (the record of the devnet event)stub: run s7 Part A with the difficulty branch and {"difficulty_rule":"igneum-dual"}, compare the trajectory to the kaspa-sampled baseline this harness records. Needs the difficulty branch.stub

Full JSON per scenario under /tmp/igneum-harness/results and /tmp/igneum-harness/sim. The simulator (igneum/harness-sim in the fork worktree) runs real consensus code in virtual time with PoW skipped, as rusty-kaspa simpa does; the live scenarios (5, 6, 7 Part B) drive real igneumd processes over wRPC and the fork's own p2p (igneum/p2p-probe).

@@ -342,7 +342,7 @@ table{min-width:560px}
block-78-increment, CPU proverProve sProof bytesVerify sVerified
Setup (pk, vk; vk hash 0x00c3a917...)6.9
Core (STARK shards)22.07,317,2170.164yes
Compressed (recursion, one shard)55.71,272,7690.033yes

Reading: at 626 k cycles the block is far below one SP1 shard, so these times are fixed overhead (proof system setup and the recursion stack), not throughput; cycles per EVM gas (9 to 14) is the first data point for the pgas table calibration (R1) and is dominated by the state-root computation over every account plus one secp256k1 recovery per transaction (through the patched k256). Nothing here is a 12 GB-card shard time (ledger P1); that is the RTX 5090 run of proving/windows-wsl2/ and then the 3060-class gate. The devnet was not touched. Not done: the Groth16 or Plonk wrapper (ledger P3), MPT witnesses, more than one shard per block, chain recursion, the prover key in the statement (P12).

-

2026-10-03 execution layer attack suite: malformed txs, nonce games, RPC fuzz, pgas exhaustion, reorgs, registry abuse (execution test engineer)

+

2026-10-03 execution layer attack suite: malformed txs, nonce games, RPC fuzz, pgas exhaustion, reorgs, registry abuse (execution test engineer)

Historical record of 2026-10-03: the code and the chain as they stood that day. The chain's current state is the release manifest.

Machine: Apple M5 Max (18 cores), shared with other agents' builds (load 9 to 15). Worktree vendor/igneum-node-exec-attacks on branch exec-attacks (from execution-layer fb330692); igneumd, igneum-miner and a new hostile-miner bin igneum-inject built release with CARGO_TARGET_DIR=target nice -n 19 cargo build -j 4 -p kaspad -p igneum-miner --features igneum-pow (stable-aarch64 toolchain; the default cargo on PATH is too old for edition 2024). Tools and the per-scenario commands: tools/exec-attacks/ (README, net.sh, scenario{1,2,3,4,5,6}*.mjs, igneum-inject); raw results under tools/exec-attacks/results/*.json. Network: 3 igneumd --simnet --enable-unsynced-mining --unsaferpc --disable-upnp nodes, PoW skipped, chain id 4463, eth RPC 27690/27691/27692, gRPC 27610/27620/27630, p2p 27611/27621/27631, appdir /tmp/igneum-exec-attacks; one honest stub miner for scenarios 1 to 5 and 4, three miners split into partitions for scenario 6. igneum-inject fetches a block template, replaces the EVM body with arbitrary raw EIP-2718 bytes, recomputes hash_merkle_root and resubmits, so the hostile-miner path reaches body validation and the executor directly. The live devnet (26610, 26611, 26640, 26641, 28640) and other agents' ports (up to 27599) were not touched; every process was stopped at the end.

Run in priority order 1, 2, 5, 3, 6, 4. One row per scenario: criterion (from the design), measured result, verdict.

#ScenarioCriterionResultVerdict
1Malformed and boundary txs (mempool and hostile block)State-free faults invalidate the block; state-dependent faults skip the tx with no receipt; no panic; memory bounded7 state-free faults (bad RLP, type-3 blob, wrong chain id, intrinsic gas above limit, initcode above 49,152, duplicate hash in block, non-contiguous nonces, invalid signature s=0) each made the hostile block invalid and were rejected by the mempool where decodable; 5 state-dependent faults (nonce far ahead, nonce reuse, zero fee below base, insufficient funds, max fee at 2^120) each landed in an accepted block and were skipped with no receipt; gas limit exactly at B_e executed; node kept producing blocks; node RSS 345 MiB to 348 MiB (x1.01); 0 node panics in any logPASS (30/30 checks)
2Nonce games across parallel blocksExactly one execution per nonce; deterministic; state roots identical on all nodesnonces n..n+3 spread across 3 parallel blocks with heavy duplication executed once each, account nonce advanced to n+4; a conflicting same-nonce pair in two parallel blocks executed exactly once; state roots identical on all 3 nodes at the tip in both roundsPASS (9/9)
5RPC fuzzErrors not crashes; honest latency under 200 ms31 eth_*/igneum_* methods x 9 junk param shapes plus deep nesting (5,000 levels) and broken bodies all returned a JSON-RPC envelope or a handled HTTP error, none dropped the connection or crashed; under a one-client eth_call flood of 4,184 req/s (about 200x honest) honest p95 latency 29.1 ms, max 33.5 ms, 0 flood errors; node kept advancingPASS (5/5)
3Proving-gas (pgas) exhaustionThe per-block pgas budget B_p caps inclusion and the template respects it; measure execution time per blockB_p = 30,000,000. modexp loops: 1,000 iters executed 3.45 M pgas in 1.34 ms; 3,000 -> 10.33 M pgas, 4.56 ms; 6,000 -> 20.64 M pgas, 7.54 ms; 9,000 -> would-be 30.96 M pgas, skipped with BlockProvingBudget after 10.85 ms of native execution; no executed block carried more than B_p (max 20.64 M)PASS (4/4)
6Reorgs under executionState root recomputed deterministically; displaced-tx receipts handled per design; no stuck mempoolPartition P1={node1}/P2={node2,node3} healed via igneum-inject addpeer after 1/3/5/8 s forced selected-chain reorgs of depth 3, 6, 13, 11 on the losing node; all 3 nodes converged to one sink and agreed on the state root at the common height each time; the tx executed on the pre-heal chain re-resolved to one canonical, cross-node-consistent outcome (DAG merges the losing blocks, design 1.2/1.3; it does not orphan them); a fresh tx was mined after every reorg (mempool not stuck)PASS (31/31 checks over 4 cycles)
4Developer registry abuseDesign 4.5: base fees burned, no positive-expectation loop; record the max share a self-dealer recoversregister(someone-else's-contract) and register(unrelated EOA) both revert; a factory's CREATE and CREATE2 children inherit the factory payee; a same-tx creator override sets a different payee; an EOA cannot override a factory child; an unregistered factory's child has no payee (share burns); self-dealer (sender = payee = block miner) recovered 100.0% of the tip but only 56.45% of total fees paid, because both base fees are burned; recovered < paid alwaysPASS (19/19). Max share a self-dealer recovers: 56.45% of fees paid (tip only; base fees always lost)
@@ -354,7 +354,7 @@ table{min-width:560px}

4 October 2026, sim/economy: mining versus proving under stress, agent-based (economist; model, not hardware)

Machine: Apple M5 Max, shared (load 9 to 25), single process at nice 19, about 28 minutes of compute in total. sim/economy/sim.py, Python 3.10.10, numpy 2.2.6; 1,000 operators, 30 days, 180-s ticks, 13 to 25 s per run. Inputs: RTX 5090 229 MH/s (measured, this log); every other number approximate (docs/analysis/economy-2026-10-04.md, assumptions table). Six scenarios x 5 seeds (sim/economy/results.md): no backlog, no window miss, no hash under 50% of pre-event in any run. Hash troughs: a 0.95, b (price down 70%, external x10) 0.82, c 0.97, d (20% operator leaves) 0.75, e (30% withholder) 0.98, f (2x pool arrives) 0.95 of pre-event; day 30: 1.00 / 0.87 / 1.00 / 0.80 / 1.00 / 1.92. Blocks proven within 60 s: 1.00 in every hour; within 20 s: 0.14 to 0.41. Cards in hybrid mode (mine, answer own assignments) at day 30: 42 to 54%; cards off: 1% (a, c, e) to 10% (b). Profit $ per card-day, baseline: 5090 6.37, 3090 1.66, 3060 0.78, small 0.39; shard share 5090 0.59, 3090 0.26, 3060 0.16. Proving-share 10-90 range over the last 10 days 3 to 9 points (one seed of f at 10.1). Sensitivities on b (2 seeds, sim/economy/levers.md): traffic 3 / 30 / 100 / 300 shards per block gives hash trough 0.81 / 0.82 / 0.63 / 0.06, oldest unproven age 0 / 0 / 85 / permanent, worst day within 60 s 1.000 / 1.000 / 0.994 / 0.825, hours under 50% hash 0 / 0 / 0 / 22. Observation window 20 min to 24 h: score 0.939 to 0.952, churn only. Lever study on b at 100 shards per block (2 seeds): window 5 / 10 / 20 / 30 s gives age max 565 / 325 / 0 / 0 s, hash trough 0.53 / 0.62 / 0.77 / 0.77, score 0.592 / 0.765 / 0.948 / 0.948; pool 0.1 / 0.2 / 0.3 / 0.4 gives age 168 / 325 / 16 / 0 and cards off 0.05 / 0.07 / 0.07 / 0.10; burn 0 to 0.5 and claim timeout 60 to 600 s leave the age at 325 s in every row. Proposal (not applied): window = p90 shard time plus one swap, 25 s at today's targets (O-5.1); B_p tied to the live proving fleet rather than a launch calibration. Not done: DAG and network latency, pool protocol, bonds on jobs beyond a class filter, price feedback from burns, the launch ramp; the age column of the 300-shard sensitivity row predates the age-formula fix.

-

2026-10-04 execution layer attack fixes: F-exec-A (mempool gas-limit bound) and F-exec-B (pgas abort rule, spec 7.5) (execution-engineer)

+

2026-10-04 execution layer attack fixes: F-exec-A (mempool gas-limit bound) and F-exec-B (pgas abort rule, spec 7.5) (execution-engineer)

Historical record of 2026-10-04: the code and the chain as they stood that day. The chain's current state is the release manifest.

Machine: Apple M5 Max (18 cores), shared with other agents' builds (load 13 to 18). Worktree vendor/igneum-node-exec, branch execution-layer (fix commit on top of fb330692); built release with CARGO_TARGET_DIR=target nice -n 19 cargo build --release -j 4 -p kaspad -p igneum-miner --features igneum-pow (stable-aarch64 toolchain), unit tests with cargo test --release -j 4 -p igneum-exec -p igneum-evm-types. Network: 3 igneumd --simnet --enable-unsynced-mining --unsaferpc --disable-upnp nodes from this worktree, one honest stub miner, eth RPC 27990/27991/27992, gRPC 27910/27920/27930, p2p 27911/27921/27931, appdir /tmp/igneum-exec-fix; hostile blocks through the attack suite's igneum-inject (vendor/igneum-node-exec-attacks/target/release, same wire protocol). The attack scripts of tools/exec-attacks ran unchanged against this network with IGNEUM_RPCS and IGNEUM_GRPC1 pointed at it, from copies outside the repository so results/*.json of the 3 October run stay as recorded; the after-fix reproduction is a separate script (session scratchpad, scenario3_after.mjs, 25 checks) written against the new rule. The live devnet and the attack suite's 276xx ports were not touched; every process was stopped at the end; 0 panics in the three node logs.

What changed (spec 7.5, design 10 note): the inspector meters pgas against the including block's remaining B_p and halts the transaction before the opcode or precompile that would cross it (a precompile over the cap is answered with a revert that spends none of the forwarded gas, and the parent halts at its next instruction); the executor charges an aborted transaction as out of gas for the gas and pgas consumed to the abort, status 0, nonce advanced, receipt pgasAborted; the proving charge never takes a sender past the signed budget. The mempool refuses gas_limit > B_e (F-exec-A) and an estimated pgas above B_p (estimate = simulation at the tip under the cap), the template packs by the estimate, eth_estimateGas and eth_call fail naming the pgas when the cap is hit, igneum_estimateGas returns both dimensions. Simulations now read the state through DatabaseRef instead of cloning it per call. igneum-exec-diff treats a pgasAborted transaction as an Igneum-only flow (plain revm would run it to its own end).

Unit tests (new, all pass): pool::gas_limit_is_bounded_by_the_block_execution_limit, pool::estimated_proving_gas_is_bounded_by_the_block_proving_limit, pool::template_never_exceeds_the_remaining_proving_budget, executor::over_budget_pgas_is_aborted_charged_and_the_nonce_advances (an SLOAD-loop bomb with a 30 M gas limit, about 54 M pgas if run out, is cut under B_p, charged exactly gas_used x price + pgas_used x f_p, nonce advanced; a second inclusion skips with NonceTooLow in under 100 ms; the next nonce executes), executor::the_cap_is_the_remaining_block_budget (two bombs in one block fill it to within 1,000 pgas of B_p; a third copy skips at its intrinsic pgas), executor::estimate_reports_the_cap. 6 of 6 in igneum-exec, 3 of 3 in igneum-evm-types.

@@ -368,7 +368,7 @@ table{min-width:560px}

3 October 2026, per-identity hash rate "decay" on the RTX 5090: diagnosis and Metal reproduction (miner-community-lead)

Machine for the reproduction: Apple M5 Max, 64 GiB, Darwin 25.6.0, load average 2 to 147 (other agents' builds and, during R1, another agent's Metal worker on the same GPU); everything at nice -n 19. Binaries: HEAD proto-metal/main.swift built with swiftc -O into the scratchpad (465,529 bytes, the same size as proto-metal/igneum-bench), vendor/igneum-node-diff/target/release/igneumd and igneum-miner (22:38 and 21:17 UTC, the difficulty worktree pair; the miner's Seeder and worker protocol are the same code as HEAD and as the Windows build 745d41ef). Private networks on 127.0.0.1 ports 27500 to 27562, appdirs under /tmp/igneum-decay-test, all stopped afterwards. Full write-up: docs/analysis/hashrate-decay-2026-10-03.md; proposed fix: docs/analysis/hashrate-decay-2026-10-03.patch (not applied; git apply --check passes against vendor/igneum-node). PC data (node tools/logs.mjs <run_id> --all, STATUS lines deduplicated by timestamp, per-interval rates from consecutive cumulative figures): segment 22:57 to 23:04 UTC, nvidia-1: 40 jobs in the first 30 s then exactly 32 per 30 s for 12 intervals at 17.5 to 18.4 MH/s wall while the printed cumulative figure fell 22.18 to 18.13; nvidia-8 (started 4.7 s later) printed a rising 16.80 to 17.71. Segment 22:23 to 22:57 UTC (epoch 2, DAA 8,474 to 10,513): per-identity gap between jobs 0.098 s to 0.330 s per 0.68 to 0.81 s job, inside-jobs rate rising 28.7 to 34.7 MH/s, wall falling 24.6 to 20.6 MH/s, card total 197 to about 165 MH/s; at the 22:57 epoch boundary the gap returned to 2% and the difficulty held (84.5M to 83.0M). Code audit: nothing allocated per job survives the job in proto-cuda/host.cu, proto-opencl/host.c or proto-metal/main.swift serve loops (tables in the analysis); the miner's only per-job growth is time in Seeder::seeds_for (memo keyed by (epoch, sink), one getBlock RPC per block from the sink to the epoch start on every miss, 1,274 to 3,313 calls on the RTX 5090 machine). cudaDeviceSynchronize at the default schedule spins one thread per worker (the founder's 6.2% per process); the hot-swap working tree sets cudaDeviceScheduleBlockingSync and swaps clFinish for clWaitForEvents. Metal runs (STATUS every 30 s; "gap" = 1 minus wall over inside, per interval): R1 control, epoch 0, genesis bits 0x1d100000, 308 s (cut by the 22:21:37 UTC SIGTERM of every process of this session): first interval 25.18 MH/s alone on the GPU, then 14.0 to 14.4 MH/s in every interval after another agent's worker joined at 25 s, gap 0 to 2%, worker RSS 56.8 MiB flat. R2 walk reproduction, 900 s: skip_proof_of_work node pumped to DAA 4,000 (one-second timestamps, difficulty held at 76.8M), one identity, pumped blocks at 1/s for 300 s, none for 300 s, 1/s for 300 s: inside 27.0 to 27.7 MH/s in all 29 intervals; wall 22.3 to 24.3 (gap 12 to 18%, walk 400 to 700), 25.9 to 27.3 (gap 0 to 4%), 18.0 to 21.0 (gap 25 to 35%, walk 700 to 1,000); miner CPU 0 to 1% in the quiet phase, 11 to 21% in the last. R3 one worker at difficulty 2^25 (Kaspa sampled rule, genesis bits held), 600 s: 30.51 wall / 30.72 inside, 1,091 jobs, 224 blocks, 53 to 56 jobs per 30 s throughout. R4 eight workers at 2^25: 29.38 / 29.45 summed (3.32 to 4.38 each), 1,053 jobs, 242 blocks, 7 jobs per 100 s per identity in every interval, worker CPU 0.0 to 0.6%, RSS 46 to 57 MiB. R5 one worker at 2^31: 37.01 / 37.75, 1,324 jobs, 4 blocks, flat. R6 eight workers at 2^31: 36.67 / 36.75 summed (4.29 to 5.55 each), 1,314 jobs, 5 blocks, flat. (R5 and R6 ran a different epoch-0 program from R3 and R4, 112 loads per hash, hence 37 against 30.5 MH/s.) Side findings: the difficulty worktree's node panics at consensus/src/processes/difficulty.rs:431 ("Work should not exceed 2**192") when fed 85 blocks/s with wall-clock timestamps under the Igneum dual rule (a pump artefact, logged for the consensus-engineer); skip_proof_of_work nodes still log "PoW rejected ... by igneum-lottery-v1-bound" for every block they accept. Not done: the fix applied and measured on the RTX 5090 machine (the acceptance figure is a flat gap at DAA 10,800 with eight identities); the OpenCL event wait checked on the AMD driver; a unit test of seeds_for (the client is concrete).

-

2026-10-04 finality v2 attack harness: seven hostile scenarios on a six-voter private test network (consensus test engineer, cryptographer)

+

2026-10-04 finality v2 attack harness: seven hostile scenarios on a six-voter private test network (consensus test engineer, cryptographer)

Historical record of 2026-10-04: the code and the chain as they stood that day. The chain's current state is the release manifest.

Machine: Apple M5 Max, rustc stable, macOS Darwin 25.6.0. Fork: worktree vendor/igneum-node-fin-attacks, branch fin-attacks on master c6d47547 to 2a00ff55 (BLS votes, certificates in coinbase extra data, p2p message 70, the finality RPCs). Build: CARGO_TARGET_DIR=target nice -n 19 cargo build --release -j 4 -p kaspad -p igneum-miner --features kaspad/igneum-pow. Tool: tools/finality-attacks (run.mjs, lib/, README with the proposed fixes). Network: igneum-devnet-800, ports 27800 and up, data /tmp/igneum-fin-attacks, skip_proof_of_work (the hostile miners never hash; each gets its block share from a Poisson clock; every other consensus rule unchanged). Devnet finality parameters: interval 30, depth 20, weight window 7,200 DAA, dust 5, presence 20 indices, 8 aggregators, ban 7,200 DAA, quorum 2/3 of active and 17/30 of total. Durations at SCALE 0.6. The live devnet (26610, 26611, 26640, 26641, 28640) was never touched. Run time 32 min of process time (the machine slept twice during the run, which pauses the monotonic clocks the harness and the miners use, so wall-clock timestamps in the log jump; no result depends on wall time).

Hostile pieces are test-only flags of igneum-miner, never honest node or consensus code: vmine (Poisson submit at a chosen hash share, decoupled 0.5-s voter), --equivocate, --sybil b:bb:a:ab (one miner mints many vote keys), --drop-votes (strips the node's finality section from its coinbase so its blocks carry no votes or certificates while it still votes over RPC), --pulse burst:on:period, and fin-rpc-attack (malformed, mis-signed, replayed, oversized and non-hex votes over submitFinalityVote). Six voters throughout; three nodes for the cross-node scenarios, two nodes over a TCP proxy for the partitions.

#Scenario (priority order)Criterion (spec 03)MeasuredVerdict
3Dishonest aggregators (6 voters, 3 nodes, every node aggregates)other aggregators' certificates still lock; a sub-quorum certificate cannot lock (Q3); block-carried votes give participation (F3); lock latency under 2 s median35 / 35 / 35 locked per node, identical lock hashes on all three, 0 conflicting certificates, median lock latency 1,018 ms (bounded by the miners' 1-s poll). Sub-quorum rejection is by code review (lock_test needs both integer tests; a certificate below either is Certified, never Locked); injecting one on the wire needs a finality-aware p2p probe (not built)PASS (wire injection not run)
2Sybil dust (one miner mints 200 keys at 4 blocks and 200 at 6, dust 5; 3 honest voters)dust keys zero weight and no voters; above-dust weight = blocks; total weight = voters' blue blocks; sortition by weight not key count (F17)200 dust keys seen, all voter false; 203 voters above dust; total weight 1,240 = sum of voter blocks 1,240; aggregator sortition is PER KEY (is_aggregator(output, voters, 8) counts keys), with 203 voters a real signer's chance to be an aggregator fell to about 8/203 and the last checkpoint named 0 aggregators (zero-aggregator certificates, "anyone MAY aggregate")weights PASS; sortition FAIL (F17)
1Equivocation at scale (2 of 6 keys sign two checkpoints at every index, 3 nodes)both keys stripped within one checkpoint on every node; no conflicting certificate; honest locks continuestripped keys 2 / 2 / 2 on the three nodes, 78 / 8 / 8 detections (node-local on the equivocators' node, block-carried evidence on the others), 0 conflicting certificates, 35 / 35 / 35 locks by the 4 honest keysPASS
6APartition 3/3 for 90 s after a 252-s shared warmup (window 1,439 DAA at the cut), then healzero locks on either side during the split; locks resume after the heal; no conflicting certificatesside 0: no new lock in 90 s; side 1: first new lock at 84 s, 8 locks before the heal; 0 conflicting certificates (side 0 never locked those indices); locks resumed on both sides after the heal. Side 1 crossed the floor because its own fresh blocks raised its share of its window: at the cut each side held 50% of 1,439 DAA of weight; the 3-miner side added about 2.6 blocks/s and by 84 s held (720 + 220) / (1,439 + 220) = 56.7%. The model is share(T) = (F/2 + R T) / (F + R T) with F the window weight at the cut and R the side's block rate, so the floor holds for T* = 2F / (13R): 74 s predicted at F = 1,439 and R = 3, 84 s measured (sibling losses lower R). The simulation used fixed weights and could not see this (spec 3.7 item 8)FAIL (floor is time-bounded)
6BPartition 4/2 for 90 s after a 252-s warmup, then healthe 4 side (66.7% of total) keeps locking; the 2 side (33%) does not; no conflicting certificates4 side locked 47 to 59 (first new lock 15 s after the cut, the active test passes at exactly 2/3); 2 side stayed at 47; 0 conflicting certificates; both resumed after the healPASS
4Vote-dropping block producer (40% of blocks carry no finality section, 2 nodes)participation and locks unaffected because other blocks carry the votes; delay measuredthe node that saw the dropper's blocks only through gossip and the other producers' blocks locked 35 checkpoints; median lock latency 1,019 ms with the dropper vs 1,019 ms control, 0 ms addedPASS
8Malformed votes over the RPC (9 cases, fresh key per case)rejected without a crash; node stays upcontrol vote accepted; replay answered "already known" (deduplicated, not double-counted); bad signature and wrong chain id rejected "invalid vote signature"; a vote for a hash the node does not hold at a known index is recorded and flagged, not certified; 8-byte, 2 MB and non-hex payloads rejected "vote must be 280 bytes" / "vote is not hex" before any processing; node answered getInfo after all 9. The message-70 half (sub-quorum and replayed certificates, oversized bitmaps) needs the p2p probe; by code review Certificate::read bounds the bitmap at 1 MB, the relay bounds a message at 1 MB and a malformed one is a ProtocolError that disconnects the peerPASS (RPC half)
5Pulsed miner (base share 1/6, 10x for 20 s of every 120 s, 5 steady voters, 216 s, Kaspa's DAA rule as master runs it)weight proportional to block share over the window (no retarget amplification, W2 and F14); cannot lock aloneweight share 35.3% vs block share 35.3%, ratio 0.999: W2 counts blocks and the retarget lag bought nothing extra. But checkpoints 1 to 10 were locked by the burster ALONE: its first 20-s burst gave one key 66.7% to 71.7% of a window that held under 300 blocks (cp 5: 98 of 147 signed by 1 of 6 voters; cp 10: 201 of 297), above both Q3 tests. From cp 11 every lock needed 3 or 4 signers as its share decayed to 35%. This is ledger F1 measured live: with no first-month gate (min_daa 0 on devnet, 3,600 DAA on mainnet, spec 3.8 not implemented) a short burst owns a young windowamplification PASS; lock-alone FAIL (F1)
7Eclipse of one voter with an adversarial side chainnot run: needs the finality-aware p2p probe to feed a private forknot measurednot run
@@ -379,7 +379,7 @@ table{min-width:560px}

4 October 2026, difficulty rule under attack: pool hopping, pulsed rental, timestamp stretching, short-lane oscillation, epoch games, polluted window, block flood (consensus test engineer)

Machine: the same Apple M5 Max, shared with other agents' builds and test networks (load 15 to 30). Simulator sim/difficulty/attacks/attacks.py over sim/difficulty/sim.py (controllers unchanged): several miners with on/off strategies, block attribution by hash share at the solve, hashes per miner, timestamp forging inside the fork's rules (132 s ahead, above the 27-sample past median). Node runs on branch diff-attacks of vendor/igneum-node (worktree vendor/igneum-node-diff-attacks, from difficulty at 3ea7a3e3; adds only the attack variable IGNEUM_ATTACK_TS_OFFSET_MS in the template builder and a reproduction test), ports 27700 to 27721, appdir /tmp/igneum-diff-attacks, genesis bits 0x1f010000. Everything in sim/difficulty/attacks/README.md, raw tables in results.md, headers of the three test-network runs in testnet/. Simulator, seeds 7 to 9, Igneum / Kaspa's rule, criterion, verdict: (1) pool hopper 10 to 100% of the base, on while D is below its 6-hour mean, 24 h: hopper's blocks per hash +1.5% at most / +0.8% at most, under 5% both, Igneum 0.7 points above Kaspa's in every greedy cell (unchanged with the ease clamp at 6% or 3%: the price of a controller that moves inside the hour; a 60 s dwell turns the 50% and 100% hoppers into losers, -1.7% and -4.0%): PASS under 5%, FAIL on "no larger than Kaspa's" by the letter, no change proposed. (2) 50x burst for 10 min every hour: pulser's weight per hash 0.26 / 0.98 of the base's, blocks per hash 3.7% / 85% of the base's; once: 0.13 / 0.87: PASS (no weight amplifier under either rule; Kaspa's makes the burst cheap, Igneum's makes it 27x dearer; the hour after costs the base 37% and a 153 s worst gap under Igneum). (3) forger at 30 or 50% stamping at the latest allowed, the earliest allowed, or alternating: Igneum block rate 0.66 / 0.42 / 0.51 at 30% and 0.56 / 0.12 / 0.23 at 50%, difficulty 1.5x to 9.9x on an unchanged hash rate, worst gap 234 s; Kaspa's rule +5% to +11% easing: FAIL both, Igneum far worse. Cause: the symmetric per-step clamp turns every forged block and the honest block after it into zero measured time (spec 2.3's "the next honest block cancels it" is the bug, not the defence), so the lanes measure 1 - 2a(1 - a) of real time at share a; past-stamping also drags the past median down without bound. (4) 25% miner on and off every 120 blocks: std of the rate ratio 0.160 / 0.147 against 0.045 / 0.010 steady and a 0.143 floor from the attacker's own square wave: FAIL by the letter for both, neither oscillates (12% and 3% above the floor), no change proposed. (5) hold dodger 30%, hold flooders 10x and 30%: 0.0 / +0.7 / +0.3% against 0.0 / 0.0 / -0.1%: PASS. (6) 10x miner leaving at block 600 of an epoch, where the long lane takes over: settled 303 s (292 s with the short lane engaged at the switch), worst gap 17 s, against 334 s for a leave at block 1,200; Kaspa's 2,910 to 3,540 s: PASS. (7) side finding, blocks every 12 ms fed to the rule (another agent's pump): the target passes below 2^64 after 4,142 blocks and calc_work panics at difficulty.rs:431 (should_panic test igneum_flood_at_85_blocks_per_second_drives_the_target_below_block_work_range on diff-attacks): FAIL, floor proposed. Test network, 3 igneumd nodes, honest 4-thread miner A on node 1 for 15 min, forger F (4 threads, about 50%) honest on node 2 for 5 min then on node 3 with the offset: Igneum, earliest allowed stamp: 0.97 blocks/s at difficulty 91,000 before, 0.24 blocks/s at 275,000 during forging and 0.20 at 341,000 in the last 5 min, forger offsets -121 to -566 s, hash unchanged (A 0.078, F 0.069 MH/s). Igneum, latest allowed stamp (+134 s): 0.98 blocks/s at 89,000 before, 0.59 at 170,000 during, 0.50 at 191,000 in the last 5 min (A 0.112, F 0.110 MH/s); the simulator's 50% cases give 0.12 at 9.9x and 0.56 at 1.8x. Kaspa's rule, earliest allowed stamp: 1.73 blocks/s on a 2.5x too easy genesis to block 600 at 210 s, then 1.02 blocks/s at 83,400 through ten minutes of -180 s stamps. 517, 767 and 1,454 blocks, 0 rejected. Proposed (README.md, diffs, not applied): Part A, timestamp rules: 10 s future tolerance (FUTURE_TOLERANCE_MS, a new constant so the past-median window keeps its 27 samples) and a floor at the selected parent's timestamp minus 10 s (BACK_TOLERANCE_MS) beside the past median; Part B, the chain steps of the short and epoch lanes measured on a sanitised running clock 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), stored per header, so forgeries telescope instead of cancelling; the long lane unchanged. Measured, both parts, 3 seeds: the 50% forger drifts the rate +0.7% (past), +0.9% (future), +1.1% (alternating), worst seed +2.7%; base profiles unchanged except down50 762 s against 782 s, warm-up 327 s against 381 s, polluted peak 11.4x against 8.0x; the other attacks identical. Either part alone fails (unchanged rule under the tight rules: -36% and -83% to past-stamping; the clock under the 132 s rules: collapse at 50%, a martingale once the forgery range exceeds half the cap). Part C for the flood: clamp the output at MIN_DIFFICULTY_TARGET = 2^128 beside the existing maximum, in both rules. Not done: the candidate in the node (simulator only; the per-header clock is a store change); DAG effects of forged stamps on red and merged blocks (one chain in the simulator); a rule change for the hopper's 0.7-point excess (none found that keeps the controller fast; README.md, scenario 1); Kaspa's rule under the flood (same hole, 17x slower, not run).

-

2026-10-04 finality fixes F17 and F1: aggregators drawn by weight, first-month gate min_daa = window; attack scenarios 2 and 5 before and after (consensus-engineer)

+

2026-10-04 finality fixes F17 and F1: aggregators drawn by weight, first-month gate min_daa = window; attack scenarios 2 and 5 before and after (consensus-engineer)

Historical record of 2026-10-04: the code and the chain as they stood that day. The chain's current state is the release manifest.

Machine: Apple M5 Max, rustc stable, macOS Darwin 25.6.0. Branch fin-fixes (worktree vendor/igneum-node-fin-fixes, from master 2a00ff55), commit da1eb889. Build: CARGO_TARGET_DIR=target nice -n 19 cargo build --release -j 4 -p kaspad -p igneum-miner --features kaspad/igneum-pow. Tests: cargo test --release -p kaspa-consensus-core -p kaspa-consensus -- finality: 6 of 6 in consensus-core (sortition_threshold, sortition_is_by_weight_not_key_count with 200 dust keys and 6 real ones, first_month_rule_is_the_full_window, the three pre-existing), 1 of 1 in consensus (processes::finality::tests::no_certificate_while_the_window_is_filling, a 150-block TestConsensus chain at a 60-DAA window where one key holds all the weight: nothing certifies under DAA 60, a hand-built early certificate is refused, every checkpoint from DAA 60 locks). The live devnet (26610, 26611, 26640, 26641, 28640) and the other agents' nodes (26680, 27700 to 27720, 28680) were never touched.

The two diffs. (1) F17: is_aggregator(output, weight, total_weight, aggregators) is eligible when output x total < aggregators x weight x 2^64 (was output x voters < 8 x 2^64, drawn per key); ingest_vote passes the key's weight and the table total. A key split into n parts holds n thresholds that sum to the one it had; a key without weight never draws; a key at 1/8 of total or more always draws. A node that serves a drawn aggregator aggregates at once; any other node after checkpoint_depth + aggregator_fallback (15) DAA seconds, so anyone MAY aggregate stays the liveness fallback. (2) F1: min_daa = weight_window (mainnet 2,592,000, devnet 7,200); evaluate never locks and ingest_certificate refuses any certificate while the checkpoint's DAA score is below it; the node logs and reports "finality not active, window filling, N of M" (finality_reason, window_filled_daa, window_full_daa on getFinalityCheckpoints).

Re-run of scenarios 2 and 5 (tools/finality-attacks, hostile igneum-miner from the fin-attacks worktree, unchanged; it drove the fixed node without modification because the new RPC fields are additive). Six voters on one node, skip_proof_of_work, 600 s per run. The harness copy used for the runs is /tmp/igneum-fin-fixes/harness (lib/net.mjs with ports, data directory, network suffix and the finality override taken from the environment; rerun.mjs with the s2 and s5 measurements below); the repo harness was not edited, and its s2 pass test still reads "voters > 8 means per-key sortition", which is now wrong and needs the by-weight test below. Finality override for every run: interval 30, depth 20, window 1,800 DAA, dust 5, presence 20, 8 aggregators, ban 1,800; min_daa 0 for the before runs (the master default) and 1,800 for the after runs (the fixed rule, min_daa = window), fallback 15. The window was shortened from 7,200 to 1,800 so it fills inside a 10-minute run; the rule under test is the equality, not the number. Before = fin-attacks igneumd (master code, built 3 Oct 23:25) on ports 28100 and 28300, network ids igneum-devnet-801 and 803; after = fin-fixes igneumd on 28500 and 28700, ids 805 and 807. Results in /tmp/igneum-fin-fixes/{before,after}-{s2,s5}/.

@@ -403,7 +403,7 @@ table{min-width:560px}
CheckResult
Rust CPU reference (igneum-pow)the packs by construction; verify 0.631 ms per unit (avg of 20), cold 0.67 to 0.81 ms, 4,096 items per unit, cache fill 179 ms; acceptance 1.3 to 3.4 ms per candidate
Apple Metal, natively (proto-metal/igneum-bench, Swift v2 generator)--export-pack igneum-genesis memory-hard: GPU cache == CPU cache, Metal cross-check PASS 3 of 3 warps, instruction list and 96 vectors identical to the Rust pack; closed-form exports of igneum-genesis, igneum-hourly, igneum-census-2026-10-03/22, /37, /51 (the last three have attempt 0 rejected: (b) r7, (c) 119.74 distinct, (b) r4; attempt 1 accepted, ids 22ed0609d079f4cf, 947705cc4eb1df0a, 9869afcc028bf9f1): instructions, seed words and 96 vectors identical to Rust on all five; fuzz --fuzz 2000 --fuzz-seed igneum-fuzz-gen2-2026-10-04: 2,000 of 2,000 PASS, 8,000 warps, loads per hash 128 to 128, compile avg 21.8 ms, wall 91.4 s (proto-metal/TESTS.md section 9)
CUDA through the clang emulation shim (proto-cuda/emu/emu.sh, --batch-log2 13 --block-warps 2)all four packs OVERALL PASS: dataset self-test, 3 warps standalone, 2 warps per block in batch; memory-hard packs cache check 67,108,864 of 67,108,864 words, host fill 174 to 178 ms
OpenCL through the clang emulation (proto-opencl/emu/emu.sh), sub-group 32 local exchange and wave64 sub-group shuffleigneum-genesis-mh and igneum-devnet-v4-epoch0: 96 of 96 in both configurations, fingerprints f2a95d5bb84d961e and 8e22ad069cb2a8c3 at 2^13, identical across configurations
Apple OpenCL on the M5 Max (proto-opencl/host.c)all four packs: cache check PASS, 96 of 96 standalone and in batch (also --group-warps 2), fingerprint f2a95d5bb84d961e at 2^13 = the emulator's; 2^24 fingerprints 25f96e7dce90bd4e (genesis-mh), 3cc4fbf90fa6366c (devnet); rate 27.5 to 27.9 Mhash/s, 14.1 to 14.3 GB/s useful on every pack (version 1 genesis: 45.0 at 80 distinct loads; the census projected 28 at 128)
igneum-census, 20,000 programs, --gen v2 --warps 64, memory-hard day 2026-10-03, 8 threads, 254.8 srejected 5.225 percent (static 4.130, dynamic 1.095), 1.0551 candidates per epoch; accepted programs: distinct addresses per hash mean 127.887, min 120.127, p1 126.897, p50 127.999, max 128.000; static loads 128 on every program (census-v2-20k.tsv and its summary in the session scratchpad, not checked in). Against the 100,000-seed figure of 3 October: 5.14 percent
devnet-v4 node and miner (vendor/igneum-node-v4, path dependency bumped to igneum-pow 0.2.0, engine name v2)cargo build --release -p kaspad -p igneum-miner --features igneum-pow into vendor/igneum-node/target-integration (1 min 17 s warm): release/igneumd 40,480,112 B, release/igneum-miner 7,932,880 B (07:41 UTC); cargo test --release -p kaspa-pow --features igneum-pow 11 of 11; Windows cross-build (proto-cuda/windows-node/cross-build.sh vendor/igneum-node-v4 6, 4 min 53 s): target-integration/x86_64-pc-windows-gnu/release/igneumd.exe 50,179,072 B, igneum-miner.exe 10,065,920 B (libstdc++-6.dll import as before)
2-node test network on the real engine (ports 29000 to 29012, /tmp/igneum-gen2, igneum-devnet-900, IGNEUM_DEVNET_GENESIS_BITS=0x1f010000, IGNEUM_POW_EPOCH_BLOCKS=100, IGNEUM_POW_EPOCH_LEAD=20, one 3-thread CPU miner per node for 300 s)338 blocks accepted on both nodes, 0 rejected, 0 invalid, sink identical at 10 of 10 samples; four epochs crossed (DAA 0, 100, 200, 300; epoch seeds 234e08..., d3f427..., de316c..., 971384..., all attempt 0, ids 8f8806638d59850f, c015349db63beb2c, d7d52120407a0b69, 512527bb7a528476), program and cache ready in 192 to 284 ms on the miners, 4 cache builds per node; m1 158 and m2 180 blocks at 0.046 MH/s each; one WARN per node (eth JSON-RPC port 26790 held by the live devnet node, harmless)

Not done: no NVIDIA or AMD hardware has run a version 2 pack (the RTX 5090's 192 of 192 and the gfx1036 run of 3 October were version 1; the kernel text is unchanged); the edge, stats, determinism and memcheck sections of TESTS.md were not re-run (they do not depend on the generator); the live devnet (v3, version 1 programs) was not touched, so the cut-over is where version 2 goes live; proto-metal/main.swift carries the version 2 port uncommitted next to the hot-swap working-tree changes (not in this agent's file list), and the Apple M5 Max app's Metal worker must be rebuilt from it before the cut-over or Mac GPU shares will fail the CPU re-check; the v4 binaries above were built from the worktree as found, which also holds another agent's uncommitted finality floor change (2/3 of total, O-3.15); the GPU prepare hot-swap path was not exercised here (CPU miners only). The ten non-load weights and the 6-sigma bias threshold remain prototype values (spec 1.16).

-

2026-10-04 finality floor 2/3: the total-weight floor raised from 17/30 to two thirds, simulator A to L re-run, attack scenarios 6A and 6B on a three-node, six-voter network (cryptographer)

+

2026-10-04 finality floor 2/3: the total-weight floor raised from 17/30 to two thirds, simulator A to L re-run, attack scenarios 6A and 6B on a three-node, six-voter network (cryptographer)

Historical record of 2026-10-04: the code and the chain as they stood that day. The chain's current state is the release manifest.

Decision of 4 October 2026 (the founder, O-3.15): a lock needs two thirds of all 30-day weight, and finality pauses whenever less than two thirds of that weight is connected and signing; the chain continues on proof of work meanwhile and the node reports it. Spec 3.3, 3.3.1, 3.7, 3.9, 3.11 rewritten; litepaper Finality and "What Igneum does not claim" updated; ledger F2, F9, F16, F18 restated and F21 added (the window bound of attack scenario 6A).

Node. Branch devnet-v4 of vendor/igneum-node (worktree vendor/igneum-node-v4, from dc749905), commit 6457ca95, two files: consensus/core/src/finality.rs (FLOOR_NUM / FLOOR_DEN 2/3, was 17/30; the Q3 arithmetic as FinalityParams::{quorum_met, floor_met, locks}, both comparisons inclusive) and consensus/src/processes/finality.rs (lock_test calls it). Build CARGO_TARGET_DIR=target-integration nice -n 10 cargo build --release -j 6 -p kaspad --features kaspad/igneum-pow, 3 min 17 s on a machine at load 3 to 13 (another agent's igneum-pow rebuild and the live devnet running). Tests cargo test --release -j 6 -p kaspa-consensus-core -p kaspa-consensus -- finality: 7 of 7 in consensus-core including the new floor_is_two_thirds_of_total_and_inclusive (4 of 6 locks, 3 of 6 does not, 2 of 3 locks, 67 of 100 locks, 66 does not, 57 does not; the total test implies the active test at every participation; a 3/3 side never locks whatever the other side's participation decays to), 2 of 2 in consensus (no_certificate_while_the_window_is_filling unchanged). The live devnet (26610, 26611, 26640, 26641, 28640, the seed relay on 26680 and observer.mjs) was never touched.

Simulator. sim/finality_v2.py: --floor f (a lock needs f x 2/3 of total; default 1.0 since this date, --floor 0.85 reproduces the 3 October tables), the +local partition mode (a side's weight table counts only the blocks it has seen since the split, as a real node's window does; the 3 October tables kept weights global), scenario L (silent weight at 25 to 45%, churn, the poisoned eclipse, 12-day partitions with local weights), H widened to 30% and 33% attackers, I given the 34% case. A to G at --quick for seeds 7, 11, 13, 17, 19 (about 1 min a seed), H to L at full length for the same seeds (H 25 s, I 13 s, J 16 s, K 400 s, L 240 s), all at nice 10. Full tables and the 0.85 against 2/3 deltas in sim/results_v2.md, "Floor 2/3".

@@ -443,7 +443,7 @@ table{min-width:560px}
RTX 5090 (PROVE-SHARD.bat)shard at S_p: execute, core, compressedtwo-shard block end to endfour-shard block end to end
pending

Reading: the shard at S_p is 60 M cycles on the prototype table, 9 cycles per pgas against the unit's 1,000 (the modexp entry is about 100x its SP1 cost: R1, one number); a plain transfer shard is 1,400 to 1,600 cycles per pgas because the 200-pgas intrinsic charge carries the fixed cost of the witness check and the two root computations. The aggregator statement is 1.5 to 1.7 M cycles (bincode, an unpatched sha256 of each shard's public values, the keccaks), small next to a shard. The CPU proof times are 3.8x and 4.9x the 3 October v0 numbers on a comparable statement, on a machine three times as loaded; the GPU row stays empty until the RTX 5090 machine runs. The devnet was not touched; the simnet ran on ports 29300, 29301 and 29390 and was stopped.

-

2026-10-04, fast time (60x test profile), Linux cross-compile from the Apple M5 Max, CI on every push (consensus-engineer)

+

2026-10-04, fast time (60x test profile), Linux cross-compile from the Apple M5 Max, CI on every push (consensus-engineer)

Historical record of 2026-10-04: the code and the chain as they stood that day. The chain's current state is the release manifest.

Machine: Apple M5 Max, 64 GB, shared with four other agents and the live devnet (load 40 to 76 throughout), every job at nice 19 with at most 4 cargo jobs. The live devnet (26610/26611, 26640/26641, 28640), the Metal worker and the seed's <server path> were not touched.

Fast time. infra/fast-time/override-60x.json is the devnet with every clock-like consensus parameter divided by 60 and every block count unchanged (infra/fast-time/README.md lists each field and why it scales or not). The hourly program epoch and its lead are now consensus parameters carried by the override file (pow_epoch_blocks, pow_epoch_lead, plus pow_day_ms for the dataset day; devnet-v4 a5ef8b07, devnet defaults unchanged: kaspa-consensus-core 79 tests, kaspa-pow 7, igneum-pow 39 pass, and a new test reads the 60x file and checks every rule against DEVNET_PARAMS). Proof (infra/fast-time/simnet.mjs, three devnet-v4 nodes on ports 29500+, igneum-devnet-950, three vmine voters sharing 1 block/s, one real-hash CPU miner thread): next epoch seed in the template at 56.1 s (DAA 53), program swap at 65.1 s wall (DAA 60; the CPU miner's new program and cache ready 397 ms later), first finality lock at 185.5 s wall (checkpoint 5, blue score 150, DAA 149; checkpoint 4 sat one DAA under min_daa 120), sinks identical on all three nodes. The devnet reaches the same two events at DAA 3,600 and DAA 7,200 plus a checkpoint.

Harness run, same binariesDevnet profile60x profile (--fast-time)
tools/finality-attacks s3, dishonest aggregatorscatalogue 32 min at SCALE 0.6 on the 3 Oct node (above); on today's rule the window fills at DAA 7,200 = 20 min at 6 blocks/s before any lock113 s wall: 16 locks per node, 0 conflicting certificates, lock hashes agree, median lock latency 1,018 ms, PASS
tools/harness s3, partition and heal (in-process simulator of the devnet-v4 line)983 s wall, four cuts of 120 / 600 / 1,800 / 3,700 virtual s (46 / 151 / 400 / 831 s wall), all PASS43 s wall, three cuts of 10 / 30 / 62 virtual s (18 / 20 / 26 s wall), all PASS; the 62-s cut beyond the 60-s merge depth converged with a 34-block reorg
@@ -495,7 +495,7 @@ table{min-width:560px}

4 October 2026, first outside machine on the devnet: an Apple silicon laptop through the Igneum Miner app

A friend of the project installed Igneum Miner 0.3.1 from the DMG on an Apple silicon laptop (machine id 3a9bf309, no toolchain, no instructions beyond the five steps in the morning summary: drag to Applications, Open Anyway in Privacy & Security once, Get started, Make me an address, Start mining). Node synced from the seed and the LAN-less path (the seed at the public address first), the Metal worker reported ready and the first block was accepted within the first minutes; after 7 minutes: 33 accepted blocks, 0 rejected, 21.0 MH/s average (24.3 MH/s at the moment of the report), CPU re-check OK on every share. Node 1 counted 7 peers with the laptop connected. The log intake received its uploads every minute under the per-install id, so the machine is observable without any contact from its owner. Observed by the team; the machine is not ours, so this is the first row that is not "the project's own hardware".

-

2026-10-04 (afternoon) proving v0 end to end on a 3-node test network (Mac, CPU prover)

+

2026-10-04 (afternoon) proving v0 end to end on a 3-node test network (Mac, CPU prover)

Historical record of 2026-10-04: the code and the chain as they stood that day. The chain's current state is the release manifest.

Machine: Apple M5 Max, load 5 to 8 shared with the live devnet, other agents' builds and a Windows cross-build in the last minutes. Node: branch proving of the fork at 8c0cff15 (vendor/igneum-node-proving/target/release), 3 nodes on 127.0.0.1:29800+, network igneum-devnet-955, infra/fast-time/override-60x.json with skip_proof_of_work and proving_v0_activation_daa 60; three igneum-miner vmine producers sharing 1 block/s and voting; node 0 with IGNEUM_PROOF_VERIFIER = the SP1 host, nodes 1 and 2 in trust mode. Prover: proving/igneum-prove host built 14:58 (guest rebuilt with the payouts input), SP1_PROVER=cpu. Script: tools/proving-v0/run.mjs; report tools/proving-v0/report-2026-10-04.json. Second run; the first (14:08) failed at the carriage step because the template never carried the record section (fixed in 8c0cff15), everything before it identical.

StepMeasured
Activation DAA 60 reached62.8 s after start (DAA 65)
Transfer executed in chain block 6865.8 s
Shard plan of block 68: 1 shard, 200 pgas (one transfer, intrinsic only), 3 eligible keys of 67 window blocks, 3 assignees (every eligible key holds a slot), shard credit 633,911,390,000,000,000 weiidentical on nodes 0 and 1
igneum-prove-export on the chain export (68 segments)0.005 s; plan equals the node's (pre-root, post-root, links, receipts root, pgas)
igneum-prove-host --mode compressed, shard 0 of block 68execute 0.027 s, 293,603 cycles; compressed proof 61.3 s, 1,272,897 bytes, local verify 0.029 s; 70.3 s with setup
igneum-miner sign-record + igneum_submitProofRecord to node 1 (trust mode)accepted (native statement matched), 137.6 s after start
Record on node 0 over p2p (message 71)1.0 s after the submission
Carried by a block and paid on node 0 (chain block 150, carrier 0x8302cf39...)4.0 s after the submission
Node 0's verifier (SP1 compressed proof against the shard vk, statement compared)VERIFIED, 9.3 s in all (SP1 client and key setup; the verify itself 0.029 s)
Payout on all three nodes0x8cc1b0cf4062c00 wei on each; the payout address holds exactly the shard's credit; pool escrow 100.16 IGN after the payment
End to endPASSED in 150.6 s

Reading. The whole loop (plan, export, cut, prove, sign, submit, relay, verify, carry, pay) runs and three nodes agree on the payment. The exporter's cut equals the node's cut on the same trace, which is the condition for a prover to prove what the node pays. The 200-pgas shard is the smallest possible (one plain transfer); its 61 s compressed proof on this CPU is a correctness number, not a throughput number, and says nothing about S_p. The verifier's 9.3 s is nearly all SP1 setup per invocation (the pool runs one process per proof); a resident verifier would cut it to the 0.03 s verify. The trust-mode nodes carried the record before node 0 had verified it, which is the v0 limitation of spec 7.7 item 4 in one line: carriage and payout rest on the native statement, verification on the producer's pool policy.

@@ -515,7 +515,7 @@ table{min-width:560px}

4 October 2026, correction: the 78-minute observer gap was the Apple M5 Max hibernating

The "observer fell 45 minutes behind" entry left the cause open. The cloud-devnet agent's logs show the Apple M5 Max hibernated on a 1% battery from 11:56 to 13:16 UTC: node 1, the observer node, observer.mjs, the Apple M5 Max miner and every agent on the machine stopped; the two PCs, the seed and the cloud network carried the chain (no gap in the chain itself: every block the observer later stored carried its original header time). The lag-proofing stays (it is right on its own), the restart loop stays, and the public-face watch now runs from the same machine, so it also sleeps when the Apple M5 Max does; the fix is the charger and keep-awake, not software. The cloud scripts now re-exec under caffeinate -i.

-

2026-10-04 (afternoon) the app's prover loop end to end on the Apple M5 Max (Igneum Miner engine, packaged binaries, private test network)

+

2026-10-04 (afternoon) the app's prover loop end to end on the Apple M5 Max (Igneum Miner engine, packaged binaries, private test network)

Historical record of 2026-10-04: the code and the chain as they stood that day. The chain's current state is the release manifest.

Machine: Apple M5 Max, load 2 to 31 through the runs (other agents' builds and a Linux cross-build of the SP1 host ran alongside). Network: tools/proving-v0/run.mjs --network-only (3 proving nodes on 29800+, igneum-devnet-955, 60x fast time, activation 60, node 0 with the SP1 verifier, nodes 1 and 2 in trust mode, three vmine voters at 1 block/s). App: app/igneum-app engine (release, commit 77ea5b6) staged at /tmp/igneum-app-proving with bin/ = the proving node and miner (vendor/igneum-node-proving/target/release), the Metal worker, igneum-prove-host and igneum-prove-export (proving/igneum-prove/target/release), and an igneum-app.json whose node_override_params is the fast-time profile with skip_proof_of_work and the activation height; environment IGNEUM_APP_DEVNET_SUFFIX=955, RPC 29850, peers 127.0.0.1:29811 and 29801. Driven through its own API (setup with a pasted address 0x4343..., start, api/prove {on:true}); the Proving tile read every 5 s from api/state.

Run 1 (14:36 to 14:49 UTC, mining on the Metal worker at 12 to 20 MH/s): tile states as they happened:

Wall (UTC)TileNote
14:36:53idle, "no shard assigned to this machine in the last 60 blocks", 3 blocks acceptedthe key needs 5 blue blocks in the 120-DAA window (dust)
14:37:49idle, 5 blocks acceptedeligible from here
14:37:59proving block 140 shard 0 (0 txs, 0 pgas), assigned 10, "proving on the CPU (slow)"the first plan after eligibility assigned the key to 10 of the last 60 shards
14:40:02submitted (proved 1, submitted 1)compressed proof 107.0 s; the app's node accepted the record (verify Off: the app's node has no verifier, it relays)
14:40:04(node log) chain block 259 paid 634,083,030,000,000,000 wei to 0x4343...2 s after the submission; carried by a trust-mode node's block
14:43:22, 14:46:12blocks 268 and 447 proved (143.1 s, 115.3 s) and paid the same waythe tile still said paid 0
diff --git a/site/build.html b/site/build.html index 100e86345..b0ebaf8e8 100644 --- a/site/build.html +++ b/site/build.html @@ -253,7 +253,7 @@ table{min-width:560px}

The EVM you already know. Solidity deploys unchanged. Standard JSON-RPC, EIP-1559 transactions, the chain id in the signature, cancun as the EVM version. Gas has two dimensions on Igneum, execution and proving, and the node folds the second into the price it quotes, so eth_estimateGas and eth_gasPrice work as they do on Ethereum.

Networks

-
Devnet 3TestnetMainnet
Chain id4464 (0x1170) since its class v5 floor on 8 October 2026; 4463 below it4462 (0x116e)4461 (0x116d)
Network idigneum-devnet-3igneum-testnet-1not started
RPChttps://rpc.devnet.igneum.network (a node you run serves http://127.0.0.1:26790)https://rpc.testnet.igneum.network (answers; nothing mines there yet, so a transaction waits)none
Coinsno value, resets without noticeno value, resets with noticenot started
Symbol, decimalsIGN, 18IGN, 18IGN, 18
+
Devnet 3TestnetMainnet
Chain id4464 (0x1170) since its class v5 floor on 8 October 2026; 4463 below it4462 (0x116e)4461 (0x116d)
Network idigneum-devnet-3igneum-testnet-1not started
RPChttps://rpc.devnet.igneum.network (a node you run serves http://127.0.0.1:26790)https://rpc.testnet.igneum.network (answers; nothing mines there yet, so a transaction waits)none
Coinsno value, resets without noticeno value, resets with noticenot started
Symbol, decimalsIGN, 18IGN, 18IGN, 18
Machine-readable/release.json: the chain id, the source commits and fingerprints, the mining class, the finality rule, the proof program ids, the fee schedule and the current version per platform, with a generated date

Devnet 3 is where you build today. It is a developer network: it resets without notice and its coins have no value. Its public RPC takes the read methods, eth_sendRawTransaction and a wRPC websocket at /ws, at 20 requests a second per address. The public testnet exists, its RPC answers, and no blocks are being produced on it until it opens. Mainnet has no date. Devnet 3 answered 4463 until its class v5 floor at DAA 68,400 on 8 October 2026 and 4464 from it; read it with eth_chainId rather than fixing it, since a transaction signed for the wrong id is refused.

Endpoints and tools

diff --git a/site/build.mjs b/site/build.mjs index e31da1944..cb7063759 100644 --- a/site/build.mjs +++ b/site/build.mjs @@ -131,11 +131,27 @@ function meta(title, desc, path) { `; } +// The release manifest (8 October 2026, an accepted external review): site/release-manifest.json is served at /release.json +// (vercel.json rewrite) and every number a status page carries from it sits in ..., filled here +// at build; tools/ci/release-manifest-check.mjs holds the committed pages to the manifest and the manifest to its sources. +const RM = JSON.parse(readFileSync(join(here, 'release-manifest.json'), 'utf8')); +export function rmValue(path) { + const v = path.split('.').reduce((o, k) => (o == null ? undefined : o[k]), RM); + if (v === undefined) throw new Error(`release-manifest.json: no value at ${path}`); + return typeof v === 'number' && !/_id$/.test(path) ? v.toLocaleString('en-GB') : String(v); // an id is never grouped +} +export function fillManifest(html) { + // the hand pages carry ; the markdown sources carry {{rm:path}} (their renderer escapes raw HTML) + html = html.replace(/\{\{rm:([a-z0-9_.-]+)\}\}/g, (m, p) => `${rmValue(p).replace(/&/g, '&').replace(/`); + return html.replace(/[^<]*<\/span>/g, (m, p) => `${rmValue(p).replace(/&/g, '&').replace(/`); +} function sectionise(bodyHtml) { // the markdown renderer's flat stream, cut at every h2 into
so the contents rail and the // text filter work on sections; anything before the first h2 is its own section const parts = bodyHtml.split(/(?=

${p}

`).join('\n'); + // a dated log entry is a historical record (8 October 2026): the label sits under its heading, the current state is /release.json + const hist = (p) => p.replace(/^(

[\s\S]*?<\/h2>)/, (m, h, d) => `${h}

Historical record of ${d}: the code and the chain as they stood that day. The chain's current state is the release manifest.

`); + return parts.filter(p => p.trim()).map(p => `
${hist(p)}
`).join('\n'); } function page(title, desc, bodyHtml, toc, note, { path = '/bench', heading = title, eyebrow, crumb, filter = true } = {}) { const active = path.replace(/^\//, ''); @@ -288,7 +304,8 @@ for (const [src, file, title, desc, heading, lead, eyebrow] of [ ]) { const mdp = join(docs, 'build', src); if (!existsSync(mdp)) continue; // the gate builds a copy of site/ alone: the committed page stands, as for /bench - const { html, toc } = md(readFileSync(mdp, 'utf8')); + const { html: mdHtml, toc } = md(readFileSync(mdp, 'utf8')); + const html = fillManifest(mdHtml); const path = '/' + file.replace(/\.html$/, ''); writeFileSync(join(here, file), page(title, desc, html, toc, lead, { path, heading, crumb: heading, eyebrow, filter: false }).replace('

Generated from the repository at build time. Times are UTC. Machine names are model names.

', `

Generated from docs/build/${src} in the repository at build time. Times are UTC.

`)); built.push(file); @@ -378,7 +395,7 @@ function renderEvidence(html) { const start = src.indexOf('\n| # | Claim |'); const end = src.indexOf('\n## Count by status'); if (start < 0 || end < 0) throw new Error('evidence.md: claims table not found'); const rows = src.slice(start, end).split('\n').filter(l => /^\| \d+ \|/.test(l)); - const LABELS = ['designed', 'implemented', 'tested by the team', 'reproduced externally', 'reviewed independently']; + const LABELS = ['designed', 'implemented', 'activated', 'tested by the team', 'reproduced externally', 'reviewed independently']; const inl = t => esc(t.trim()).replace(/`([^`]+)`/g, (m, c) => `${c}`); const cells = l => l.replace(/^\| /, '').replace(/ \|$/, '').split(' | '); const counts = Object.fromEntries(LABELS.map(k => [k, 0])); @@ -424,6 +441,30 @@ for (const [file, active] of PAGES) { html = stampDownloads(html, file, downloads); html = stampMarks(html); if (file === 'evidence.html') html = renderEvidence(html); + // /economics, "Who pays for proving" (8 October 2026, an accepted external review): the model table is computed here from + // site/lib/emission.mjs (the node's constants) and the release manifest, never typed; the measured rows on the page are the + // observer's proving view as read that day. Labels: the per-day pool is modelled from the schedule; the per-shard and per-key + // lines hold today's measured shard and key counts constant; nothing here is a price. + if (file === 'economics.html' && html.includes('')) { + const em = await import('./lib/emission.mjs'); + const ign = (s) => Number(em.sompiToIgn(s)); + const fmt = (n, d = 2) => n.toLocaleString('en-GB', { maximumFractionDigits: d, minimumFractionDigits: d }); + const PV = RM.proving_view; // the measured 24-hour read on the page (shards paid, IGN paid, keys, planned) + const daa = Number(PV.read_daa); + const poolShare = Number(RM.fees.subsidy_split.proving_pool_percent) / 100; + const rows = []; + const line = (label, subsidyIgn, when, note) => { + const poolBlock = subsidyIgn * poolShare, poolDay = poolBlock * 86400; + rows.push(`${label}${fmt(subsidyIgn, 3)}${fmt(poolBlock, 3)}${fmt(poolDay, 0)}${fmt(poolDay / PV.shards_planned_24h, 2)}${fmt(poolDay / 24 / PV.prover_keys_24h, 1)}${when}${note ? `; ${note}` : ''}`); + }; + line('Today, inside the launch ramp', ign(em.blockSubsidy(daa)), `DAA ${daa.toLocaleString('en-GB')}, ${(em.rampFactor(daa) * 100).toFixed(1)} percent of the full rate`, 'modelled; the measured payout is in the row above'); + const names = ['Full rate (years 1 to 2)', 'After the first halving (years 3 to 4)', 'After the second (years 5 to 6)', 'After the third (years 7 to 8)', 'After the fourth (years 9 to 10)', 'After the fifth (years 11 to 12)']; + names.forEach((n, p) => line(n, ign(em.subsidyPerSecond(p)), `period ${p} of the schedule`, p === 0 ? 'from day 30' : '')); + const table = `
${rows.join('')}
WhenSubsidy per block, IGNPool per block, IGNPool per day, IGNPer planned shard, IGNPer prover key per hour, IGNBasis
+

Modelled from emission.rs (the schedule as site/lib/emission.mjs carries it) and the release manifest at build time, with today's measured shard count (${PV.shards_planned_24h.toLocaleString('en-GB')} planned in 24 hours) and key count (${PV.prover_keys_24h}) held constant; the per-shard figure is the pool's credit per planned shard, the per-key figure the pool per day divided by the keys and by 24. More shards or more keys lower both; a block's unproven shards leave their credit in the escrow.

`; + html = inject(html, 'proving-model', table, file); + } + html = fillManifest(html); if (file === 'index.html' && html.includes('')) html = inject(html, 'journey', ``, file); // /income (8 October 2026): the calculator's card list is the bench table's current rows, stock and tuned apart, inlined // at build so the page needs no fetch; a row's watts carry their class when they were read under another (watts_class) diff --git a/site/economics.html b/site/economics.html index 474d02ba7..1018b4af5 100644 --- a/site/economics.html +++ b/site/economics.html @@ -4,7 +4,7 @@ Igneum economics: the emission as the node encodes it - + @@ -193,7 +193,7 @@

The economics, as the node encodes them.

-

Every number below is read from the node’s source at one commit, with the file and the line. No price of IGN appears and nothing is projected: this page says what the code pays, to whom, and from what.

+

Every number below is read from the node’s source at one commit, with the file and the line, and the constants the chain runs on are the release manifest’s, filled at build time (node f8da7515, read 8 October 2026, 15:50 UK). No price of IGN appears and nothing is projected: this page says what the code pays, to whom, and from what.

Source: the node fork, branch release-0.3.25-node at e0644958 (the Devnet 3 cut of 8 October 2026), confirmed by the node lane on 8 October 2026; every line number is that commit’s. Devnet 3 inherits the devnet parameters (consensus/core/src/config/params.rs 2173 and 2207).

@@ -203,7 +203,7 @@
- + @@ -216,8 +216,8 @@
FieldCURRENT (Devnet 3 today, mainnet)TESTNET_1 (igneum-testnet-1)Where
Launch rate3,168,808,781 base units a DAA second (109 IGN x 108 / 31,557,600, floored: one billion IGN in year one)100 IGN a DAA secondemission.rs 85 to 123; igneum.rs 34
Launch rate3,168,808,781 base units a DAA second (109 IGN x 108 / 31,557,600, floored: one billion IGN in year one)100 IGN a DAA secondemission.rs 85 to 123; igneum.rs 34
Ramp2,592,000 s (30 days) from 10 percent7,776,000 s (90 days) from 10 percentigneum.rs 76 launch_ramp
Step63,115,200 s (two years), the rate halved each step (decay 231 of 232)2,629,800 s (a month), the rate times 2-1/24 each step (decay 4,172,697,914 of 232: a two-year half-life)emission.rs 85 to 123
Tailnone: the curve runs to zero and the sum is the hard cap, 4,000,000,000 IGN1 percent of supply a year (100 basis points) once the glide falls below itemission.rs 69 to 71
- - + + @@ -228,7 +228,7 @@ - +
ShareGoes toStateWhere
80 percentthe miner whose key found the blockin consensus on every networkconsensus/core/src/igneum.rs 44 (PROVING_POOL_SHARE_PERCENT = 20), applied at 87 and 202
20 percentthe proving pool, paid per shard to the provers of a segment record from a keyless escrow accountin consensus; the escrow is PROVING_POOL_ADDRESS in the execution layerigneum.rs 44; igneum/exec/src/config.rs
80 percentthe miner whose key found the blockin consensus on every networkconsensus/core/src/igneum.rs 44 (PROVING_POOL_SHARE_PERCENT = 20), applied at 87 and 202
20 percentthe proving pool, paid per shard to the provers of a segment record from a keyless escrow accountin consensus; the escrow is PROVING_POOL_ADDRESS in the execution layerigneum.rs 44; igneum/exec/src/config.rs
A silent block’s bonusa slice of the producer’s share moved to the pool when the producer did not sign its checkpoints, nothing destroyeddesigned and in the code, not active: signing_bonus_activation_daa is u64::MAX on every objectigneum.rs 96 silent_split; params.rs 1717
0any team, foundation, fund or treasuryno such output exists in the subsidy and no protocol tip reaches any addressigneum.rs; spec 05 section 5.5
RouteWhat happensStateWhere
Base fee, both gas dimensionsburned in full: gas used times the execution base fee, pgas used times the proving base fee, debited and credited to no onein the code on Devnet 3igneum/exec/src/executor.rs 320 to 371 (327 and 357, 328 and 360)
Priority fee (the tip)80 percent to the block’s miner; 20 percent to the developer registrations of the contracts whose code ran, pro rata by each frame’s gas; an unregistered frame’s part is credited to nobody, which is a burnin the code on Devnet 3executor.rs 335 to 339; igneum/exec/src/pgas.rs 290; igneum/exec/src/config.rs 76 (DEVELOPER_SHARE_PERCENT = 20)
Priority fee (the tip)80 percent to the block’s miner; 20 percent to the developer registrations of the contracts whose code ran, pro rata by each frame’s gas; an unregistered frame’s part is credited to nobody, which is a burnin the code on Devnet 3executor.rs 335 to 339; igneum/exec/src/pgas.rs 290; igneum/exec/src/config.rs 76 (DEVELOPER_SHARE_PERCENT = 20)
External proving jobs90 percent to the provers who delivered, 10 percent burned, once jobs settle in IGNdesigned, not in the code: no constant exists; at launch a job is paid on the customer’s own chainspec 05 section 5.4; the litepaper’s Proving section
@@ -246,6 +246,30 @@
+

Who pays for proving

+

Three incomes, kept apart. Each has its own source and its own state.

+
+ + + +
IncomeWhere it comes fromWho gets itState
Block securitythe block subsidy (80 percent of each block) and 80 percent of the priority feethe miner whose key found the blockin consensus on every network (measured)
Internal provingthe proving pool: a fifth of each block’s subsidy (20 percent), paid per shard against a valid proof record, plus the provers’ part of the priority feethe prover keys that delivered the shardsin consensus on Devnet 3 (measured below)
External customerspayments from other chains for proofs, settled in IGN: 90 percent to the provers, 10 percent burnedthe provers who took the jobdesigned, not implemented: no constant exists, no job has been paid
+

The proving base fee pays nobody. A transaction’s pgas times the proving base fee is burned in full today (executor.rs, the base-fee row above). It is not a prover’s income and it does not fill the pool. The pool is filled by the subsidy alone, and the subsidy halves every two years.

+

What the pool pays, measured

+

On Devnet 3 in the 24 hours to 12:16 UK on 8 October 2026: 8,209 shards paid, 9,913.09 IGN in all, to 29 prover keys; 40,502 shards planned, so about a fifth of the planned shards were proven and paid and the rest left their credit in the escrow; 905 shards paid in the last hour; the lag from a proven block to the block that pays p50 514 and p90 953 DAA seconds. Per shard paid that is about 1.21 IGN; per key about 12 shards and 14 IGN an hour averaged over the day, across keys that prove at very different rates (measured; the observer’s proof tables through /api/explorer?proving=1).

+

What reaches provers under the schedule, modelled

+

Low fees and no external demand, which is the chain today: the pool is a fifth of the subsidy and nothing else. The table holds today’s shard count and key count constant and walks the halvings. No price of IGN appears; whether a row covers a card’s electricity depends on the price, which this page does not state.

+ +
WhenSubsidy per block, IGNPool per block, IGNPool per day, IGNPer planned shard, IGNPer prover key per hour, IGNBasis
Today, inside the launch ramp3.8940.77967,2861.6696.7DAA 65,900, 12.3 percent of the full rate; modelled; the measured payout is in the row above
Full rate (years 1 to 2)31.6886.338547,57013.52786.7period 0 of the schedule; from day 30
After the first halving (years 3 to 4)15.8443.169273,7856.76393.4period 1 of the schedule
After the second (years 5 to 6)7.9221.584136,8933.38196.7period 2 of the schedule
After the third (years 7 to 8)3.9610.79268,4461.6998.3period 3 of the schedule
After the fourth (years 9 to 10)1.9810.39634,2230.8449.2period 4 of the schedule
After the fifth (years 11 to 12)0.9900.19817,1120.4224.6period 5 of the schedule
+

Modelled from emission.rs (the schedule as site/lib/emission.mjs carries it) and the release manifest at build time, with today's measured shard count (40,502 planned in 24 hours) and key count (29) held constant; the per-shard figure is the pool's credit per planned shard, the per-key figure the pool per day divided by the keys and by 24. More shards or more keys lower both; a block's unproven shards leave their credit in the escrow.

+ +

Per card, per hour, now and at each halving

+

A card’s proving income is its shards times the credit per shard. Measured rates: an RTX 5090 proves an empty live shard beside its miner in 7.0 to 7.7 s and a full shard in 10.9 s alone, about 37 s a shard end to end (export, cut, key set-up, prove, sign, submit), 1.4 shards a minute; an RTX 3060 (12 GB) proves the v1 shard beside its miner in 37.5 s; an RTX 4060 (8 GB) proves it alone in 18.4 s (the engineering log, 4 to 6 October 2026). At those rates one card can prove 80 to 100 shards an hour, more than the 905 an hour the whole chain paid to 29 keys, so today a prover is limited by the shards on offer, not by its card: the hourly figure per key in the table is the ceiling an evenly shared pool gives, and a 5090 and a 3060 take the same credit per shard. At each halving the credit per shard halves with the pool; a card’s watts do not. (Modelled from the measured rates; the chain’s shard count is the real limit.)

+

Two honest routes to sustain it

+
+ + +
RouteWhat it doesWhat it is worthState
A defined share of fees to the proving poola fixed percentage of the base fees burned today (both gas dimensions) credited to the pool instead, by a rule at genesis or a class changeeach percent of the share adds one percent of the day’s burned base fees to the pool. Priced per unit, not predicted: at 100,000 IGN of base fees burned in a day (a hypothetical volume, not a forecast) a 10 percent share adds 10,000 IGN a day, about today’s measured payout; at Devnet 3’s fee volume today it adds almost nothing, because almost nothing is burneddesigned as an option; no constant exists
External settlement in IGNother chains pay for proofs in IGN; 90 percent to the provers, 10 percent burnedthe price a prover must charge is the subsidy it forgoes while it proves: per shard, (card hash ÷ network hash) × 0.8 × the block subsidy × shard seconds. For an RTX 5090 at 136 MH/s on a 1 GH/s network and a 37 s shard that is about 16 IGN a shard inside the ramp today and about 128 IGN at the full rate, against the pool’s 1.2 IGN a shard measured; the quote falls as one over network hash and is competitive near 100 GH/s (the litepaper, Building on Igneum)designed; the settlement contract is not built
+

The chip question (whether a chip gets built against the hash, and what it would earn) is a conditional argument of its own on the litepaper’s chip model, not part of this page.

Units and decimals

@@ -258,7 +282,7 @@

The symbol is IGN on every network. A wallet shows 18 decimals everywhere; on Devnet 3 the chain pays in 8 and the bridge shows the same amount at 18.

What this page does not do

-

It names no price, projects no income and models no market. The income page turns these rules into IGN a day for a card you pick, and money a day only at a price you type. Devnet and testnet IGN have no value.

+

It names no price and models no market; the proving model above walks the subsidy schedule at today’s measured shard and key counts and states no price. The income page turns these rules into IGN a day for a card you pick, and money a day only at a price you type. Devnet and testnet IGN have no value.

Not legal advice.

diff --git a/site/evidence.html b/site/evidence.html index 282d168a4..a08382de4 100644 --- a/site/evidence.html +++ b/site/evidence.html @@ -4,13 +4,13 @@ Igneum evidence - + - + @@ -18,7 +18,7 @@ - + @@ -246,57 +246,59 @@ td.mono{font-family:var(--f-mono);font-size:12.5px;min-width:180px}td.iv{color:v
31 claims · 5 labels · 8 Oct 2026

Evidence.

-

Every claim the homepage and the litepaper make, one row each, with one of five labels: designed (a decision, no code), implemented (code with passing test vectors), tested by the team (measured by the project on a named machine, in the engineering log), reproduced externally (a third party ran the published command and got the published result) and reviewed independently (a named outside reviewer published a finding on that version). Nothing on this chain has been reproduced externally or reviewed independently; every row says so. A label belongs to the exact version in the row, and an audit of one version never covers a newer one. The 12-node cloud network of 4 October 2026 is the project's own, so its rows are tested by the team, not reproduced externally.

+

Every claim the homepage and the litepaper make, one row each, with one of six labels: designed (a decision, no code), implemented (code with passing test vectors), activated (live on a named chain by its activation height, on the node’s own line), tested by the team (measured by the project on a named machine, in the engineering log), reproduced externally (a third party ran the published command and got the published result) and reviewed independently (a named outside reviewer published a finding on that version). Nothing on this chain has been reproduced externally or reviewed independently; every row says so. A label belongs to the exact version in the row, and an audit of one version never covers a newer one. The 12-node cloud network of 4 October 2026 is the project's own, so its rows are tested by the team, not reproduced externally.

designed
6

A decision in the design document or the specification. No code, or a stub

implemented
3

Code in the repository with test vectors that pass. Not measured as the claim

+
activated
0

Live on a named chain by its activation height, on the node’s own line. Not yet a measurement of the claim

tested by the team
22

Measured or exercised by the project on a named machine, with the command in the log

reproduced externally
0

None yet. Nobody outside the project has run a published command yet

reviewed independently
0

None yet. What review would cost and who pays is in the funding plan

-
+

The table is wider than this screen. Scroll it sideways.

NetworkConsensus sideEVM sideWhere
- + - - - - - - - - - - - - + + + + + + + + + + + + - - + + - - + + - + - - - - + + + +
#ClaimStatusVersion or commitReproducible testResult, date, machineIndependent verification
1A new mining program every hour, compiled by the miner, with no human in the loop and no pause in mining
Homepage hero and "This hour's program"; litepaper Mining
tested by the teamigneum-pow 0.2.0; repo b27da39, 1292110, 100c5d7; fork devnet-v4 6457ca95The live devnet v4: the node announces next_epoch_seed 150 DAA past the seed score, igneum-miner sends prepare to its worker, the worker builds the next program while the current one mines; Metal (proto-metal/igneum-bench), CUDA and OpenCL workers; bench-log "first hourly program swap on the live devnet"Epoch boundary at DAA 3,600 (10:05:07 UTC, 4 October 2026) crossed live on three vendors: the Apple M5 Max M5 Max (Metal) compiled the next program in 82 ms, 449 DAA before the boundary, swapped in 0.01 ms, 26.7 MH/s before and after; the RTX 5090 compiled in 1,285 ms, swapped in 0.00 ms, 121.8 before and 123.4 MH/s after; the integrated AMD chip 2.74 MH/s before and after. 0 restarts, 0 rejected blocks, 0 rebuilds. The epoch seed is the epoch block hash; the delay of row 2 is not wired in. At a later boundary (DAA 18,000) one OpenCL worker on the RTX 5090 Windows rig stayed on the previous epoch after an app reinstall and answered 514 jobs with a seed mismatch; fixed in the miner (3bfe346f, workers emit a need line), the swap time of that forced prepare not measurednone yet
1A new mining program every hour, compiled by the miner, with no human in the loop and no pause in mining
Homepage hero and "This hour's program"; litepaper Mining
tested by the teamigneum-pow 0.2.0; repo b27da39, 1292110, 100c5d7; fork devnet-v4 6457ca95The live devnet v4: the node announces next_epoch_seed 150 DAA past the seed score, igneum-miner sends prepare to its worker, the worker builds the next program while the current one mines; Metal (proto-metal/igneum-bench), CUDA and OpenCL workers; bench-log "first hourly program swap on the live devnet"Epoch boundary at DAA 3,600 (10:05:07 UTC, 4 October 2026) crossed live on three vendors: the Apple M5 Max M5 Max (Metal) compiled the next program in 82 ms, 449 DAA before the boundary, swapped in 0.01 ms, 26.7 MH/s before and after; the RTX 5090 compiled in 1,285 ms, swapped in 0.00 ms, 121.8 before and 123.4 MH/s after; the integrated AMD chip 2.74 MH/s before and after. 0 restarts, 0 rejected blocks, 0 rebuilds. The epoch seed is the epoch block hash; the delay of row 2 is not wired in. At a later boundary (DAA 18,000) one OpenCL worker on the RTX 5090 Windows rig stayed on the previous epoch after an app reinstall and answered 514 jobs with a seed mismatch; fixed in the miner (3bfe346f, workers emit a need line), the swap time of that forced prepare not measurednone yet
2The program seed passes through a 10-minute verifiable delay from a certified checkpoint, so nobody can grind the seed
Litepaper Mining, vs RandomX ("Closed by a verifiable delay")
implementedrepo 792776e; proto-vdf/proto-vdf full 10-minute runs and the tamper cases in proto-vdf/README.md; bench-log "proto-vdf"Class group 1024-bit: 163,000 squarings per second, 10-min eval 585.4 s, prove 9.1 s on 12 threads, verify 4.47 ms, 516-byte proof; wrong checkpoint, flipped seed bit and T+1 all rejected; grinding model gains 0 blocks per epoch with the delay against +3.62 at a 30% advantage without it. 3 October 2026, Apple M5 Max, one core. Prototype only: not in the node on 4 October either, not reviewed against chiavdf (O-4.1)none yet
3The dataset is memory-hard: computing an item costs more than loading it, and every hash does 128 distinct dataset reads
Litepaper Mining and vs RandomX; homepage vs RandomX ("Memory 2 GB, growing")
tested by the teamrepo 58a5a63 (memory-hard), b27da39 (generator 2); igneum-pow 0.2.0 (memhard.rs, generator.rs, accept.rs); spec 01 sections 1.4.2 to 1.4.6; proto-metal/MEMHARD.mdproto-metal/igneum-bench --inline-dataset against the honest run at 1 GiB and 256 MiB; igneum-census --gen v2 --warps 64 over 20,000 programs; bench-log "memory-hard dataset" and "generator version 2 adopted"Honest 45.2 Mhash/s, inline (never reads the dataset) 9.49 Mhash/s, ratio 0.21 at 1 GiB, 0.10 at 256 MiB. 3 October 2026, Apple M5 Max. Generator 2, 4 October 2026: 20,000 programs, 128 static loads on every program, distinct addresses per hash mean 127.9, minimum 120.1; 5.2% of candidates rejected by the acceptance rule. The price of the 128 fresh reads is the hash rate: Apple OpenCL 45.0 MH/s on a version 1 program with 80 distinct loads against 27.5 to 27.9 on version 2; the RTX 5090 229 MH/s on a 104-load version 1 program at 1 GiB (3 October) against 121.8 to 124.2 MH/s mining version 2 on the live devnet (4 October). Apple only for the shortcut ratio (O-1.5); the on-die cache question of ledger M16 is unchangednone yet
4The same program produces identical hashes on three GPU vendors, cache and dataset included
Litepaper vs RandomX ("Bit-exact on Apple, NVIDIA and AMD, measured"), For miners; homepage
tested by the teamrepo f2e903e, 0f1fdaf (version 1 packs), b27da39 (version 2 packs igneum-genesis-mh, igneum-devnet-v4-epoch0); igneum-pow 0.2.0The 96 test vectors of a pack through proto-metal/igneum-bench, proto-cuda/host.cu, proto-opencl/host.c; batch fingerprint at --batch-log2 24; the miner's CPU re-check of every share a GPU worker finds on the devnet; bench-log entries "RTX 5090, memory-hard dataset", "AMD gfx1036", "RTX 5090 through NVIDIA OpenCL", "generator version 2 adopted", "the gfx1036 worker fault"Version 1: 96/96 on Apple Metal (M5 Max), NVIDIA CUDA and NVIDIA OpenCL (RTX 5090, Windows), AMD OpenCL (Ryzen 7 9800X3D integrated gfx1036, 1 compute unit), Apple OpenCL, pocl and two CPU references; batch fingerprint 98af644e993239e2 over 16.7 million nonces identical on the AMD chip and the 5090, 3 October 2026. Version 2: 96/96 on Apple Metal, Apple OpenCL and the CUDA and OpenCL emulators with identical fingerprints; on real NVIDIA and AMD silicon the version 2 vectors have not run as a pack, but both mined accepted blocks on the live devnet with the CPU re-check clean on every share (RTX 5090 at 124.2 MH/s, gfx1036 at 3.3 MH/s), 4 October 2026. The AMD device is an integrated chip; no discrete AMD card and no Intel card has run anything (O-1.15)none yet
5A CPU verifies one hash in under 10 ms by simulating one warp
Litepaper Mining ("about ten milliseconds"), vs RandomX; roadmap gate 2
tested by the teamrepo 75cac18, b27da39; igneum-pow 0.2.0 (verify.rs)cargo test and the crate bench in igneum-pow/; bench-log "igneum-pow: Rust crate bit-exact with proto-metal" and "generator version 2 adopted"0.411 to 0.579 ms per 32-lane warp steady, 0.41 to 0.87 ms cold, average of 20, 1 GiB dataset, cache held, one M5 Max performance core, 3 October 2026; version 2 units 0.631 ms (average of 20), cold 0.67 to 0.81 ms, 4 October 2026. Gate margin about 16x on this core. Not measured on a 2019-class laptop core (O-1.14)none yet
6The hash is bound to the header: one nonce serves one header, and a wrong nonce is rejected
Spec 1.6; litepaper Mining (implied by "checks a hash")
tested by the teamrepo 33f7b33, 9812466, b27da39; igneum-pow 0.2.0 (bind.rs, bound vectors re-cut for version 2, 39 crate tests)igneum-miner bad-nonce against a devnet node; igneum-pow hash-bound for the 96-nonce job across the 2^32 lane boundary; bench-log "first devnet blocks on the real lottery hash" and "generator version 2 adopted"833 blocks accepted by igneum-lottery-v1-bound on 3 nodes, 0 rejections; bad-nonce gave Reject(BlockInvalid); Metal, OpenCL and CUDA (emulated) workers bit-exact with the crate on the lane-boundary job, 3 October 2026, Apple M5 Max. Version 2: the node's engine reports igneum-lottery-v2-bound, 39 of 39 crate tests, and the live devnet v4 accepts its blocks under it, 4 October 2026none yet
7The devnet runs at one block a second
Homepage stats ("1 / s"); litepaper Speed; roadmap phase 3
tested by the teamrepo 9812466, e9328c6, 8dae48b; fork devnet-v4 dc749905The merged node's 3-node test network (igneum-devnet-880, 960 s); the live devnet v4 record sim/difficulty/records/live-2026-10-04.csv; the 12-node cloud network's arrival logs; bench-log "devnet-v4 integration", "difficulty rule v2", "first devnet blocks"Devnet 3, 7 October 2026: first block accepted at 17:06 UTC, 85 of 85 GPU blocks by 17:10 UTC and 287 by 17:14 UTC, 0 rejected (docs/plans/release-0.3.22.md section 5). Merged node, 4 October 2026, Apple M5 Max: 1,055 blocks in 960 s, 1.03 blocks/s, sink identical on 3 nodes at 31 of 31 samples, 0 rejected. Live devnet v4 the same day: 49 to 81 blocks a minute while two RTX 5090s joined and left (row 12), 1.1 to 1.2 blocks/s in the oscillating window, then within 1.3% per minute with one PC and the Apple M5 Max. The 12-node cloud network at one block a second: 644 blocks in a 10-minute window. The 3 October CPU devnet: 1.29 blocks/s over 641 s, 1.03 after the first retarget. The phase 3 gate also asks for proofs under 60 s behind the tip; no proof is on the chain (row 15)none yet
8Blocks are mined by GPUs on Apple and NVIDIA
Homepage live strip; journey phase 3 ("GPU miners on three vendors")
tested by the teamrepo 9812466, e9328c6, d7e1f89, 2309c8d; fork devnet-v4Metal worker proto-metal/igneum-bench --serve driven by igneum-miner --worker; the live devnet v4 hash-rate record sim/difficulty/records/live-2026-10-04-hashrate.csv (587 worker STATUS lines by run id); bench-log "first devnet blocks", "devnet v4 cut-over", "difficulty rule v2", "first machine on the Igneum Miner app"Metal: 506 jobs, 5,636 blocks found and accepted, 0 rejected, 0 CPU/GPU mismatches, 28.2 MH/s wall, 3 October 2026. Live devnet v4, 4 October 2026: the three-card Windows rig's RTX 5090 at 122 MH/s with 8 identities, the RTX 5090 Windows rig's at 124 MH/s with 8 identities (117 to 119 MH/s inside the one-click app, 34 accepted blocks in its first minute, CPU re-check OK on every share), the Apple M5 Max's Metal worker at 26.7 MH/s; 17 vote keys signed the first finality lock (row 10); from the afternoon an Apple silicon laptop outside the project at 21.0 MH/s through the app (row 30). Two RTX 5090s and two Apple chips; no other NVIDIA model has minednone yet
9Blocks are mined by a GPU on AMD
Journey phase 3 ("three vendors")
tested by the teamrepo 2c4b30f (generic OpenCL worker, --pack), 112acf6 (fault guards); bound kernel kernel_bound.cl in the packigneum-worker-opencl.exe --pack on the RTX 5090 Windows rig's integrated Radeon against the live devnet v4 through the Windows package; bench-log "the gfx1036 worker fault", "first hourly program swap", "first machine on the Igneum Miner app"the RTX 5090 Windows rig's integrated gfx1036 (1 compute unit) mined on the live devnet on 4 October 2026: 8 accepted blocks at 3.3 MH/s over 577 s with the CPU re-check clean, and 2.74 MH/s through the hourly program swap with 0 rejected. At about 600 s the AMD runtime began answering every call with success while running nothing (906 jobs became 56,384 in 30 s, 4.3 GH/s of phantom work); not reproduced on Apple OpenCL in 4,565 jobs with 0 leaked objects; the worker and miner now refuse a job 20x faster than the mean or an unchanged output buffer and restart (112acf6), and the next gfx1036 run names the guard that fires. One integrated chip; no discrete AMD card has run anythingnone yet
10Checkpoints lock every 30 s of chain at two thirds of all 30-day weight, and the floor stops conflicting locks in partitions and eclipses for as long as neither side's own new blocks carry it past two thirds of its window (about 10 days of a 30-day window at a 50/50 split)
Litepaper Finality, "What Igneum does not claim"; homepage "locked every 30 seconds"
tested by the teamrepo a3a9833 (2/3 floor, O-3.15), bbb264a (simulation), c16ccf1; fork devnet-v4 6457ca95 (FLOOR_NUM / FLOOR_DEN 2/3), da1eb889 (F17 by-weight sortition, F1 first-month gate min_daa = window); spec 3.3, 3.3.1, 3.7, 3.9The live devnet v4 (getFinalityCheckpoints, tools/observer/observer.mjs, /api/checkpoint); sim/finality_v2.py --floor 1.0, scenarios A to L; the three-node, six-voter partition runs igneum-devnet-921 to -923; tools/finality-attacks scenarios 1 to 6 and 8; bench-log "first finality lock on the live devnet", "finality floor 2/3", "finality v2 attack harness", "finality fixes F17 and F1"Devnet 3, 7 October 2026: finality rule v3 from block zero, first lock at 19:02 UTC, under two hours after the first block (docs/plans/release-0.3.22.md). The first devnet: the first lock on the live devnet was checkpoint 242 at 11:03:44 UTC on 4 October 2026, two hours after genesis (the window and min_daa are 7,200 DAA), with 77.4% of all weight and of active weight signed by 12 aggregated votes from 17 vote keys; observer.mjs saw it 0.7 s after the miner's own lock line. By 13:21 UTC the observer held 280 certificates, indices 241 to 522 (DAA 7,229 to 17,982), 17 to 27 voters, no index with two hashes. Test networks, 4 October 2026, Apple M5 Max: a 4/2 split locked on the 4 side (67.9%) 2 to 8 s after the cut and never on the 2 side, 0 conflicts; a 3/3 split locked on neither side for 150 s with 0 conflicts, where the 3 October floor (56.7%) would have locked both sides at 76 and 106 s; the rule guarantees one lock history for partitions shorter than the window bound W / (3R) (200 s on that test network's 1,800-DAA window, about 40 minutes on the devnet, about 10 days at the 30-day mainnet window); beyond that bound each side can reach two thirds of its own window, so the next finality rule freezes the weight table at the last certified checkpoint and pauses instead. Simulator with the 2/3 floor: 0 conflicts up to a 33% equivocator (34% splits a 50/50 partition), silent weight pauses locks from 34%, a 50/50 partition locks alone from day 10.1. Harness: equivocating keys stripped on every node, Sybil dust at zero weight, a pulsed miner's weight equal to its block share (ratio 0.96 to 1.0), the first-month gate stops a young window locking under one key. Not demonstrated: certificate injection on the wire, an eclipse with a private fork, the 2-hour presence window at mainnet lengthnone yet
11Hashrate that arrived today has almost no vote: ten days of the whole network's hashrate to reach a third of the weight, twenty for two thirds; 51% never reaches two thirds while honest miners stay
Litepaper Finality; homepage firsts
tested by the teamrepo bbb264a; sim/finality_v2.pyScenario B of sim/finality_v2.py, seeds 7 and 11share(t) = (t/30) x a/(1+a) holds to 0.04 points; a renter equal to the whole honest network (a = 1) crosses 1/3 on day 20 and never reaches 2/3; a = 9 crosses 1/3 on day 11.1 and 2/3 on day 22.2. The ten-day figure is a = infinity, honest miners gone. 3 October 2026, Apple M5 Max. A model with 1,000 Pareto keys and no DAG; the live devnet's window is two hours old, so the claim has no live measurement yetnone yet
12The difficulty rule recovers from a hashrate step within minutes, where Kaspa's sampled rule never settles. A step inside an epoch set the rule oscillating on the live devnet on 4 October 2026; rule v2 removes it in the simulator and on a test network and is built but not yet rolled out
Spec 2.3; litepaper Speed (implied); bench page
tested by the teamrepo e9328c6, abb5a5d (attacks), 67bf226 (rule v2); fork difficulty branch (timestamp fix) and devnet-v4 a21ff239 (difficulty_v2_activation_daa, REF_WINDOW_V2 = 600); sim/difficulty/sim.py --liveThe live record sim/difficulty/records/live-2026-10-04.csv (8,090 headers, pull_live.py) and the hash-rate record beside it; sim/difficulty/sim.py on the synthetic set and the DAG replay; sim/difficulty/attacks/attacks.py; sim/difficulty/testnet_v2.py (3 nodes, activation at DAA 900); cargo test --release -p kaspa-consensus --lib difficulty (15 pass); bench-log "difficulty controller", "difficulty rule under attack", "timestamp attack fixed", "difficulty rule v2"Live devnet v4, 4 October 2026 (UTC): a second RTX 5090 joining 7 minutes into an epoch (about 152 to 280 MH/s) hardened the difficulty 70M to 144M in 90 s and then swung by about a third for 40 minutes around the true level of 139M while the epoch-long reference lane carried the join; that card leaving for 4 minutes eased 116M to 67M and back to 106M; the epoch boundary with both PCs restarting took 152M to 77M in 3 minutes, after which the rule held within 1.3% per minute with no flips. Cause: the reference lane covered the whole epoch, so a mid-epoch step polluted it for the hour and the 25% trigger flipped on the short lane's noise. The DAG replay reproduces the record (std of log difficulty 0.115 against 0.134, 4.3 peaks against 4). Rule v2 (reference window 600 DAA) on the replay: std 0.026, 0 flips, mean 142.6M against 139M true; on a 3-node test network the v2 nodes eased a leave with no peak and held a rejoin within 3% after 60 s, and a node without the activation height forked off at it as designed. Rule v2 rolled onto the 12-node cloud network on 4 October (all nodes crossed the height on one chain; a hash-rate step then settled in 160 to 270 s with no swing) and activates on the devnet at DAA 33,000 the same evening. Timestamp forging (ledger M23) fixed the same day: a 50% forger drifts the rate under 1.1% where the 3 October rule gave it a 9.9x difficulty. Simulator, settled seconds: x50 step 62 to 66 (Kaspa 1,542), /50 step 657 to 753 (Kaspa 12,296). Apple M5 Max under load 7 to 442; the DAG model is fitted on one scale; the pool hopper's 0.7-point excess over Kaspa's rule stays opennone yet
13Every node executes the ordered transactions natively and reaches the same state root
Litepaper Proving ("Every node executes ... natively"), Building ("runs on Igneum unchanged")
tested by the teamrepo f5f8c80, 8dae48b; fork devnet-v4 dc749905; revm 43.0.3node tools/evm-smoke/smoke.mjs against a 3-node igneumd; igneum-exec-diff seq.json; bench-log "execution layer devnet v3" and "devnet-v4 integration"Simnet, 3 October 2026: 87 of 87 viem checks, state roots identical on 3 nodes at four heights, 57 executed and 19 skipped transactions agree with plain revm, 0 mismatches. Merged node on real proof of work, 4 October 2026: 84 of 85 checks (the miss needs parallel blocks the network did not produce in 36 s), 59 transfers in 10 chain blocks, state roots identical on 3 nodes, igneum-exec-diff 0 mismatches over 59 transactions; the live devnet v4 runs this execution layer. Apple M5 Max. The prover is a stub; state is rebuilt from genesis at start; no EVM transaction relay between nodesnone yet
14Ethereum bytecode runs unchanged, with the documented differences of spec 7.1
Homepage Build card; litepaper Building
tested by the teamas row 13; fixes F-exec-A, F-exec-B (spec 7.5)tools/evm-smoke/smoke.mjs: deploy via viem, increment, hashLoop, eth_estimateGas, eth_getLogs; tools/exec-attacks scenarios 1 and 3; bench-log "execution layer attack fixes"Deployment, calls, reverts, logs and gas estimates behave as viem expects; chain id 4463; the prototype pgas table gives 0.0095 to 0.028 pgas per gas, below the design's band before calibration, 3 October 2026. 4 October 2026: a transaction that would cross the block's proving budget is refused by the mempool and, if forced in, aborted and charged with its nonce advanced (25 of 25 checks; 30 of 30 malformed cases). Apple M5 Max. The Prover precompile, proof records and the shard planner are not in the nodenone yet
3The dataset is memory-hard: computing an item costs more than loading it, and every hash does 128 distinct dataset reads
Litepaper Mining and vs RandomX; homepage vs RandomX ("Memory 2 GB, growing")
tested by the teamrepo 58a5a63 (memory-hard), b27da39 (generator 2); igneum-pow 0.2.0 (memhard.rs, generator.rs, accept.rs); spec 01 sections 1.4.2 to 1.4.6; proto-metal/MEMHARD.mdproto-metal/igneum-bench --inline-dataset against the honest run at 1 GiB and 256 MiB; igneum-census --gen v2 --warps 64 over 20,000 programs; bench-log "memory-hard dataset" and "generator version 2 adopted"Honest 45.2 Mhash/s, inline (never reads the dataset) 9.49 Mhash/s, ratio 0.21 at 1 GiB, 0.10 at 256 MiB. 3 October 2026, Apple M5 Max. Generator 2, 4 October 2026: 20,000 programs, 128 static loads on every program, distinct addresses per hash mean 127.9, minimum 120.1; 5.2% of candidates rejected by the acceptance rule. The price of the 128 fresh reads is the hash rate: Apple OpenCL 45.0 MH/s on a version 1 program with 80 distinct loads against 27.5 to 27.9 on version 2; the RTX 5090 229 MH/s on a 104-load version 1 program at 1 GiB (3 October) against 121.8 to 124.2 MH/s mining version 2 on the live devnet (4 October). Apple only for the shortcut ratio (O-1.5); the on-die cache question of ledger M16 is unchangednone yet
4The same program produces identical hashes on three GPU vendors, cache and dataset included
Litepaper vs RandomX ("Bit-exact on Apple, NVIDIA and AMD, measured"), For miners; homepage
tested by the teamrepo f2e903e, 0f1fdaf (version 1 packs), b27da39 (version 2 packs igneum-genesis-mh, igneum-devnet-v4-epoch0); igneum-pow 0.2.0The 96 test vectors of a pack through proto-metal/igneum-bench, proto-cuda/host.cu, proto-opencl/host.c; batch fingerprint at --batch-log2 24; the miner's CPU re-check of every share a GPU worker finds on the devnet; bench-log entries "RTX 5090, memory-hard dataset", "AMD gfx1036", "RTX 5090 through NVIDIA OpenCL", "generator version 2 adopted", "the gfx1036 worker fault"Version 1: 96/96 on Apple Metal (M5 Max), NVIDIA CUDA and NVIDIA OpenCL (RTX 5090, Windows), AMD OpenCL (Ryzen 7 9800X3D integrated gfx1036, 1 compute unit), Apple OpenCL, pocl and two CPU references; batch fingerprint 98af644e993239e2 over 16.7 million nonces identical on the AMD chip and the 5090, 3 October 2026. Version 2: 96/96 on Apple Metal, Apple OpenCL and the CUDA and OpenCL emulators with identical fingerprints; on real NVIDIA and AMD silicon the version 2 vectors have not run as a pack, but both mined accepted blocks on the live devnet with the CPU re-check clean on every share (RTX 5090 at 124.2 MH/s, gfx1036 at 3.3 MH/s), 4 October 2026. The AMD device is an integrated chip; no discrete AMD card and no Intel card has run anything (O-1.15)none yet
5A CPU verifies one hash in under 10 ms by simulating one warp
Litepaper Mining ("about ten milliseconds"), vs RandomX; roadmap gate 2
tested by the teamrepo 75cac18, b27da39; igneum-pow 0.2.0 (verify.rs)cargo test and the crate bench in igneum-pow/; bench-log "igneum-pow: Rust crate bit-exact with proto-metal" and "generator version 2 adopted"0.411 to 0.579 ms per 32-lane warp steady, 0.41 to 0.87 ms cold, average of 20, 1 GiB dataset, cache held, one M5 Max performance core, 3 October 2026; version 2 units 0.631 ms (average of 20), cold 0.67 to 0.81 ms, 4 October 2026. Gate margin about 16x on this core. Not measured on a 2019-class laptop core (O-1.14)none yet
6The hash is bound to the header: one nonce serves one header, and a wrong nonce is rejected
Spec 1.6; litepaper Mining (implied by "checks a hash")
tested by the teamrepo 33f7b33, 9812466, b27da39; igneum-pow 0.2.0 (bind.rs, bound vectors re-cut for version 2, 39 crate tests)igneum-miner bad-nonce against a devnet node; igneum-pow hash-bound for the 96-nonce job across the 2^32 lane boundary; bench-log "first devnet blocks on the real lottery hash" and "generator version 2 adopted"833 blocks accepted by igneum-lottery-v1-bound on 3 nodes, 0 rejections; bad-nonce gave Reject(BlockInvalid); Metal, OpenCL and CUDA (emulated) workers bit-exact with the crate on the lane-boundary job, 3 October 2026, Apple M5 Max. Version 2: the node's engine reports igneum-lottery-v2-bound, 39 of 39 crate tests, and the live devnet v4 accepts its blocks under it, 4 October 2026none yet
7The devnet runs at one block a second
Homepage stats ("1 / s"); litepaper Speed; roadmap phase 3
tested by the teamrepo 9812466, e9328c6, 8dae48b; fork devnet-v4 dc749905The merged node's 3-node test network (igneum-devnet-880, 960 s); the live devnet v4 record sim/difficulty/records/live-2026-10-04.csv; the 12-node cloud network's arrival logs; bench-log "devnet-v4 integration", "difficulty rule v2", "first devnet blocks"Devnet 3, 7 October 2026: first block accepted at 17:06 UTC, 85 of 85 GPU blocks by 17:10 UTC and 287 by 17:14 UTC, 0 rejected (docs/plans/release-0.3.22.md section 5). Merged node, 4 October 2026, Apple M5 Max: 1,055 blocks in 960 s, 1.03 blocks/s, sink identical on 3 nodes at 31 of 31 samples, 0 rejected. Live devnet v4 the same day: 49 to 81 blocks a minute while two RTX 5090s joined and left (row 12), 1.1 to 1.2 blocks/s in the oscillating window, then within 1.3% per minute with one PC and the Apple M5 Max. The 12-node cloud network at one block a second: 644 blocks in a 10-minute window. The 3 October CPU devnet: 1.29 blocks/s over 641 s, 1.03 after the first retarget. The phase 3 gate also asks for proofs under 60 s behind the tip; no proof is on the chain (row 15)none yet
8Blocks are mined by GPUs on Apple and NVIDIA
Homepage live strip; journey phase 3 ("GPU miners on three vendors")
tested by the teamrepo 9812466, e9328c6, d7e1f89, 2309c8d; fork devnet-v4Metal worker proto-metal/igneum-bench --serve driven by igneum-miner --worker; the live devnet v4 hash-rate record sim/difficulty/records/live-2026-10-04-hashrate.csv (587 worker STATUS lines by run id); bench-log "first devnet blocks", "devnet v4 cut-over", "difficulty rule v2", "first machine on the Igneum Miner app"Metal: 506 jobs, 5,636 blocks found and accepted, 0 rejected, 0 CPU/GPU mismatches, 28.2 MH/s wall, 3 October 2026. Live devnet v4, 4 October 2026: the three-card Windows rig's RTX 5090 at 122 MH/s with 8 identities, the RTX 5090 Windows rig's at 124 MH/s with 8 identities (117 to 119 MH/s inside the one-click app, 34 accepted blocks in its first minute, CPU re-check OK on every share), the Apple M5 Max's Metal worker at 26.7 MH/s; 17 vote keys signed the first finality lock (row 10); from the afternoon an Apple silicon laptop outside the project at 21.0 MH/s through the app (row 30). Two RTX 5090s and two Apple chips; no other NVIDIA model has minednone yet
9Blocks are mined by a GPU on AMD
Journey phase 3 ("three vendors")
tested by the teamrepo 2c4b30f (generic OpenCL worker, --pack), 112acf6 (fault guards); bound kernel kernel_bound.cl in the packigneum-worker-opencl.exe --pack on the RTX 5090 Windows rig's integrated Radeon against the live devnet v4 through the Windows package; bench-log "the gfx1036 worker fault", "first hourly program swap", "first machine on the Igneum Miner app"the RTX 5090 Windows rig's integrated gfx1036 (1 compute unit) mined on the live devnet on 4 October 2026: 8 accepted blocks at 3.3 MH/s over 577 s with the CPU re-check clean, and 2.74 MH/s through the hourly program swap with 0 rejected. At about 600 s the AMD runtime began answering every call with success while running nothing (906 jobs became 56,384 in 30 s, 4.3 GH/s of phantom work); not reproduced on Apple OpenCL in 4,565 jobs with 0 leaked objects; the worker and miner now refuse a job 20x faster than the mean or an unchanged output buffer and restart (112acf6), and the next gfx1036 run names the guard that fires. One integrated chip; no discrete AMD card has run anythingnone yet
10Checkpoints lock every 30 s of chain at two thirds of all 30-day weight, and the floor stops conflicting locks in partitions and eclipses for as long as neither side's own new blocks carry it past two thirds of its window (about 10 days of a 30-day window at a 50/50 split)
Litepaper Finality, "What Igneum does not claim"; homepage "locked every 30 seconds"
tested by the teamrepo a3a9833 (2/3 floor, O-3.15), bbb264a (simulation), c16ccf1; fork devnet-v4 6457ca95 (FLOOR_NUM / FLOOR_DEN 2/3), da1eb889 (F17 by-weight sortition, F1 first-month gate min_daa = window); spec 3.3, 3.3.1, 3.7, 3.9The live devnet v4 (getFinalityCheckpoints, tools/observer/observer.mjs, /api/checkpoint); sim/finality_v2.py --floor 1.0, scenarios A to L; the three-node, six-voter partition runs igneum-devnet-921 to -923; tools/finality-attacks scenarios 1 to 6 and 8; bench-log "first finality lock on the live devnet", "finality floor 2/3", "finality v2 attack harness", "finality fixes F17 and F1"Devnet 3, 7 October 2026: finality rule v3 from block zero, first lock at 19:02 UTC, under two hours after the first block (docs/plans/release-0.3.22.md). The first devnet: the first lock on the live devnet was checkpoint 242 at 11:03:44 UTC on 4 October 2026, two hours after genesis (the window and min_daa are 7,200 DAA), with 77.4% of all weight and of active weight signed by 12 aggregated votes from 17 vote keys; observer.mjs saw it 0.7 s after the miner's own lock line. By 13:21 UTC the observer held 280 certificates, indices 241 to 522 (DAA 7,229 to 17,982), 17 to 27 voters, no index with two hashes. Test networks, 4 October 2026, Apple M5 Max: a 4/2 split locked on the 4 side (67.9%) 2 to 8 s after the cut and never on the 2 side, 0 conflicts; a 3/3 split locked on neither side for 150 s with 0 conflicts, where the 3 October floor (56.7%) would have locked both sides at 76 and 106 s; the rule guarantees one lock history for partitions shorter than the window bound W / (3R) (200 s on that test network's 1,800-DAA window, about 40 minutes on the devnet, about 10 days at the 30-day mainnet window); beyond that bound each side can reach two thirds of its own window, so the next finality rule freezes the weight table at the last certified checkpoint and pauses instead. Simulator with the 2/3 floor: 0 conflicts up to a 33% equivocator (34% splits a 50/50 partition), silent weight pauses locks from 34%, a 50/50 partition locks alone from day 10.1. Harness: equivocating keys stripped on every node, Sybil dust at zero weight, a pulsed miner's weight equal to its block share (ratio 0.96 to 1.0), the first-month gate stops a young window locking under one key. Not demonstrated: certificate injection on the wire, an eclipse with a private fork, the 2-hour presence window at mainnet lengthnone yet
11Hashrate that arrived today has almost no vote: ten days of the whole network's hashrate to reach a third of the weight, twenty for two thirds; 51% never reaches two thirds while honest miners stay
Litepaper Finality; homepage firsts
tested by the teamrepo bbb264a; sim/finality_v2.pyScenario B of sim/finality_v2.py, seeds 7 and 11share(t) = (t/30) x a/(1+a) holds to 0.04 points; a renter equal to the whole honest network (a = 1) crosses 1/3 on day 20 and never reaches 2/3; a = 9 crosses 1/3 on day 11.1 and 2/3 on day 22.2. The ten-day figure is a = infinity, honest miners gone. 3 October 2026, Apple M5 Max. A model with 1,000 Pareto keys and no DAG; the live devnet's window is two hours old, so the claim has no live measurement yetnone yet
12The difficulty rule recovers from a hashrate step within minutes, where Kaspa's sampled rule never settles. A step inside an epoch set the rule oscillating on the live devnet on 4 October 2026; rule v2 removes it in the simulator and on a test network and is built but not yet rolled out
Spec 2.3; litepaper Speed (implied); bench page
tested by the teamrepo e9328c6, abb5a5d (attacks), 67bf226 (rule v2); fork difficulty branch (timestamp fix) and devnet-v4 a21ff239 (difficulty_v2_activation_daa, REF_WINDOW_V2 = 600); sim/difficulty/sim.py --liveThe live record sim/difficulty/records/live-2026-10-04.csv (8,090 headers, pull_live.py) and the hash-rate record beside it; sim/difficulty/sim.py on the synthetic set and the DAG replay; sim/difficulty/attacks/attacks.py; sim/difficulty/testnet_v2.py (3 nodes, activation at DAA 900); cargo test --release -p kaspa-consensus --lib difficulty (15 pass); bench-log "difficulty controller", "difficulty rule under attack", "timestamp attack fixed", "difficulty rule v2"Live devnet v4, 4 October 2026 (UTC): a second RTX 5090 joining 7 minutes into an epoch (about 152 to 280 MH/s) hardened the difficulty 70M to 144M in 90 s and then swung by about a third for 40 minutes around the true level of 139M while the epoch-long reference lane carried the join; that card leaving for 4 minutes eased 116M to 67M and back to 106M; the epoch boundary with both PCs restarting took 152M to 77M in 3 minutes, after which the rule held within 1.3% per minute with no flips. Cause: the reference lane covered the whole epoch, so a mid-epoch step polluted it for the hour and the 25% trigger flipped on the short lane's noise. The DAG replay reproduces the record (std of log difficulty 0.115 against 0.134, 4.3 peaks against 4). Rule v2 (reference window 600 DAA) on the replay: std 0.026, 0 flips, mean 142.6M against 139M true; on a 3-node test network the v2 nodes eased a leave with no peak and held a rejoin within 3% after 60 s, and a node without the activation height forked off at it as designed. Rule v2 rolled onto the 12-node cloud network on 4 October (all nodes crossed the height on one chain; a hash-rate step then settled in 160 to 270 s with no swing) and activates on the devnet at DAA 33,000 the same evening. Timestamp forging (ledger M23) fixed the same day: a 50% forger drifts the rate under 1.1% where the 3 October rule gave it a 9.9x difficulty. Simulator, settled seconds: x50 step 62 to 66 (Kaspa 1,542), /50 step 657 to 753 (Kaspa 12,296). Apple M5 Max under load 7 to 442; the DAG model is fitted on one scale; the pool hopper's 0.7-point excess over Kaspa's rule stays opennone yet
13Every node executes the ordered transactions natively and reaches the same state root
Litepaper Proving ("Every node executes ... natively"), Building ("runs on Igneum unchanged")
tested by the teamrepo f5f8c80, 8dae48b; fork devnet-v4 dc749905; revm 43.0.3node tools/evm-smoke/smoke.mjs against a 3-node igneumd; igneum-exec-diff seq.json; bench-log "execution layer devnet v3" and "devnet-v4 integration"Simnet, 3 October 2026: 87 of 87 viem checks, state roots identical on 3 nodes at four heights, 57 executed and 19 skipped transactions agree with plain revm, 0 mismatches. Merged node on real proof of work, 4 October 2026: 84 of 85 checks (the miss needs parallel blocks the network did not produce in 36 s), 59 transfers in 10 chain blocks, state roots identical on 3 nodes, igneum-exec-diff 0 mismatches over 59 transactions; the live devnet v4 runs this execution layer. Apple M5 Max. The prover is a stub; state is rebuilt from genesis at start; no EVM transaction relay between nodesnone yet
14Ethereum bytecode runs unchanged, with the documented differences of spec 7.1
Homepage Build card; litepaper Building
tested by the teamas row 13; fixes F-exec-A, F-exec-B (spec 7.5)tools/evm-smoke/smoke.mjs: deploy via viem, increment, hashLoop, eth_estimateGas, eth_getLogs; tools/exec-attacks scenarios 1 and 3; bench-log "execution layer attack fixes"Deployment, calls, reverts, logs and gas estimates behave as viem expects; chain id 4463 at that version (4464 since the class v5 floor, 8 October 2026); the prototype pgas table gives 0.0095 to 0.028 pgas per gas, below the design's band before calibration, 3 October 2026. 4 October 2026: a transaction that would cross the block's proving budget is refused by the mempool and, if forced in, aborted and charged with its nonce advanced (25 of 25 checks; 30 of 30 malformed cases). Apple M5 Max. The Prover precompile, proof records and the shard planner are not in the nodenone yet
15Every block is proven, with the proof landing within about a minute at launch
Homepage stats ("~60 s to a proof"); litepaper Proving; roadmap phase 3 gate
implementedrepo d7e1f89 (GPU proof), e01a3cc, 292e800, eedd136 (proving/igneum-prove: shard cutter, MPT witnesses, shard and aggregator guests); SP1 6.8.1; spec 7.2, 7.6proving/windows-wsl2 (SETUP-PROVER, PROVE-BLOCK) on the RTX 5090; igneum-prove-host --mode block on proving/fixtures/; bench-log "proving v0 on the RTX 5090" and "proving: devnet v4 shards"First GPU proof of an Igneum block, 4 October 2026, RTX 5090 (WSL2, SP1 cuda, mining paused): fixture block-78-increment (2 transactions), core proof 1.4 s (7.3 MB, verify 0.221 s), compressed proof 2.7 s (1.27 MB, verify 0.038 s), post-state and receipts roots identical to the node's; 15.7x and 20.6x faster than a loaded M5 Max CPU. The same day on that CPU (load 38 to 47): a three-shard block proved shard by shard and aggregated by recursion, 19 min (1,139 s) end to end, 245 to 337 s per compressed shard proof, every proof verified. What is not there: no proof is produced, carried or checked on the chain (the devnet prover is a stub that signs claims), the proving pool pays nobody (row 21), the block proven is far below one shard, and the 60-second figure remains a design target; the pass mark is the standard in docs/benchmarks/proving-e2e.md. Second RTX 5090 run, 4 October 2026 evening (job run-20261004-173115): a full shard at the provisional S_p (6.75 M pgas, 60.8 M cycles) executed in 1.63 s, core proof 8.3 s (18.1 MB), compressed proof 10.9 s (1.27 MB, verify 0.040 s); a two-shard block (13.5 M pgas) proved shard by shard (11.7 s and 10.0 s) and aggregated in 2.2 s, 24 s of GPU stages end to end, every proof verified, six tampered witnesses rejected. The two host defects (an abort after the upload, an idle wait that turned out to be an unbuffered 18 MB proof save through the WSL2 file bridge, 24 minutes) are fixed (ledger P20) 5 October 2026, live devnet with real transactions (bench-log "real transactions, the first non-empty shard proven and paid"): block 72704 shard 0, 29 transfers, 5,800 pgas, proven on the RTX 5090 Windows rig in 34 s, verified on the Apple M5 Max in 0.297 s and paid 1.7623 IGN, 53 s after the chain block executed; of about 1,400 blocks in the 20-minute window 36 were proven (the one prover takes the newest shard assigned to it), so "every block" is not yet true; a second content shard (72803, all copies skipped) failed the native-execution veto on the exporter's block structure, fixed with fixtures the same day, the node side pending the 0.3.9 rollout 5 October 2026, evening (bench-log "proving v1"): the aggregated segment record, the chain rule and the unproven rule are implemented behind proving_v1_activation_daa (branch proving-v1, not on the devnet before 0.3.11); on the RTX 5090 a chain of 8 consecutive live blocks proved and aggregated by recursion in 135.6 s with the miner on the card (17 s a block, one proof of 1,272,909 bytes attesting all 8, verified in 0.04 s); the 3-node fast-time harness paid a segment record 1.0 s after submission and refused a late one after its deadline (21 checks); the devnet itself, with one prover, carried proofs for 2.4% of blocks over 30 minutes at a block-to-record latency p50 44 s, p99 52 s. The "within about a minute" holds per proven block; "every block" needs 18 mining 5090s or 6 proving-only cards at empty blocks on the measured rates, and the mandatory rule stays off until the share is onenone yet
16A 12 GB card proves one shard in about 20 s (WITHDRAWN 5 October 2026: a 24 GB card proves a full shard at the adopted size in 4.3 s; 32 GB mines and proves)
Litepaper Proving ("The proving budget"); roadmap gate 2
designedspec 5.1 (Target), 7.6 (S_p provisional, 7,500,000 pgas = B_p / 4)PROVE-SHARD.bat on the RTX 5090 (pending); the end-to-end standard in docs/benchmarks/proving-e2e.md; bench-log "proving: devnet v4 shards"Measured on a 32 GB card, not yet on a 12 GB card. A shard at the provisional S_p is 60.8 M SP1 cycles on the prototype pgas table (9 cycles per pgas, 44 per EVM gas; the modexp entry about 100x its SP1 cost); on an RTX 5090 (4 October 2026 evening, job run-20261004-173115) it executed in 1.63 s and its compressed proof took 10.9 s, verified in 0.040 s, so the 32 GB card is inside the 20 s target with margin. Whether a 12 GB card proves it at all, and in what time, is the next measurement (an RTX 3060 and an RTX 5060 Ti 16 GB are on order). A per-shard time can be met by shrinking the shard, so the project does not use it as a pass mark 5 October 2026, evening (bench-log "proving v1", the S_p curve): measured on the RTX 5090 with SP1 6.8.1's GPU prover, the card to itself, 1-s nvidia-smi samples: an empty shard 13,874 MiB and 2.2 s; a full shard at the ADOPTED v1 budget (30,000 pgas, 4.7 M cycles) 20,434 MiB and 4.3 s; the full prototype shard (6.75 M pgas, 60 M cycles) 28,307 MiB and 10.8 s; beside the miner 15,670 and 30,039 MiB. No environment knob of SP1 moves the 13.9 GB floor and the GPU server has no options of its own, so on this build a 12 GB card proves nothing, a 16 GB card only empty shards, a 24 GB card the adopted full shard alone and beside the miner (22,210 MiB and 13.2 s, measured on the 32 GB card: the 5090's allocation pattern, not yet a run on a 24 GB card) and a 32 GB card the prototype shard beside the miner with 2.5 GB spare. The litepaper line now says so; the 12 GB gate returns when a prover build with a smaller floor is measured on a 12 GB cardnone yet
17The chip resistance claim, served as the class v6 close words it: Class v6 adopts the 64-register window and retains it across every rotation. Current modelling places the strongest specialised designs assessed against the GPU tier at about 2.3x to 3.3x energy-efficiency advantage a node ahead (2.0x to 2.9x on the GPU's own node), a bracket that is approximate and provisional until the placed gated core rows land. The long-program and select-tree proposals were rejected. Economic resistance depends on development cost, deployment economics and productive hardware lifetime; family transitions receive an obsolescence benefit only where a loss of competitiveness is demonstrated; programmable multi-epoch designs are included in the assessment. Beside it: class v4 is live from the first block on the testnet and the mainnet; class v5 makes the dataset the chain's state so a stateless or stale chip is wrong on every item; the hot-set cache is bounded at 1.067x at the ceiling and the weak-day FPGA at 12 percent on 15 days a century, both routed to the next class; datacentre silicon does not change the question; the three statements (energy resistance, economic resistance, response capability) are served separate, with the harness and the scoring rule linked
the home page's chip line, the litepaper's chip section (/litepaper#chip-model), the miner page's line
the GPU side tested by the team (the RTX 5080 and RTX 5090 clock-lock passes under class v4, every card, the verifier, the two attack-pass bounds, the H100); the chip core synthesised on ASAP7 and scaled to N3, claimed; the chip's memory modelled; the node column claimed scaling; the economic surface modelled, first cut, conditional; the rotation schedule measured per boundary; class v5 designed; the Antminer X5 an observed comparison, not a ceiling; the X9 a withdrawn pre-order, never benchmarkeddocs/design/class-v6-rotating-family.md section 10 (10.0 to 10.0h, the close and its two accepted external reviews, 8 October 2026); docs/design/class-v5-stored-state.md sections 0, 13 and 14 and docs/design/class-v5-harness/ (branch class-v5); docs/design/class-rotation-four-layers.md; docs/analysis/chip-model-v3.md 5 and 6; docs/analysis/latency-shadow-2026-10-06.md; docs/analysis/attack-pass/f8-uniform.md, f4-weakday.md, docs/analysis/ca3-v4-uniform.md; the H100 row of 7 October; docs/plans/cryptanalysis/in-house-pass.md (the internal adversarial pass)the scoring rule in the close (the minimum over workloads of the maximum over free adversarial designs of the GPU's joules per hash over the adversary's, under the 10 percent GPU-cost budget at the lock, the verifier limit, cross-vendor correctness and hardware accessibility); the card rows by the benchmark package; the class v5 harness and the family harness; the attack-pass harnesses tools/attack/f8-uniform and the F4 census; the verifier by igneum-pow bench136 MH/s at 350 W (5090, bench) and 290 W (app); the class v4 efficiency passes (bench log "7 to 8 October 2026, the class v4 efficiency passes: the core clock lock on the RTX 5090 and the RTX 5080", measured): the 5090 at 136.84 MH/s and 475.5 W unlocked, 134.98 at 316.3 W at a 1,400 MHz core lock, the best points class v4 at 1,200 MHz (133.80 MH/s, 305.1 W, 0.439 MH/W) and class v3 at 1,300 MHz (134.62, 223.3 W, 0.603), the premium 145 W unlocked and 82 W at the best points, the knee 1,300 MHz; the RTX 5080 (8 October 2026, the dock card of the three-card Windows rig) at 71.41 MH/s and 253.1 W unlocked under class v4 against 71.28 at 169.7 W under class v3, the best points class v4 at 1,100 MHz (71.20 MH/s, 146.6 W, 0.486 MH/W) and class v3 at 1,000 MHz (71.11, 103.7 W, 0.686), the premium 83.4 W unlocked and 41 W at the best points, the knee between 1,000 and 900 MHz; per tier: a 5080 owner on class v4 locked near 1,100 MHz pays 147 W instead of 253 for 0.3 percent less rate, MH per watt up 72 percent, the lever Ember Tune's core-clock knob in 0.3.24; 27 MH/s at 21 W (M5 Max); 249 MH/s (H100 SXM) at 98 percent of its read ceiling, 1.78x hash, 1.15x MH/W, a third per rented dollar; 2.33 ms per warp; the GPU side of the close: the RTX 5080 at its 1,100 MHz lock 2.06 microjoules per hash and the RTX 5090 at its 1,300 MHz lock 2.33 (class v4, 8 October 2026); the modelled bracket about 2.3x to 3.3x a node ahead and 2.0x to 2.9x node for node (approximate, provisional; the clock-gated base core k about 0.37 at N3, the gated window adding about 0.13; the first placed core 64 percent above synthesis), the placed gated row expected near 2.6x to 3.1x and 2.3x to 2.7x and served when it lands; the shadow's premium on a 5090 81.8 W at its knee (class v4 at the 1,200 MHz lock 133.80 MH/s at 305.1 W; class v3 at 1,300 MHz 134.62 at 223.3 W; 7 October 2026); 1.067x at the ceiling; 12 percent on 15 days a century; 10.85 ms at rung 3; 6 to 8 October 2026, the M5 Max, the desk rigs' RTX 5090, RTX 5080, RX 9070 XT and RTX 4070, rented pods, a rented H100 SXM, igneum-build-1 Bitmain's Antminer X9 (RandomX; 1,000 KH/s, 2,472 W, 2.47 J per KH, USD 5,600; pre-orders 26 December 2025) was withdrawn in mid-May 2026 with buyers refunded before any unit shipped, no independent benchmark, commodity Sophgo SG2044 server SoCs with an AES accelerator, no tapeout: it is a precedent on the served pages, not a chip core against the model (attack pass AP-F5-1, 7 October 2026; the close's 10.0f, 8 October 2026). Withdrawn from the served pages on 8 October 2026 and not restated: the 2.1x and 3.4x launch line, the 5x to 9x class v3 baseline, the ladder's 2.8x row, the USD 100 M pay-back row, any chip-arrival probability, the lifetime claim and the USD 300 M and 340 M lines.none yet; the next test is the internal adversarial pass (three lanes new to the hash code, outsider inputs only, reports published whole), whose floor reading is in (measured, 8 October 2026; ledger AP-F8-1 and AP-F8-6): nine of nine hot sets refused; the diffuse era-stride excess, bounded under 0.1 percent of a hash's reads per site, is not caught by the floor and is the next class's test, and no outside review has run yet
18The chip resistance measurements: the program is latency-bound (dependent reads spread over the whole dataset), not bandwidth-bound, on every card we own, and sits beyond a card's on-chip cache; measured 8 October 2026: the distinct-index floor holds at 0.995 on every accepted program, about half of epochs carry one load site with a biased address bit at the era's stride rotation, priced at about 1.6 percent of a hash's reads to a chip storing half the dataset and nothing to one storing all of it (docs/analysis/class-v6/family-gate.md, lane D; adv-cache-2's report-chained-cache-2.md section 2.3 on its branch; ledger AP-F8-7)
Litepaper Mining ("waits on memory latency, not on maths or bandwidth"), vs RandomX; the numbers page
tested by the teamreadwidth e752fc7 (docs/plans/read-width.md), ca2-era 78c0ee4, ca2-cache 2de19e5 (docs/plans/hot-table.md)The dependent-read probes at 32 to 1,024 MiB and the hash rate per class on the three cards; the latency-bound share = rate over the probe ceiling per loadLatency-bound share at the 1 GiB dataset: RTX 5090 0.96 (v2) and 1.01 (v3), RX 9070 XT 0.87 and 0.95, M5 Max 1.01 and 1.06; wider reads do not close the AMD gap (the 9070 XT does 2.4 G dependent reads per second at every width; the 5090 goes bandwidth-bound at 64 B, share 0.58); a 32 to 96 MiB hot table is not kept resident by any card while the dataset streams (g 0.80 to 0.87 in the added form). 5 October 2026none yet
19The lottery hash is sound as a hash: uniform output, deterministic, no out-of-bounds read, fuzzed; class v3 bit-exact on the three vendors
Litepaper vs RandomX ("Every number above is measured and logged"), the numbers page
tested by the teamca2-mixer 1ab8b21 (tests/mixer.rs, tests/scratch.rs), ca2-era 78c0ee4, ca2-soundness a465881 (docs/analysis/scratch-soundness.md), igneum-pow/tests/packs.rsThe crate suite (53 + 4 + 19 + 7), the Metal fuzz, edge, stats and determinism runs on the v3 construction, the pack vectors and 2^24 fingerprints on Metal, Apple OpenCL, the RTX 5090 and the RX 9070 XT, the 1,024-hash CPU re-check per cardClass v3 (mixer x8 + era): 200-program fuzz 200 of 200 on Metal, every tenth on Apple OpenCL; the pinned v3 packs 3/3 + 3/3 and 96 of 96 lanes on Metal and Apple OpenCL; the six era packs' fingerprints equal on the three vendors (the three-card Windows rig (RTX 5090, RTX 4070, RX 9070 XT) job run-ca2-era-pc1-20261005, 5 October 2026); the v2 exports byte-identical on the v3 crate; the final-class PC rows and the G2 re-check: job run-ca2-era-pc1b-20261005 (pending at the time of writing)none yet
18The chip resistance measurements: the program is latency-bound (dependent reads spread over the whole dataset), not bandwidth-bound, on every card we own, and sits beyond a card's on-chip cache; measured 8 October 2026: the distinct-index floor holds at 0.995 on every accepted program, about half of epochs carry one load site with a biased address bit at the era's stride rotation, priced at about 1.6 percent of a hash's reads to a chip storing half the dataset and nothing to one storing all of it (docs/analysis/class-v6/family-gate.md, lane D; adv-cache-2's report-chained-cache-2.md section 2.3 on its branch; ledger AP-F8-7)
Litepaper Mining ("waits on memory latency, not on maths or bandwidth"), vs RandomX; the numbers page
tested by the teamreadwidth e752fc7 (docs/plans/read-width.md), ca2-era 78c0ee4, ca2-cache 2de19e5 (docs/plans/hot-table.md)The dependent-read probes at 32 to 1,024 MiB and the hash rate per class on the three cards; the latency-bound share = rate over the probe ceiling per loadLatency-bound share at the 1 GiB dataset: RTX 5090 0.96 (v2) and 1.01 (v3), RX 9070 XT 0.87 and 0.95, M5 Max 1.01 and 1.06; wider reads do not close the AMD gap (the 9070 XT does 2.4 G dependent reads per second at every width; the 5090 goes bandwidth-bound at 64 B, share 0.58); a 32 to 96 MiB hot table is not kept resident by any card while the dataset streams (g 0.80 to 0.87 in the added form). 5 October 2026none yet
19The lottery hash is sound as a hash: uniform output, deterministic, no out-of-bounds read, fuzzed; class v3 bit-exact on the three vendors
Litepaper vs RandomX ("Every number above is measured and logged"), the numbers page
tested by the teamca2-mixer 1ab8b21 (tests/mixer.rs, tests/scratch.rs), ca2-era 78c0ee4, ca2-soundness a465881 (docs/analysis/scratch-soundness.md), igneum-pow/tests/packs.rsThe crate suite (53 + 4 + 19 + 7), the Metal fuzz, edge, stats and determinism runs on the v3 construction, the pack vectors and 2^24 fingerprints on Metal, Apple OpenCL, the RTX 5090 and the RX 9070 XT, the 1,024-hash CPU re-check per cardClass v3 (mixer x8 + era): 200-program fuzz 200 of 200 on Metal, every tenth on Apple OpenCL; the pinned v3 packs 3/3 + 3/3 and 96 of 96 lanes on Metal and Apple OpenCL; the six era packs' fingerprints equal on the three vendors (the three-card Windows rig (RTX 5090, RTX 4070, RX 9070 XT) job run-ca2-era-pc1-20261005, 5 October 2026); the v2 exports byte-identical on the v3 crate; the final-class PC rows and the G2 re-check: job run-ca2-era-pc1b-20261005 (pending at the time of writing)none yet
20No premine, no pre-sale, no allocation: every coin is minted by the schedule and every coin goes to the block producer (80%) and the proving pool (20%)
Homepage stats and Economics tiles; litepaper Supply, Economics
implementedrepo 6ac80a3; fork "igneum-node devnet v0"; consensus/core/src/igneum.rs, coinbase.rscargo test -p kaspa-consensus-core igneum (8 pass: subsidy table, ramp, split, cap) and cargo test -p kaspa-consensus coinbase (8 pass); igneum-miner inspect 40; bench-log "igneum-node devnet v0"Coinbases on the devnet: 80/20 exact on 39 of 39 single-payee blocks, the 20% to the igneum-proving-pool-v0 output; the per-second schedule sums to under the 4,000,000,000 cap by less than 100 coins; 3,168,808,781 units per DAA second in years 0 to 2, halving at 63,115,200 DAA s. 3 October 2026, Apple M5 Max. The devnet genesis carries no allocation; the mainnet genesis does not exist yet, so the claim is about the code and the stated rule, not a launch that has happenednone yet
21The proving pool's 20% reaches shard provers and aggregators
Litepaper Economics; homepage "20% provers"
tested by the teamspec 5.3; proving/igneum-prove carries the prover's payout address in every shard proof (ledger P12)None. The pool output exists (row 20); the payout from it against proof records is unwritten. Since 5 October 2026: the payout rule is live on the devnet (proving.rs shard_payouts, the carrying segment pays the first valid record per shard its part of the segment's pool credit)The escrow accumulated on the simnet (92.55 IGN at the end of the v3 run) and nothing can draw it. Rule decided: per block, divided among shards by consensus proving cost, sortition to 8 provers for 10 s then open (spec 7.2). The economy model of 4 October 2026 (sim/economy, 1,000 operators, 30 days) kept every block proven within 60 s under six stress scenarios; a model, not hardware Live devnet, 5 October 2026: 388 shards paid by 16:02 UTC, 446.13 IGN from the pool to the RTX 5090 Windows rig's payout address, 0.8813 IGN per mergeset block of the proven segment (bench-log entries of 5 October: "the first shards proven, verified and paid" and "real transactions, the first non-empty shard proven and paid")none yet
22The base fee is burned in full and the priority fee splits 80% to the miner and provers, 20% to the apps whose code ran
Homepage Economics caption and Build card; litepaper "Where fees go"
tested by the teamrepo f5f8c80; fork worktree vendor/igneum-node-exectools/evm-smoke/smoke.mjs receipt checks; bench-log "execution layer devnet v3"Transfer receipt: burnedProvingFee 200 gwei, minerTip 16,800 gwei (80%), unregistered developer share 4,200 gwei burned; contract call: 80% to the miner, 20% credited to the payee the constructor registered, balance delta equal. 3 October 2026, Apple M5 Max simnet. The provers' part of the 80% is not split out (no provers exist); the base fee stayed at the 1 gwei floor throughoutnone yet
21The proving pool's 20% reaches shard provers and aggregators
Litepaper Economics; homepage "20% provers"
tested by the teamspec 5.3; proving/igneum-prove carries the prover's payout address in every shard proof (ledger P12)None. The pool output exists (row 20); the payout from it against proof records is unwritten. Since 5 October 2026: the payout rule is live on the devnet (proving.rs shard_payouts, the carrying segment pays the first valid record per shard its part of the segment's pool credit)The escrow accumulated on the simnet (92.55 IGN at the end of the v3 run) and nothing can draw it. Rule decided: per block, divided among shards by consensus proving cost, sortition to 8 provers for 10 s then open (spec 7.2). The economy model of 4 October 2026 (sim/economy, 1,000 operators, 30 days) kept every block proven within 60 s under six stress scenarios; a model, not hardware Live devnet, 5 October 2026: 388 shards paid by 16:02 UTC, 446.13 IGN from the pool to the RTX 5090 Windows rig's payout address, 0.8813 IGN per mergeset block of the proven segment (bench-log entries of 5 October: "the first shards proven, verified and paid" and "real transactions, the first non-empty shard proven and paid")none yet
22The base fee is burned in full and the priority fee splits 80% to the miner and provers, 20% to the apps whose code ran
Homepage Economics caption and Build card; litepaper "Where fees go"
tested by the teamrepo f5f8c80; fork worktree vendor/igneum-node-exectools/evm-smoke/smoke.mjs receipt checks; bench-log "execution layer devnet v3"Transfer receipt: burnedProvingFee 200 gwei, minerTip 16,800 gwei (80%), unregistered developer share 4,200 gwei burned; contract call: 80% to the miner, 20% credited to the payee the constructor registered, balance delta equal. 3 October 2026, Apple M5 Max simnet. The provers' part of the 80% is not split out (no provers exist); the base fee stayed at the 1 gwei floor throughoutnone yet
23No fee to any team, foundation or fund; 0 admin keys in consensus
Homepage Economics tiles and caption; litepaper "No fund, no foundation" and Governance
designedspec 5.5, 5.6 (decided 3 October 2026); spec 08Reading: no coinbase output, fee route or consensus key in the fork names any party (coinbase.rs, docs/fork-divergence.md)The emission code has two outputs (row 20) and the fee code has three routes (row 22), none to a team. The 1% fee of the official client is a client setting, not a protocol rule, and is not implemented. The release key of spec 08 signs client updates (the Igneum Miner app's over-the-air manifest since 4 October 2026, Ed25519) and holds no consensus power; its custody policy is open (O-8.1)none yet
24External proving jobs pay 90% to the provers who delivered and burn 10%, once settled in IGN
Homepage "IGN burned from jobs, phase two"; litepaper Proving and Economics
designedspec 5.4None. Needs the proof bridge (spec 7.3, phase two) and the settlement switch (O-5.2)At launch jobs are paid on the customer's chain in the customer's currency and nothing is burned (ledger P10). No job market code existsnone yet
25The 4 billion cap, halving every two years, with a 30-day ramp from 10%
Homepage "4B IGN hard cap"; litepaper Supply and the emission chart
tested by the teamrepo 6ac80a3; fork consensus/core/src/igneum.rscargo test -p kaspa-consensus-core igneum; bench-log "igneum-node devnet v0"Ramp day 0 paid 10.03% of the full rate (317,767,704 units at DAA 806); the schedule table and the cap assert in the crate's own tests. 3 October 2026, Apple M5 Max. Base unit (8 or 18 decimals) is open (O-2.6); the spec was changed to follow the code's 365.25-day year (ledger E9) and a test that reads the published numbers back is still owednone yet
25The 4 billion cap, halving every two years, with a 30-day ramp from 10%
Homepage "4B IGN hard cap"; litepaper Supply and the emission chart
tested by the teamrepo 6ac80a3; fork consensus/core/src/igneum.rscargo test -p kaspa-consensus-core igneum; bench-log "igneum-node devnet v0"Ramp day 0 paid 10.03% of the full rate (317,767,704 units at DAA 806); the schedule table and the cap assert in the crate's own tests. 3 October 2026, Apple M5 Max. Base unit (8 or 18 decimals) is open (O-2.6); the spec was changed to follow the code's 365.25-day year (ledger E9) and a test that reads the published numbers back is still owednone yet
26A phone or browser verifies the chain from a locked checkpoint, at about 3.44 MB per day in checkpoint mode
Homepage "Browser checks Igneum" card; litepaper Building ("Light clients"), firsts row 6
designedspec 10 (10.5 bytes per day: 3.44 MB at 1,000 voters, 6.68 MB at 10,000, derived, approximate); repo f874f80 for the browser card; site/api/checkpoint.mjsNone for the byte figure; site/verify/ for the card against /api/checkpoint. BLS verification on a phone and in WebAssembly is O-10.3; the full-header mode on a phone is O-10.4Since 11:03 UTC on 4 October 2026 the homepage card verifies the live devnet's own certificates in the tab (index 522 with 27 voters at 13:42 UTC), BLS aggregate against the voter list the node serves, light client v0; before that it verified the 3 October test network's. The byte figure is arithmetic on designed sizes (header 400 bytes, proof 400 bytes), measured nowhere; the execution proof the card would also check is not on the chain (row 15)none yet
27The node survives malformed input, floods, withholding, partitions and eclipses
Litepaper Speed ("GHOSTDAG, the BlockDAG consensus proven on Kaspa"); spec 2
tested by the teamrepo 394030c, 8dae48b, 6b5bd92; fork worktree vendor/igneum-node-harness and devnet-v4; tools/harness/; infra/cloud-devnet/experiments/partition.shtools/harness/ against a private igneumd test network; the merged node's harness scenarios 2 and 5; the cloud network's 10-minute partition of Singapore (results/2026-10-04/partition-sin-20261004-110906/partition.md); bench-log "consensus attack harness", "devnet-v4 integration"3 October 2026, Apple M5 Max: 63 malformed cases, node up on every one; withholding at 10% to 45% within 2 sigma of share; partitions of 120 s to 3,700 s healed to one chain in 10 s; eclipse victims rejoined in 10 s; 50x floods left template p95 under 4 ms; one FAIL, a 45% withholder releasing every 20 blocks took 50.7% of blues (bound 47.4%). Merged node, 4 October 2026: 63 cases, node up, 0 cache builds; the 10 s timestamp floor and future bound exact. Cloud network, 4 October 2026: 12 nodes in five locations on their own chain, Singapore cut off by iptables for 10 minutes; the two minority nodes adopted the majority chain 10 and 14 s after the heal with reorgs of 445 and 516 blocks, the majority's deepest reorg was 2 blocks, 0 conflicting locks (none were possible: the weight window stood at DAA 3,030 of 7,200). CPU miners only; the finality rules under partition are row 10none yet
28Headers are validated cheaply before the lottery engine runs, so forged timestamps cannot force 256 MiB cache builds
Spec 2.4; ledger M15
tested by the teamrepo 0953ec7, 8dae48b; fork worktree vendor/igneum-node-r3 branch r3-fixes at 5166ee26, merged into devnet-v4measure_m15_attack_before_and_after (ignored test, release, --features igneum-pow); kaspa-pow 8, header_processor 1, p2p pow_guard 2 tests; harness scenario 5 on the merged node50 forged headers: before, 50 cold builds in 10,595 ms and the live day evicted; after, 0 builds, all 50 rejected in 14 ms, 3 October 2026, Apple M5 Max under load 60 to 110. Merged node, 4 October 2026: 63 harness cases with 0 cache builds (the node log shows one build, the honest day) and the M15 p2p cases disconnected by the strike guard; the live devnet v4 runs it. Measured through the validate path with skip_proof_of_work, not the daemon RPCnone yet
29Blocks reach every node well inside GHOSTDAG's delay bound across continents
Litepaper Speed (GHOSTDAG at one block a second); spec 03 C1 (lock latency); infra/cloud-devnet/README.md
tested by the teamrepo 6b5bd92; infra/cloud-devnet/experiments/latency.sh, analyze.py; the Linux cross-build infra/cross/build-linux.sh12 igneumd nodes on cloud VMs in Helsinki, Falkenstein, Ashburn, Hillsboro and Singapore (own chain igneum-devnet-20, one CPU trickle miner each), a ping matrix, then 10 minutes of per-node arrival logs joined on block hash; results/2026-10-04/latency/propagation.md and rtt-by-region.md644 blocks in the window, 642 seen by at least 80% of nodes; arrival at a node minus the first arrival anywhere: p50 343 ms, p90 497 ms, p99 666 ms, max 2,313 ms; by region p50 239 ms (Falkenstein) to 413 ms (Singapore), p90 455 to 632 ms; inter-region RTT 35 ms (Helsinki to Falkenstein) to 289 ms (Ashburn to Singapore); first arrival minus header time median 490 ms. 4 October 2026. The network is the project's own: 12 nodes not 20 (a new account's limits), CPU hash rate only, clocks by chrony, one evening of data; the 5 s bound behind GHOSTDAG k is a design parameter this run did not challengenone yet
30One click: install, press start, the card mines; the app looks after its node
Homepage Mine section ("One click: install, press start"); litepaper "One click, for everyone else"; journey phase 5
tested by the teamrepo 3bb50d6, 2c4b30f, 6461540 (package 0.3.0: prebuilt NVRTC CUDA worker and generic OpenCL worker, driver only), a1a33cb, 7c794df, 0d4498e, 6c083db (Igneum Miner 0.3.0), 78903cd (0.3.1, over-the-air updates)Igneum-Miner-Setup-0.3.0.exe (runner-built, unsigned) on a an RTX 5090 on Windows with an RTX 5090 and no toolchain; proto-cuda/nvrtc/emu/serve-check.sh on the Apple M5 Max; proto-cuda/windows-app/TEST.md; bench-log "one-click Windows workers", "first machine on the Igneum Miner app", "a node 60 s behind the clock is silently dead", "the gfx1036 worker fault"Four machines by 14:45 UTC on 4 October 2026: the RTX 5090 Windows rig, then the three-card Windows rig (RTX 5090, RTX 4070, RX 9070 XT) (RTX 5090 at 110 MH/s under the 80% power cap), the project's Apple M5 Max (25 MH/s) and the outside Apple silicon laptop (row 29), all on Igneum Miner 0.3.1. The NVRTC worker compiled the pack on the card with no toolchain installed and mined at 124.2 MH/s, equal to the nvcc-built worker, 0 rejected, CPU re-check clean; inside the app 117 to 119 MH/s with 34 accepted blocks in the first minute, the integrated AMD chip at 3.3 MH/s beside it (row 9). Two defects found by the install, both fixed the same hour: a clock 62 s slow after a power cut made the node reject every relayed block for 12 minutes with no visible reason (the app now reads the skew from the node's warnings, the block timestamps over the EVM RPC and an HTTPS Date header, warns over 5 s and blocks Start over 10 s, with a one-click clock sync; checked on the Apple M5 Max with a fake 60 s skew; a one-line node warning is filed), and the node card said "syncing" while the miner was already accepted. The Mac could only emulate the NVIDIA path (17 of 17 sampled hashes) and the AMD path on Apple OpenCL (15 of 15). Over-the-air updates were dry-run on a private devnet (0.3.0 to 0.3.1 and back), not on a user's machine. The installer is unsigned (SmartScreen "run anyway"). Second machine, the same afternoon: a friend of the project installed Igneum Miner 0.3.1 from the DMG on an Apple silicon laptop with no toolchain and no instructions beyond five steps; the node synced from the seed, the Metal worker reported ready, 33 accepted blocks and 0 rejected in 7 minutes at 21.0 MH/s average, CPU re-check OK on every share, uploads arriving every minute under its per-install id. That laptop is not the project's hardware, but the result is observed through the project's own log intake and reported by the project, so it stays tested by the team until an outsider publishes a run of their own. The devnet's other GPU machines (the three-card Windows rig (RTX 5090, RTX 4070, RX 9070 XT) and the Apple M5 Max) run the same workers through the launcher, not the appnone yet
27The node survives malformed input, floods, withholding, partitions and eclipses
Litepaper Speed ("GHOSTDAG, the BlockDAG consensus proven on Kaspa"); spec 2
tested by the teamrepo 394030c, 8dae48b, 6b5bd92; fork worktree vendor/igneum-node-harness and devnet-v4; tools/harness/; infra/cloud-devnet/experiments/partition.shtools/harness/ against a private igneumd test network; the merged node's harness scenarios 2 and 5; the cloud network's 10-minute partition of Singapore (results/2026-10-04/partition-sin-20261004-110906/partition.md); bench-log "consensus attack harness", "devnet-v4 integration"3 October 2026, Apple M5 Max: 63 malformed cases, node up on every one; withholding at 10% to 45% within 2 sigma of share; partitions of 120 s to 3,700 s healed to one chain in 10 s; eclipse victims rejoined in 10 s; 50x floods left template p95 under 4 ms; one FAIL, a 45% withholder releasing every 20 blocks took 50.7% of blues (bound 47.4%). Merged node, 4 October 2026: 63 cases, node up, 0 cache builds; the 10 s timestamp floor and future bound exact. Cloud network, 4 October 2026: 12 nodes in five locations on their own chain, Singapore cut off by iptables for 10 minutes; the two minority nodes adopted the majority chain 10 and 14 s after the heal with reorgs of 445 and 516 blocks, the majority's deepest reorg was 2 blocks, 0 conflicting locks (none were possible: the weight window stood at DAA 3,030 of 7,200). CPU miners only; the finality rules under partition are row 10none yet
28Headers are validated cheaply before the lottery engine runs, so forged timestamps cannot force 256 MiB cache builds
Spec 2.4; ledger M15
tested by the teamrepo 0953ec7, 8dae48b; fork worktree vendor/igneum-node-r3 branch r3-fixes at 5166ee26, merged into devnet-v4measure_m15_attack_before_and_after (ignored test, release, --features igneum-pow); kaspa-pow 8, header_processor 1, p2p pow_guard 2 tests; harness scenario 5 on the merged node50 forged headers: before, 50 cold builds in 10,595 ms and the live day evicted; after, 0 builds, all 50 rejected in 14 ms, 3 October 2026, Apple M5 Max under load 60 to 110. Merged node, 4 October 2026: 63 harness cases with 0 cache builds (the node log shows one build, the honest day) and the M15 p2p cases disconnected by the strike guard; the live devnet v4 runs it. Measured through the validate path with skip_proof_of_work, not the daemon RPCnone yet
29Blocks reach every node well inside GHOSTDAG's delay bound across continents
Litepaper Speed (GHOSTDAG at one block a second); spec 03 C1 (lock latency); infra/cloud-devnet/README.md
tested by the teamrepo 6b5bd92; infra/cloud-devnet/experiments/latency.sh, analyze.py; the Linux cross-build infra/cross/build-linux.sh12 igneumd nodes on cloud VMs in Helsinki, Falkenstein, Ashburn, Hillsboro and Singapore (own chain igneum-devnet-20, one CPU trickle miner each), a ping matrix, then 10 minutes of per-node arrival logs joined on block hash; results/2026-10-04/latency/propagation.md and rtt-by-region.md644 blocks in the window, 642 seen by at least 80% of nodes; arrival at a node minus the first arrival anywhere: p50 343 ms, p90 497 ms, p99 666 ms, max 2,313 ms; by region p50 239 ms (Falkenstein) to 413 ms (Singapore), p90 455 to 632 ms; inter-region RTT 35 ms (Helsinki to Falkenstein) to 289 ms (Ashburn to Singapore); first arrival minus header time median 490 ms. 4 October 2026. The network is the project's own: 12 nodes not 20 (a new account's limits), CPU hash rate only, clocks by chrony, one evening of data; the 5 s bound behind GHOSTDAG k is a design parameter this run did not challengenone yet
30One click: install, press start, the card mines; the app looks after its node
Homepage Mine section ("One click: install, press start"); litepaper "One click, for everyone else"; journey phase 5
tested by the teamrepo 3bb50d6, 2c4b30f, 6461540 (package 0.3.0: prebuilt NVRTC CUDA worker and generic OpenCL worker, driver only), a1a33cb, 7c794df, 0d4498e, 6c083db (Igneum Miner 0.3.0), 78903cd (0.3.1, over-the-air updates)Igneum-Miner-Setup-0.3.0.exe (runner-built, unsigned) on a an RTX 5090 on Windows with an RTX 5090 and no toolchain; proto-cuda/nvrtc/emu/serve-check.sh on the Apple M5 Max; proto-cuda/windows-app/TEST.md; bench-log "one-click Windows workers", "first machine on the Igneum Miner app", "a node 60 s behind the clock is silently dead", "the gfx1036 worker fault"Four machines by 14:45 UTC on 4 October 2026: the RTX 5090 Windows rig, then the three-card Windows rig (RTX 5090, RTX 4070, RX 9070 XT) (RTX 5090 at 110 MH/s under the 80% power cap), the project's Apple M5 Max (25 MH/s) and the outside Apple silicon laptop (row 29), all on Igneum Miner 0.3.1. The NVRTC worker compiled the pack on the card with no toolchain installed and mined at 124.2 MH/s, equal to the nvcc-built worker, 0 rejected, CPU re-check clean; inside the app 117 to 119 MH/s with 34 accepted blocks in the first minute, the integrated AMD chip at 3.3 MH/s beside it (row 9). Two defects found by the install, both fixed the same hour: a clock 62 s slow after a power cut made the node reject every relayed block for 12 minutes with no visible reason (the app now reads the skew from the node's warnings, the block timestamps over the EVM RPC and an HTTPS Date header, warns over 5 s and blocks Start over 10 s, with a one-click clock sync; checked on the Apple M5 Max with a fake 60 s skew; a one-line node warning is filed), and the node card said "syncing" while the miner was already accepted. The Mac could only emulate the NVIDIA path (17 of 17 sampled hashes) and the AMD path on Apple OpenCL (15 of 15). Over-the-air updates were dry-run on a private devnet (0.3.0 to 0.3.1 and back), not on a user's machine. The installer is unsigned (SmartScreen "run anyway"). Second machine, the same afternoon: a friend of the project installed Igneum Miner 0.3.1 from the DMG on an Apple silicon laptop with no toolchain and no instructions beyond five steps; the node synced from the seed, the Metal worker reported ready, 33 accepted blocks and 0 rejected in 7 minutes at 21.0 MH/s average, CPU re-check OK on every share, uploads arriving every minute under its per-install id. That laptop is not the project's hardware, but the result is observed through the project's own log intake and reported by the project, so it stays tested by the team until an outsider publishes a run of their own. The devnet's other GPU machines (the three-card Windows rig (RTX 5090, RTX 4070, RX 9070 XT) and the Apple M5 Max) run the same workers through the launcher, not the appnone yet
31Card lifetime: a 4 GB card mines about four years and an 8 GB card about twelve, under the dataset's step schedule (2 GB at genesis, doubling at years 4, 12, 28, 60) with the cache freed after the daily build
Litepaper Hardware and vs RandomX ("Dataset" row); homepage Mine card and "Memory" row
designeddocs/analysis/card-lifetime-2026-10-05.md (branch card-lifetime 1fecfe2); spec 1.13.3 option (b) recommended to the owner 5 October 2026 (docs/plans/counter-asic-2-rollout.md 6c)The per-tier working-set arithmetic of that document (GTX 1650, RTX 3050, RTX 3060, RTX 4090 tiers) against the step scheduleA design claim: under the continuous mapping (a) a 4 GB card is out within 1 to 1.5 years and an 8 GB card at 6 to 7.5 years, so the sentence is true only under the step schedule (b), which the spec has not yet fixed (O-1.13)none yet
-

Click a column heading to sort; click again to reverse. Versions: igneum-pow is the Rust crate at version 0.2.0 (generator version 2, 4 October 2026); repo commits are this repository's; fork commits are the node fork and its worktrees, named by message as the engineering log names them. Source of every number: the engineering log. The source of this page is docs/evidence.md in the repository.

+

Click a column heading to sort; click again to reverse. Versions: igneum-pow is the Rust crate at version 0.2.0 (generator version 2, 4 October 2026); Devnet 3 runs node f8da7515 on release-0.3.25-node with igneum-pow 1c420786, chain id 4464 since its class v5 floor (4463 from genesis), read 8 October 2026, 15:50 UK; the current state, machine-readable, is the release manifest, which fills these at build time. The labels stay distinct: a claim never moves up a label without the artefact the next table names. The public reference repository exists now (the specifications, the pow crate, the simulators and the test material, at git.igneum.network); the full node, the miner and the proving code open later, so a row that cites them is tested by the team until they do. Repo commits are this repository's; fork commits are the node fork and its worktrees, named by message as the engineering log names them. Source of every number: the engineering log. The source of this page is docs/evidence.md in the repository.

What would move a row

+ - +
FromToWhat it takes
designedimplementedCode in this repository with test vectors that pass
implementedactivatedA node’s own start line on a named chain naming the rule and its activation height
implementedtested by the teamA bench-log entry with the machine, the date, the command and the number
tested by the teamreproduced externallyThe command published, and a third party's run with the same result, linked from the row
tested by the teamreproduced externallyThe code the row names public in the reference repository (the specifications, the pow crate, the simulators and the test material are; the node, the miner and the proving code open later), the command published, and a third party’s run with the same result, linked from the row
reproduced externallyreviewed independentlyA named reviewer's published finding on that version. Funding for review is docs/plans/funding.md
anythe row's status falls backA new version of the code or rule the row names
diff --git a/site/lc/core.js b/site/lc/core.js index b70123826..7bd74d777 100644 --- a/site/lc/core.js +++ b/site/lc/core.js @@ -265,7 +265,7 @@ export function verifyBalance(cp, proof, deps) { const step = (name, fn) => { try { const d = fn(); steps.push({ name, ok: true, detail: d }); return d; } catch (e) { steps.push({ name, ok: false, detail: String(e.message || e) }); throw e; } }; const done = extra => ({ ...extra, steps, ms: Math.round((now() - t0) * 10) / 10 }); try { - const cert = step('certificate: BLS aggregate over the checkpoint, 2/3 of active and 17/30 of total weight', () => { + const cert = step('certificate: BLS aggregate over the checkpoint, 2/3 of active and 2/3 of total weight', () => { const r = verifyCheckpoint(cp, { blake2b, bls }); if (!r.verified) throw new Error(r.reason); return `checkpoint ${r.index}, ${r.signers} of ${r.voters} voters, ${(r.weight_fraction_total * 100).toFixed(1)}% of total weight, ${r.headers_checked} headers to the previous lock`; @@ -338,7 +338,7 @@ export function verifyReceipt(receipt, deps) { const done = extra => ({ ...extra, steps, ms: Math.round((now() - t0) * 10) / 10 }); try { const cp = receipt.checkpoint.certificate; - const cert = step('certificate: BLS aggregate over the checkpoint, 2/3 of active and 17/30 of total weight', () => { + const cert = step('certificate: BLS aggregate over the checkpoint, 2/3 of active and 2/3 of total weight', () => { const r = verifyCheckpoint(cp, { blake2b, bls }); if (!r.verified) throw new Error(r.reason); if (strip(cp.hash) !== strip(receipt.checkpoint.hash) || receipt.chain_id !== cp.chain_id) throw new Error('the receipt names another checkpoint or chain than its certificate'); diff --git a/site/lc/verify-receipt.js b/site/lc/verify-receipt.js index e2aec4e52..55b169102 100644 --- a/site/lc/verify-receipt.js +++ b/site/lc/verify-receipt.js @@ -5241,7 +5241,7 @@ function verifyReceipt(receipt2, deps2) { const done = (extra) => ({ ...extra, steps, ms: Math.round((now() - t0) * 10) / 10 }); try { const cp = receipt2.checkpoint.certificate; - const cert = step("certificate: BLS aggregate over the checkpoint, 2/3 of active and 17/30 of total weight", () => { + const cert = step("certificate: BLS aggregate over the checkpoint, 2/3 of active and 2/3 of total weight", () => { const r2 = verifyCheckpoint(cp, { blake2b: blake2b2, bls: bls2 }); if (!r2.verified) throw new Error(r2.reason); if (strip(cp.hash) !== strip(receipt2.checkpoint.hash) || receipt2.chain_id !== cp.chain_id) throw new Error("the receipt names another checkpoint or chain than its certificate"); diff --git a/site/light.html b/site/light.html index 2ad9cb2eb..62de7dd4a 100644 --- a/site/light.html +++ b/site/light.html @@ -260,7 +260,7 @@

What is checked, in order

    -
  1. The certificate: the aggregate BLS signature of the signers over igneum-vote-v1/igneum-devnet-3 || index || checkpoint hash, the canonical voter order, the rule (two thirds of active weight, 17/30 of total), and the header chain from the previous lock.
  2. +
  3. The certificate: the aggregate BLS signature of the signers over igneum-vote-v1/igneum-devnet-3 || index || checkpoint hash, the canonical voter order, the rule (two thirds of active weight and two thirds of total weight), and the header chain from the previous lock.
  4. The header path from the carrier block up to the certified checkpoint: every header hash recomputes (BLAKE2b-256 keyed BlockHash over the header fields), every next header names the previous as a direct parent.
  5. The coinbase transaction is in the carrier block: its hash recomputes (BLAKE2b-256 keyed TransactionHash over the serialized transaction) and the merkle path reaches the header's hash_merkle_root.
  6. The segment record in the coinbase extra data: the aggregator's BLS signature over the record under the network's tag, whether the key is a voter with weight or a prove-only key, and the statement names the chain and the block whose state it commits.
  7. diff --git a/site/litepaper.html b/site/litepaper.html index 92168d4e6..7d75d3128 100644 --- a/site/litepaper.html +++ b/site/litepaper.html @@ -425,7 +425,7 @@ body.all .pager{display:none}
    Five layers plus the external proving market. A block flows down the column; outside demand feeds the same miners from the side.

    Live on Devnet 3, 7 October 2026

    -

    Devnet 3 (igneum-devnet-3, chain id 4463) made its first block at 18:06 UK on 7 October 2026 with every upgrade on from block zero, and locked its first checkpoint at 20:02 UK. The first devnet ran from 3 October 2026 and took each upgrade by height. Coins on Devnet 3 have no value and the chain may be reset. What is on it:

    +

    Devnet 3 (igneum-devnet-3, chain id 4464 since its class v5 floor at DAA 68,400, 4463 from genesis to the floor; the chain’s current state is the release manifest) made its first block at 18:06 UK on 7 October 2026 with every upgrade on from block zero, and locked its first checkpoint at 20:02 UK. The first devnet ran from 3 October 2026 and took each upgrade by height. Coins on Devnet 3 have no value and the chain may be reset. What is on it:

    diff --git a/site/miner.html b/site/miner.html index e94f716f8..a46c64c31 100644 --- a/site/miner.html +++ b/site/miner.html @@ -290,6 +290,7 @@ pre b{color:var(--molten-text);font-weight:500}

    Ember for Linux and HiveOS

    a tarball for rigs and Hive flight sheets

    For the rig people. One tarball, the miner and the node inside, the same signed manifest as the desktop apps.

    Download the tarball v0.3.22 · 28.8 MB +

    Current versions: Windows 0.3.20, macOS 0.3.20, HiveOS 0.3.22, the wallet 0.1.5; the node on Devnet 3 igneumd/2.1.0-f8da7515, read 8 October 2026, 15:50 UK. The machine-readable list, with every file’s SHA-256, is /release.json.

    HiveOS Flight Sheet. Miner: Custom. Installation URL: https://dl.igneum.network/dl/public/igneum-hive-0.3.22.tar.gz. Miner name igneum, wallet and worker 0x<your 40-hex payout address>.%WORKER_NAME%. Hive itself is untested on our side: tell us what breaks.

    sha256 8ad6dcef9edc57dcd33e8d5a97cbef5cdda0e384a6e56d3f62f8903029c4c764

    diff --git a/site/provenance.html b/site/provenance.html index e695f12d6..498736c4f 100644 --- a/site/provenance.html +++ b/site/provenance.html @@ -248,7 +248,7 @@ table{min-width:560px}

    How to read the licence column. "Verified" means the LICENSE file or the crate's Cargo.toml was read in this repository on 3 October 2026. "Approximate" means the licence is stated from memory because the source is not cloned under vendor/ yet; it is checked again when the clone lands.

    The table

    -
    LayerStateSince
    ComponentOrigin (project, licence, repository)What Igneum changedWhy the design needs the changeHow the change is measured
    GHOSTDAG orderingKaspa, rusty-kaspa. ISC, verified (vendor/rusty-kaspa/LICENSE, "Copyright (c) 2022-2024 Kaspa developers"; workspace license = "ISC"). https://github.com/kaspanet/rusty-kaspaUnchanged algorithm. Parameters set for 1 block per second: k 18, 10 max parents, mergeset limit 180, merge depth 3,600 blocks (consensus/core/src/config/bps.rs, params.rs)Launch rate is 1 block a second (the design document), rising later. These are the values Kaspa mainnet ran before Crescendo, so nothing new is asserted about the orderingSpec section 2.1; bench-log "igneum-node devnet v0: 3-node igneum-devnet at 1 BPS"; a test in params.rs pins every value
    Node software (the fork)rusty-kaspa v2.1.0, commit 01b532e8 (22 Sep 2026). ISC, verified. Fork at vendor/igneum-node, one commit per change on top of the baseHeader gains vote_key_hash; genesis blocks; network ids igneum-*; devnet ports; DNS seeders emptied; address prefixes; emission schedule and 80/20 coinbase; PoW engine trait; PoW check moved after GHOSTDAG; rename of every user-visible string to igneumd. Full list: docs/fork-divergence.mdEach row there states the reason. The short version: finality rule v2 needs a vote key in every header, the emission is Igneum's own, the lottery hash needs chain state, and no Igneum node may ever dial a Kaspa peerdocs/fork-divergence.md (file, change, why, risk, merge note per row); bench-log devnet v0 and "first devnet blocks on the real lottery hash" entries; the four-node rename test of 3 Oct 2026
    Difficulty controllerKaspa sampled DAA (KIP-4) in rusty-kaspa, ISC, verified, kept as the retarget. Prior art studied: LWMA by Zawy (zawy12/difficulty-algorithms, licence approximate: MIT) and Monero's sorted and trimmed window (monero-project/monero, approximate: BSD-3-Clause). No code from eitherUnchanged in the fork today (comment block only, consensus/core/src/config/constants.rs). The hash speed steps at every hourly program change, so a rule that tracks a step within an epoch is in progress: a two-speed rule (fast response to a step, slow drift otherwise). Not in spec 0.1Programs differ in cost (35 to 48 Mhash/s across seeds on one GPU), so a 44-minute window spends half an epoch at the wrong block rateSpec section 2.3 names the two remedies and the gate 2 simpa run that decides; bench-log first-run and RTX 5090 entries hold the per-seed rates. The two-speed rule gets its own bench-log entry when it is simulated
    Random-program ideaRandomX by tevador, Monero. Licence approximate: BSD-3-Clause. https://github.com/tevador/RandomX (not yet cloned under vendor/; the design document asks for it)The idea only. Igneum's generator is new code (igneum-pow/src/generator.rs): a program drawn once per hourly epoch and compiled to native GPU code, with a per-hash random data path. RandomX draws a program per hash and interprets it on a CPUA GPU cannot interpret a fresh program per hash at a useful rate; it compiles one program per hour instead. The target hardware is the opposite of RandomX's by designSpec section 1 (generator, test vectors); bench-log "proto-metal first run", "RTX 5090 first run", "igneum-pow bit-exact" (96/96 vectors, three GPU vendors)
    Memory-hard datasetRandomX cache lineage (tevador, BSD-3-Clause approximate): a small cache that derives a large dataset by dependent readsNew construction, same shape: 256 MiB cache of chained ChaCha12 blocks, 8 dependent reads per item, dataset 1 GiB in the prototype and 2 GB at genesis, growing on a genesis-fixed schedule (igneum-pow/src/memhard.rs, proto-metal/MEMHARD.md)A light verifier must hold only the cache; a miner must hold the dataset; the dataset must outgrow any fixed chip memory. RandomX's dataset has one size for everproto-metal/MEMHARD.md section 2.2 (recompute 4.8x slower than load, Apple only); bench-log "memory-hard dataset" entries on Metal and the RTX 5090
    ChaCha, SplitMix64, FNV-1a inside the lottery hashChaCha by D. J. Bernstein (public domain, approximate); SplitMix64 by Steele, Lea and Flood (algorithm from the 2014 paper, approximate); FNV-1a by Fowler, Noll and Vo (public domain, approximate). All three re-implemented from the definitions in igneum-pow, no code importedUsed as published: ChaCha12 core with feed-forward for the cache fill, SplitMix64 as the program stream, FNV-1a 64 for seed words and the cache digestStandard, well-studied primitives for a cache fill and a seed stream; nothing in the design asks for moreSpec sections 1.3 and 1.8 with test vectors; bench-log "igneum-pow bit-exact" (cache digest 48c4f5bf24166b2e matches Swift and C++)
    ProgPoW and KAWPOWProgPoW (EIP-1057 text, ifdefelse/ProgPOW; KAWPOW on Ravencoin since 2020, RavenProject/Ravencoin, MIT approximate). Prior art, no code used. Not yet cloned; docs/fud-fixes.md item 48 asks for the clone and citation before the repository is publicNothing taken. The difference: ProgPoW and KAWPOW randomise the maths inside a fixed program shape every few blocks; Igneum regenerates the whole program every hour over a growing dataset, with automatic era draws and no human in the loopStated so that the "first" claim in the litepaper is accurate (FUD ledger M4)Litepaper "What has never been done before", row 1, rewritten 3 Oct 2026
    Class-group VDFChia, chiavdf. Apache-2.0, verified (vendor/chiavdf/LICENSE), commit 7e62ce14. Wesolowski's proof (Efficient Verifiable Delay Functions, EUROCRYPT 2019), a paper, no licenceNUDUPL and NUCOMP ported from chiavdf's qfb_nudupl and qfb_nucomp into proto-vdf (Rust, over GMP through rug); fresh 1024-bit prime discriminant per input; 256-bit Fiat-Shamir prime (Chia uses 264); Igneum tags for the epoch and era paths. The textbook composition is kept as an oracleThe program seed must come from a certified checkpoint with a delay no miner can skip, so the seed cannot be ground. Chia's group needs no trusted setupSpec section 4.2 (15,000 random cases agree with the oracle; 163,000 squarings per second; 4.5 ms verify); bench-log "proto-vdf" entry. GMP itself: LGPL-3.0 or GPL-2.0 dual, approximate, prototype only; the production dependency is decided with the wire format (O-4.5)
    revmEthereum ecosystem, bluealloy/revm. Licence approximate: MIT. https://github.com/bluealloy/revm (not yet cloned)Unchanged, credited. Driven by an Igneum block executor that feeds it the DAG's canonical sequence with the environment table of spec 7.1 and two-dimensional gasThe same EVM runs natively and inside the zkVM (reth, rsp and SP1 Reth all use it), so native and proven execution share one code pathdocs/design/execution-layer.md D6 and section 2.1; differential test plan against reth (section 8.5). Nothing measured yet
    SP1-class proversSuccinct, succinctlabs/sp1. Licence approximate: MIT or Apache-2.0. Not yet clonedUnchanged, behind the versioned ProofSystem trait (docs/design/execution-layer.md 5.6). Version 1 is SP1 (Hypercube class, hash-based). Devnet v1 runs a stub that signs claimsConsumer cards prove hash-based systems without elliptic-curve MSM; the trait makes a swap a release (90% signalling, 3-month overlap, one wrap), never a redesignNo SP1 shard has been proven on any card in this repository (FUD ledger P1, P3). Phase 2 gate: shard time on a 3060-class card, published pass or fail
    BLS12-381Curve by Barreto, Lynn and Scott; blst by Supranational. Licence approximate: Apache-2.0. https://github.com/supranational/blst (not yet cloned)Unchanged, credited. The header carries the BLAKE2b hash of a G1 compressed public key (48 bytes); every voter signs every 30-s checkpoint; signatures aggregateFinality rule v2 needs one aggregate signature per checkpoint from thousands of keysSpec section 3.1 (W1) and 2.4; sim/results_v2.md for the rule itself. Signature cost not yet measured
    Hashing in the noderusty-kaspa crypto/hashes, ISC, verified. Crates linked by the fork, licences read from the local cargo registry: blake2b_simd 1.0.2 (MIT), blake3 1.8.3 (CC0-1.0 or Apache-2.0), sha2 0.10.8 (MIT or Apache-2.0), keccak 0.1.6 (Apache-2.0 or MIT); sha3 0.10.8 not in the local registry, approximate: MIT or Apache-2.0Unchanged, credited. BLAKE2b with domain separation for block, transaction and PoW pre-hashes (BlockHash, TransactionHash, ...), BLAKE3 keyed for the sequencing-commitment and payload hashers, SHA-256 for ECDSA signing hashes, cSHAKE256 (Keccak) in the kHeavyHash stub that stays as the default engine and for pruning-proof block levelsThe chain's hash for everything except the lottery is the one the forked commit uses (spec 0.6), so nothing unverified enters consensushash_override_nonce_time gained one field (fork-divergence row 1); every header-hash test vector was regenerated and the four genesis hashes re-derived
    Address formatBitcoin BIP 173 character set (bech32, Pieter Wuille and Greg Maxwell; BIP licence approximate: BSD-2-Clause) with the CashAddr polymod checksum of Bitcoin Cash (the source cites bch.info), as implemented in rusty-kaspa crypto/addresses/src/bech32.rs, ISC, verifiedPrefixes only: igneum, igneumtest, igneumsim, igneumdev (Kaspa: kaspa, kaspatest, kaspasim, kaspadev). The script public key behind an address is unchangedNo Igneum address string may parse as a Kaspa address on any networkFork-divergence row 9; test vectors in addresses and txscript regenerated and passing
    The EVMEthereum (Yellow Paper and ethereum/execution-specs, CC0 approximate). Cancun opcode set, precompiles 0x01 to 0x09Semantics on a DAG: block.number is selected-chain height, block.timestamp is non-decreasing by a max rule, prevrandao is the VDF epoch seed, chain ids 4461, 4462, 4463; 0x0a absent; gas has a second dimensionBlocks on a DAG have no single parent and no header state root; proving cost is a second resource; the random beacon must be unbiasableSpec section 7.1 (normative table); devnet measurement R9 for timestamp drift; ethereum/tests replay in the differential plan
    kHeavyHash (kept as a stub)Kaspa, rusty-kaspa crypto/hashes/src/pow_hashers.rs and consensus/pow/src/matrix.rs, ISC, verifiedKept untouched as HeavyHashEngine, the default engine when the igneum-pow feature is off, and the block-level source for pruning proofs until seeds are threaded throughLets the devnet run and lets upstream pow changes merge cleanlyFork-divergence rows 14 and 15; open item in the same file (pruning-proof block levels)
    +
    ComponentOrigin (project, licence, repository)What Igneum changedWhy the design needs the changeHow the change is measured
    GHOSTDAG orderingKaspa, rusty-kaspa. ISC, verified (vendor/rusty-kaspa/LICENSE, "Copyright (c) 2022-2024 Kaspa developers"; workspace license = "ISC"). https://github.com/kaspanet/rusty-kaspaUnchanged algorithm. Parameters set for 1 block per second: k 18, 10 max parents, mergeset limit 180, merge depth 3,600 blocks (consensus/core/src/config/bps.rs, params.rs)Launch rate is 1 block a second (the design document), rising later. These are the values Kaspa mainnet ran before Crescendo, so nothing new is asserted about the orderingSpec section 2.1; bench-log "igneum-node devnet v0: 3-node igneum-devnet at 1 BPS"; a test in params.rs pins every value
    Node software (the fork)rusty-kaspa v2.1.0, commit 01b532e8 (22 Sep 2026). ISC, verified. Fork at vendor/igneum-node, one commit per change on top of the baseHeader gains vote_key_hash; genesis blocks; network ids igneum-*; devnet ports; DNS seeders emptied; address prefixes; emission schedule and 80/20 coinbase; PoW engine trait; PoW check moved after GHOSTDAG; rename of every user-visible string to igneumd. Full list: docs/fork-divergence.mdEach row there states the reason. The short version: finality rule v2 needs a vote key in every header, the emission is Igneum's own, the lottery hash needs chain state, and no Igneum node may ever dial a Kaspa peerdocs/fork-divergence.md (file, change, why, risk, merge note per row); bench-log devnet v0 and "first devnet blocks on the real lottery hash" entries; the four-node rename test of 3 Oct 2026
    Difficulty controllerKaspa sampled DAA (KIP-4) in rusty-kaspa, ISC, verified, kept as the retarget. Prior art studied: LWMA by Zawy (zawy12/difficulty-algorithms, licence approximate: MIT) and Monero's sorted and trimmed window (monero-project/monero, approximate: BSD-3-Clause). No code from eitherUnchanged in the fork today (comment block only, consensus/core/src/config/constants.rs). The hash speed steps at every hourly program change, so a rule that tracks a step within an epoch is in progress: a two-speed rule (fast response to a step, slow drift otherwise). Not in spec 0.1Programs differ in cost (35 to 48 Mhash/s across seeds on one GPU), so a 44-minute window spends half an epoch at the wrong block rateSpec section 2.3 names the two remedies and the gate 2 simpa run that decides; bench-log first-run and RTX 5090 entries hold the per-seed rates. The two-speed rule gets its own bench-log entry when it is simulated
    Random-program ideaRandomX by tevador, Monero. Licence approximate: BSD-3-Clause. https://github.com/tevador/RandomX (not yet cloned under vendor/; the design document asks for it)The idea only. Igneum's generator is new code (igneum-pow/src/generator.rs): a program drawn once per hourly epoch and compiled to native GPU code, with a per-hash random data path. RandomX draws a program per hash and interprets it on a CPUA GPU cannot interpret a fresh program per hash at a useful rate; it compiles one program per hour instead. The target hardware is the opposite of RandomX's by designSpec section 1 (generator, test vectors); bench-log "proto-metal first run", "RTX 5090 first run", "igneum-pow bit-exact" (96/96 vectors, three GPU vendors)
    Memory-hard datasetRandomX cache lineage (tevador, BSD-3-Clause approximate): a small cache that derives a large dataset by dependent readsNew construction, same shape: 256 MiB cache of chained ChaCha12 blocks, 8 dependent reads per item, dataset 1 GiB in the prototype and 2 GB at genesis, growing on a genesis-fixed schedule (igneum-pow/src/memhard.rs, proto-metal/MEMHARD.md)A light verifier must hold only the cache; a miner must hold the dataset; the dataset must outgrow any fixed chip memory. RandomX's dataset has one size for everproto-metal/MEMHARD.md section 2.2 (recompute 4.8x slower than load, Apple only); bench-log "memory-hard dataset" entries on Metal and the RTX 5090
    ChaCha, SplitMix64, FNV-1a inside the lottery hashChaCha by D. J. Bernstein (public domain, approximate); SplitMix64 by Steele, Lea and Flood (algorithm from the 2014 paper, approximate); FNV-1a by Fowler, Noll and Vo (public domain, approximate). All three re-implemented from the definitions in igneum-pow, no code importedUsed as published: ChaCha12 core with feed-forward for the cache fill, SplitMix64 as the program stream, FNV-1a 64 for seed words and the cache digestStandard, well-studied primitives for a cache fill and a seed stream; nothing in the design asks for moreSpec sections 1.3 and 1.8 with test vectors; bench-log "igneum-pow bit-exact" (cache digest 48c4f5bf24166b2e matches Swift and C++)
    ProgPoW and KAWPOWProgPoW (EIP-1057 text, ifdefelse/ProgPOW; KAWPOW on Ravencoin since 2020, RavenProject/Ravencoin, MIT approximate). Prior art, no code used. Not yet cloned; docs/fud-fixes.md item 48 asks for the clone and citation before the repository is publicNothing taken. The difference: ProgPoW and KAWPOW randomise the maths inside a fixed program shape every few blocks; Igneum regenerates the whole program every hour over a growing dataset, with automatic era draws and no human in the loopStated so that the "first" claim in the litepaper is accurate (FUD ledger M4)Litepaper "What has never been done before", row 1, rewritten 3 Oct 2026
    Class-group VDFChia, chiavdf. Apache-2.0, verified (vendor/chiavdf/LICENSE), commit 7e62ce14. Wesolowski's proof (Efficient Verifiable Delay Functions, EUROCRYPT 2019), a paper, no licenceNUDUPL and NUCOMP ported from chiavdf's qfb_nudupl and qfb_nucomp into proto-vdf (Rust, over GMP through rug); fresh 1024-bit prime discriminant per input; 256-bit Fiat-Shamir prime (Chia uses 264); Igneum tags for the epoch and era paths. The textbook composition is kept as an oracleThe program seed must come from a certified checkpoint with a delay no miner can skip, so the seed cannot be ground. Chia's group needs no trusted setupSpec section 4.2 (15,000 random cases agree with the oracle; 163,000 squarings per second; 4.5 ms verify); bench-log "proto-vdf" entry. GMP itself: LGPL-3.0 or GPL-2.0 dual, approximate, prototype only; the production dependency is decided with the wire format (O-4.5)
    revmEthereum ecosystem, bluealloy/revm. Licence approximate: MIT. https://github.com/bluealloy/revm (not yet cloned)Unchanged, credited. Driven by an Igneum block executor that feeds it the DAG's canonical sequence with the environment table of spec 7.1 and two-dimensional gasThe same EVM runs natively and inside the zkVM (reth, rsp and SP1 Reth all use it), so native and proven execution share one code pathdocs/design/execution-layer.md D6 and section 2.1; differential test plan against reth (section 8.5). Nothing measured yet
    SP1-class proversSuccinct, succinctlabs/sp1. Licence approximate: MIT or Apache-2.0. Not yet clonedUnchanged, behind the versioned ProofSystem trait (docs/design/execution-layer.md 5.6). Version 1 is SP1 (Hypercube class, hash-based). Devnet v1 runs a stub that signs claimsConsumer cards prove hash-based systems without elliptic-curve MSM; the trait makes a swap a release (90% signalling, 3-month overlap, one wrap), never a redesignNo SP1 shard has been proven on any card in this repository (FUD ledger P1, P3). Phase 2 gate: shard time on a 3060-class card, published pass or fail
    BLS12-381Curve by Barreto, Lynn and Scott; blst by Supranational. Licence approximate: Apache-2.0. https://github.com/supranational/blst (not yet cloned)Unchanged, credited. The header carries the BLAKE2b hash of a G1 compressed public key (48 bytes); every voter signs every 30-s checkpoint; signatures aggregateFinality rule v2 needs one aggregate signature per checkpoint from thousands of keysSpec section 3.1 (W1) and 2.4; sim/results_v2.md for the rule itself. Signature cost not yet measured
    Hashing in the noderusty-kaspa crypto/hashes, ISC, verified. Crates linked by the fork, licences read from the local cargo registry: blake2b_simd 1.0.2 (MIT), blake3 1.8.3 (CC0-1.0 or Apache-2.0), sha2 0.10.8 (MIT or Apache-2.0), keccak 0.1.6 (Apache-2.0 or MIT); sha3 0.10.8 not in the local registry, approximate: MIT or Apache-2.0Unchanged, credited. BLAKE2b with domain separation for block, transaction and PoW pre-hashes (BlockHash, TransactionHash, ...), BLAKE3 keyed for the sequencing-commitment and payload hashers, SHA-256 for ECDSA signing hashes, cSHAKE256 (Keccak) in the kHeavyHash stub that stays as the default engine and for pruning-proof block levelsThe chain's hash for everything except the lottery is the one the forked commit uses (spec 0.6), so nothing unverified enters consensushash_override_nonce_time gained one field (fork-divergence row 1); every header-hash test vector was regenerated and the four genesis hashes re-derived
    Address formatBitcoin BIP 173 character set (bech32, Pieter Wuille and Greg Maxwell; BIP licence approximate: BSD-2-Clause) with the CashAddr polymod checksum of Bitcoin Cash (the source cites bch.info), as implemented in rusty-kaspa crypto/addresses/src/bech32.rs, ISC, verifiedPrefixes only: igneum, igneumtest, igneumsim, igneumdev (Kaspa: kaspa, kaspatest, kaspasim, kaspadev). The script public key behind an address is unchangedNo Igneum address string may parse as a Kaspa address on any networkFork-divergence row 9; test vectors in addresses and txscript regenerated and passing
    The EVMEthereum (Yellow Paper and ethereum/execution-specs, CC0 approximate). Cancun opcode set, precompiles 0x01 to 0x09Semantics on a DAG: block.number is selected-chain height, block.timestamp is non-decreasing by a max rule, prevrandao is the VDF epoch seed, chain ids 4461, 4462, 4463 (historical: Devnet 3 answers chain id 4464 since its class v5 floor at DAA 68,400 on 8 October 2026, 4463 below it; the current id is in /release.json); 0x0a absent; gas has a second dimensionBlocks on a DAG have no single parent and no header state root; proving cost is a second resource; the random beacon must be unbiasableSpec section 7.1 (normative table); devnet measurement R9 for timestamp drift; ethereum/tests replay in the differential plan
    kHeavyHash (kept as a stub)Kaspa, rusty-kaspa crypto/hashes/src/pow_hashers.rs and consensus/pow/src/matrix.rs, ISC, verifiedKept untouched as HeavyHashEngine, the default engine when the igneum-pow feature is off, and the block-level source for pruning proofs until seeds are threaded throughLets the devnet run and lets upstream pow changes merge cleanlyFork-divergence rows 14 and 15; open item in the same file (pruning-proof block levels)

What is new in Igneum

Nothing here has a precedent that Igneum could have copied. Each item names the measurement or specification it rests on.

diff --git a/site/receipt.html b/site/receipt.html index 85c536d19..d630d496a 100644 --- a/site/receipt.html +++ b/site/receipt.html @@ -265,7 +265,7 @@
  • The transaction hash is keccak256 of the raw signed transaction in the file, so the recipient, the amount and the data are the signed ones.
  • The transaction is a leaf of the including block's hash_merkle_root (BLAKE2b-256 keyed MerkleBranchHash up the path).
  • Every header from the including block to the certified checkpoint recomputes and links to the next by a direct parent.
  • -
  • The certificate over that checkpoint verifies: the aggregate BLS signature of the signers, the voter order, two thirds of active weight and 17/30 of total.
  • +
  • The certificate over that checkpoint verifies: the aggregate BLS signature of the signers, the voter order, two thirds of active weight and two thirds of total weight.
  • Not proven by the file: the execution result (status, gas) is carried as the node reported it and labelled so; the voter table with weights comes from the node (spec 10.1). Both are named on the result.

    Devnet 3, no value. The chain may reset. A demonstration of the verification path, not a product.

    diff --git a/site/release-manifest.json b/site/release-manifest.json new file mode 100644 index 000000000..4c480d02b --- /dev/null +++ b/site/release-manifest.json @@ -0,0 +1,243 @@ +{ + "format": "igneum-release-manifest-v1", + "generated": "2026-10-08T15:55:00Z", + "read_at": "read 8 October 2026, 15:50 UK, from the Devnet 3 seed and the fleet census (the node lane), the download index and the ELF manifest", + "labels": { + "measured": "read from a running node, a binary or a record", + "designed": "in the specification or the design document, not yet carried by code on the live chain", + "modelled": "a model's figure", + "claimed": "stated by a third party, not measured here" + }, + "network": { + "id": "igneum-devnet-3", + "name": "Igneum Devnet 3", + "kind": "developer network: resets without notice, its coins have no value", + "chain_id": 4464, + "chain_id_hex": "0x1170", + "chain_id_below_floor": 4463, + "chain_id_note": "4464 since the class v5 floor at DAA 68,400 (crossed 8 October 2026, 12:57 UK); 4463 from genesis to the floor; a transaction carries the id in force at its block", + "genesis": { + "first_block_utc": "2026-10-07T17:06:00Z", + "first_lock_utc": "2026-10-07T19:02:00Z", + "note": "every upgrade on from block zero: era VDF, finality v3, fees v1, proving v1, the latency ladder at rung 0" + }, + "rpc": "https://rpc.devnet.igneum.network", + "explorer": "https://igneum.network/explorer", + "faucet": "https://faucet.igneum.network", + "vote_domain": "igneum-vote-v1/igneum-devnet-3", + "decimals": 8, + "block_target_seconds": 1, + "consensus_digest": "2066aa57505e5ecbd585d061364abb0032d5b5b29cc41c54f4b38cb81c2ba6eb", + "label": "measured", + "others": [ + { + "id": "igneum-testnet-1", + "chain_id": 4462, + "chain_id_hex": "0x116e", + "rpc": "https://rpc.testnet.igneum.network", + "state": "armed: three seed nodes and the public RPC are up, nothing mines until the go word", + "genesis_hash": "87617621714af1bf33bd17f291f90a7e0bff760a669bba53083ea8c0f7cbd840", + "decimals": 18 + }, + { + "id": "igneum-mainnet", + "chain_id": 4461, + "chain_id_hex": "0x116d", + "state": "not started", + "decimals": 18 + } + ] + }, + "source": { + "repository": "https://git.igneum.network/igneum-network/igneum", + "repository_note": "the public reference repository: the specifications, the igneum-pow crate, the simulators and the test material; the full node, the miner and the proving code open later", + "node": { + "fork_of": "rusty-kaspa v2.1.0 (01b532e8)", + "branch": "release-0.3.25-node", + "commit": "f8da7515", + "version_string": "igneumd/2.1.0-f8da7515", + "pin": "c9ad753a (the move of 8 October 2026, 15:25 UK)", + "pending": "acaf08b0, cut 15:43 UK, gates running, its move not yet named", + "label": "measured" + }, + "pow": { + "crate": "igneum-pow", + "version": "0.2.0", + "commit": "1c420786", + "freeze": "class-v5-freeze 2026-10-07", + "tree_fingerprint": "cbc5bd0aa10585c8576e71e37a8ee47a045ae51754e9ddf749d0c21e6a535f88", + "binary_line": "igneum-pow fingerprint cbc5bd0aa10585c8 (the freeze)", + "below_floor": "017e7037 (class v4 sub-version 3, the audit-freeze-2026-10-07 tag) paired below the class v5 floor", + "label": "measured" + }, + "app": { + "name": "Ember", + "channel": "devnet-3", + "note": "the shipped artefacts and their SHA-256 are the versions block; the app ships from the same repository" + } + }, + "mining": { + "class": "v5", + "class_since_daa": 68400, + "class_at_genesis": "v4", + "class_note": "class v4 (the latency shadow, about 100,000 integer ops per hash at the ladder's rung 0) from block zero; class v5 (the dataset keyed by the chain's own state) from DAA 68,400", + "block_version": 1538, + "program": { + "epoch_daa": 3600, + "epoch_lead_daa": 601, + "vdf_minutes": 10, + "instructions": 64, + "loads_per_program": 16, + "lanes": 32, + "registers_per_lane": 8, + "dataset_reads_per_hash": 128 + }, + "dataset": { + "items_log2": 24, + "size": "1 GiB on the devnets (2^24 items at the genesis size)", + "keyed_by": "the execution state after the epoch's reference block (class v5)", + "cache": "256 MiB day cache (class v3 lineage)", + "growth": "no growth step is set on Devnet 3; the genesis-fixed schedule of spec 1.13.3 is a mainnet matter; class v6's step schedule (5.5 / 8.5 / 11.5 GiB) is a design on its branch, not live" + }, + "ladder": { + "rung": 0, + "ops_per_hash": "about 100,000", + "move_rule": "90 percent of blue blocks in each of seven consecutive days, one rung at a time" + }, + "label": "measured; the dataset growth line designed" + }, + "finality": { + "rule": "v3", + "since_checkpoint_daa": 0, + "statement": "a checkpoint locks when the signers hold at least two thirds of active weight and at least two thirds of total weight; weight is blue blocks per vote key over a flat 30-day window of past-median time", + "checkpoint_interval_daa": 30, + "checkpoint_depth": 20, + "weight_window_seconds": 2592000, + "presence_window_seconds": 7200, + "dust": 5, + "presence": 20, + "aggregators": 8, + "ban_daa": 7200, + "certificate_fold_daa": 3, + "frozen_table": "the weight table is frozen at the last certified checkpoint on the selected chain (spec 03 Q5), active for every checkpoint from DAA 0 on Devnet 3", + "node_line": "Finality v2 (igneum-devnet-3): interval 30 depth 20 window 7200 DAA dust 5 presence 20 aggregators 8 ban 7200 fold 3; rule v3 from checkpoint DAA 0", + "label": "measured" + }, + "proving": { + "verifier_in_consensus": "off", + "verifier_note": "proving v0: every producer verifies off the consensus path; consensus checks the record's statement against native execution and its signature; the in-consensus verifier switches on when the proven share of blocks reads one (ledger P21)", + "shard_market": "on from DAA 0: segment records of 8 blocks, unproven after 600 DAA, aggregator share 1,000 bps", + "proof_system": "SP1", + "sp1_circuit_version": "v6.1.0", + "sp1_crate_version": "6.8.1", + "pinned_at": "2026-10-05T16:20:38Z", + "shard_program_id": "0x2b1a81cb413236cf063077b46ed3111628f6c41036bcf6e23ee4cbbf5679ef7a", + "shard_elf_sha256": "0x150f4c05a2951fc56174a87089707a030b18df8fbe7e053a66459edb83053083", + "shard_vk_sha256": "0x8b4da5bff86d963f4210a78e5d800a1cd00ab41b158f6962f4ac009edc249d4c", + "aggregator_program_id": "0x474678f35f7545db28055d5e5bbc308231d84a5a072202087a2a8d5b09123896", + "aggregator_elf_sha256": "0x143d9c243dd12e87e90be71f6b8cd42353e513bf8ce78903ef6f972f1bc9aa7b", + "aggregator_vk_sha256": "0xad17bc1ae5be816554dbb13cb5b4d242678adfb8e1a4f7247ceb8b5ba9001b9f", + "manifest_file": "proving/igneum-prove/elf/manifest.json", + "label": "measured" + }, + "fees": { + "subsidy_split": { + "miner_percent": 80, + "proving_pool_percent": 20, + "where": "consensus/core/src/igneum.rs 44" + }, + "base_fee": { + "route": "burned in full, both gas dimensions (gas times the execution base fee, pgas times the proving base fee)", + "where": "igneum/exec/src/executor.rs 320 to 371" + }, + "priority_fee": { + "miner_percent": 80, + "developer_percent": 20, + "note": "the developer part goes to the registrations of the contracts whose code ran, pro rata by each frame's gas; an unregistered frame's part is a burn", + "where": "executor.rs 335 to 339; pgas.rs 290" + }, + "proving_fee_ceiling": { + "value": 90000, + "multiple": 4, + "note": "the proving-fee ceiling of the live object" + }, + "external_jobs": { + "provers_percent": 90, + "burn_percent": 10, + "state": "designed, not in the code" + }, + "dev_fee": { + "percent": 1, + "mechanism": "one block template in a hundred with the dev payout address, a counter, not a draw", + "default": "on", + "off": "--dev-fee 0, the app switch, DEV_FEE=0 on HiveOS; none in pool mode", + "where": "igneum/miner/src/main.rs 718" + }, + "emission": { + "launch_rate_base_units_per_daa_second": 3168808781, + "year_one_ign": 1000000000, + "ramp_seconds": 2592000, + "ramp_start_percent": 10, + "halving_seconds": 63115200, + "cap_ign": 4000000000, + "tail": "none", + "where": "consensus/core/src/emission.rs 85 to 123; igneum.rs 34, 76" + }, + "label": "measured in the code on Devnet 3; external jobs designed" + }, + "versions": { + "miner-hive": { + "version": "0.3.22", + "file": "igneum-hive-0.3.22.tar.gz", + "sha256": "8ad6dcef9edc57dcd33e8d5a97cbef5cdda0e384a6e56d3f62f8903029c4c764", + "size": 28771228, + "url": "https://dl.igneum.network/dl/public/igneum-hive-0.3.22.tar.gz" + }, + "miner-mac": { + "version": "0.3.20", + "file": "Igneum-Miner-0.3.20.dmg", + "sha256": "73796c5febc2050646f038c1f8c32a1d854033d125d0c02478b983ea8020419e", + "size": 44467804, + "url": "https://dl.igneum.network/dl/public/Igneum-Miner-0.3.20.dmg" + }, + "miner-windows": { + "version": "0.3.20", + "file": "Igneum-Miner-Setup-0.3.20.exe", + "sha256": "45b2f3fb54f40f839cde8efac53b40eca3738a4009af1a4e356f6445883df6b5", + "size": 63025372, + "url": "https://dl.igneum.network/dl/public/Igneum-Miner-Setup-0.3.20.exe" + }, + "wallet-mac": { + "version": "0.1.5", + "file": "Igneum-Wallet-0.1.5.dmg", + "sha256": "daf259f272934f0c1a8155ef68762c344164ae8a77c8d0621d0fceed0fb163fa", + "size": 20122390, + "url": "https://dl.igneum.network/dl/public/Igneum-Wallet-0.1.5.dmg" + } + }, + "versions_updated": "2026-10-07T20:43:23Z", + "sources": { + "network": "docs/build/build.md (the Networks table); the node lane's read of build-1's seed", + "node": "docs/plans/release-0.3.22.md and the node lane's read; the version string from igneumd --version", + "pow": "packaging/pow-freeze.txt; the binaries' fingerprint line", + "finality": "docs/spec/03-finality.md 3.3; the node's start line", + "proving": "proving/igneum-prove/elf/manifest.json; docs/fud-ledger.md P21", + "fees": "site/economics.html (the file and line of every constant); site/lib/emission.mjs", + "versions": "site/downloads.json (dl.igneum.network's index)" + }, + "read_at_short": "read 8 October 2026, 15:50 UK", + "proving_view": { + "read_at": "12:16 UK on 8 October 2026", + "read_daa": 65900, + "read_daa_note": "approximate: DAA seconds since genesis at 17:06 UTC on 7 October 2026, one a second", + "shards_paid_24h": 8209, + "ign_paid_24h": "9,913.09", + "prover_keys_24h": 29, + "shards_planned_24h": 40502, + "paid_per_hour": 905, + "lag_p50_daa": 514, + "lag_p90_daa": 953, + "source": "the observer's proof tables through /api/explorer?proving=1, the proving page", + "label": "measured" + } +} diff --git a/site/vercel.json b/site/vercel.json index c8ceddbd4..7a5b8a018 100644 --- a/site/vercel.json +++ b/site/vercel.json @@ -37,6 +37,10 @@ "source": "/address/:addr", "destination": "/address" }, + { + "source": "/release.json", + "destination": "/release-manifest.json" + }, { "source": "/benchmarks", "destination": "/miners" diff --git a/tools/ci/checks.txt b/tools/ci/checks.txt index 325456ec1..55da9c617 100644 --- a/tools/ci/checks.txt +++ b/tools/ci/checks.txt @@ -9,6 +9,7 @@ no founder name, personal login, earlier business or personal address in any tra every check in tools/ci/checks.txt has its run line here and every run line is listed (a conflict resolution cannot drop a check unseen; self-test first) site build (in a temporary copy here, in place only inside GitHub Actions) internal link check of site/*.html +the release manifest: site/release-manifest.json parses, its versions are downloads.json's, its proof ids the ELF manifest's, /release.json served, every data-rm span on a committed page carries its value every served page carries the slim bar (mark, Mine, Network, Learn, Download) with every route in its panels and the sheet (self-test, then the tree) vendor marks: site/lib/marks.mjs is brand/marks/vendor-marks.mjs byte for byte (the app and the site draw one set) the phone menu opens and is seen at 390 px on every page (self-test first; needs the box or CI browser, says so without one) diff --git a/tools/ci/link-check.mjs b/tools/ci/link-check.mjs index 324e87b2f..273798dc7 100644 --- a/tools/ci/link-check.mjs +++ b/tools/ci/link-check.mjs @@ -23,6 +23,9 @@ function resolves(target) { return candidates.some(c => existsSync(c) && statSync(c).isFile()); } +// a literal vercel.json rewrite (no :param) resolves to its destination (/release.json -> /release-manifest.json, 8 October 2026) +const rewrites = Object.fromEntries((JSON.parse(readFileSync(join(site, 'vercel.json'), 'utf8')).rewrites || []).filter(r => !r.source.includes(':')).map(r => [r.source, r.destination])); +const resolvesOrRewritten = (p) => resolves(p) || (rewrites[p.replace(/[?].*$/, '')] != null && resolves(rewrites[p.replace(/[?].*$/, '')])); for (const page of pages) { const html = readFileSync(join(site, page), 'utf8'); const ids = new Set([...html.matchAll(/\sid="([^"]+)"/g)].map(m => m[1])); @@ -34,7 +37,7 @@ for (const page of pages) { checked++; if (t.startsWith('#')) { if (t.length > 1 && !ids.has(t.slice(1))) broken.push(`${page}: fragment ${t}`); continue; } const [path, frag] = t.split('#'); - if (!resolves(path)) { broken.push(`${page}: ${t}`); continue; } + if (!resolvesOrRewritten(path)) { broken.push(`${page}: ${t}`); continue; } if (frag) { const rel = path.replace(/[?].*$/, '').replace(/^\//, ''); const file = [join(site, rel), join(site, `${rel}.html`), join(site, rel, 'index.html')].find(c => existsSync(c) && statSync(c).isFile()); diff --git a/tools/ci/pre-push.sh b/tools/ci/pre-push.sh index 695938a82..cfd968da5 100755 --- a/tools/ci/pre-push.sh +++ b/tools/ci/pre-push.sh @@ -107,6 +107,7 @@ never_push_checks() { tree_checks() { run "site build (in a temporary copy here, in place only inside GitHub Actions)" site_build run "internal link check of site/*.html" node tools/ci/link-check.mjs + run "the release manifest: site/release-manifest.json parses, its versions are downloads.json's, its proof ids the ELF manifest's, /release.json served, every data-rm span on a committed page carries its value" node tools/ci/release-manifest-check.mjs run "every served page carries the slim bar (mark, Mine, Network, Learn, Download) with every route in its panels and the sheet (self-test, then the tree)" bash -c 'node tools/ci/site-nav-check.mjs --self-test && node tools/ci/site-nav-check.mjs' run "vendor marks: site/lib/marks.mjs is brand/marks/vendor-marks.mjs byte for byte (the app and the site draw one set)" cmp brand/marks/vendor-marks.mjs site/lib/marks.mjs run "the phone menu opens and is seen at 390 px on every page (self-test first; needs the box or CI browser, says so without one)" node tools/site/sheet-test.mjs --self-test diff --git a/tools/ci/release-manifest-check.mjs b/tools/ci/release-manifest-check.mjs new file mode 100644 index 000000000..1513dfbc9 --- /dev/null +++ b/tools/ci/release-manifest-check.mjs @@ -0,0 +1,50 @@ +// Release manifest check (8 October 2026, an accepted external review): site/release-manifest.json is served at /release.json +// and is the one source of the chain's identity, sources, class, finality rule, proof ids, fees and versions on the status +// pages. This holds it together: the manifest parses and carries every block; its versions are the download index's; its +// proof ids are the ELF manifest's (when the tree carries it); vercel.json serves it at /release.json; every +// on a committed page carries the manifest's value; and no forbidden string is in it. +// node tools/ci/release-manifest-check.mjs exit 1 listing every fault +import { readFileSync, existsSync, readdirSync } from 'node:fs'; +import { join, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +const root = join(dirname(fileURLToPath(import.meta.url)), '..', '..'); +const site = join(root, 'site'); +const fails = []; +const m = JSON.parse(readFileSync(join(site, 'release-manifest.json'), 'utf8')); +for (const k of ['format', 'generated', 'read_at', 'network', 'source', 'mining', 'finality', 'proving', 'fees', 'versions', 'sources']) if (!(k in m)) fails.push(`manifest: no "${k}" block`); +if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/.test(m.generated || '')) fails.push('manifest: "generated" is not an ISO UTC date'); +if (m.network?.chain_id !== 4464 || m.network?.chain_id_hex !== '0x1170') fails.push('manifest: Devnet 3 chain id is 4464 (0x1170)'); +if (!/two thirds of active weight and at least two thirds of total weight/.test(m.finality?.statement || '')) fails.push('manifest: the finality statement must say two thirds of active and two thirds of total weight'); +if (m.proving?.verifier_in_consensus !== 'off') fails.push('manifest: the verifier is off in consensus (ledger P21) until that row moves'); +const dl = JSON.parse(readFileSync(join(site, 'downloads.json'), 'utf8')); +for (const [k, v] of Object.entries(dl.files)) { + const w = m.versions?.[k]; + if (!w) { fails.push(`manifest: versions.${k} missing (in downloads.json)`); continue; } + for (const f of ['version', 'file', 'sha256', 'size']) if (w[f] !== v[f]) fails.push(`manifest: versions.${k}.${f} is ${w[f]}, downloads.json says ${v[f]}`); +} +if (m.versions_updated !== dl.updated) fails.push(`manifest: versions_updated ${m.versions_updated} is not downloads.json's ${dl.updated}`); +const elfp = join(root, 'proving', 'igneum-prove', 'elf', 'manifest.json'); +if (existsSync(elfp)) { + const e = JSON.parse(readFileSync(elfp, 'utf8')); + for (const [a, b] of [['shard_program_id', e.shard.program_id], ['shard_elf_sha256', e.shard.elf_sha256], ['shard_vk_sha256', e.shard.vk_sha256], ['aggregator_program_id', e.aggregator.program_id], ['aggregator_elf_sha256', e.aggregator.elf_sha256], ['aggregator_vk_sha256', e.aggregator.vk_sha256], ['sp1_circuit_version', e.sp1_circuit_version], ['sp1_crate_version', e.sp1_crate_version], ['pinned_at', e.pinned_at]]) + if (m.proving[a] !== b) fails.push(`manifest: proving.${a} is ${m.proving[a]}, the ELF manifest says ${b}`); +} +const vercel = JSON.parse(readFileSync(join(site, 'vercel.json'), 'utf8')); +if (!(vercel.rewrites || []).some(r => r.source === '/release.json' && r.destination === '/release-manifest.json')) fails.push('vercel.json: no rewrite /release.json -> /release-manifest.json'); +const value = (p) => { const v = p.split('.').reduce((o, k) => (o == null ? undefined : o[k]), m); return v === undefined ? undefined : (typeof v === 'number' && !/_id$/.test(p) ? v.toLocaleString('en-GB') : String(v)); }; +let spans = 0; +for (const f of readdirSync(site).filter(f => f.endsWith('.html'))) { + const html = readFileSync(join(site, f), 'utf8'); + for (const [, p, text] of html.matchAll(/([^<]*)<\/span>/g)) { + spans++; + const want = value(p); + if (want === undefined) fails.push(`${f}: data-rm="${p}" names no manifest value`); + else if (text.replace(/&/g, '&').replace(/</g, '<') !== want) fails.push(`${f}: data-rm="${p}" carries "${text.slice(0, 60)}", the manifest says "${want.slice(0, 60)}" (rebuild the site)`); + } +} +if (spans < 10) fails.push(`only ${spans} data-rm spans on the committed pages; the status pages read the manifest`); +const raw = readFileSync(join(site, 'release-manifest.json'), 'utf8'); +for (const pat of readFileSync(join(root, 'tools', 'ci', 'forbidden-strings.txt'), 'utf8').split('\n').filter(l => l && !l.startsWith('#'))) + if (new RegExp(pat).test(raw)) fails.push(`manifest: forbidden string ${pat}`); +if (fails.length) { console.error(`release-manifest check: ${fails.length} fault(s)\n ${fails.join('\n ')}`); process.exit(1); } +console.log(`release-manifest check: manifest ${m.generated}, ${Object.keys(m.versions).length} platform versions match downloads.json, proof ids match the ELF manifest, /release.json served, ${spans} data-rm spans carry the manifest's values`);