From 6a93297dfec0f3a827ba79f470ade6f00ebafd9c Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Sat, 3 Oct 2026 21:46:04 +0000 Subject: [PATCH] Share card: compact 256 px coin so chat apps show the small card Co-Authored-By: Claude Fable 5.1 --- site/bench.html | 16 ++++++++++++---- site/build.mjs | 4 ++-- site/index.html | 8 ++++---- site/litepaper.html | 8 ++++---- site/live.html | 8 ++++---- site/og-small.png | Bin 0 -> 25215 bytes 6 files changed, 26 insertions(+), 18 deletions(-) create mode 100644 site/og-small.png diff --git a/site/bench.html b/site/bench.html index 80808d303..36f85b548 100644 --- a/site/bench.html +++ b/site/bench.html @@ -13,8 +13,8 @@ - - + + @@ -61,7 +61,7 @@ footer{border-top:1px solid var(--line);padding-block:24px 48px;font-size:13px;c

Engineering log

Every measurement the project has made, newest at the bottom, written by the people and agents who ran it, with the commands and hardware. Prototype numbers are not mining numbers and say so.

- +

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

@@ -111,7 +111,15 @@ footer{border-top:1px solid var(--line);padding-block:24px 48px;font-size:13px;c

3 October 2026, igneum-node devnet v0: 3-node igneum-devnet at 1 BPS with the 80/20 coinbase and vote_key_hash (consensus-engineer)

Machine: Apple M5 Max (18 logical cores), rustc 1.99.0, fork vendor/igneum-node at commit "Build: forward the igneum-pow feature" on top of rusty-kaspa v2.1.0 01b532e8. Release build of kaspad and igneum-miner; the kHeavyHash stub engine (default feature set); cargo check -p kaspad --features igneum-pow also builds. Network: three kaspad --devnet --nodnsseed --disable-upnp --enable-unsynced-mining nodes, P2P 26611/26621/26631, gRPC 26610/26620/26630, nodes 2 and 3 --connect to node 1 and node 3 also to node 2; network name igneum-devnet, k 18, merge depth 3,600 blocks, DAA 661 samples x 4 blocks, genesis bits 0x1e020000 (2^23 expected hashes per block). Miners: three igneum-miner mine processes, 6 threads each, one per node, 960 s, each with its own vote-key label: 2.21 MH/s each (6.63 MH/s total), found 253 + 284 + 270 = 807 blocks, 0 rejected. Blocks per second: 0.84 on all three nodes over the 901.9 s watch window (755 blocks each); expected 0.79 from hash rate over genesis difficulty, then the DAA lowered difficulty from 4,194,304 to 3,444,348 after its 600-block minimum window (block 600 to 711), still converging to 1.00 when the run ended. Propagation: block count, DAA score and sink hash identical on all three nodes at 90 of 90 ten-second samples; 1.11 parents and 1.11 mergeset per block on average, tips stayed at 1 (three serial CPU miners rarely collide). vote_key_hash: igneum-miner inspect 40 read the same 40 selected-chain blocks from all three nodes over gRPC and found the header's vote_key_hash identical on every node for 40 of 40 blocks, with the three miners' distinct hashes (17 + 17 + 6 blocks) all present, so the field round-trips through the template RPC, submit, p2p relay and the header hash. Emission: 80/20 exact on 39 of 39 single-payee coinbases (the 40th merged two blues, three outputs, pool share still 0.2000); at DAA 806 the payload subsidy was 317,767,704 units (launch ramp day 0, 10.03%), split 254,213,284 to the miner and 63,553,320 to the OP_RETURN igneum-proving-pool-v0 output. Unit tests, release profile: kaspa-consensus-core igneum 8 pass (subsidy table, ramp, split, cap), params window test 1 pass, kaspa-pow 5 pass (stub) and 6 pass with --features igneum-pow (engine smoke, one 256 MiB cache, 0.39 s), kaspa-consensus coinbase 8 pass. Per-second subsidy, 8 decimals: 3,168,808,781 units (31.68808781 coins) for years 0 to 2, 1,584,404,390 for years 2 to 4, 792,202,195 for years 4 to 6, 1 unit in period 31, 0 from period 32; ramp day 0 is 316,880,878; the sum is under the 4,000,000,000-coin cap by less than 100 coins. Not done: the devnet ran on the kHeavyHash stub, not the lottery engine (the miner has no igneum-pow path yet and the lane hash does not absorb the header); no VDF seed, no finality, no prover payout; 8 versus 18 decimals open (docs/fork-divergence.md).

3 October 2026, first devnet blocks on the real lottery hash: CPU, then Metal GPU, three worker implementations (consensus-engineer)

-

Machine: Apple M5 Max (18 logical cores, 40 GPU cores), rustc 1.99.0, Swift 5.8.1, fork vendor/igneum-node at "PoW: header-bound lottery engine, real-hash miner modes, genesis bits 0x1e400000" plus the overnight genesis commit; igneum-pow at "igneum-pow: header binding ...". Release builds with --features igneum-pow. Binding (spec 01 section 1.6, O-1.9, igneum-pow/src/bind.rs): I = seed_words_from_bytes("igneum-block/" || H || nonce_hi_le32), lane nonce = low 32 bits of the 64-bit header nonce, H = header hash with the nonce zeroed and the timestamp kept, pow256 = lane hash in the top 64 bits with zero low bits (pow <= target is exactly lane <= target >> 192). Interim day seed "igneum-day/" || day_le64 (day = timestamp_ms / 86,400,000); epoch seed = the 32 bytes of the epoch block hash (genesis for epoch 0). 8 bound vectors in igneum-pow/README.md; 29 crate tests pass; the 288 pack vectors and the pack files are unchanged, program_bound.metal, kernel_bound.cu and kernel_bound.cl are new pack files. CPU rate on the real hash: 0.44 ms per 32-lane warp on one core (crate bench); 0.142 MH/s with one 6-thread miner (1.35 ms per warp per thread); 0.294 MH/s with three 6-thread miners at once (2.0 ms per warp per thread, memory-latency bound), 0.37 MH/s later in the run. Genesis bits for the CPU devnet: 0x1e400000 = 2^18 expected hashes per block. CPU devnet, 3 nodes (node 1 RPC and p2p on 0.0.0.0, ports 26610/26611, 26620/26621, 26630/26631), three 6-thread igneum-miner mine --engine igneum-pow, 660 s: found 252 + 309 + 272 = 833 blocks, 0 rejected; watch window 641 s: 825 blocks on all three nodes = 1.29 blocks/s; sink identical on all nodes at 61 of 64 samples (tips 1 or 2, twice 3). DAA: 1.43 blocks/s over the first 600 blocks at difficulty 131,072, then difficulty 184,000 to 187,000 (1.41x) and 1.03 blocks/s over blocks 610 to 816. Each node logged "PoW accepted <hash> by igneum-lottery-v1-bound" 833 times, 0 rejections during the run. igneum-miner bad-nonce: Reject(BlockInvalid) and a "PoW rejected ... by igneum-lottery-v1-bound" line. inspect 30: vote_key_hash identical on all 3 nodes for 30 of 30, 80/20 exact on 19 of 19 single-payee coinbases. Epoch 0 seed = devnet genesis hash 03115da0...d86b, day 20729, program 104 loads/hash. Metal GPU worker (proto-metal/igneum-bench --serve, runtime-compiled igneum_hash_bound, init words in buffer 3, 2^22 nonces per dispatch, CPU-side scan of the 64-bit outputs) driven by igneum-miner --worker on node 1 of the same devnet, 300 s: 506 jobs of 2^24 nonces, 5,636 blocks found and accepted, 0 rejected, 0 CPU/GPU mismatches (every found nonce is re-hashed on the CPU before submit); nodes 833 -> 5,073 blocks on all three (14.57 blocks/s over the 291 s watch window), sink identical at 28 of 29 samples; difficulty 180,562 -> 7,134,312 (39x) and still rising at the end. Epoch change crossed live at DAA 3,600: new seed 76c39fcf..., 128-load program compiled by the worker in 129 ms (first program 6.5 ms), no rejected blocks across the change. Rate through the worker: 32.4 MH/s inside jobs, 28.2 MH/s wall, against 45.2 MH/s raw bench (igneum-bench 2^22 x 4 batches): the gap is the read-back and CPU scan per dispatch, one command buffer per dispatch, and the template round trip per job. Early in the run one job found about 45 sibling blocks of one template; the miner now submits one block per job. Overnight devnet (started 20:07 BST): genesis bits 0x1d100000 = 2^28 expected hashes per block, sized for RTX 5090 229 + M5 Max 45 + gfx1036 4 = 278 MH/s (1.04 blocks/s); genesis hash edc4fa84...fb07; epoch 0 program 136 loads/hash compiled in 69.5 ms on Metal; node 1 alone (0.0.0.0:26610/26611, caffeinate -dims, logs /tmp/igneum-devnet/node1.log) with the Metal worker (/tmp/igneum-devnet/metal-worker.log): 31 blocks in 273 s = 0.11 blocks/s at 31.1 MH/s, as expected for 2^28 until the PC joins. Worker implementations, all bit-exact with igneum-pow hash-bound for a 96-nonce job across the 2^32 lane boundary (nonces 4294967264 to 4294967359, prehash ab x 32, devnet seeds): Metal (M5 Max GPU), OpenCL (proto-opencl/host.c --serve, Apple OpenCL 1.2 on the M5 Max, local-memory exchange, --vendor device filter added), CUDA (proto-cuda/host.cu --serve with the pack's kernel_bound.cu, through the clang emulation shim: bench PASS on the Rust-exported devnet pack, serve job bit-exact, seed-mismatch error exercised). CUDA and OpenCL are built ahead of time per pack; the Windows launcher re-exports and rebuilds at each epoch or day change (miner exit 42). igneum-miner.exe cross-compiled for x86_64-pc-windows-gnu with Homebrew mingw-w64 (9.4 MB; no rocksdb in the miner's closure). Not done: no NVIDIA or AMD run of the bound kernels yet (the Windows package ~/Desktop/igneum-mine-test.zip is the next step); NVRTC and runtime OpenCL rebuilds inside the workers; the block level for pruning proofs on a lane-only pow value; 8 vs 18 decimals; the VDF seeds and finality.

+

Machine: Apple M5 Max (18 logical cores, 40 GPU cores), rustc 1.99.0, Swift 5.8.1, fork vendor/igneum-node at "PoW: header-bound lottery engine, real-hash miner modes, genesis bits 0x1e400000" plus the overnight genesis commit; igneum-pow at "igneum-pow: header binding ...". Release builds with --features igneum-pow. Binding (spec 01 section 1.6, O-1.9, igneum-pow/src/bind.rs): I = seed_words_from_bytes("igneum-block/" || H || nonce_hi_le32), lane nonce = low 32 bits of the 64-bit header nonce, H = header hash with the nonce zeroed and the timestamp kept, pow256 = lane hash in the top 64 bits with zero low bits (pow <= target is exactly lane <= target >> 192). Interim day seed "igneum-day/" || day_le64 (day = timestamp_ms / 86,400,000); epoch seed = the 32 bytes of the epoch block hash (genesis for epoch 0). 8 bound vectors in igneum-pow/README.md; 29 crate tests pass; the 288 pack vectors and the pack files are unchanged, program_bound.metal, kernel_bound.cu and kernel_bound.cl are new pack files. CPU rate on the real hash: 0.44 ms per 32-lane warp on one core (crate bench); 0.142 MH/s with one 6-thread miner (1.35 ms per warp per thread); 0.294 MH/s with three 6-thread miners at once (2.0 ms per warp per thread, memory-latency bound), 0.37 MH/s later in the run. Genesis bits for the CPU devnet: 0x1e400000 = 2^18 expected hashes per block. CPU devnet, 3 nodes (node 1 RPC and p2p on 0.0.0.0, ports 26610/26611, 26620/26621, 26630/26631), three 6-thread igneum-miner mine --engine igneum-pow, 660 s: found 252 + 309 + 272 = 833 blocks, 0 rejected; watch window 641 s: 825 blocks on all three nodes = 1.29 blocks/s; sink identical on all nodes at 61 of 64 samples (tips 1 or 2, twice 3). DAA: 1.43 blocks/s over the first 600 blocks at difficulty 131,072, then difficulty 184,000 to 187,000 (1.41x) and 1.03 blocks/s over blocks 610 to 816. Each node logged "PoW accepted <hash> by igneum-lottery-v1-bound" 833 times, 0 rejections during the run. igneum-miner bad-nonce: Reject(BlockInvalid) and a "PoW rejected ... by igneum-lottery-v1-bound" line. inspect 30: vote_key_hash identical on all 3 nodes for 30 of 30, 80/20 exact on 19 of 19 single-payee coinbases. Epoch 0 seed = devnet genesis hash 03115da0...d86b, day 20729, program 104 loads/hash. Metal GPU worker (proto-metal/igneum-bench --serve, runtime-compiled igneum_hash_bound, init words in buffer 3, 2^22 nonces per dispatch, CPU-side scan of the 64-bit outputs) driven by igneum-miner --worker on node 1 of the same devnet, 300 s: 506 jobs of 2^24 nonces, 5,636 blocks found and accepted, 0 rejected, 0 CPU/GPU mismatches (every found nonce is re-hashed on the CPU before submit); nodes 833 -> 5,073 blocks on all three (14.57 blocks/s over the 291 s watch window), sink identical at 28 of 29 samples; difficulty 180,562 -> 7,134,312 (39x) and still rising at the end. Epoch change crossed live at DAA 3,600: new seed 76c39fcf..., 128-load program compiled by the worker in 129 ms (first program 6.5 ms), no rejected blocks across the change. Rate through the worker: 32.4 MH/s inside jobs, 28.2 MH/s wall, against 45.2 MH/s raw bench (igneum-bench 2^22 x 4 batches): the gap is the read-back and CPU scan per dispatch, one command buffer per dispatch, and the template round trip per job. Early in the run one job found about 45 sibling blocks of one template; the miner now submits one block per job. Overnight devnet (started 20:07 BST): genesis bits 0x1d100000 = 2^28 expected hashes per block, sized for RTX 5090 229 + M5 Max 45 + gfx1036 4 = 278 MH/s (1.04 blocks/s); genesis hash edc4fa84...fb07; epoch 0 program 136 loads/hash compiled in 69.5 ms on Metal; node 1 alone (0.0.0.0:26610/26611, caffeinate -dims, logs /tmp/igneum-devnet/node1.log) with the Metal worker (/tmp/igneum-devnet/metal-worker.log): 31 blocks in 273 s = 0.11 blocks/s at 31.1 MH/s, as expected for 2^28 until the PC joins. Worker implementations, all bit-exact with igneum-pow hash-bound for a 96-nonce job across the 2^32 lane boundary (nonces 4294967264 to 4294967359, prehash ab x 32, devnet seeds): Metal (M5 Max GPU), OpenCL (proto-opencl/host.c --serve, Apple OpenCL 1.2 on the M5 Max, local-memory exchange, --vendor device filter added), CUDA (proto-cuda/host.cu --serve with the pack's kernel_bound.cu, through the clang emulation shim: bench PASS on the Rust-exported devnet pack, serve job bit-exact, seed-mismatch error exercised). CUDA and OpenCL are built ahead of time per pack; the Windows launcher re-exports and rebuilds at each epoch or day change (miner exit 42). igneum-miner.exe cross-compiled for x86_64-pc-windows-gnu with Homebrew mingw-w64 (9.4 MB; no rocksdb in the miner's closure). Not done: no NVIDIA or AMD run of the bound kernels yet (the Windows package ~/Desktop/igneum-mine-test.zip is the next step); NVRTC and runtime OpenCL rebuilds inside the workers; the block level for pruning proofs on a lane-only pow value; 8 vs 18 decimals; the VDF seeds and finality.

+

3 October 2026, Windows node package: igneumd cross-compiled for x86_64-pc-windows-gnu, two-peer sync test (consensus-engineer)

+

Machine: Apple M5 Max, load average 60 to 110 (three other agents building), rustc 1.99.0, Homebrew mingw-w64 (gcc 16.2.0), Homebrew llvm (libclang). Worktree vendor/igneum-node-win, branch windows-node at 352495f6 (the rename commit d62708a8 plus one miner change: watch prints blue= and synced= after sink=). Cross-compile: cargo build --release -j 6 -p kaspad -p igneum-miner --features igneum-pow --target x86_64-pc-windows-gnu at nice -n 19, 8 min 25 s from a clean target directory (recipe in proto-cuda/windows-node/cross-build.sh). librocksdb-sys (bindgen plus the bundled rocksdb and snappy C++) built with LIBCLANG_PATH=/opt/homebrew/opt/llvm/lib, BINDGEN_EXTRA_CLANG_ARGS_x86_64_pc_windows_gnu="--target=x86_64-w64-mingw32 --sysroot=<mingw sysroot> -I<mingw include>" and CXX_x86_64_pc_windows_gnu=x86_64-w64-mingw32-g++; zstd, lz4, bzip2, zlib, secp256k1 and mimalloc built with the mingw gcc. igneumd.exe 43,172,352 bytes, igneum-miner.exe 9,391,104 bytes. The exe imports libstdc++-6.dll: -static-libstdc++ is ignored by the gcc driver rustc links with, and -C link-arg=-static (second full build, 8 min) does not cover a library rustc passes as -Bdynamic; the package ships libstdc++-6.dll, libgcc_s_seh-1.dll and libwinpthread-1.dll next to the exe (fix for next time: empty CXXSTDLIB_x86_64_pc_windows_gnu plus -Wl,-Bstatic -lstdc++). Not run on Windows yet. Sync test (native build of the same worktree, 21:44 to 21:46 BST, live node on 26610/26611 untouched): node A on 27000/27001 with START-NODE.bat's flags (--addpeer=192.168.68.64:26611 --listen=0.0.0.0:27001 --nodnsseed --disable-upnp --nologfiles) connected and started IBD within 20 ms, had 5,144 headers and 1,386 blocks at 7 s, and from 17 s on matched the live node's block count, DAA score, blue score and sink at every 10-s sample over 60 s (5,157 to 5,175 blocks, sink identical 5 of 6 samples, synced=true); every header checked by igneum-lottery-v1-bound. Live node peers 1 -> 2 -> 1. Node B on 27010/27011 dialled A's listener, synced to the same sink within 25 s and learnt the live node from A (outbound 2): a node with --addpeer plus --listen accepts inbound connections (--connect would set the inbound limit to 0, kaspad/src/daemon.rs). SIGINT stopped both cleanly. Package: ~/Desktop/igneum-node-windows.zip from proto-cuda/windows-node/make-package.sh (exe, miner exe, src.zip snapshot of the worktree HEAD plus igneum-pow/, scripts, README). Build on the PC (BUILD-NODE.bat) estimated at 15 to 25 minutes on the 9800X3D, approximate, untested.

+

3 October 2026, R3.26 / M15: PoW checked after the cheap checks, cache-build cap, attack before and after (consensus-engineer)

+

Machine: Apple M5 Max (18 logical cores), load average 60 to 110 (three other agents building at the same time), rustc 1.99.0. Worktree vendor/igneum-node-r3, branch r3-fixes at 5166ee26 on top of the rename commit d62708a8. Release builds; the real engine needs --features igneum-pow. Fix: validate_header now runs version, timestamp-not-in-future, parent, vote-key, parents-exist, GHOSTDAG, pruning, DAA-score, difficulty, blue-score, blue-work and past-median checks before the PoW engine; the engine (the one 256 MiB cache per day seed) is the last check that chooses seeds. The engine is process-wide, holds KEEP = 4 (epoch seed, day) caches, keeps the chain's current and next day resident, runs at most one build per seed pair and at most 2 at once with a queue of 4 (then PowCacheQueueFull, retryable, not a peer fault). A per-peer p2p guard counts an off-day cold build or a rejected-before-PoW header as a strike; more than IGNEUM_POW_STRIKES (default 2) in an hour disconnects the peer and bans its IP for an hour. Cache build time: one 256 MiB ChaCha12 program-plus-cache build in 222 ms on one core under this load (the engine smoke test on an idle machine earlier the same day measured about 0.2 s; proto-metal reported 273.6 ms for the CPU reference fill under the same load). The honest 20-to-60 s proving lag and the 10 ms CPU verify gate are unaffected. Attack, before and after (ignored test measure_m15_attack_before_and_after, release, --features igneum-pow, validate_and_insert_block, the path submit_block and block relay call into): an honest 10-block chain builds 1 cache (genesis epoch, genesis day). Then 50 headers with bogus timestamps (50 distinct past days) and bogus DAA scores.

+ +

Tests: kaspa-pow --features igneum-pow 8 pass (engine smoke, one_build_per_seed_pair_under_contention, live_days_survive_off_day_builds, build_queue_is_bounded, index and live-day helpers, shared-engine, stub); kaspa-consensus header_processor cheap_checks_run_before_the_pow_engine pass; kaspa-p2p-flows pow_guard 2 pass; the full kaspa-consensus release suite otherwise unchanged. M16 Metal note (R3.5, cheap reconfirmation only): the Mac --inline-dataset shortcut at the 256 MiB cache, 256 MiB dataset, under the same heavy load, ran honest 91.7 Mhash/s against inline 5.29 Mhash/s (inline about 17x slower); this is noisier and slower than the idle-machine figures already in proto-metal/MEMHARD.md (10x slower at a 256 MiB dataset, 4.8x at 1 GiB), because the inline kernel is compute-bound and the machine was loaded. The 64 MiB on-die-SRAM emulation M16 wants (inline kernel with a 64 MiB cache, cacheLog2Words = 24 in proto-metal/main.swift) is the RTX 5090 run reserved for the project lead's PC, as R3.5 states; it is not done here and the Mac number above does not price a die. Not done: the real-engine daemon RPC run (honest blocks need GPU-mined pow, so the measurement used the equivalent validate path with skip_proof_of_work); the 64 MiB-cache inline kernel on the 5090; the chain-derived day seed by DAA score (spec 01 section 1.12, still the timestamp-day devnet rule); the VDF epoch seed and finality.

+

3 October 2026, difficulty controller: devnet record, simulator, Igneum dual-lane rule, 3-node CPU test network (consensus-engineer)

+

Machine: the same Apple M5 Max, shared with two other build agents (load average 60 to 98 during the Rust builds). Fork worktree vendor/igneum-node-diff, branch difficulty from d62708a8. Everything in docs/analysis/difficulty-2026-10-03.md; raw outputs in sim/difficulty/results.md. Record: 3,682 headers of the overnight devnet pulled read-only through the observer node's wRPC JSON (ws://127.0.0.1:28640, getBlocks from genesis) into sim/difficulty/devnet-2026-10-03.csv. Kaspa's sampled DAA held genesis difficulty 134,217,727 through block 600 at 0.6 blocks/s (PC, 116 MH/s estimated from the blocks), then eased 4.8x at the first retarget (DAA 600, 19:56:12 UTC) and on to 15.7x (8,552,118) because the 600-block window spanned the 21-minute Metal-only period and a 13-minute idle gap; 5.44 blocks/s over the next five minutes, 355 blocks in the peak minute, 1,633 blocks above 2x, then 1.5x too hard; the DAG widened to 3,681 blocks for 1,656 chain blocks. Exact replay of the record's bits through rusty-kaspa's integer arithmetic matches 244 of 244 retargets while the devnet was a chain and diverges from DAA 845 (merged blocks a chain-only replay cannot see). Simulator sim/difficulty/sim.py (Python, one chain, exponential solve times, 1 BPS): Kaspa sampled DAA, Monero 720, LWMA 60 and 120, the Igneum rule and the brief's literal trigger, on nine synthetic profiles plus the record. Two design findings: Zawy's average-target LWMA estimator is biased while targets ramp (the fast lane stalled at 15x of a 50x step), so every Igneum lane uses work over time (Kaspa's estimateNetworkHashesPerSecond estimator); the brief's trigger (short-window rate off target) chatters once the short window is back on target while the long window is still polluted (polluted case 1,876 s against 70 s), so the trigger compares the two lanes. Tuned on the synthetic set only: short window 120, hold 8, prior 16, long lane from 600 blocks of the epoch, trigger 25%, harden 3% per block, ease 10% per block, solvetime cap 20 T. Settled seconds (121-block mean within 10% for 100 blocks), Kaspa / Monero / LWMA60 / LWMA120 / Igneum: x50 step 1,542 / 94 / 105 / 231 / 62; /50 step 12,296 / 6,433 / 578 / 1,074 / 657 (worst gap 179 / 187 / 119 / 65 / 35 s); epoch +-30% steps 1,583 / 456 / 157 / 153 / 144; 10x hopping never / 284 (6 of 12 never) / 264 / 326 / 212; polluted window 2,748 (peak 7.9x) / 124 (peak 15x) / 66 / 110 / 70; genesis 10x too hard never / 287 / 155 / 188 / 322; steady std of rate 0.012 / 0.037 / 0.131 / 0.092 / 0.038; the record's 75x step never (peak 7.6x, 2,340 blocks above 2x) / 136 / 75 / 157 / 79. With +-500 ms timestamp jitter the ordering holds (Igneum x50 169 s, /50 1,047 s, epoch 55 s, polluted 71 s). Implementation: DifficultyRule { KaspaSampled, IgneumDual } as a network parameter (IgneumDual on all four networks, "difficulty_rule": "kaspa-sampled" in the override file selects Kaspa's), OverrideParams.genesis_bits (genesis hash recomputed) for test networks, SampledDifficultyManager::igneum_difficulty_bits over a selected-chain walk plus the in-epoch samples of the existing window, pure integer core igneum_target (Uint320). cargo test -p kaspa-consensus --lib difficulty: 9 pass (hold, steady state, 3% harden, 10% ease, trigger, epoch shrinkage, max target, Kaspa's two level-work tests); cargo test -p kaspa-consensus-core --lib params: 4 pass. The miner now takes the genesis from the node (pruning point before the first pruning) so it mines an override-genesis network; before the fix it hashed the compiled devnet genesis as the epoch seed and every block was rejected. TESTNET_BENCH Not done: no DAG in the simulator (red blocks' work is ignored by every lane, as by Kaspa's estimator); Monero and LWMA reproduced from memory (approximate); real-time targeting left out; the chain walk (600 reads per header early in an epoch) must be re-measured before the 4 BPS step.

diff --git a/site/build.mjs b/site/build.mjs index b6245c1f1..51206fa82 100644 --- a/site/build.mjs +++ b/site/build.mjs @@ -58,8 +58,8 @@ function meta(title, desc, path) { - - + + diff --git a/site/index.html b/site/index.html index dbbb735de..fe669f790 100644 --- a/site/index.html +++ b/site/index.html @@ -12,14 +12,14 @@ - - - + + + - + diff --git a/site/litepaper.html b/site/litepaper.html index 923712fb0..a98680787 100644 --- a/site/litepaper.html +++ b/site/litepaper.html @@ -12,14 +12,14 @@ - - - + + + - + diff --git a/site/live.html b/site/live.html index 0b2c315d1..d8917f85d 100644 --- a/site/live.html +++ b/site/live.html @@ -12,14 +12,14 @@ - - - + + + - + diff --git a/site/og-small.png b/site/og-small.png new file mode 100644 index 0000000000000000000000000000000000000000..2eea54acf831c9e097fba0b57ed8708c4d824dee GIT binary patch literal 25215 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 Ef+9k?bpQYW literal 0 HcmV?d00001