Difficulty: the live oscillation of 4 October, its cause, the DAG replay and rule v2 (reference window 600 behind a height switch)
Live devnet v4: a second RTX 5090 joining 7 minutes into an epoch left the whole-epoch reference lane polluted for the hour; the short lane read 11 to 25% above it and the 25% trigger flipped between the two for 40 minutes (102M to 164M, 54 to 81 blocks a minute). Record and hash-rate truth under sim/difficulty/records/. sim.py gains a DAG model (miners on nodes with igneum-miner's template staleness, GHOSTDAG, the rule as the node runs it) and --live replay: std of log difficulty 0.115 against the record's 0.134, 4.3 peaks of 1.31x against 4 of 1.37x. The brief's candidates (short lane 240/360, ease clamp 3%, clamp once per DAA second, hysteresis, median of three) leave 0.09 to 0.13; capping the reference lane at the newest 600 blocks of the epoch gives 0.026 with no flips. Rule v2 = that cap, epoch lane only, behind difficulty_v2_activation_daa (devnet-v4 fork). Attack suite and synthetic set before and after, 3-node test network of the switch (testnet_v2.py), analysis document, spec 2.3, bench-log entry, ledger M24, fast-time file carries the new field. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
9de0429633
commit
c01b9544a4
16 changed files with 11822 additions and 18 deletions
308
docs/analysis/difficulty-2026-10-04-oscillation.md
Normal file
308
docs/analysis/difficulty-2026-10-04-oscillation.md
Normal file
|
|
@ -0,0 +1,308 @@
|
||||||
|
# Difficulty oscillation on the live devnet, 4 October 2026: record, replay, cause, rule v2
|
||||||
|
|
||||||
|
4 October 2026, consensus-engineer. Follows `difficulty-2026-10-03.md` (the rule) and
|
||||||
|
`sim/difficulty/attacks/README.md` (the attacks). Everything measured here is reproducible from
|
||||||
|
`sim/difficulty/` (record, hash-rate truth, simulator with the DAG model, test-network script) and the
|
||||||
|
`devnet-v4` branch of `vendor/igneum-node` (worktree `vendor/igneum-node-v4`).
|
||||||
|
|
||||||
|
## 1. The finding
|
||||||
|
|
||||||
|
Live devnet v4 (genesis 10:05 BST, `docs/bench-log.md` "devnet v4 cut-over"), 09:05 to 10:58 UTC. One
|
||||||
|
RTX 5090 (PC 1, 122 MH/s, 8 identities through its own node) plus the Mac's Metal worker (26.7 MH/s, on
|
||||||
|
the Mac node) and an integrated Radeon (2.8 MH/s) mined from 09:11. A second RTX 5090 (PC 2, 124 MH/s,
|
||||||
|
8 identities, through the Mac node) joined at 10:12:17 UTC, left at 10:31:25 and came back at 10:35:19.
|
||||||
|
The network went from about 152 to about 280 MH/s. The two PCs are clones with the same Windows
|
||||||
|
computer name, so their identities carried the same vote keys (fixed the same day: identities now come
|
||||||
|
from a per-install machine id); the log intake tells them apart by run id.
|
||||||
|
|
||||||
|
What the rule did, from the observer's difficulty events and the header record:
|
||||||
|
|
||||||
|
| Period (UTC) | What was mining | Difficulty band (node convention, 2^255 / target) | Blocks per minute | Chain blocks merging 2+ blues |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| 09:24 to 10:04 | PC 1 + Mac + Radeon | 56.7M to 67M, within 1% per minute from 09:24 (one excursion to 82M at 09:43) | 49 to 79 | 38.7% |
|
||||||
|
| 10:14 to 10:16 | PC 2 joins | 70M to 144M in 90 s (23 harden steps of 3%) | | |
|
||||||
|
| 10:17 to 10:32 | both PCs | 101.8M to 164.3M, 5 peaks of 1.33x spaced 132 chain blocks, std of log difficulty 0.123 | 54 to 81 | 36.3% |
|
||||||
|
| 10:33 to 10:36 | PC 2 off, then back | 116M down to 67M, back to 106M | | |
|
||||||
|
| 10:37 to 10:54 | both PCs | 103M to 150M, 4 peaks of 1.35x spaced 150 chain blocks, std 0.072; the floor rises 110M to 127M | 55 to 76 | 34.5% |
|
||||||
|
| 11:02 | epoch boundary (DAA 7,200 at 11:01:52) and both PCs restarted for the machine-id package | 152M down to 77M in 3 minutes | | |
|
||||||
|
| 11:07 to 11:17 | one PC + Mac | 69.0M to 72.7M, within 1.3% per minute, no flips | 45 to 73 | |
|
||||||
|
|
||||||
|
The true level for 280 MH/s at one block a second is 139M. The rule sat on a floor of 110M to 127M (the
|
||||||
|
chain ran at 1.1 to 1.2 blocks a second) and burst to 146M to 164M every two to three minutes. The
|
||||||
|
observer's per-poll events show the bursts as stacked clamp steps: "up 6.1%" is two 3% hardens inside
|
||||||
|
one 2-second poll, "up 15.9%" five, "down 24.3%" three 10% eases.
|
||||||
|
|
||||||
|
Records: `sim/difficulty/records/live-2026-10-04.csv` (8,090 headers through 11:18 UTC from the observer
|
||||||
|
node's read-only wRPC, `pull_live.py`: hash, DAA and blue score, stamp, bits, difficulty, parents,
|
||||||
|
selected parent, blue work, mergeset sizes, vote key) and `live-2026-10-04-hashrate.csv` (587 STATUS
|
||||||
|
lines of the four GPU workers from the log intake: the last-30-s hash rate every 30 s, with run id and
|
||||||
|
node; the Mac Metal worker does not upload, its 26.7 MH/s is the bench-log value of the hourly swap).
|
||||||
|
|
||||||
|
## 2. The cause
|
||||||
|
|
||||||
|
Spec 2.3 as implemented on 3 October: the reference lane R is the epoch window, every block of the
|
||||||
|
block's own epoch (the epoch lane for the first 600 blocks, Kaspa's sampled window restricted to the
|
||||||
|
epoch after that); the short lane S is the newest 120 chain blocks; S rules while S and R disagree by
|
||||||
|
more than 25%, else R rules; the output moves at most 3% harder or 10% easier per block.
|
||||||
|
|
||||||
|
A hash-rate step inside an epoch leaves R polluted by the pre-step blocks for the rest of the hour. PC 2
|
||||||
|
joined 7 minutes into epoch 1 (the boundary was 10:05:09). From then on R was the average of 7 minutes at
|
||||||
|
152 MH/s and m minutes at 280: 224 MH/s at m = 7, 252 at m = 36. S read the true 280 with its own noise
|
||||||
|
(about 10% for 120 linearly weighted blocks, more on a DAG where a chain step carries one to three
|
||||||
|
blocks' work). While S/R was above 1.25 (the first 7 minutes after the join) S ruled and the target was
|
||||||
|
right. Once R had climbed to within 25% of S, R ruled and the target eased to R's level, 11 to 20% too
|
||||||
|
easy. Every upward noise excursion of S past 1.25 R re-engaged S, the target hardened 3% a block toward
|
||||||
|
S's momentary value (which at that moment was 25 to 45% above R), then S fell back under 1.25 R, R ruled
|
||||||
|
again and the target eased 10% a block back to the floor. A relaxation oscillation with period set by
|
||||||
|
how often S's noise crosses the trigger and amplitude set by the trigger band and S's noise: 1.3x to
|
||||||
|
1.5x peaks every two to three minutes, exactly the record.
|
||||||
|
|
||||||
|
The two other suspects in the brief are real but secondary. The DAG's bursts (38% of chain blocks merge
|
||||||
|
two or more blues; a chain step's work is one to three blocks') widen S's noise, which sets how often
|
||||||
|
the trigger is crossed. The per-block clamps stack inside a burst of chain blocks (three 10% eases in
|
||||||
|
two seconds), which steepens each flip. Neither starts the oscillation: the chain-only simulator with a
|
||||||
|
1.85x step 10 minutes into an epoch oscillates the same way (section 4). The epoch boundary ends it: the
|
||||||
|
new epoch's R starts clean, which is what the live chain did at 11:02 (section 1, last two rows; the
|
||||||
|
hash rate also stepped down there, so the live boundary is consistent with the cause, not a clean test
|
||||||
|
of it).
|
||||||
|
|
||||||
|
The 3 October simulator could not see this because its step profiles put the step at an epoch boundary
|
||||||
|
(up50 and down50 step at 3 h = DAA 10,800) or ran steps so large (10x hops) that S/R stayed outside the
|
||||||
|
band until R had washed out.
|
||||||
|
|
||||||
|
## 3. The DAG model and the replay
|
||||||
|
|
||||||
|
`sim/difficulty/sim.py --live` (new, section "DAG model"). Miners on nodes: PC 1 on the PC node, PC 2
|
||||||
|
and the Mac on the Mac node, the two nodes 95 ms apart. A miner fetches a template from its node every
|
||||||
|
150 ms (the Mac: 630 ms, one job), the template reaches the card 260 ms later (the Mac: 675 ms, the
|
||||||
|
2-deep job queue; `igneum-miner` lines 947 to 975 and 1018), the miner refetches 30 ms after its own
|
||||||
|
block; the block carries the parents and the node's stamp of its template, as `igneum-miner` does (it
|
||||||
|
never touches the stamp). GHOSTDAG with every merged block blue: selected parent by blue work, blue work
|
||||||
|
of a chain step = the work of the selected parent's mergeset blues (checked on the record: 215 of 215
|
||||||
|
single-merge steps), DAA score advances by the mergeset size. The rule runs as
|
||||||
|
`SampledDifficultyManager::igneum_difficulty_bits`: the chain walk from the virtual's selected parent
|
||||||
|
with blue-work increments over sanitised-clock steps, and the sampled window (every 4th block of each
|
||||||
|
mergeset, selected parent first then descending blue work, 661 samples) restricted to the epoch. The
|
||||||
|
hash-rate schedule is the STATUS series of the four workers plus the Mac's constant. One scale factor
|
||||||
|
(`--dag-delay 0.75`) was fitted to the merge fraction; nothing else was tuned to the record.
|
||||||
|
|
||||||
|
Three seeds against the record, the join window 10:20 to 10:31 UTC (three short windows after the join,
|
||||||
|
both PCs on, the whole window polluted):
|
||||||
|
|
||||||
|
| Source | Blocks/s | Chain blocks merging 2+ % | Difficulty mean M | Min M | Max M | Std log D | Peaks over 15% | Mean peak/trough | Blocks/min min | Blocks/min max | Lane flips | Short lane % |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| record | 1.08 | 36.3 | 128.2 | 101.8 | 164.3 | 0.134 | 4 | 1.37 | 59 | 72 | | |
|
||||||
|
| simulator, rule v1 | 1.10 | 37.1 | 128.8 | 110.7 | 167.2 | 0.115 | 4.3 | 1.31 | 56.7 | 73.7 | 22.3 | 38.1 |
|
||||||
|
|
||||||
|
The whole polluted window 10:17 to 10:32: record std 0.123, 5 peaks of 1.33x, 101.8M to 164.3M, 54 to 81
|
||||||
|
blocks a minute; simulator 0.118, 5.3 peaks of 1.33x, 104.1M to 169.2M, 53.7 to 77.0. The rejoin window
|
||||||
|
10:42 to 10:54: record 0.067, 3 peaks of 1.31x; simulator 0.045, 1.7 peaks of 1.25x. The solo window
|
||||||
|
09:25 to 10:04: record 0.053 with 1 peak; simulator 0.054 with 4.7 peaks (the simulator flips more in the
|
||||||
|
first 20 minutes, where R still carried the Mac-only minutes before PC 1; the record flipped there too,
|
||||||
|
09:14 to 09:23, 52M to 78M). The simulator reproduces the amplitude, the period and the mean level.
|
||||||
|
Raw outputs: `sim/difficulty/results.md`, section "Live replay".
|
||||||
|
|
||||||
|
## 4. Candidates
|
||||||
|
|
||||||
|
Measured on the live replay (3 seeds, mean), the join window 10:20 to 10:31 and the rejoin window 10:42
|
||||||
|
to 10:54. The standard from the brief: damped within three short windows (the join window starts three
|
||||||
|
short windows after the step). True difficulty for the hash rate: 139M.
|
||||||
|
|
||||||
|
| Rule | Join: std log D | Join: peaks | Join: lane flips | Join: mean M | Rejoin: std log D | Rejoin: peaks | Rejoin: mean M | Solo: std log D |
|
||||||
|
|---|---|---|---|---|---|---|---|---|
|
||||||
|
| v1 (spec 2.3 of 3 October) | 0.115 | 4.3 | 22.3 | 128.8 | 0.045 | 1.7 | 125.0 | 0.054 |
|
||||||
|
| (a) short lane 240 | 0.125 | 1.3 | 10.3 | 132.8 | 0.043 | 0.3 | 125.2 | 0.060 |
|
||||||
|
| (a) short lane 360 | 0.107 | 1.0 | 11.3 | 132.9 | 0.041 | 0.0 | 125.6 | 0.068 |
|
||||||
|
| (b) ease clamp 3% | 0.113 | 3.0 | 20.3 | 127.1 | 0.055 | 1.3 | 125.1 | 0.062 |
|
||||||
|
| (c) clamp once per DAA second | 0.132 | 4.3 | 20.7 | 129.3 | 0.054 | 1.0 | 125.7 | 0.067 |
|
||||||
|
| (d) hysteresis, leave at 10% | 0.090 | 2.0 | 1.7 | 142.2 | 0.054 | 0.7 | 130.4 | 0.068 |
|
||||||
|
| (e) median of three on S | 0.124 | 4.7 | 15.0 | 129.0 | 0.056 | 2.3 | 126.6 | 0.056 |
|
||||||
|
| soft trigger (blend 10% to 25%) | 0.110 | 3.0 | 13.0 | 137.6 | 0.055 | 1.0 | 128.5 | 0.070 |
|
||||||
|
| reference window 1,200 | 0.108 | 3.7 | 14.3 | 133.4 | 0.048 | 1.0 | 130.8 | 0.038 |
|
||||||
|
| reference window 900 | 0.081 | 0.7 | 8.3 | 134.2 | 0.063 | 0.0 | 129.5 | 0.043 |
|
||||||
|
| reference window 720 | 0.055 | 0.0 | 4.3 | 136.4 | 0.052 | 0.0 | 132.3 | 0.053 |
|
||||||
|
| reference window 600 | 0.024 | 0.0 | 0.0 | 140.9 | 0.028 | 0.0 | 137.8 | 0.044 |
|
||||||
|
| reference window 600, epoch lane only (v2) | 0.026 | 0.0 | 0.0 | 142.6 | 0.031 | 0.0 | 136.1 | 0.050 |
|
||||||
|
| reference window 480, epoch lane only | 0.021 | 0.0 | 0.0 | 141.3 | 0.019 | 0.0 | 135.0 | 0.052 |
|
||||||
|
| reference window 600 + hysteresis | 0.035 | 0.3 | 1.0 | 141.9 | 0.044 | 0.3 | 135.8 | 0.046 |
|
||||||
|
|
||||||
|
The brief's five candidates each leave the join window between 0.09 and 0.13: they shape the
|
||||||
|
oscillation (fewer, larger swings with a longer short lane; S ruling almost always with hysteresis,
|
||||||
|
0.09 from S's own DAG noise) without removing its cause, which is R. Capping the reference window at the
|
||||||
|
newest 600 DAA score of the epoch removes it: R carries a step for 10 minutes instead of an hour, so by the
|
||||||
|
join window S and R agree, R rules, and the target sits on the true level (140.9M against 139M) with the
|
||||||
|
noise of a 600-block work-over-time estimate (std 0.024, no flips). The cap at 600 makes Kaspa's sampled
|
||||||
|
long lane moot (600 DAA holds at most 150 samples, the long lane's minimum), so v2 uses the epoch lane
|
||||||
|
alone over that window: one estimator, one clock (the sanitised clock), no flicker between the two
|
||||||
|
estimators at the boundary. 480 is marginally better on the live case and 720 clearly worse; 600 (10
|
||||||
|
minutes at target, the long lane's old minimum) is kept.
|
||||||
|
|
||||||
|
Chain-only check (`sim.py`, a 1.85x step 10 minutes into epoch 1, seeds 7 to 9, 8 to 25 minutes after
|
||||||
|
the step): v1 std of log difficulty 0.179 / 0.136 / 0.189 with 102 / 142 / 96 lane flips; v2 0.052 /
|
||||||
|
0.022 / 0.081 with the mean rate ratio 1.013 / 0.998 / 0.974.
|
||||||
|
|
||||||
|
## 5. Rule v2
|
||||||
|
|
||||||
|
One change to spec 2.3 rule 2: the reference lane R is the epoch lane over the newest min(k, 600)
|
||||||
|
chain blocks of the block's epoch (DAA score at least max(epoch start, DAA - 600)), blended with the
|
||||||
|
parent's implied rate as k_ref : 16 where k_ref is the DAA span of that window; Kaspa's sampled window is
|
||||||
|
not consulted. The hold (8 blocks of the epoch), the short lane (newest 120 of the same walk), the
|
||||||
|
trigger (25%), the clamps (3% harden, 10% ease), the sanitised clock and the floor are unchanged.
|
||||||
|
Constant `REF_WINDOW_V2 = 600` (`kaspa_consensus_core::igneum::difficulty`).
|
||||||
|
|
||||||
|
Activation: `difficulty_v2_activation_daa`, a consensus parameter (`Params`, `OverrideParams`, the
|
||||||
|
`--override-params-file` parser, following `pow_epoch_blocks`). Every network's default is `u64::MAX`
|
||||||
|
(never); the override file sets it. A node upgraded ahead of the height rules v1 for every block whose
|
||||||
|
DAA score is below it and v2 from the block whose DAA score reaches it, so the devnet keeps its genesis
|
||||||
|
and its chain. Implementation: `reference_window(daa_score, epoch_blocks, activation)` returns the epoch
|
||||||
|
start, the reference start and the v2 flag; `igneum_difficulty_bits` bounds the chain walk at the
|
||||||
|
reference start, skips the long lane in v2 and passes `k_ref` to the pure `igneum_target`, which blends
|
||||||
|
the epoch lane on it. Cost: the walk is 600 chain blocks per header in v2 (2 compact-header, 2 blue-work
|
||||||
|
and 2 clock reads each, all cached stores), the same as the first 600 blocks of every epoch today; the
|
||||||
|
3 October note to re-measure before the 4 BPS step stands.
|
||||||
|
|
||||||
|
Unit tests (`cargo test --release -p kaspa-consensus --lib difficulty`): 15 pass, the 12 of 3 and 4 October
|
||||||
|
unchanged plus `reference_window_switches_at_the_activation_height` (never, one block before, at, inside a
|
||||||
|
fresh epoch, activation 0), `v2_reference_window_follows_a_step_inside_the_epoch_where_v1_eases_into_it`
|
||||||
|
(1,200 blocks at rate 1 then a step to 2 and a dip of the short lane to 1.4 with the parent at 1.4: v1's
|
||||||
|
polluted reference reads 1.147, within 25% of 1.4, rules, and the target EASES by the 10% clamp; v2's
|
||||||
|
reference over the newest 600 reads 1.55, rules, and the target HARDENS by the 3% clamp) and
|
||||||
|
`v1_and_v2_agree_in_a_steady_epoch`.
|
||||||
|
`cargo test --release -p kaspa-consensus-core --lib params`: 7 pass (`override_params_carry_the_difficulty_v2_activation`:
|
||||||
|
every network's default is never, the file sets it, `u64::MAX` round-trips through JSON; the fast-time
|
||||||
|
file test now checks the field too).
|
||||||
|
|
||||||
|
## 6. What v2 costs elsewhere
|
||||||
|
|
||||||
|
Synthetic set (`sim.py`, seed 7, honest stamps; the 3 October standard for the 50x step-up is under 90 s):
|
||||||
|
|
||||||
|
| Case | v1 | v2 |
|
||||||
|
|---|---|---|
|
||||||
|
| Hash rate x50, settled s | 61.7 | 65.5 |
|
||||||
|
| Hash rate x50, overshoot | 0.140 | 0.222 |
|
||||||
|
| Hash rate /50, settled s | 628.5 | 752.7 |
|
||||||
|
| Hash rate /50, worst gap s | 32.3 | 61.8 |
|
||||||
|
| Epoch step +-30%, first within 10% s (mean of 6) | 86.5 | 113.5 |
|
||||||
|
| Epoch step +-30%, settled s (mean of 6) | 143.7 | 143.4 |
|
||||||
|
| 3x pool hopping every 15 min, settled s | 189.5 | 181.9 |
|
||||||
|
| 10x pool hopping every 15 min, settled s | 211.3 | 199.6 |
|
||||||
|
| Polluted window (devnet case), settled s | 62.7 | 66.6 |
|
||||||
|
| Polluted window, overshoot | 0.180 | 0.089 |
|
||||||
|
| Genesis 10x too hard, settled s | 321.9 | 321.9 |
|
||||||
|
| Genesis 10x too easy, settled s | 58.7 | 58.7 |
|
||||||
|
| Steady std of the expected block rate, constant hash rate | 0.038 | 0.049 |
|
||||||
|
| Steady blocks/min CV (Poisson alone 0.129) | 0.135 | 0.130 |
|
||||||
|
| Steady std, 10%/h random walk | 0.062 | 0.060 |
|
||||||
|
|
||||||
|
The cost is the reference lane's noise: a 600-block work-over-time estimate carries about 4% of Poisson
|
||||||
|
noise where Kaspa's 2,644-block window carried 2%, so the steady std of the expected rate rises from
|
||||||
|
0.038 to 0.049; the realised blocks per minute do not change (CV 0.130 against 0.135, Poisson alone
|
||||||
|
0.129). The 50x step-down is slower on this seed (753 s against 629 s, worst gap 62 s against 32 s): with
|
||||||
|
blocks 50 s apart the reference window holds 12 blocks instead of the epoch's, and the epoch lane's
|
||||||
|
prior blend holds it back; the step-up stays under the 90 s standard. Hops are slightly faster and the
|
||||||
|
polluted window's overshoot halves, both because the reference forgets sooner. With +-500 ms stamp
|
||||||
|
jitter the v1 numbers of 3 October stand (`results.md`); v2 was not re-run with jitter.
|
||||||
|
|
||||||
|
Attack suite (`sim/difficulty/attacks/attacks.py`, seeds 7 to 9, the forger under the 10 s rules; v1 rows are
|
||||||
|
the 4 October rule's rows of `attacks/results.md`, "igneum-san" there, v2 rows `results.md` "Rule v2"):
|
||||||
|
|
||||||
|
| Scenario | Measure | v1 | v2 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 1. Pool hopping, 24 h, hopper at 10 / 30 / 50 / 100% of the base, greedy | hopper's blocks per hash over the base, minus 1 | +1.5% / +1.0% / +0.9% / +0.7% | +2.5% / +1.6% / +1.2% / +1.0% |
|
||||||
|
| 1. the same with a 60 s dwell | | +1.3% / +0.1% / -1.7% / -4.0% | +2.3% / +0.8% / -0.3% / -1.5% |
|
||||||
|
| 2. Pulsed rental, 50x for 10 min every hour | pulser's blocks per hash over the base, minus 1; weight per hash | -96.4%; 0.262 | -96.3%; 0.262 |
|
||||||
|
| 2. the same, once | | -97.1%; 0.130; worst gap 78 s | -97.2%; 0.130; worst gap 98 s |
|
||||||
|
| 3. Timestamp stretching, 30 / 50% forger, latest / earliest / alternating | block-rate drift after 1 h | +0.8 / +0.8 / +0.4% and +0.9 / +0.7 / +1.1% (worst seed +2.7%) | +0.2 / -0.2 / +0.1% and +0.4 / -0.8 / +0.5% (worst seed -1.5%) |
|
||||||
|
| 4. Short-lane oscillation, 25% miner on and off every 120 blocks | std of rate after / before | 3.75 (worst 4.82) | 3.29 (worst 3.71) |
|
||||||
|
| 5. Epoch games: hold dodger / 10x hold flooder / 30% hold flooder | gamer's blocks per hash over the base, minus 1 | 0.0% / +0.7% / +0.3% | 0.0% / +0.4% / 0.0% |
|
||||||
|
| 6. Polluted window, 10x miner joins at 0 / 480 / 480 / 0 and leaves at 600 / 600 / 720 / 1,200 | settled after the leave, s | 297 / 287 / 312 / 329 | 297 / 288 / 312 / 331 |
|
||||||
|
| 7. Flood at 85 blocks a second | floor reached, no overflow | block 2,635 (unit test) | unchanged (the floor is outside the lanes) |
|
||||||
|
| Base profiles, 3-seed means: up50 / down50 / epoch30 / hop10 / polluted / warmup-hard | settled s | 154 / 762 / 88 / 245 / 75 / 327 | 150 / 822 / 88 / 233 / 76 / 327 |
|
||||||
|
| Base profiles | steady std | 0.042 | 0.053 |
|
||||||
|
|
||||||
|
What v2 loses: the greedy hopper gains one more point (at most +2.5% against +1.5%), because a reference
|
||||||
|
that forgets in 10 minutes follows the hopper's own effect on the difficulty sooner; the 50x step-down is
|
||||||
|
8% slower; the steady estimate is noisier by a quarter. What it gains: the live oscillation (sections 3
|
||||||
|
and 4), a smaller forger drift (within 1% on every cell, worst seed 1.5% against 2.7%: both lanes now
|
||||||
|
run on the sanitised clock, so a forged step is paid back in both), a smaller oscillation gain in
|
||||||
|
scenario 4 (3.3 against 3.8), and the pulsed renter's recovery gap 10% shorter. The pulse, the epoch games
|
||||||
|
and the polluted window are unchanged to the first decimal.
|
||||||
|
|
||||||
|
## 7. Test network
|
||||||
|
|
||||||
|
`sim/difficulty/testnet_v2.py`, 3 `igneumd` nodes from `devnet-v4` with the change (ports 29600 to 29622,
|
||||||
|
appdir `/tmp/igneum-diffv2/run1`, `igneum-devnet-960`), `infra/fast-time/override-60x.json` plus genesis
|
||||||
|
bits `0x1f010000` (2^16 hashes per block), the devnet's program epoch (3,600 blocks, lead 600: the 60x
|
||||||
|
file's one-minute epoch would empty the reference window every minute and hide the pollution) and
|
||||||
|
`difficulty_v2_activation_daa` 900 on nodes 1 and 2; node 3 started without it (rule v1 for ever) as a
|
||||||
|
follower. CPU miners `igneum-miner mine --engine igneum-pow`, 4 threads each: A on node 1 for the run, B
|
||||||
|
on node 2 from minute 4 (a 2x step inside epoch 0 under v1), off at minute 19 (a step down under v2), back
|
||||||
|
at minute 23 (a step up under v2). Record: `records/testnet-v2-2026-10-04.csv` (1,471 blocks, 1,249 chain
|
||||||
|
blocks, 18.7% with two or more parents), schedule beside it.
|
||||||
|
|
||||||
|
The switch: node 1's virtual DAA score reached 900 at 1,022 s (12:47:52 BST). Node 3 rejected the first
|
||||||
|
v2 block, "difficulty of 520437997 is not the expected value of 520406991", struck and banned its peer
|
||||||
|
and stayed at DAA 900 for the rest of the run (901 headers exported, a prefix of node 1's); nodes 1 and 2
|
||||||
|
exported the same 1,472 headers and the same sink through the end. The node logs print "Difficulty rule
|
||||||
|
v2 from the override file: active from DAA score 900" at start.
|
||||||
|
|
||||||
|
The rule: the Mac carried four other agents' builds during the run (load average 184 at minute 10, 418 at
|
||||||
|
minute 46), the miners ran at a fraction of a core each, and the python schedule itself was starved for
|
||||||
|
80 minutes after minute 26 (the chain ends at 1,560 s). The delivered hash rate swung by 2x on its own:
|
||||||
|
the difficulty fell 40% after miner B joined (7,868 at 240 s to 4,308 at 480 s) and rose back to 7,400 by
|
||||||
|
660 s, so the v1 phase cannot be read as oscillation evidence either way. Under v2: the leave at 1,140 s
|
||||||
|
eased the difficulty from 6,589 to 5,972 over 180 s with the std of log difficulty 0.036 and no peak over
|
||||||
|
15%; the rejoin at 1,380 s hardened 6,154 to 8,312 within 60 s and then held 8,333 to 8,826 (within 3%)
|
||||||
|
until the chain stopped. Per phase (30-s bins in `schedule.log`, `testnet_v2.py --analyse`):
|
||||||
|
|
||||||
|
| Phase | Chain blocks | Std log D | Peaks over 15% | Min | Max |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| A alone, warm-up from a 2x too-hard genesis (60 to 240 s) | 153 | 0.207 | 1 | 7,953 | 14,650 |
|
||||||
|
| B joins under v1 (240 to 480 s) | 146 | 0.155 | 0 | 4,603 | 7,968 |
|
||||||
|
| both under v1 (480 to 1,020 s) | 402 | 0.208 | 1 | 3,910 | 7,451 |
|
||||||
|
| the switch (1,020 to 1,140 s) | 121 | 0.069 | 1 | 5,674 | 8,028 |
|
||||||
|
| B leaves under v2 (1,140 to 1,380 s) | 202 | 0.036 | 0 | 5,929 | 6,639 |
|
||||||
|
| B rejoins under v2 (1,380 to 1,680 s) | 168 | 0.149 | 1 | 6,066 | 9,157 |
|
||||||
|
|
||||||
|
What the test network establishes: the switch takes effect at the height and nowhere else, a node
|
||||||
|
without the parameter forks off there, two nodes with it stay on one sink, and v2 follows a step down and
|
||||||
|
a step up on a real DAG with no rejected block between the v2 nodes. The damping comparison between v1
|
||||||
|
and v2 rests on the live record and the two simulators (sections 3 and 4); the run should be repeated on
|
||||||
|
a quiet machine, which takes 30 minutes.
|
||||||
|
|
||||||
|
## 8. Rollout
|
||||||
|
|
||||||
|
Binaries: `devnet-v4` of `vendor/igneum-node` at the commit of this entry, built as today's devnet
|
||||||
|
binaries are (Mac: `cargo build --release -p kaspad -p igneum-miner --features kaspad/igneum-pow`; Linux:
|
||||||
|
`infra/cross/build-linux.sh`; Windows: the launcher package's `igneumd.exe`). Only `igneumd` changes; the
|
||||||
|
miners follow templates and need nothing. A node without the parameter in its override file keeps rule
|
||||||
|
v1 and forks off at the height (section 7), so every node of a chain must carry the same value before
|
||||||
|
the height arrives.
|
||||||
|
|
||||||
|
1. The 12 Hetzner nodes (`infra/cloud-devnet`, their own chain) first: put `"difficulty_v2_activation_daa"`
|
||||||
|
in their override file at their current DAA score plus 1,800 (30 minutes), restart them one by one,
|
||||||
|
then have one miner join and leave 10 minutes into an epoch and read the difficulty events: no flips
|
||||||
|
after the height.
|
||||||
|
2. The devnet: choose the activation DAA score about two hours ahead of the first restart (7,200 blocks,
|
||||||
|
so every node can be restarted in turn with the chain running). Order: the observer node
|
||||||
|
(26640/28640, a follower, lowest risk), the seed (`/opt/igneum/v4/bin`, `infra/seed-nodes/stage-v4.sh`),
|
||||||
|
Mac node 1 (26610/26611), PC 1's node (its launcher's `igneumd.exe`; PC 2 mines through the Mac node
|
||||||
|
and needs nothing). Each node gets the same `"difficulty_v2_activation_daa": N` in its override file.
|
||||||
|
the project lead restarts the live processes; this entry does not.
|
||||||
|
3. Watch the observer's difficulty events across the height and the next epoch boundary; with a miner
|
||||||
|
joining inside an epoch the floor and the bursts of section 1 must not return.
|
||||||
|
|
||||||
|
A new network sets the parameter to 0 (v2 from genesis).
|
||||||
|
|
||||||
|
## 9. Not done
|
||||||
|
|
||||||
|
- The DAG model has one fitted scale (the miners' template staleness); its merge fraction is 35 to 37%
|
||||||
|
against the record's 34 to 39%, the Mac's stale stamps are modelled as its job queue. Red blocks are
|
||||||
|
not modelled (none seen on the record: every merged block was blue).
|
||||||
|
- The Mac Metal worker's hash rate is the bench-log constant, not a log series.
|
||||||
|
- The live boundary at 11:02 coincided with a hash-rate step (both PCs restarted), so the clean
|
||||||
|
prediction "the oscillation stops at the epoch boundary with the hash rate unchanged" is checked in the
|
||||||
|
simulator only.
|
||||||
|
- The 600-block reference window is noisier than Kaspa's 2,644-block sampled window in steady state
|
||||||
|
(section 6); a longer window with the pollution washed out by a different mechanism (a window that
|
||||||
|
restarts at the last clamped ramp) was not tried.
|
||||||
|
|
@ -783,3 +783,16 @@ blocks in the first minute, CPU re-check OK on every share, the integrated AMD c
|
||||||
from the run, both fixed in the app the same hour: no clock-skew warning (now detected from the node's warning, block
|
from the run, both fixed in the app the same hour: no clock-skew warning (now detected from the node's warning, block
|
||||||
timestamps and an HTTPS Date header; Start is blocked above 10 s), and the node card stayed on "syncing" after the late
|
timestamps and an HTTPS Date header; Start is blocked above 10 s), and the node card stayed on "syncing" after the late
|
||||||
catch-up while the miner was already accepted (state now re-derived every poll).
|
catch-up while the miner was already accepted (state now re-derived every poll).
|
||||||
|
|
||||||
|
## 4 October 2026, difficulty rule v2: the live oscillation, its cause, the DAG replay, the fix behind a height switch (consensus-engineer)
|
||||||
|
|
||||||
|
Machine: Apple M5 Max shared with four other agents' builds (load average 7 at the start, 184 to 442 from 12:40 BST on); every simulation and build at nice 19, cargo at 4 jobs; the live devnet (26610/26611, 26640/28640, observer.mjs, the Metal miner) untouched, read through the observer node's wRPC only. Worktree `vendor/igneum-node-v4`, branch `devnet-v4`, built in its own `target/`. Everything in `docs/analysis/difficulty-2026-10-04-oscillation.md`; ledger M24; spec 2.3 revised.
|
||||||
|
Live finding (devnet v4, UTC): PC 1 (RTX 5090, 122 MH/s, 8 identities through its own node) with the Mac (26.7 MH/s) and a Radeon (2.8) from 09:11; PC 2 (RTX 5090, 124 MH/s, 8 identities through the Mac node) from 10:12:17, off 10:31:25 to 10:35:19; both PCs restarted at 11:00 for the machine-id package (they are clones with one computer name and had signed with the same vote keys). Difficulty (node convention): flat 56.7M to 67M within 1% per minute from 09:24 to 10:04; 70M to 144M in 90 s after the join; then 101.8M to 164.3M from 10:17 to 10:32 (5 peaks of 1.33x spaced 132 chain blocks, std of log difficulty 0.123, 54 to 81 blocks a minute) and 103M to 150M from 10:37 to 10:54 (4 peaks of 1.35x, std 0.072, a floor rising 110M to 127M) against a true 139M; after the epoch boundary at DAA 7,200 (11:01:52) 69.0M to 72.7M within 1.3% per minute. Stacked clamps in the observer's 2-s polls: "up 15.9%" = five 3% hardens, "down 24.3%" = three 10% eases. DAG: 6,741 blocks to 10:54, 38% of chain blocks merging two or more blues, every merged block blue. Records `sim/difficulty/records/live-2026-10-04.csv` (8,090 headers, `pull_live.py`) and `live-2026-10-04-hashrate.csv` (587 worker STATUS lines from the log intake, by run id and node).
|
||||||
|
Cause: spec 2.3's reference lane is the whole epoch, so a step 7 minutes into the hour left it polluted for the hour; the short lane read 11 to 25% above it; the 25% trigger flipped on the short lane's noise; the clamps turned each flip into a ramp. The DAG's bursts widen the short lane's noise and the stacked clamps steepen each flip; neither starts it. The 3 October simulator stepped at epoch boundaries, so it never saw it.
|
||||||
|
Replay: `sim.py --live`, a DAG model (miners on two nodes with `igneum-miner`'s template staleness, templates stamped by the node, GHOSTDAG, the rule as `igneum_difficulty_bits` runs it, the sampled window per mergeset), one scale fitted to the merge fraction. Join window 10:20 to 10:31, 3 seeds: std of log difficulty 0.115 against the record's 0.134, 4.3 peaks of 1.31x against 4 of 1.37x, 110.7M to 167.2M against 101.8M to 164.3M, 56.7 to 73.7 blocks a minute against 59 to 72, 22 lane flips, the short lane ruling 38% of the time. Whole polluted window: 0.118 against 0.123, 5.3 peaks against 5. The chain-only simulator with a 1.85x step 10 minutes into an epoch: std 0.136 to 0.189 with 96 to 142 flips (v1).
|
||||||
|
Candidates on the live replay (join window, 3 seeds, std of log difficulty / lane flips): v1 0.115 / 22; short lane 240 0.125 / 10; 360 0.107 / 11; ease clamp 3% 0.113 / 20; clamp once per DAA second 0.132 / 21; hysteresis leave at 10% 0.090 / 2 (short lane ruling 78%); median of three 0.124 / 15; soft trigger 0.110 / 13; reference window 1,200 0.108, 900 0.081, 720 0.055, 600 0.024 / 0, 480 0.021 / 0. Adopted: v2 = the reference lane is the epoch lane over the newest 600 DAA score of the epoch, the sampled long lane not consulted: 0.026 / 0, mean 142.6M against 139M true; rejoin window 0.031 / 0; chain-only 0.022 to 0.081.
|
||||||
|
Cost (synthetic set seed 7, v1 / v2): x50 settled 61.7 / 65.5 s (standard under 90), /50 628 / 753 s (worst gap 32 / 62 s), epoch +-30% settled 144 / 143 s, hop10 211 / 200 s, polluted overshoot 0.180 / 0.089, warm-ups equal, steady std 0.038 / 0.049 with blocks-per-minute CV 0.135 / 0.130. Attacks (seeds 7 to 9, v1 / v2): greedy hopper at most +1.5% / +2.5%, with a 60 s dwell -4.0% / -1.5% at 100%; pulsed rental -96.4% / -96.3% with weight per hash 0.262 / 0.262; forger drift +0.4 to +1.1% / -0.8 to +0.5% (worst seed 2.7% / 1.5%); short-lane oscillation gain 3.75 / 3.29; epoch games 0.0 to +0.7% / 0.0 to +0.4%; polluted window settled 287 to 329 s / 288 to 331 s; base profiles 3-seed up50 154 / 150 s, down50 762 / 822 s, epoch30 88 / 88 s, hop10 245 / 233 s, polluted 75 / 76 s, steady std 0.042 / 0.053.
|
||||||
|
Implementation (devnet-v4): `difficulty_v2_activation_daa` in `Params` (every network `u64::MAX`), `OverrideParams`, `override_params`, the daemon's file parser (prints the height), `SampledDifficultyManager` (new field, `reference_window(daa_score, epoch_blocks, activation)`), `REF_WINDOW_V2 = 600`, `IgneumInputs.k_ref`; `infra/fast-time/override-60x.json` carries the field as never. `cargo test --release -p kaspa-consensus --lib difficulty`: 15 pass (12 of 3 and 4 October plus `reference_window_switches_at_the_activation_height`, `v2_reference_window_follows_a_step_inside_the_epoch_where_v1_eases_into_it`, `v1_and_v2_agree_in_a_steady_epoch`); `-p kaspa-consensus-core --lib params`: 7 pass (`override_params_carry_the_difficulty_v2_activation`, the fast-time file test extended). Build 2 min incremental for `igneumd` and `igneum-miner`.
|
||||||
|
Test network (`sim/difficulty/testnet_v2.py`, 3 nodes on 29600 to 29622, the 60x file with the devnet epoch, genesis bits 2^16, activation 900 on nodes 1 and 2, node 3 without it; CPU miners A from 0, B from minute 4, off at 19, back at 23): node 1 reached DAA 900 at 1,022 s; node 3 rejected the first v2 block ("difficulty of 520437997 is not the expected value of 520406991"), banned its peer and stayed at DAA 900 (901 headers, a prefix of node 1's 1,472); nodes 1 and 2 agreed on every header and the sink. Under v2 the leave eased 6,589 to 5,972 over 180 s (std 0.036, no peak), the rejoin hardened 6,154 to 8,312 within 60 s and held within 3%. The v1 phase is not readable: the load swung the CPU miners' delivered hash rate 2x on its own (difficulty fell 40% after B joined). Record `records/testnet-v2-2026-10-04.csv`. Repeat on a quiet machine, 30 minutes.
|
||||||
|
Rollout: only `igneumd` changes (the Mac build, `infra/cross/build-linux.sh` for the seed and the Hetzner nodes, the Windows package for PC 1's node); every node of a chain needs the same `"difficulty_v2_activation_daa": N` in its override file before the height or it forks off there. First the 12 Hetzner nodes on their own chain (N = current DAA + 1,800, restart one by one, a miner joins inside an epoch, no flips after the height), then the devnet with N about two hours ahead: observer node, seed, Mac node 1, PC 1's node, in that order, by the project lead. A new network sets 0.
|
||||||
|
Not done: a quiet-machine test-network run; the DAG model's red blocks and the Mac's log series; v2 with +-500 ms stamp jitter.
|
||||||
|
|
|
||||||
|
|
@ -1493,10 +1493,22 @@ the project lead's decision of 4 October 2026: the total-weight floor of Q3 is 2
|
||||||
- **F9** (half the hashrate leaves and finality stalls for ten days). Status: Conceded, stated (4 October 2026). Under the 2/3 floor the critic's number is back: 50% churn pauses finality for 10 days and 35% churn for 1.4 days, until the departed weight ages out of the window (`sim/results_v2.md` D's total column, which the 2/3 floor equals arithmetically, and L2). The chain runs on proof of work meanwhile, the node reports the pause, and the litepaper says so. This is the price of the one-third safety bound and was taken knowingly. Was: Answered by design (the active denominator recovered in two hours).
|
- **F9** (half the hashrate leaves and finality stalls for ten days). Status: Conceded, stated (4 October 2026). Under the 2/3 floor the critic's number is back: 50% churn pauses finality for 10 days and 35% churn for 1.4 days, until the departed weight ages out of the window (`sim/results_v2.md` D's total column, which the 2/3 floor equals arithmetically, and L2). The chain runs on proof of work meanwhile, the node reports the pause, and the litepaper says so. This is the price of the one-third safety bound and was taken knowingly. Was: Answered by design (the active denominator recovered in two hours).
|
||||||
- **F21** (new, from attack scenario 6A). "Your floor is a fraction of a table each side computes for itself. Cut the network in half and leave it cut: after a while each half's window is full of its own blocks, each half holds two thirds of its own table, and both lock without any attacker at all. Your simulation never saw it because it kept the weights global." Status: Conceded, stated (4 October 2026): spec 3.3.1, 3.7 item 9, 3.9 guidance; `sim/results_v2.md` L4 (view-local weights). Correct. A side with pre-split share s holds s + (1 - s) t / 30 of its own table on day t and two thirds of it from day 30 (2/3 - s) / (1 - s): day 10 at 50/50 (day 4 under the old floor), day 5 for the 60 side of 60/40 (at once under the old floor). On the devnet the old floor fell at 84 s of a young 1,439-DAA window (`docs/bench-log.md`, "finality v2 attack harness", S6A); at 2/3 the same cut on a full 1,800-DAA window held for the whole 150-s split and fell at 205 s against a predicted W / (3R) = 200 s (`docs/bench-log.md`, "finality floor 2/3", 6A and 6A long heal). What the devnet adds to the simulation: after the heal the other side's blocks are merged red, so each side's own share jumps rather than drifts, both sides of a 50/50 split certify their own checkpoints within 10 s of each other, and F1 then pins each node to its own certified chain: 26 conflicting certificates and 23 disagreeing locked indices across three nodes, no equivocation, a finality fork that the network heal did not undo and that only an operator's trusted certificate (F5, not implemented) can resolve. No rule removes it, because a view cannot count blocks it has never seen; the floor at two thirds moved the day from 4 to 10, and the exchange guidance treats a node partitioned for more than a day as proof of work until it has rejoined. A rule option for gate 3, not adopted: evaluate the floor against the table of the last locked checkpoint while no newer lock exists, which trades F9's 10-day recovery for a manual override.
|
- **F21** (new, from attack scenario 6A). "Your floor is a fraction of a table each side computes for itself. Cut the network in half and leave it cut: after a while each half's window is full of its own blocks, each half holds two thirds of its own table, and both lock without any attacker at all. Your simulation never saw it because it kept the weights global." Status: Conceded, stated (4 October 2026): spec 3.3.1, 3.7 item 9, 3.9 guidance; `sim/results_v2.md` L4 (view-local weights). Correct. A side with pre-split share s holds s + (1 - s) t / 30 of its own table on day t and two thirds of it from day 30 (2/3 - s) / (1 - s): day 10 at 50/50 (day 4 under the old floor), day 5 for the 60 side of 60/40 (at once under the old floor). On the devnet the old floor fell at 84 s of a young 1,439-DAA window (`docs/bench-log.md`, "finality v2 attack harness", S6A); at 2/3 the same cut on a full 1,800-DAA window held for the whole 150-s split and fell at 205 s against a predicted W / (3R) = 200 s (`docs/bench-log.md`, "finality floor 2/3", 6A and 6A long heal). What the devnet adds to the simulation: after the heal the other side's blocks are merged red, so each side's own share jumps rather than drifts, both sides of a 50/50 split certify their own checkpoints within 10 s of each other, and F1 then pins each node to its own certified chain: 26 conflicting certificates and 23 disagreeing locked indices across three nodes, no equivocation, a finality fork that the network heal did not undo and that only an operator's trusted certificate (F5, not implemented) can resolve. No rule removes it, because a view cannot count blocks it has never seen; the floor at two thirds moved the day from 4 to 10, and the exchange guidance treats a node partitioned for more than a day as proof of work until it has rejoined. A rule option for gate 3, not adopted: evaluate the floor against the table of the last locked checkpoint while no newer lock exists, which trades F9's 10-day recovery for a manual override.
|
||||||
|
|
||||||
|
### M24. Your two-lane controller oscillates for an hour when a second miner joins mid-epoch
|
||||||
|
"Watched your devnet this morning. The second 5090 came in at 10:12 and the difficulty never settled: 102M to 164M for forty minutes, 54 to 81 blocks a minute, three or four clamp steps stacked inside a second. Your fast lane and your slow lane disagree by a hair under the trigger and the rule flips between them every two minutes. One card joining is the mildest event a chain can see."
|
||||||
|
|
||||||
|
Status: Fix built, pending rollout (4 October 2026). Was: Open (10:46 UTC, 4 October 2026, the live finding).
|
||||||
|
|
||||||
|
Answer: Correct, measured on the live chain and reproduced in the simulator (`docs/analysis/difficulty-2026-10-04-oscillation.md`). The cause is the reference lane: spec 2.3 of 3 October gave it the whole epoch, so a hash-rate step inside an epoch left it polluted by the pre-step blocks for the rest of the hour; the short lane read the true rate 11 to 25% above it, the 25% trigger flipped between the two on the short lane's noise, and the per-block clamps turned every flip into a ramp (3% a block up, 10% a block down). The DAG replay (`sim/difficulty/sim.py --live`, miners on two nodes with `igneum-miner`'s template staleness, GHOSTDAG, the rule as the node runs it) reproduces the record: std of log difficulty 0.115 against 0.134, 4.3 peaks of 1.31x against 4 of 1.37x, 104M to 169M against 102M to 164M, 54 to 77 blocks a minute against 54 to 81. The brief's five candidates (longer short lane, 3% ease clamp, one clamp per DAA second, hysteresis, median of three) each leave it between 0.09 and 0.13 because none of them cleans the reference lane. Rule v2 caps the reference lane at the newest 600 DAA score of the epoch (the epoch lane only; Kaspa's sampled window is not consulted): 0.026 with 0 lane flips and the target on the true level (142.6M against 139M) on all three seeds; the chain-only simulator agrees (0.14 to 0.19 against 0.02 to 0.08). Cost on the synthetic set (seed 7): steady std of the block rate 0.049 against 0.038 (blocks per minute CV unchanged, 0.130 against 0.135), the 50x step-up settles in 65.5 s against 61.7 s, the 50x step-down 753 s against 629 s, hops slightly faster, the polluted window's overshoot halved. Under attack (`attacks.py`, seeds 7 to 9): the greedy hopper gains one more point (at most +2.5% against +1.5%), the forger's drift falls to within 1% (worst seed 1.5% against 2.7%), the pulsed rental, the epoch games and the polluted window are unchanged, the 50x step-down is 8% slower and the steady estimate a quarter noisier. Built behind a height switch, `difficulty_v2_activation_daa` (a consensus parameter, default never, set by the override file), so the devnet moves to v2 at a chosen DAA score on the same chain. The epoch boundary itself clears the pollution, which the live chain showed at 11:02 UTC (DAA 7,200: within 1.3% per minute from 11:07 with no flips, the hash rate having also stepped down there).
|
||||||
|
|
||||||
|
Evidence: `sim/difficulty/records/live-2026-10-04.csv` and `live-2026-10-04-hashrate.csv`; `sim/difficulty/results.md` "Live replay"; `docs/bench-log.md`, 4 October 2026 "difficulty rule v2"; unit tests `difficulty::tests::reference_window_switches_at_the_activation_height`, `difficulty::tests::v2_reference_window_follows_a_step_inside_the_epoch_where_v1_eases_into_it`, `difficulty::tests::v1_and_v2_agree_in_a_steady_epoch`, `params::tests::override_params_carry_the_difficulty_v2_activation`. Rollout: the bench-log entry names the binaries and the order (Hetzner chain first, then the devnet nodes with the activation DAA in their override file).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 9. Developers and apps (4 October 2026)
|
## 9. Developers and apps (4 October 2026)
|
||||||
|
|
||||||
Added 4 October 2026 from `docs/design/developer-adoption.md` (section 6, ten reasons a founder says no). Only the conceded objections are entered; the answered ones are in that document with their evidence. Entries are numbered D for developers.
|
Added 4 October 2026 from `docs/design/developer-adoption.md` (section 6, ten reasons a founder says no). Only the conceded objections are entered; the answered ones are in that document with their evidence. Entries are numbered D for developers.
|
||||||
|
|
||||||
|
|
||||||
### D1. Your users are a gate, not a fact
|
### D1. Your users are a gate, not a fact
|
||||||
"The miners are your user base? Nine devnet identities today, a 1,000-miner testnet gate whose word 'independent' is still undefined (X5), and miners are the most mercenary users of all: they sell."
|
"The miners are your user base? Nine devnet identities today, a 1,000-miner testnet gate whose word 'independent' is still undefined (X5), and miners are the most mercenary users of all: they sell."
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,14 +35,14 @@ What the nonce commits to: the pre-PoW header hash `H` enters the register initi
|
||||||
|
|
||||||
## 2.3 Difficulty adjustment (fork points c1, c2)
|
## 2.3 Difficulty adjustment (fork points c1, c2)
|
||||||
|
|
||||||
Status: Implemented on the `difficulty` branch of `vendor/igneum-node` (`SampledDifficultyManager::igneum_difficulty_bits`, pure core `igneum_target`, constants `kaspa_consensus_core::igneum::difficulty`), measured in `sim/difficulty/` and on a 3-node CPU test network (`docs/analysis/difficulty-2026-10-03.md`). Network parameter `difficulty_rule`: `igneum-dual` on every Igneum network, `kaspa-sampled` selectable through the override file (`{"difficulty_rule": "kaspa-sampled"}`) so the two rules can be compared on the same genesis. This closes O-2.1: the window is not shortened and the cost-equalising rule of section 1.4.2 is no longer load-bearing for difficulty (it remains desirable for the verifier bound). Revised 4 October 2026 after the attack run of `sim/difficulty/attacks/README.md` (ledger M23): the timestamp rules are Igneum's own (10 s both ways), every chain step is measured on a sanitised clock stored per header (`stores::clock`), and the output has a floor; the addendum of `docs/analysis/difficulty-2026-10-03.md` has the before and after.
|
Status: Implemented on the `difficulty` branch of `vendor/igneum-node` (`SampledDifficultyManager::igneum_difficulty_bits`, pure core `igneum_target`, constants `kaspa_consensus_core::igneum::difficulty`), measured in `sim/difficulty/` and on a 3-node CPU test network (`docs/analysis/difficulty-2026-10-03.md`). Rule v2 (4 October 2026, `docs/analysis/difficulty-2026-10-04-oscillation.md`, on `devnet-v4`): the reference lane is capped at the newest 600 DAA score of the epoch and the sampled long lane is not consulted, behind the height switch `difficulty_v2_activation_daa` (a consensus parameter, default never, set by the override file; rule v1 below it, v2 from it, no new genesis). Measured on the live devnet: a second RTX 5090 joining 7 minutes into an epoch left the whole-epoch reference lane polluted for the rest of the hour, the short lane disagreed with it by 11 to 25%, and the trigger flipped between the two for 40 minutes (difficulty 102M to 164M against a true 139M, 54 to 81 blocks a minute); the DAG replay reproduces it (std of log difficulty 0.115 against the record's 0.134) and v2 settles it within 10 minutes (0.026, 0 flips, 142.6M). Network parameter `difficulty_rule`: `igneum-dual` on every Igneum network, `kaspa-sampled` selectable through the override file (`{"difficulty_rule": "kaspa-sampled"}`) so the two rules can be compared on the same genesis. This closes O-2.1: the window is not shortened and the cost-equalising rule of section 1.4.2 is no longer load-bearing for difficulty (it remains desirable for the verifier bound). Revised 4 October 2026 after the attack run of `sim/difficulty/attacks/README.md` (ledger M23): the timestamp rules are Igneum's own (10 s both ways), every chain step is measured on a sanitised clock stored per header (`stores::clock`), and the output has a floor; the addendum of `docs/analysis/difficulty-2026-10-03.md` has the before and after.
|
||||||
|
|
||||||
Lineage, credited: the long lane is Kaspa's KIP-4 sampled window (`difficulty.rs`, samples at every 4th block, 661 samples, `estimateNetworkHashesPerSecond`'s blue-work-over-time estimator); the short lane is Zawy's LWMA weighting (linear weights rising to the newest block, solvetimes clamped symmetrically, 20 target times here against Zawy's 6) applied to the same work-over-time estimator instead of LWMA's average target, which is biased while targets ramp (measured: the fast lane stalled at 15x of a 50x step before the change, `docs/analysis/difficulty-2026-10-03.md`).
|
Lineage, credited: the long lane is Kaspa's KIP-4 sampled window (`difficulty.rs`, samples at every 4th block, 661 samples, `estimateNetworkHashesPerSecond`'s blue-work-over-time estimator); the short lane is Zawy's LWMA weighting (linear weights rising to the newest block, solvetimes clamped symmetrically, 20 target times here against Zawy's 6) applied to the same work-over-time estimator instead of LWMA's average target, which is biased while targets ramp (measured: the fast lane stalled at 15x of a 50x step before the change, `docs/analysis/difficulty-2026-10-03.md`).
|
||||||
|
|
||||||
### The rule
|
### The rule
|
||||||
|
|
||||||
1. Every lane estimates the hash rate as work over time (blue-work increment over the step of a sanitised clock), never as average target times average solvetime. The clock: c(genesis) = t(genesis); c(b) = max(c(p) + clamp(t(b) - c(p), -20 T, +20 T), t(b) - 60 T) for selected parent p (`sanitised_clock`); the step of b is min(c(b) - c(p), 20 T) (`clock_step`). The steps of a lane sum to the clock's span over it, so a forged stamp is paid back by the honest blocks after it; the 60 T bound keeps an honest idle gap from being paid back as cap-sized steps for many blocks (measured: without it the polluted case peaks at 275x, with it 11.4x against 8.0x before). The clock is computed at header validation and stored beside blue work; a header whose selected parent carries no clock (a pruning-proof or trusted header) starts from the parent's raw stamp. The long lane keeps the raw sampled span.
|
1. Every lane estimates the hash rate as work over time (blue-work increment over the step of a sanitised clock), never as average target times average solvetime. The clock: c(genesis) = t(genesis); c(b) = max(c(p) + clamp(t(b) - c(p), -20 T, +20 T), t(b) - 60 T) for selected parent p (`sanitised_clock`); the step of b is min(c(b) - c(p), 20 T) (`clock_step`). The steps of a lane sum to the clock's span over it, so a forged stamp is paid back by the honest blocks after it; the 60 T bound keeps an honest idle gap from being paid back as cap-sized steps for many blocks (measured: without it the polluted case peaks at 275x, with it 11.4x against 8.0x before). The clock is computed at header validation and stored beside blue work; a header whose selected parent carries no clock (a pruning-proof or trusted header) starts from the parent's raw stamp. The long lane keeps the raw sampled span.
|
||||||
2. Short lane S: the newest 120 selected-chain blocks of the block's own epoch, linear weights. Reference lane R: for the first 600 blocks of an epoch the epoch window (all its blocks, blended with the parent's implied rate as k : 16); from block 600 of the epoch Kaspa's sampled window restricted to the epoch.
|
2. Short lane S: the newest 120 selected-chain blocks of the block's own epoch, linear weights. Reference lane R, rule v1 (below `difficulty_v2_activation_daa`): for the first 600 blocks of an epoch the epoch window (all its blocks, blended with the parent's implied rate as k : 16); from block 600 of the epoch Kaspa's sampled window restricted to the epoch. Reference lane R, rule v2 (from `difficulty_v2_activation_daa`): the epoch window capped at the newest 600 DAA score of the epoch (chain blocks with DAA score at least max(epoch start, DAA - 600)), blended with the parent's implied rate as k_ref : 16 where k_ref is the DAA span of that window; the sampled window is not consulted. Why: a hash-rate step inside an epoch must leave R within 10 minutes, not at the next epoch boundary; measured 4 October 2026, the whole-epoch R polluted by a 1.85x step 7 minutes into the hour held the trigger flipping for 40 minutes (`docs/analysis/difficulty-2026-10-04-oscillation.md`).
|
||||||
3. S takes over when S and R differ by more than 25%; otherwise R rules. The trigger compares the two lanes, not the short rate to target (the literal form chatters once the short window is back on target while the long window is still polluted: measured 1,910 s against 72 s to settle on the polluted-window case).
|
3. S takes over when S and R differ by more than 25%; otherwise R rules. The trigger compares the two lanes, not the short rate to target (the literal form chatters once the short window is back on target while the long window is still polluted: measured 1,910 s against 72 s to settle on the polluted-window case).
|
||||||
4. The output may make the target fall (difficulty rise) by at most 3% per block and rise (difficulty fall) by at most 10% per block, relative to the selected parent's target, then is bounded to [`MIN_DIFFICULTY_TARGET`, `MAX_DIFFICULTY_TARGET`] (`bound_target`, both rule paths). `MIN_DIFFICULTY_TARGET` = 2^128: 2^128 expected hashes per block is unreachable by any network (the whole Bitcoin network is near 2^69 hashes per second, approximate) and keeps every block's work under 2^128, so the 192-bit blue work cannot overflow (measured: without the floor, 85 blocks per second of PoW-less input underflowed the work type after 4,142 blocks and the node panicked, `sim/difficulty/attacks/README.md` scenario 7; with it the flood stops at 2^128 after about 2,630 blocks, unit test `igneum_flood_at_85_blocks_per_second_stops_at_the_minimum_target`).
|
4. The output may make the target fall (difficulty rise) by at most 3% per block and rise (difficulty fall) by at most 10% per block, relative to the selected parent's target, then is bounded to [`MIN_DIFFICULTY_TARGET`, `MAX_DIFFICULTY_TARGET`] (`bound_target`, both rule paths). `MIN_DIFFICULTY_TARGET` = 2^128: 2^128 expected hashes per block is unreachable by any network (the whole Bitcoin network is near 2^69 hashes per second, approximate) and keeps every block's work under 2^128, so the 192-bit blue work cannot overflow (measured: without the floor, 85 blocks per second of PoW-less input underflowed the work type after 4,142 blocks and the node panicked, `sim/difficulty/attacks/README.md` scenario 7; with it the flood stops at 2^128 after about 2,630 blocks, unit test `igneum_flood_at_85_blocks_per_second_stops_at_the_minimum_target`).
|
||||||
5. The parent's target is held for the first 8 blocks of every epoch, including epoch 0: the warm-up starts at block 8, not 600.
|
5. The parent's target is held for the first 8 blocks of every epoch, including epoch 0: the warm-up starts at block 8, not 600.
|
||||||
|
|
@ -53,8 +53,10 @@ Lineage, credited: the long lane is Kaspa's KIP-4 sampled window (`difficulty.rs
|
||||||
| Short window | 120 chain blocks | `SHORT_WINDOW` | Measured: 60 is noisier (steady std 0.069 vs 0.039), 180 slower on hops (356 s vs 276 s) |
|
| Short window | 120 chain blocks | `SHORT_WINDOW` | Measured: 60 is noisier (steady std 0.069 vs 0.039), 180 slower on hops (356 s vs 276 s) |
|
||||||
| Hold at epoch start | 8 blocks | `EPOCH_HOLD` | Designed |
|
| Hold at epoch start | 8 blocks | `EPOCH_HOLD` | Designed |
|
||||||
| Epoch-lane prior weight | 16 blocks | `PRIOR_BLOCKS` | Measured: 8, 16, 32 indistinguishable |
|
| Epoch-lane prior weight | 16 blocks | `PRIOR_BLOCKS` | Measured: 8, 16, 32 indistinguishable |
|
||||||
| Long lane from | 600 blocks of the epoch (150 samples) | `LONG_MIN` | Kaspa's minimum window, kept |
|
| Long lane from (v1 only) | 600 blocks of the epoch (150 samples) | `LONG_MIN` | Kaspa's minimum window, kept |
|
||||||
| Long window | 661 samples at 4-block intervals (2,644 blocks), restricted to the epoch | Kaspa's constants, kept | Designed |
|
| Long window (v1 only) | 661 samples at 4-block intervals (2,644 blocks), restricted to the epoch | Kaspa's constants, kept | Designed |
|
||||||
|
| Reference window (v2) | newest 600 DAA score of the epoch, epoch lane only | `REF_WINDOW_V2` | Measured on the live replay (3 seeds, join window): whole epoch std of log difficulty 0.115 with 22 lane flips; 1,200 blocks 0.108; 900 0.081; 720 0.055; 600 0.026 with 0 flips; 480 0.021. The brief's candidates (short lane 240 or 360, ease clamp 3%, clamp once per DAA second, hysteresis, median of three) each leave 0.09 to 0.13 |
|
||||||
|
| Rule v2 activation | DAA score, default never (`u64::MAX`), set by the override file | `difficulty_v2_activation_daa` | Designed: a height switch so upgraded nodes rule v1 until the height and v2 from it on the same chain |
|
||||||
| Trigger | 25% disagreement between S and R | `TRIGGER_PERCENT` | Measured: 15% engages on noise (steady std 0.077), 35% slower on hops |
|
| Trigger | 25% disagreement between S and R | `TRIGGER_PERCENT` | Measured: 15% engages on noise (steady std 0.077), 35% slower on hops |
|
||||||
| Harden clamp | 3% per block | `HARDEN_PERCENT` | Measured: 2% slows the 50x step-up to 84 s from 62 s, 5% buys nothing on the up step |
|
| Harden clamp | 3% per block | `HARDEN_PERCENT` | Measured: 2% slows the 50x step-up to 84 s from 62 s, 5% buys nothing on the up step |
|
||||||
| Ease clamp | 10% per block | `EASE_PERCENT` | Measured: 3% leaves the 50x step-down at 1,786 s and a 211 s worst gap, 10% gives 1,164 s and 65 s |
|
| Ease clamp | 10% per block | `EASE_PERCENT` | Measured: 3% leaves the 50x step-down at 1,786 s and a 211 s worst gap, 10% gives 1,164 s and 65 s |
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ Time parameters, divided by 60 (devnet value, 60x value):
|
||||||
| `blockrate.pruning_depth` (DAA s) | 108,000 | 13,838 | 30 hours / 60 = 1,800 is under Kaspa's anticone finalisation bound (finality + 2 x merge + 4 x mergeset x k + 2k + 2 = 13,838 at k 18, mergeset 180), and `Bps::pruning_depth` takes the larger, so this does |
|
| `blockrate.pruning_depth` (DAA s) | 108,000 | 13,838 | 30 hours / 60 = 1,800 is under Kaspa's anticone finalisation bound (finality + 2 x merge + 4 x mergeset x k + 2k + 2 = 13,838 at k 18, mergeset 180), and `Bps::pruning_depth` takes the larger, so this does |
|
||||||
| `blockrate.coinbase_maturity` (s) | 100 | 2 | 100 s / 60 rounds up |
|
| `blockrate.coinbase_maturity` (s) | 100 | 2 | 100 s / 60 rounds up |
|
||||||
| `deflationary_phase_daa_score` | 0 | 0 | the devnet has no deflationary phase |
|
| `deflationary_phase_daa_score` | 0 | 0 | the devnet has no deflationary phase |
|
||||||
|
| `difficulty_v2_activation_daa` | never (`18446744073709551615`) | never | a height, not a clock: difficulty rule v2 (4 Oct 2026, `docs/analysis/difficulty-2026-10-04-oscillation.md`) switches on at this DAA score; a test network sets it in its merged file (`sim/difficulty/testnet_v2.py` uses 900) |
|
||||||
|
|
||||||
Unchanged, and why:
|
Unchanged, and why:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,5 +49,6 @@
|
||||||
},
|
},
|
||||||
"pow_epoch_blocks": 60,
|
"pow_epoch_blocks": 60,
|
||||||
"pow_epoch_lead": 10,
|
"pow_epoch_lead": 10,
|
||||||
"pow_day_ms": 1440000
|
"pow_day_ms": 1440000,
|
||||||
|
"difficulty_v2_activation_daa": 18446744073709551615
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,15 @@ devnet record behind `docs/analysis/difficulty-2026-10-03.md` and section 2.3 of
|
||||||
| `devnet-2026-10-03.csv` | every header of the overnight devnet (observer node wRPC, `ws://127.0.0.1:28640`): hash, DAA score, blue score, timestamp, bits, difficulty (2^255 / target, the node's convention), log2 target, epoch, chain flag, parent count, selected parent |
|
| `devnet-2026-10-03.csv` | every header of the overnight devnet (observer node wRPC, `ws://127.0.0.1:28640`): hash, DAA score, blue score, timestamp, bits, difficulty (2^255 / target, the node's convention), log2 target, epoch, chain flag, parent count, selected parent |
|
||||||
| `results.md` | raw simulator output: synthetic set, timestamp-noise set, tuning sweeps, record replay, test-network comparison |
|
| `results.md` | raw simulator output: synthetic set, timestamp-noise set, tuning sweeps, record replay, test-network comparison |
|
||||||
| `testnet-igneum-2026-10-03.csv`, `testnet-kaspa-2026-10-03.csv` | every header of the two 3-node CPU test networks (Igneum rule, 20 min; Kaspa rule, 10 min), same columns |
|
| `testnet-igneum-2026-10-03.csv`, `testnet-kaspa-2026-10-03.csv` | every header of the two 3-node CPU test networks (Igneum rule, 20 min; Kaspa rule, 10 min), same columns |
|
||||||
|
| `records/live-2026-10-04.csv` | every header of live devnet v4 through 11:18 UTC on 4 October 2026 (observer node wRPC, `records/pull_live.py`): the columns above plus blue work, mergeset blues and reds, vote key hash |
|
||||||
|
| `records/live-2026-10-04-hashrate.csv` | the hash-rate truth of the same hours: every STATUS line of the four GPU workers from the log intake (last-30-s MH/s every 30 s, run id, which node the worker mined through) |
|
||||||
|
| `testnet_v2.py` | the 3-node CPU test network of rule v2 and its height switch (ports 29600 and up, `/tmp/igneum-diffv2`) |
|
||||||
|
|
||||||
|
`docs/analysis/difficulty-2026-10-04-oscillation.md` holds the live finding, the DAG replay and rule v2.
|
||||||
|
|
||||||
## Model
|
## Model
|
||||||
|
|
||||||
One selected chain, DAA score = height, target 1 block per second, solve times exponential with
|
Chain model (every synthetic profile and the attacks): one selected chain, DAA score = height, target 1 block per second, solve times exponential with
|
||||||
mean (expected hashes per block) / (hash rate). A hash-rate profile is piecewise constant in time
|
mean (expected hashes per block) / (hash rate). A hash-rate profile is piecewise constant in time
|
||||||
(miners joining and leaving) or keyed to the 3,600-block epoch (program cost steps). Timestamps are
|
(miners joining and leaving) or keyed to the 3,600-block epoch (program cost steps). Timestamps are
|
||||||
the true times in milliseconds; `--ts-noise N` adds uniform +-N ms miner clock jitter.
|
the true times in milliseconds; `--ts-noise N` adds uniform +-N ms miner clock jitter.
|
||||||
|
|
@ -25,6 +30,13 @@ the far side; blocks spent above 2x and below 0.5x target rate; worst inter-bloc
|
||||||
standard deviation of the expected rate ratio over a steady hour, blocks-per-minute coefficient of
|
standard deviation of the expected rate ratio over a steady hour, blocks-per-minute coefficient of
|
||||||
variation (Poisson alone gives 0.129 at 60 blocks per minute).
|
variation (Poisson alone gives 0.129 at 60 blocks per minute).
|
||||||
|
|
||||||
|
DAG model (`--live`, 4 October 2026): miners on nodes, each fetching templates from its node with the staleness of
|
||||||
|
`igneum-miner`'s job queue, blocks carrying the parents and the node's stamp of their template, GHOSTDAG with every
|
||||||
|
merged block blue, the rule run exactly as the node runs it (chain walk from the virtual's selected parent, sampled
|
||||||
|
window per mergeset). The hash-rate schedule comes from the records CSV. Fitted once to the record's merge fraction
|
||||||
|
(`--dag-delay`); compared per UTC window on block rate, DAG width, difficulty band, std of log difficulty, peaks over
|
||||||
|
15%, blocks per minute, lane flips.
|
||||||
|
|
||||||
## Controllers
|
## Controllers
|
||||||
|
|
||||||
| Name | Rule |
|
| Name | Rule |
|
||||||
|
|
@ -34,6 +46,8 @@ variation (Poisson alone gives 0.129 at 60 blocks per minute).
|
||||||
| `lwma60`, `lwma120` | Zawy LWMA-1 (2018 reference), linear weights, solvetimes in [-132 s, 6 T] |
|
| `lwma60`, `lwma120` | Zawy LWMA-1 (2018 reference), linear weights, solvetimes in [-132 s, 6 T] |
|
||||||
| `igneum` | the Igneum rule of spec 2.3 (two lanes, work-over-time estimators, epoch windows, 3% harden and 10% ease clamps) |
|
| `igneum` | the Igneum rule of spec 2.3 (two lanes, work-over-time estimators, epoch windows, 3% harden and 10% ease clamps) |
|
||||||
| `igneum-literal` | the same with the brief's literal trigger (short-window rate off target by 25%), kept to show the chatter |
|
| `igneum-literal` | the same with the brief's literal trigger (short-window rate off target by 25%), kept to show the chatter |
|
||||||
|
| `igneum-v2` | rule v2 (4 October 2026): the reference lane is the epoch lane over the newest 600 blocks of the epoch; the sampled long lane is not consulted |
|
||||||
|
| `igneum:key=value+...` | any variant: `ns`, `trig`, `trig_exit` (hysteresis), `soft=a/b` (blend), `median3`, `clamp_window` (ms), `ref_window`, `long_min`, `clamp_pct`, `ease_pct`, `cap`, `k0` |
|
||||||
|
|
||||||
## Runs
|
## Runs
|
||||||
|
|
||||||
|
|
@ -45,12 +59,18 @@ variation (Poisson alone gives 0.129 at 60 blocks per minute).
|
||||||
exact replay check of Kaspa's rule on the record,
|
exact replay check of Kaspa's rule on the record,
|
||||||
then the record as a hash-rate profile through every controller
|
then the record as a hash-rate profile through every controller
|
||||||
python3 sim.py --dump up50:igneum per-block trajectory (t ms, height, D, hash rate, rate ratio)
|
python3 sim.py --dump up50:igneum per-block trajectory (t ms, height, D, hash rate, rate ratio)
|
||||||
|
python3 sim.py --live records/live-2026-10-04.csv --hashrate records/live-2026-10-04-hashrate.csv \
|
||||||
|
--controllers igneum,igneum-v2 --seed 7 --dag-delay 0.75 --live-end 10:58
|
||||||
|
the live devnet replayed through the DAG model against the record
|
||||||
|
python3 testnet_v2.py --minutes 28 --activation 900 --out /tmp/igneum-diffv2/run1
|
||||||
|
3 CPU nodes: a 2x step under v1, the switch at DAA 900, steps under v2
|
||||||
|
|
||||||
Requirements: Python 3 only (numpy not needed). The full synthetic set takes about two minutes.
|
Requirements: Python 3 only (numpy not needed). The full synthetic set takes about two minutes.
|
||||||
|
|
||||||
## Limits
|
## Limits
|
||||||
|
|
||||||
No DAG (one chain, no parallel blocks, no reds), no network latency, no miner template refresh
|
The chain model has no DAG (one chain, no parallel blocks, no reds), no network latency, no miner template
|
||||||
delay, honest timestamps unless `--ts-noise`. The exact-replay check of Kaspa's rule matches the
|
refresh delay, honest timestamps unless `--ts-noise`. The DAG model has no reds, one fitted staleness scale, and
|
||||||
|
the Mac's hash rate as a constant. The exact-replay check of Kaspa's rule matches the
|
||||||
record bit for bit while the devnet was a chain and diverges once it widened past one block per
|
record bit for bit while the devnet was a chain and diverges once it widened past one block per
|
||||||
second, because a chain-only replay cannot see the merged blocks that the sampled window includes.
|
second, because a chain-only replay cannot see the merged blocks that the sampled window includes.
|
||||||
|
|
|
||||||
|
|
@ -398,3 +398,77 @@ test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 81 filtered out; fin
|
||||||
| igneum-ease3 | 50 | 60 | -0.012 | -0.012 | 0.321 | 588.0 | 0.213 | 12.1 | 0.984 | 1 |
|
| igneum-ease3 | 50 | 60 | -0.012 | -0.012 | 0.321 | 588.0 | 0.213 | 12.1 | 0.984 | 1 |
|
||||||
| igneum-ease3 | 100 | 0 | 0.005 | 0.005 | 0.115 | 896.0 | 0.366 | 11.9 | 0.988 | 1 |
|
| igneum-ease3 | 100 | 0 | 0.005 | 0.005 | 0.115 | 896.0 | 0.366 | 11.9 | 0.988 | 1 |
|
||||||
| igneum-ease3 | 100 | 60 | -0.027 | -0.027 | 0.413 | 859.0 | 0.343 | 16.7 | 0.970 | 1 |
|
| igneum-ease3 | 100 | 60 | -0.027 | -0.027 | 0.413 | 859.0 | 0.343 | 16.7 | 0.970 | 1 |
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rule v2 (4 October 2026, `igneum:ref_window=600+long_min=100000` = `igneum-v2`): full suite under the tight timestamp rules and the base profiles, seeds 7 to 9. The v1 rows for comparison are the `igneum-san` rows of the sections above (the 4 October rule); `docs/analysis/difficulty-2026-10-04-oscillation.md` section 6 sets them side by side.
|
||||||
|
|
||||||
|
# Difficulty attacks, seeds [7, 8, 9], rules ['igneum:ref_window=600+long_min=100000']
|
||||||
|
|
||||||
|
|
||||||
|
### 1. Pool hopping: hopper's blocks per hash against the always-on base (adv = ratio - 1), 24 h
|
||||||
|
|
||||||
|
| rule | x | dwell | adv | adv_worst | hop_on_frac | switches | std | worst_gap | blocks_per_s | seeds |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 10 | 0 | 0.025 | 0.025 | 0.495 | 529.0 | 0.081 | 12.4 | 0.998 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 10 | 60 | 0.023 | 0.023 | 0.495 | 399.0 | 0.081 | 12.8 | 0.998 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 30 | 0 | 0.016 | 0.016 | 0.318 | 923.3 | 0.149 | 12.9 | 0.997 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 30 | 60 | 0.008 | 0.010 | 0.386 | 631.0 | 0.150 | 14.0 | 0.995 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 50 | 0 | 0.012 | 0.013 | 0.222 | 1124.3 | 0.218 | 14.2 | 0.996 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 50 | 60 | -0.003 | -0.008 | 0.377 | 778.3 | 0.219 | 15.3 | 0.989 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 100 | 0 | 0.010 | 0.011 | 0.122 | 1342.7 | 0.377 | 14.0 | 0.996 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 100 | 60 | -0.015 | -0.018 | 0.424 | 959.3 | 0.351 | 17.0 | 0.973 | 3 |
|
||||||
|
|
||||||
|
### 2. Pulsed hash rate: 50x for 10 min, every hour (period 3600) and once (period 1000000); weight_per_hash = block share / hash share
|
||||||
|
|
||||||
|
| rule | period_s | pulse_vs_base | pulse_vs_base_worst | weight_per_hash | weight_per_hash_worst | pulse_vs_steady | base_vs_steady | pulse_block_share | pulse_hash_share | peak_blocks_per_min | worst_gap | blocks_per_s | seeds |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 3600 | -0.963 | -0.964 | 0.262 | 0.266 | -0.977 | -0.358 | 0.234 | 0.893 | 185.0 | 198.7 | 0.834 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 1000000 | -0.972 | -0.973 | 0.130 | 0.132 | -0.977 | -0.182 | 0.105 | 0.806 | 172.0 | 97.8 | 0.912 | 3 |
|
||||||
|
|
||||||
|
### 3. Timestamp stretching inside the rules: block rate after 1 h of forging (drift = rate - 1), 6 h runs
|
||||||
|
|
||||||
|
| rule | ts_rules | share | stamp | forger_offset_s | rate_pre | rate_post | rate_last_hour | drift | drift_worst | D_ratio | std | worst_gap | forger_adv | seeds |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| igneum:ref_window=600+long_min=100000 | tight | 30 | future | 10.0 | 0.994 | 1.002 | 1.000 | 0.002 | 0.005 | 1.004 | 0.066 | 9.666 | 0.000 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | tight | 30 | past | -15.8 | 0.994 | 0.998 | 0.993 | -0.002 | -0.009 | 1.008 | 0.079 | 9.925 | 0.000 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | tight | 30 | alt | 0.997 | 0.994 | 1.001 | 0.998 | 0.001 | 0.006 | 1.005 | 0.063 | 9.623 | 0.000 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | tight | 50 | future | 10.0 | 0.994 | 1.004 | 0.996 | 0.004 | 0.009 | 1.002 | 0.071 | 9.795 | 0.000 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | tight | 50 | past | -21.9 | 0.994 | 0.992 | 0.984 | -0.008 | -0.015 | 1.013 | 0.173 | 10.3 | 0.000 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | tight | 50 | alt | 1.999 | 0.994 | 1.005 | 1.003 | 0.005 | 0.009 | 1.001 | 0.069 | 9.515 | 0.000 | 3 |
|
||||||
|
|
||||||
|
### 4. Short-lane oscillation: 25% miner on and off every 120 blocks (std_floor = the hash square wave at a fixed D)
|
||||||
|
|
||||||
|
| rule | share | period | std_pre | std_post | std_ratio | std_ratio_worst | std_floor | worst_gap_pre | worst_gap_post | blocks_per_s | osc_adv | seeds |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 25 | 120 | 0.049 | 0.159 | 3.293 | 3.707 | 0.143 | 8.725 | 11.0 | 0.983 | -0.012 | 3 |
|
||||||
|
|
||||||
|
### 5. Epoch-boundary games: hold dodger (30%, off for blocks 0 to 7), hold flooder (10x, on for blocks 0 to 7), 30% flooder
|
||||||
|
|
||||||
|
| rule | kind | gamer_adv | gamer_adv_worst | gamer_on_frac | std | worst_gap | blocks_per_s | seeds |
|
||||||
|
|---|---|---|---|---|---|---|---|---|
|
||||||
|
| igneum:ref_window=600+long_min=100000 | dodge | 0.000 | 0.000 | 0.997 | 0.062 | 9.602 | 1.000 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | flood | 0.004 | -0.019 | 0.000 | 0.472 | 9.982 | 0.994 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | flood30 | 0.000 | -0.022 | 0.001 | 0.062 | 9.812 | 0.996 | 3 |
|
||||||
|
|
||||||
|
### 6. Polluted window under adversarial timing: 10x miner joins at block join_k of an epoch and leaves at leave_k (600 = long lane takes over)
|
||||||
|
|
||||||
|
| rule | join_k | leave_k | join_first10_s | join_settled_s | leave_first10_s | leave_settled_s | leave_worst_gap_s | leave_below05 | leave_above2x | seeds |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 0 | 600 | 89.3 | 135.4 | 296.6 | 296.6 | 16.4 | 55.3 | 0.000 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 480 | 600 | none | none | 287.6 | 287.6 | 14.8 | 46.3 | 0.000 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 480 | 720 | 76.3 | 58.3 | 312.3 | 312.3 | 28.5 | 55.0 | 0.000 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 0 | 1200 | 89.3 | 135.4 | 307.2 | 331.0 | 24.6 | 55.7 | 0.000 | 3 |
|
||||||
|
|
||||||
|
### Base profiles (sim.py metrics) through each rule
|
||||||
|
|
||||||
|
| rule | profile | first10_s | settled_s | settled_s_none | worst_gap_s | steady_std | peak_rate | not_recovered | seeds |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| igneum:ref_window=600+long_min=100000 | up50 | 55.5 | 150.3 | none | 9.596 | 0.053 | none | none | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | down50 | 792.3 | 822.0 | none | 76.0 | 0.053 | none | none | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | epoch30 | 53.8 | 87.8 | none | 10.6 | 0.049 | none | 0.000 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | walk10 | none | none | 3 | 10.5 | 0.059 | none | none | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | hop10 | 207.4 | 233.2 | none | 42.4 | 0.053 | none | 0.000 | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | polluted | 76.3 | 76.3 | none | 10.2 | 0.048 | 12.2 | none | 3 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | warmup-hard | 305.8 | 326.5 | none | 34.6 | 0.049 | none | none | 3 |
|
||||||
|
|
|
||||||
588
sim/difficulty/records/live-2026-10-04-hashrate.csv
Normal file
588
sim/difficulty/records/live-2026-10-04-hashrate.csv
Normal file
|
|
@ -0,0 +1,588 @@
|
||||||
|
t_unix,utc,worker,node,run_id,mh_s_last_30s,accepted_total
|
||||||
|
1791105093.586,2026-10-04T09:11:33Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.01,76
|
||||||
|
1791105094.447,2026-10-04T09:11:34Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.55,5
|
||||||
|
1791105123.635,2026-10-04T09:12:03Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.95,119
|
||||||
|
1791105125.048,2026-10-04T09:12:05Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,5
|
||||||
|
1791105153.808,2026-10-04T09:12:33Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.44,158
|
||||||
|
1791105155.634,2026-10-04T09:12:35Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,5
|
||||||
|
1791105183.848,2026-10-04T09:13:03Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.99,186
|
||||||
|
1791105186.231,2026-10-04T09:13:06Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,5
|
||||||
|
1791105213.884,2026-10-04T09:13:33Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.00,211
|
||||||
|
1791105216.805,2026-10-04T09:13:36Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,5
|
||||||
|
1791105243.915,2026-10-04T09:14:03Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.02,239
|
||||||
|
1791105247.407,2026-10-04T09:14:07Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,6
|
||||||
|
1791105273.938,2026-10-04T09:14:33Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.06,264
|
||||||
|
1791105277.991,2026-10-04T09:14:37Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,7
|
||||||
|
1791105304.000,2026-10-04T09:15:04Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.34,291
|
||||||
|
1791105308.623,2026-10-04T09:15:08Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,9
|
||||||
|
1791105334.041,2026-10-04T09:15:34Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.98,321
|
||||||
|
1791105339.210,2026-10-04T09:15:39Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,9
|
||||||
|
1791105364.066,2026-10-04T09:16:04Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.61,350
|
||||||
|
1791105369.786,2026-10-04T09:16:09Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,9
|
||||||
|
1791105394.105,2026-10-04T09:16:34Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.99,365
|
||||||
|
1791105400.375,2026-10-04T09:16:40Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,9
|
||||||
|
1791105424.145,2026-10-04T09:17:04Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.99,387
|
||||||
|
1791105430.944,2026-10-04T09:17:10Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,10
|
||||||
|
1791105454.188,2026-10-04T09:17:34Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.98,411
|
||||||
|
1791105461.536,2026-10-04T09:17:41Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,10
|
||||||
|
1791105484.210,2026-10-04T09:18:04Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.06,431
|
||||||
|
1791105492.116,2026-10-04T09:18:12Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,11
|
||||||
|
1791105514.251,2026-10-04T09:18:34Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.98,455
|
||||||
|
1791105522.701,2026-10-04T09:18:42Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,11
|
||||||
|
1791105544.301,2026-10-04T09:19:04Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.94,491
|
||||||
|
1791105553.285,2026-10-04T09:19:13Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.67,11
|
||||||
|
1791105574.332,2026-10-04T09:19:34Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.03,525
|
||||||
|
1791105583.875,2026-10-04T09:19:43Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.81,12
|
||||||
|
1791105604.364,2026-10-04T09:20:04Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.02,557
|
||||||
|
1791105614.460,2026-10-04T09:20:14Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,13
|
||||||
|
1791105634.388,2026-10-04T09:20:34Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.05,587
|
||||||
|
1791105645.051,2026-10-04T09:20:45Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,14
|
||||||
|
1791105664.431,2026-10-04T09:21:04Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.97,614
|
||||||
|
1791105675.628,2026-10-04T09:21:15Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,14
|
||||||
|
1791105694.445,2026-10-04T09:21:34Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.09,639
|
||||||
|
1791105706.219,2026-10-04T09:21:46Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,15
|
||||||
|
1791105724.478,2026-10-04T09:22:04Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.02,670
|
||||||
|
1791105736.793,2026-10-04T09:22:16Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,15
|
||||||
|
1791105754.510,2026-10-04T09:22:34Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.46,700
|
||||||
|
1791105767.400,2026-10-04T09:22:47Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,15
|
||||||
|
1791105784.549,2026-10-04T09:23:04Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.55,725
|
||||||
|
1791105797.979,2026-10-04T09:23:17Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,15
|
||||||
|
1791105814.573,2026-10-04T09:23:34Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.06,745
|
||||||
|
1791105828.564,2026-10-04T09:23:48Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,15
|
||||||
|
1791105844.617,2026-10-04T09:24:04Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.97,769
|
||||||
|
1791105859.189,2026-10-04T09:24:19Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,16
|
||||||
|
1791105874.743,2026-10-04T09:24:34Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.63,796
|
||||||
|
1791105889.800,2026-10-04T09:24:49Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,16
|
||||||
|
1791105904.761,2026-10-04T09:25:04Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.08,823
|
||||||
|
1791105920.387,2026-10-04T09:25:20Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,16
|
||||||
|
1791105934.827,2026-10-04T09:25:34Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.88,860
|
||||||
|
1791105950.962,2026-10-04T09:25:50Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,16
|
||||||
|
1791105964.869,2026-10-04T09:26:04Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.98,889
|
||||||
|
1791105981.552,2026-10-04T09:26:21Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,18
|
||||||
|
1791105994.890,2026-10-04T09:26:34Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.07,915
|
||||||
|
1791106012.124,2026-10-04T09:26:52Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,20
|
||||||
|
1791106024.932,2026-10-04T09:27:04Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.98,948
|
||||||
|
1791106042.720,2026-10-04T09:27:22Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,22
|
||||||
|
1791106054.955,2026-10-04T09:27:34Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.06,978
|
||||||
|
1791106073.290,2026-10-04T09:27:53Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,22
|
||||||
|
1791106084.986,2026-10-04T09:28:04Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.02,1009
|
||||||
|
1791106103.883,2026-10-04T09:28:23Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,22
|
||||||
|
1791106114.998,2026-10-04T09:28:34Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.10,1037
|
||||||
|
1791106134.463,2026-10-04T09:28:54Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,23
|
||||||
|
1791106145.017,2026-10-04T09:29:05Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.07,1062
|
||||||
|
1791106165.072,2026-10-04T09:29:25Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,23
|
||||||
|
1791106175.067,2026-10-04T09:29:35Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.95,1097
|
||||||
|
1791106195.651,2026-10-04T09:29:55Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,25
|
||||||
|
1791106205.089,2026-10-04T09:30:05Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.06,1126
|
||||||
|
1791106226.230,2026-10-04T09:30:26Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,25
|
||||||
|
1791106235.195,2026-10-04T09:30:35Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.26,1154
|
||||||
|
1791106256.809,2026-10-04T09:30:56Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,25
|
||||||
|
1791106265.324,2026-10-04T09:31:05Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.17,1181
|
||||||
|
1791106287.382,2026-10-04T09:31:27Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,26
|
||||||
|
1791106295.348,2026-10-04T09:31:35Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.04,1216
|
||||||
|
1791106317.955,2026-10-04T09:31:57Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,26
|
||||||
|
1791106325.424,2026-10-04T09:32:05Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.38,1239
|
||||||
|
1791106348.512,2026-10-04T09:32:28Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,27
|
||||||
|
1791106356.115,2026-10-04T09:32:36Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.61,1264
|
||||||
|
1791106379.085,2026-10-04T09:32:59Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.77,28
|
||||||
|
1791106386.255,2026-10-04T09:33:06Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.96,1292
|
||||||
|
1791106409.663,2026-10-04T09:33:29Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,28
|
||||||
|
1791106416.334,2026-10-04T09:33:36Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.93,1324
|
||||||
|
1791106440.233,2026-10-04T09:34:00Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,28
|
||||||
|
1791106446.363,2026-10-04T09:34:06Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.02,1354
|
||||||
|
1791106470.808,2026-10-04T09:34:30Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,30
|
||||||
|
1791106476.371,2026-10-04T09:34:36Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.55,1377
|
||||||
|
1791106501.401,2026-10-04T09:35:01Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,32
|
||||||
|
1791106506.433,2026-10-04T09:35:06Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.44,1409
|
||||||
|
1791106532.027,2026-10-04T09:35:32Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,32
|
||||||
|
1791106536.462,2026-10-04T09:35:36Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.78,1436
|
||||||
|
1791106562.676,2026-10-04T09:36:02Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,32
|
||||||
|
1791106566.529,2026-10-04T09:36:06Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.31,1456
|
||||||
|
1791106593.241,2026-10-04T09:36:33Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,33
|
||||||
|
1791106596.548,2026-10-04T09:36:36Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.50,1485
|
||||||
|
1791106623.810,2026-10-04T09:37:03Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,33
|
||||||
|
1791106626.635,2026-10-04T09:37:06Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.22,1519
|
||||||
|
1791106654.374,2026-10-04T09:37:34Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,34
|
||||||
|
1791106656.758,2026-10-04T09:37:36Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.19,1545
|
||||||
|
1791106684.939,2026-10-04T09:38:04Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,34
|
||||||
|
1791106686.763,2026-10-04T09:38:06Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.56,1567
|
||||||
|
1791106715.506,2026-10-04T09:38:35Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,34
|
||||||
|
1791106716.803,2026-10-04T09:38:36Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.97,1592
|
||||||
|
1791106746.070,2026-10-04T09:39:06Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,34
|
||||||
|
1791106746.877,2026-10-04T09:39:06Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.83,1622
|
||||||
|
1791106776.646,2026-10-04T09:39:36Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,35
|
||||||
|
1791106776.970,2026-10-04T09:39:36Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.20,1652
|
||||||
|
1791106807.050,2026-10-04T09:40:07Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.37,1668
|
||||||
|
1791106807.229,2026-10-04T09:40:07Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,35
|
||||||
|
1791106837.095,2026-10-04T09:40:37Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.95,1700
|
||||||
|
1791106837.807,2026-10-04T09:40:37Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,36
|
||||||
|
1791106867.128,2026-10-04T09:41:07Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.00,1722
|
||||||
|
1791106868.381,2026-10-04T09:41:08Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,37
|
||||||
|
1791106897.141,2026-10-04T09:41:37Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.08,1748
|
||||||
|
1791106898.972,2026-10-04T09:41:38Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,38
|
||||||
|
1791106927.194,2026-10-04T09:42:07Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.92,1776
|
||||||
|
1791106929.538,2026-10-04T09:42:09Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,39
|
||||||
|
1791106957.214,2026-10-04T09:42:37Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.06,1806
|
||||||
|
1791106960.128,2026-10-04T09:42:40Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,40
|
||||||
|
1791106987.229,2026-10-04T09:43:07Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.08,1838
|
||||||
|
1791106990.700,2026-10-04T09:43:10Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,41
|
||||||
|
1791107017.257,2026-10-04T09:43:37Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.02,1871
|
||||||
|
1791107021.292,2026-10-04T09:43:41Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,41
|
||||||
|
1791107047.272,2026-10-04T09:44:07Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.08,1893
|
||||||
|
1791107051.871,2026-10-04T09:44:11Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,41
|
||||||
|
1791107077.363,2026-10-04T09:44:37Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.76,1922
|
||||||
|
1791107082.534,2026-10-04T09:44:42Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,41
|
||||||
|
1791107107.415,2026-10-04T09:45:07Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.93,1952
|
||||||
|
1791107113.165,2026-10-04T09:45:13Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,41
|
||||||
|
1791107137.557,2026-10-04T09:45:37Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,119.66,1975
|
||||||
|
1791107143.382,2026-10-04T09:45:43Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.71,42
|
||||||
|
1791107167.659,2026-10-04T09:46:07Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,108.11,2003
|
||||||
|
1791107173.452,2026-10-04T09:46:13Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.72,42
|
||||||
|
1791107197.689,2026-10-04T09:46:37Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,110.05,2028
|
||||||
|
1791107204.191,2026-10-04T09:46:44Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.73,43
|
||||||
|
1791107227.740,2026-10-04T09:47:07Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,112.21,2055
|
||||||
|
1791107234.888,2026-10-04T09:47:14Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.73,43
|
||||||
|
1791107257.787,2026-10-04T09:47:37Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,109.99,2084
|
||||||
|
1791107265.615,2026-10-04T09:47:45Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.73,47
|
||||||
|
1791107287.825,2026-10-04T09:48:07Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,110.02,2112
|
||||||
|
1791107296.369,2026-10-04T09:48:16Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.73,48
|
||||||
|
1791107317.896,2026-10-04T09:48:37Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,109.90,2134
|
||||||
|
1791107327.082,2026-10-04T09:48:47Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.73,48
|
||||||
|
1791107347.986,2026-10-04T09:49:07Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,109.84,2150
|
||||||
|
1791107357.107,2026-10-04T09:49:17Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.72,49
|
||||||
|
1791107378.091,2026-10-04T09:49:38Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,110.89,2173
|
||||||
|
1791107387.804,2026-10-04T09:49:47Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.73,50
|
||||||
|
1791107408.122,2026-10-04T09:50:08Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,109.49,2194
|
||||||
|
1791107417.832,2026-10-04T09:50:17Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.72,50
|
||||||
|
1791107438.181,2026-10-04T09:50:38Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,110.51,2217
|
||||||
|
1791107447.845,2026-10-04T09:50:47Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.72,50
|
||||||
|
1791107468.229,2026-10-04T09:51:08Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,109.99,2244
|
||||||
|
1791107478.584,2026-10-04T09:51:18Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.73,50
|
||||||
|
1791107498.364,2026-10-04T09:51:38Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,111.34,2268
|
||||||
|
1791107509.323,2026-10-04T09:51:49Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.73,50
|
||||||
|
1791107528.469,2026-10-04T09:52:08Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,117.58,2292
|
||||||
|
1791107539.931,2026-10-04T09:52:19Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,50
|
||||||
|
1791107558.565,2026-10-04T09:52:38Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.08,2330
|
||||||
|
1791107570.603,2026-10-04T09:52:50Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.73,50
|
||||||
|
1791107588.710,2026-10-04T09:53:08Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,118.54,2357
|
||||||
|
1791107600.700,2026-10-04T09:53:20Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.72,51
|
||||||
|
1791107618.798,2026-10-04T09:53:38Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,114.86,2390
|
||||||
|
1791107631.424,2026-10-04T09:53:51Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.73,51
|
||||||
|
1791107648.945,2026-10-04T09:54:08Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,117.42,2405
|
||||||
|
1791107661.468,2026-10-04T09:54:21Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.72,51
|
||||||
|
1791107679.030,2026-10-04T09:54:39Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,113.20,2427
|
||||||
|
1791107691.486,2026-10-04T09:54:51Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.72,52
|
||||||
|
1791107709.062,2026-10-04T09:55:09Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.22,2458
|
||||||
|
1791107722.088,2026-10-04T09:55:22Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,52
|
||||||
|
1791107739.074,2026-10-04T09:55:39Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.53,2484
|
||||||
|
1791107752.656,2026-10-04T09:55:52Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,53
|
||||||
|
1791107769.077,2026-10-04T09:56:09Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.57,2504
|
||||||
|
1791107783.223,2026-10-04T09:56:23Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,54
|
||||||
|
1791107799.209,2026-10-04T09:56:39Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.60,2529
|
||||||
|
1791107813.808,2026-10-04T09:56:53Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,55
|
||||||
|
1791107829.220,2026-10-04T09:57:09Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.54,2552
|
||||||
|
1791107844.371,2026-10-04T09:57:24Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,56
|
||||||
|
1791107859.340,2026-10-04T09:57:39Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.65,2574
|
||||||
|
1791107874.950,2026-10-04T09:57:54Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,57
|
||||||
|
1791107889.398,2026-10-04T09:58:09Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.23,2610
|
||||||
|
1791107905.664,2026-10-04T09:58:25Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.73,59
|
||||||
|
1791107919.428,2026-10-04T09:58:39Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.46,2641
|
||||||
|
1791107936.301,2026-10-04T09:58:56Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,59
|
||||||
|
1791107949.467,2026-10-04T09:59:09Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.42,2673
|
||||||
|
1791107966.933,2026-10-04T09:59:26Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,60
|
||||||
|
1791107979.496,2026-10-04T09:59:39Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.47,2704
|
||||||
|
1791107997.562,2026-10-04T09:59:57Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,60
|
||||||
|
1791108009.509,2026-10-04T10:00:09Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.53,2732
|
||||||
|
1791108028.140,2026-10-04T10:00:28Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,60
|
||||||
|
1791108039.523,2026-10-04T10:00:39Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.53,2756
|
||||||
|
1791108058.717,2026-10-04T10:00:58Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,60
|
||||||
|
1791108069.555,2026-10-04T10:01:09Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.45,2782
|
||||||
|
1791108089.287,2026-10-04T10:01:29Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,60
|
||||||
|
1791108099.603,2026-10-04T10:01:39Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.39,2811
|
||||||
|
1791108119.864,2026-10-04T10:01:59Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,60
|
||||||
|
1791108129.629,2026-10-04T10:02:09Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.47,2836
|
||||||
|
1791108150.448,2026-10-04T10:02:30Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,60
|
||||||
|
1791108159.666,2026-10-04T10:02:39Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.43,2858
|
||||||
|
1791108181.026,2026-10-04T10:03:01Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,61
|
||||||
|
1791108189.688,2026-10-04T10:03:09Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.49,2891
|
||||||
|
1791108211.612,2026-10-04T10:03:31Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,61
|
||||||
|
1791108219.695,2026-10-04T10:03:39Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.99,2908
|
||||||
|
1791108221.787,2026-10-04T10:03:41Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-110308,3.19,0
|
||||||
|
1791108242.181,2026-10-04T10:04:02Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,62
|
||||||
|
1791108249.743,2026-10-04T10:04:09Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.94,2934
|
||||||
|
1791108252.283,2026-10-04T10:04:12Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-110308,3.23,1
|
||||||
|
1791108272.769,2026-10-04T10:04:32Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,62
|
||||||
|
1791108279.761,2026-10-04T10:04:39Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.52,2964
|
||||||
|
1791108282.696,2026-10-04T10:04:42Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-110308,3.52,1
|
||||||
|
1791108303.339,2026-10-04T10:05:03Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.68,62
|
||||||
|
1791108309.806,2026-10-04T10:05:09Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,123.40,2984
|
||||||
|
1791108310.486,2026-10-04T10:05:10Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-110308,0.00,0
|
||||||
|
1791108313.112,2026-10-04T10:05:13Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-110308,3.52,4
|
||||||
|
1791108333.972,2026-10-04T10:05:33Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,1.51,64
|
||||||
|
1791108339.814,2026-10-04T10:05:39Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,124.67,3014
|
||||||
|
1791108343.557,2026-10-04T10:05:43Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-110308,3.51,6
|
||||||
|
1791108358.145,2026-10-04T10:05:58Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-110308,0.00,0
|
||||||
|
1791108364.521,2026-10-04T10:06:04Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.81,64
|
||||||
|
1791108369.902,2026-10-04T10:06:09Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.11,3043
|
||||||
|
1791108373.990,2026-10-04T10:06:13Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-110308,3.51,8
|
||||||
|
1791108395.002,2026-10-04T10:06:35Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,64
|
||||||
|
1791108399.995,2026-10-04T10:06:39Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.09,3068
|
||||||
|
1791108404.446,2026-10-04T10:06:44Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-110308,3.51,8
|
||||||
|
1791108420.479,2026-10-04T10:07:00Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-110308,0.00,0
|
||||||
|
1791108425.478,2026-10-04T10:07:05Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,66
|
||||||
|
1791108430.098,2026-10-04T10:07:10Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.05,3098
|
||||||
|
1791108434.872,2026-10-04T10:07:14Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-110308,3.52,8
|
||||||
|
1791108455.964,2026-10-04T10:07:35Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,66
|
||||||
|
1791108460.179,2026-10-04T10:07:40Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.14,3120
|
||||||
|
1791108465.314,2026-10-04T10:07:45Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-110308,3.51,8
|
||||||
|
1791108485.758,2026-10-04T10:08:05Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-110308,0.00,0
|
||||||
|
1791108486.434,2026-10-04T10:08:06Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,66
|
||||||
|
1791108490.279,2026-10-04T10:08:10Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.06,3140
|
||||||
|
1791108495.707,2026-10-04T10:08:15Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-110308,3.52,8
|
||||||
|
1791108516.916,2026-10-04T10:08:36Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,66
|
||||||
|
1791108520.369,2026-10-04T10:08:40Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.10,3166
|
||||||
|
1791108520.413,2026-10-04T10:08:40Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-110308,0.00,0
|
||||||
|
1791108526.173,2026-10-04T10:08:46Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-110308,3.51,8
|
||||||
|
1791108547.383,2026-10-04T10:09:07Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,66
|
||||||
|
1791108550.495,2026-10-04T10:09:10Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.96,3195
|
||||||
|
1791108556.621,2026-10-04T10:09:16Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-110308,3.51,8
|
||||||
|
1791108577.863,2026-10-04T10:09:37Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,66
|
||||||
|
1791108580.522,2026-10-04T10:09:40Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.80,3214
|
||||||
|
1791108608.333,2026-10-04T10:10:08Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,67
|
||||||
|
1791108610.648,2026-10-04T10:10:10Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.51,3237
|
||||||
|
1791108638.810,2026-10-04T10:10:38Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,68
|
||||||
|
1791108640.647,2026-10-04T10:10:40Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.35,3257
|
||||||
|
1791108669.302,2026-10-04T10:11:09Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,69
|
||||||
|
1791108670.665,2026-10-04T10:11:10Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.39,3287
|
||||||
|
1791108699.770,2026-10-04T10:11:39Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,70
|
||||||
|
1791108700.757,2026-10-04T10:11:40Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.09,3317
|
||||||
|
1791108730.251,2026-10-04T10:12:10Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,71
|
||||||
|
1791108730.837,2026-10-04T10:12:10Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.14,3341
|
||||||
|
1791108760.853,2026-10-04T10:12:40Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,119.05,3367
|
||||||
|
1791108760.877,2026-10-04T10:12:40Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.81,72
|
||||||
|
1791108767.367,2026-10-04T10:12:47Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,122.03,22
|
||||||
|
1791108767.893,2026-10-04T10:12:47Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.20,0
|
||||||
|
1791108790.955,2026-10-04T10:13:10Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.61,3385
|
||||||
|
1791108791.371,2026-10-04T10:13:11Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,72
|
||||||
|
1791108797.425,2026-10-04T10:13:17Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,124.47,44
|
||||||
|
1791108797.912,2026-10-04T10:13:17Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.35,1
|
||||||
|
1791108821.062,2026-10-04T10:13:41Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.59,3414
|
||||||
|
1791108821.858,2026-10-04T10:13:41Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,73
|
||||||
|
1791108827.433,2026-10-04T10:13:47Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,124.68,58
|
||||||
|
1791108828.522,2026-10-04T10:13:48Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.36,2
|
||||||
|
1791108851.081,2026-10-04T10:14:11Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.39,3433
|
||||||
|
1791108852.357,2026-10-04T10:14:12Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,74
|
||||||
|
1791108857.561,2026-10-04T10:14:17Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,124.74,74
|
||||||
|
1791108859.085,2026-10-04T10:14:19Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.36,2
|
||||||
|
1791108881.114,2026-10-04T10:14:41Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.89,3456
|
||||||
|
1791108882.842,2026-10-04T10:14:42Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,74
|
||||||
|
1791108887.571,2026-10-04T10:14:47Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,124.67,88
|
||||||
|
1791108889.112,2026-10-04T10:14:49Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.35,3
|
||||||
|
1791108911.216,2026-10-04T10:15:11Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.61,3467
|
||||||
|
1791108913.324,2026-10-04T10:15:13Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,74
|
||||||
|
1791108917.626,2026-10-04T10:15:17Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,124.48,100
|
||||||
|
1791108919.711,2026-10-04T10:15:19Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.36,3
|
||||||
|
1791108941.319,2026-10-04T10:15:41Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.61,3484
|
||||||
|
1791108943.818,2026-10-04T10:15:43Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,74
|
||||||
|
1791108947.687,2026-10-04T10:15:47Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,124.46,111
|
||||||
|
1791108949.777,2026-10-04T10:15:49Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.35,3
|
||||||
|
1791108971.421,2026-10-04T10:16:11Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.61,3492
|
||||||
|
1791108974.294,2026-10-04T10:16:14Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,74
|
||||||
|
1791108977.738,2026-10-04T10:16:17Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,124.54,128
|
||||||
|
1791108980.370,2026-10-04T10:16:20Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.36,3
|
||||||
|
1791109001.519,2026-10-04T10:16:41Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.63,3507
|
||||||
|
1791109004.799,2026-10-04T10:16:44Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,74
|
||||||
|
1791109007.813,2026-10-04T10:16:47Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,124.44,143
|
||||||
|
1791109010.741,2026-10-04T10:16:50Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.31,3
|
||||||
|
1791109031.601,2026-10-04T10:17:11Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.69,3518
|
||||||
|
1791109035.282,2026-10-04T10:17:15Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,75
|
||||||
|
1791109037.950,2026-10-04T10:17:17Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,123.59,157
|
||||||
|
1791109040.971,2026-10-04T10:17:20Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.26,4
|
||||||
|
1791109061.714,2026-10-04T10:17:41Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.56,3537
|
||||||
|
1791109065.784,2026-10-04T10:17:45Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,75
|
||||||
|
1791109068.002,2026-10-04T10:17:48Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,120.59,166
|
||||||
|
1791109071.598,2026-10-04T10:17:51Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.22,4
|
||||||
|
1791109091.828,2026-10-04T10:18:11Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.56,3549
|
||||||
|
1791109096.263,2026-10-04T10:18:16Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,76
|
||||||
|
1791109098.025,2026-10-04T10:18:18Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,121.87,174
|
||||||
|
1791109102.105,2026-10-04T10:18:22Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.30,4
|
||||||
|
1791109121.933,2026-10-04T10:18:41Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.60,3560
|
||||||
|
1791109126.757,2026-10-04T10:18:46Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,76
|
||||||
|
1791109128.131,2026-10-04T10:18:48Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,121.48,186
|
||||||
|
1791109132.707,2026-10-04T10:18:52Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.08,4
|
||||||
|
1791109152.033,2026-10-04T10:19:12Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.62,3573
|
||||||
|
1791109157.240,2026-10-04T10:19:17Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,76
|
||||||
|
1791109158.146,2026-10-04T10:19:18Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,123.53,202
|
||||||
|
1791109162.839,2026-10-04T10:19:22Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.27,4
|
||||||
|
1791109182.124,2026-10-04T10:19:42Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.66,3589
|
||||||
|
1791109187.737,2026-10-04T10:19:47Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,76
|
||||||
|
1791109188.172,2026-10-04T10:19:48Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,123.49,212
|
||||||
|
1791109192.870,2026-10-04T10:19:52Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.28,5
|
||||||
|
1791109212.241,2026-10-04T10:20:12Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.55,3602
|
||||||
|
1791109218.215,2026-10-04T10:20:18Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,123.98,228
|
||||||
|
1791109218.217,2026-10-04T10:20:18Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,78
|
||||||
|
1791109223.467,2026-10-04T10:20:23Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.29,7
|
||||||
|
1791109242.353,2026-10-04T10:20:42Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.57,3619
|
||||||
|
1791109248.281,2026-10-04T10:20:48Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,124.44,242
|
||||||
|
1791109248.712,2026-10-04T10:20:48Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,78
|
||||||
|
1791109253.806,2026-10-04T10:20:53Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.32,8
|
||||||
|
1791109272.428,2026-10-04T10:21:12Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.72,3628
|
||||||
|
1791109278.371,2026-10-04T10:21:18Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,124.35,254
|
||||||
|
1791109279.193,2026-10-04T10:21:19Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,78
|
||||||
|
1791109284.152,2026-10-04T10:21:24Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.32,8
|
||||||
|
1791109302.555,2026-10-04T10:21:42Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.51,3635
|
||||||
|
1791109308.498,2026-10-04T10:21:48Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,124.19,266
|
||||||
|
1791109309.673,2026-10-04T10:21:49Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,78
|
||||||
|
1791109314.287,2026-10-04T10:21:54Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-111214,3.27,8
|
||||||
|
1791109332.569,2026-10-04T10:22:12Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,116.27,3653
|
||||||
|
1791109338.514,2026-10-04T10:22:18Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,125.20,282
|
||||||
|
1791109340.298,2026-10-04T10:22:20Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.81,79
|
||||||
|
1791109362.571,2026-10-04T10:22:42Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,116.87,3672
|
||||||
|
1791109368.646,2026-10-04T10:22:48Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,126.95,292
|
||||||
|
1791109370.865,2026-10-04T10:22:50Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.81,79
|
||||||
|
1791109392.634,2026-10-04T10:23:12Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.65,3689
|
||||||
|
1791109398.767,2026-10-04T10:23:18Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,126.99,303
|
||||||
|
1791109401.362,2026-10-04T10:23:21Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,79
|
||||||
|
1791109422.690,2026-10-04T10:23:42Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.68,3699
|
||||||
|
1791109428.774,2026-10-04T10:23:48Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,126.92,320
|
||||||
|
1791109431.847,2026-10-04T10:23:51Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,79
|
||||||
|
1791109452.694,2026-10-04T10:24:12Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.90,3712
|
||||||
|
1791109458.894,2026-10-04T10:24:18Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,126.44,336
|
||||||
|
1791109462.343,2026-10-04T10:24:22Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,79
|
||||||
|
1791109482.732,2026-10-04T10:24:42Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.76,3730
|
||||||
|
1791109488.987,2026-10-04T10:24:48Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,126.55,353
|
||||||
|
1791109492.831,2026-10-04T10:24:52Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,79
|
||||||
|
1791109512.760,2026-10-04T10:25:12Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.79,3744
|
||||||
|
1791109519.015,2026-10-04T10:25:19Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,126.27,367
|
||||||
|
1791109523.323,2026-10-04T10:25:23Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,79
|
||||||
|
1791109542.777,2026-10-04T10:25:42Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.84,3761
|
||||||
|
1791109549.050,2026-10-04T10:25:49Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,126.24,387
|
||||||
|
1791109553.799,2026-10-04T10:25:53Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,79
|
||||||
|
1791109572.812,2026-10-04T10:26:12Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.77,3780
|
||||||
|
1791109579.051,2026-10-04T10:26:19Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,126.38,397
|
||||||
|
1791109584.302,2026-10-04T10:26:24Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,79
|
||||||
|
1791109602.827,2026-10-04T10:26:42Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.85,3798
|
||||||
|
1791109609.169,2026-10-04T10:26:49Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,127.02,411
|
||||||
|
1791109614.796,2026-10-04T10:26:54Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,80
|
||||||
|
1791109632.977,2026-10-04T10:27:12Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.17,3818
|
||||||
|
1791109639.288,2026-10-04T10:27:19Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,127.01,419
|
||||||
|
1791109645.284,2026-10-04T10:27:25Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,80
|
||||||
|
1791109662.994,2026-10-04T10:27:42Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.84,3829
|
||||||
|
1791109669.398,2026-10-04T10:27:49Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,127.05,438
|
||||||
|
1791109675.779,2026-10-04T10:27:55Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,80
|
||||||
|
1791109693.019,2026-10-04T10:28:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.81,3849
|
||||||
|
1791109699.524,2026-10-04T10:28:19Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,126.98,454
|
||||||
|
1791109706.257,2026-10-04T10:28:26Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,80
|
||||||
|
1791109723.040,2026-10-04T10:28:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.83,3861
|
||||||
|
1791109729.651,2026-10-04T10:28:49Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,126.99,467
|
||||||
|
1791109736.745,2026-10-04T10:28:56Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,80
|
||||||
|
1791109753.086,2026-10-04T10:29:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.72,3872
|
||||||
|
1791109759.756,2026-10-04T10:29:19Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,127.06,479
|
||||||
|
1791109767.265,2026-10-04T10:29:27Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,81
|
||||||
|
1791109783.131,2026-10-04T10:29:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.73,3885
|
||||||
|
1791109789.868,2026-10-04T10:29:49Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,127.03,486
|
||||||
|
1791109797.766,2026-10-04T10:29:57Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,81
|
||||||
|
1791109813.173,2026-10-04T10:30:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.74,3910
|
||||||
|
1791109820.350,2026-10-04T10:30:20Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,127.16,503
|
||||||
|
1791109828.249,2026-10-04T10:30:28Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,82
|
||||||
|
1791109843.189,2026-10-04T10:30:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.84,3918
|
||||||
|
1791109850.387,2026-10-04T10:30:50Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,126.79,524
|
||||||
|
1791109858.741,2026-10-04T10:30:58Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,83
|
||||||
|
1791109873.243,2026-10-04T10:31:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.69,3937
|
||||||
|
1791109880.418,2026-10-04T10:31:20Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-111214,127.38,538
|
||||||
|
1791109889.222,2026-10-04T10:31:29Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,84
|
||||||
|
1791109903.276,2026-10-04T10:31:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.78,3958
|
||||||
|
1791109919.722,2026-10-04T10:31:59Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,85
|
||||||
|
1791109933.314,2026-10-04T10:32:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.20,3966
|
||||||
|
1791109950.202,2026-10-04T10:32:30Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,85
|
||||||
|
1791109963.316,2026-10-04T10:32:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.46,3981
|
||||||
|
1791109980.693,2026-10-04T10:33:00Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,87
|
||||||
|
1791109993.346,2026-10-04T10:33:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.79,3992
|
||||||
|
1791110011.171,2026-10-04T10:33:31Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,88
|
||||||
|
1791110023.371,2026-10-04T10:33:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.81,4005
|
||||||
|
1791110041.660,2026-10-04T10:34:01Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,88
|
||||||
|
1791110053.388,2026-10-04T10:34:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.84,4022
|
||||||
|
1791110072.150,2026-10-04T10:34:32Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,88
|
||||||
|
1791110083.405,2026-10-04T10:34:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.84,4043
|
||||||
|
1791110102.643,2026-10-04T10:35:02Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,88
|
||||||
|
1791110113.414,2026-10-04T10:35:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.87,4067
|
||||||
|
1791110133.123,2026-10-04T10:35:33Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,88
|
||||||
|
1791110143.458,2026-10-04T10:35:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.73,4096
|
||||||
|
1791110149.673,2026-10-04T10:35:49Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,121.60,22
|
||||||
|
1791110150.551,2026-10-04T10:35:50Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.17,0
|
||||||
|
1791110163.610,2026-10-04T10:36:03Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.75,89
|
||||||
|
1791110173.467,2026-10-04T10:36:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.87,4122
|
||||||
|
1791110179.710,2026-10-04T10:36:19Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.56,42
|
||||||
|
1791110180.600,2026-10-04T10:36:20Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,0
|
||||||
|
1791110194.098,2026-10-04T10:36:34Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.89,91
|
||||||
|
1791110203.507,2026-10-04T10:36:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.75,4150
|
||||||
|
1791110209.734,2026-10-04T10:36:49Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.61,52
|
||||||
|
1791110211.202,2026-10-04T10:36:51Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,0
|
||||||
|
1791110224.578,2026-10-04T10:37:04Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,91
|
||||||
|
1791110233.536,2026-10-04T10:37:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.80,4161
|
||||||
|
1791110239.750,2026-10-04T10:37:19Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.65,62
|
||||||
|
1791110241.778,2026-10-04T10:37:21Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,0
|
||||||
|
1791110255.073,2026-10-04T10:37:35Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,91
|
||||||
|
1791110263.548,2026-10-04T10:37:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.86,4173
|
||||||
|
1791110269.777,2026-10-04T10:37:49Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.60,77
|
||||||
|
1791110271.831,2026-10-04T10:37:51Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,0
|
||||||
|
1791110285.553,2026-10-04T10:38:05Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,91
|
||||||
|
1791110293.574,2026-10-04T10:38:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.81,4190
|
||||||
|
1791110299.797,2026-10-04T10:38:19Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.63,87
|
||||||
|
1791110302.402,2026-10-04T10:38:22Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,1
|
||||||
|
1791110316.051,2026-10-04T10:38:36Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,92
|
||||||
|
1791110323.590,2026-10-04T10:38:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.85,4202
|
||||||
|
1791110329.826,2026-10-04T10:38:49Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.59,103
|
||||||
|
1791110332.454,2026-10-04T10:38:52Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,1
|
||||||
|
1791110346.528,2026-10-04T10:39:06Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,93
|
||||||
|
1791110353.629,2026-10-04T10:39:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.75,4221
|
||||||
|
1791110359.839,2026-10-04T10:39:19Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.65,124
|
||||||
|
1791110363.035,2026-10-04T10:39:23Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,1
|
||||||
|
1791110377.028,2026-10-04T10:39:37Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,93
|
||||||
|
1791110383.631,2026-10-04T10:39:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.90,4237
|
||||||
|
1791110389.884,2026-10-04T10:39:49Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.53,139
|
||||||
|
1791110393.086,2026-10-04T10:39:53Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,1
|
||||||
|
1791110407.516,2026-10-04T10:40:07Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,93
|
||||||
|
1791110413.658,2026-10-04T10:40:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.80,4248
|
||||||
|
1791110419.931,2026-10-04T10:40:19Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.52,157
|
||||||
|
1791110423.718,2026-10-04T10:40:23Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,1
|
||||||
|
1791110438.005,2026-10-04T10:40:38Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,94
|
||||||
|
1791110443.679,2026-10-04T10:40:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.83,4263
|
||||||
|
1791110449.977,2026-10-04T10:40:49Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.52,177
|
||||||
|
1791110453.785,2026-10-04T10:40:53Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,1
|
||||||
|
1791110468.490,2026-10-04T10:41:08Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,94
|
||||||
|
1791110473.729,2026-10-04T10:41:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.71,4286
|
||||||
|
1791110479.996,2026-10-04T10:41:19Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.64,185
|
||||||
|
1791110484.363,2026-10-04T10:41:24Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,2
|
||||||
|
1791110498.979,2026-10-04T10:41:38Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,95
|
||||||
|
1791110503.764,2026-10-04T10:41:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.77,4299
|
||||||
|
1791110510.020,2026-10-04T10:41:50Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.61,202
|
||||||
|
1791110514.415,2026-10-04T10:41:54Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.28,2
|
||||||
|
1791110529.471,2026-10-04T10:42:09Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,95
|
||||||
|
1791110533.790,2026-10-04T10:42:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.80,4313
|
||||||
|
1791110540.039,2026-10-04T10:42:20Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.07,217
|
||||||
|
1791110544.996,2026-10-04T10:42:24Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.43,4
|
||||||
|
1791110559.954,2026-10-04T10:42:39Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,95
|
||||||
|
1791110563.816,2026-10-04T10:42:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.81,4328
|
||||||
|
1791110570.079,2026-10-04T10:42:50Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,125.10,237
|
||||||
|
1791110575.060,2026-10-04T10:42:55Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,6
|
||||||
|
1791110590.447,2026-10-04T10:43:10Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,95
|
||||||
|
1791110593.830,2026-10-04T10:43:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.85,4341
|
||||||
|
1791110600.142,2026-10-04T10:43:20Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.45,251
|
||||||
|
1791110605.649,2026-10-04T10:43:25Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,7
|
||||||
|
1791110620.930,2026-10-04T10:43:40Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,95
|
||||||
|
1791110623.888,2026-10-04T10:43:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.68,4352
|
||||||
|
1791110630.162,2026-10-04T10:43:50Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.63,267
|
||||||
|
1791110636.294,2026-10-04T10:43:56Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,7
|
||||||
|
1791110651.429,2026-10-04T10:44:11Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,96
|
||||||
|
1791110653.908,2026-10-04T10:44:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.83,4371
|
||||||
|
1791110660.192,2026-10-04T10:44:20Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.59,285
|
||||||
|
1791110666.899,2026-10-04T10:44:26Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,7
|
||||||
|
1791110681.903,2026-10-04T10:44:41Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,96
|
||||||
|
1791110683.942,2026-10-04T10:44:43Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.77,4388
|
||||||
|
1791110690.221,2026-10-04T10:44:50Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.59,301
|
||||||
|
1791110697.472,2026-10-04T10:44:57Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,8
|
||||||
|
1791110712.405,2026-10-04T10:45:12Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,96
|
||||||
|
1791110713.956,2026-10-04T10:45:13Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.85,4403
|
||||||
|
1791110720.262,2026-10-04T10:45:20Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.54,310
|
||||||
|
1791110727.534,2026-10-04T10:45:27Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,8
|
||||||
|
1791110742.892,2026-10-04T10:45:42Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,97
|
||||||
|
1791110744.014,2026-10-04T10:45:44Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.68,4423
|
||||||
|
1791110750.404,2026-10-04T10:45:50Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.72,322
|
||||||
|
1791110758.111,2026-10-04T10:45:58Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,8
|
||||||
|
1791110773.381,2026-10-04T10:46:13Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,97
|
||||||
|
1791110774.046,2026-10-04T10:46:14Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.78,4436
|
||||||
|
1791110780.445,2026-10-04T10:46:20Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.54,337
|
||||||
|
1791110788.173,2026-10-04T10:46:28Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,9
|
||||||
|
1791110803.860,2026-10-04T10:46:43Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,97
|
||||||
|
1791110804.096,2026-10-04T10:46:44Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.71,4456
|
||||||
|
1791110810.457,2026-10-04T10:46:50Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.66,348
|
||||||
|
1791110818.745,2026-10-04T10:46:58Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,10
|
||||||
|
1791110834.117,2026-10-04T10:47:14Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.83,4472
|
||||||
|
1791110834.348,2026-10-04T10:47:14Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,97
|
||||||
|
1791110840.493,2026-10-04T10:47:20Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.56,363
|
||||||
|
1791110848.802,2026-10-04T10:47:28Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,10
|
||||||
|
1791110864.169,2026-10-04T10:47:44Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.70,4492
|
||||||
|
1791110864.827,2026-10-04T10:47:44Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,98
|
||||||
|
1791110870.507,2026-10-04T10:47:50Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.66,380
|
||||||
|
1791110879.373,2026-10-04T10:47:59Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,10
|
||||||
|
1791110894.197,2026-10-04T10:48:14Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.80,4507
|
||||||
|
1791110895.321,2026-10-04T10:48:15Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,98
|
||||||
|
1791110900.539,2026-10-04T10:48:20Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.58,394
|
||||||
|
1791110909.432,2026-10-04T10:48:29Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,11
|
||||||
|
1791110924.230,2026-10-04T10:48:44Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.78,4527
|
||||||
|
1791110925.810,2026-10-04T10:48:45Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,98
|
||||||
|
1791110930.565,2026-10-04T10:48:50Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.60,417
|
||||||
|
1791110940.007,2026-10-04T10:49:00Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,11
|
||||||
|
1791110954.247,2026-10-04T10:49:14Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.84,4541
|
||||||
|
1791110956.291,2026-10-04T10:49:16Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,99
|
||||||
|
1791110960.588,2026-10-04T10:49:20Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.62,433
|
||||||
|
1791110970.070,2026-10-04T10:49:30Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,13
|
||||||
|
1791110984.250,2026-10-04T10:49:44Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.90,4557
|
||||||
|
1791110986.789,2026-10-04T10:49:46Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,99
|
||||||
|
1791110990.617,2026-10-04T10:49:50Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.59,448
|
||||||
|
1791111000.643,2026-10-04T10:50:00Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,13
|
||||||
|
1791111014.300,2026-10-04T10:50:14Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.71,4576
|
||||||
|
1791111017.272,2026-10-04T10:50:17Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,99
|
||||||
|
1791111020.629,2026-10-04T10:50:20Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.66,460
|
||||||
|
1791111030.701,2026-10-04T10:50:30Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,13
|
||||||
|
1791111044.303,2026-10-04T10:50:44Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.90,4589
|
||||||
|
1791111047.768,2026-10-04T10:50:47Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,99
|
||||||
|
1791111050.657,2026-10-04T10:50:50Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.04,478
|
||||||
|
1791111061.275,2026-10-04T10:51:01Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,13
|
||||||
|
1791111074.366,2026-10-04T10:51:14Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.66,4610
|
||||||
|
1791111078.247,2026-10-04T10:51:18Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,99
|
||||||
|
1791111080.685,2026-10-04T10:51:20Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,125.15,504
|
||||||
|
1791111091.889,2026-10-04T10:51:31Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,14
|
||||||
|
1791111104.369,2026-10-04T10:51:44Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.90,4619
|
||||||
|
1791111108.735,2026-10-04T10:51:48Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,99
|
||||||
|
1791111110.726,2026-10-04T10:51:50Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.54,516
|
||||||
|
1791111121.917,2026-10-04T10:52:01Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,15
|
||||||
|
1791111134.402,2026-10-04T10:52:14Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.78,4632
|
||||||
|
1791111139.214,2026-10-04T10:52:19Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,99
|
||||||
|
1791111140.774,2026-10-04T10:52:20Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.55,525
|
||||||
|
1791111152.516,2026-10-04T10:52:32Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,16
|
||||||
|
1791111164.405,2026-10-04T10:52:44Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.90,4641
|
||||||
|
1791111169.695,2026-10-04T10:52:49Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,100
|
||||||
|
1791111170.874,2026-10-04T10:52:50Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.30,531
|
||||||
|
1791111182.596,2026-10-04T10:53:02Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,16
|
||||||
|
1791111194.538,2026-10-04T10:53:14Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.93,4655
|
||||||
|
1791111200.175,2026-10-04T10:53:20Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,100
|
||||||
|
1791111200.970,2026-10-04T10:53:20Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,123.20,541
|
||||||
|
1791111213.150,2026-10-04T10:53:33Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.30,18
|
||||||
|
1791111224.886,2026-10-04T10:53:44Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.40,4668
|
||||||
|
1791111230.653,2026-10-04T10:53:50Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,102
|
||||||
|
1791111231.028,2026-10-04T10:53:51Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.47,550
|
||||||
|
1791111243.214,2026-10-04T10:54:03Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,18
|
||||||
|
1791111254.889,2026-10-04T10:54:14Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.90,4686
|
||||||
|
1791111261.060,2026-10-04T10:54:21Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.58,564
|
||||||
|
1791111261.143,2026-10-04T10:54:21Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,103
|
||||||
|
1791111273.798,2026-10-04T10:54:33Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.36,18
|
||||||
|
1791111284.978,2026-10-04T10:54:44Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,120.43,4699
|
||||||
|
1791111291.096,2026-10-04T10:54:51Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.56,583
|
||||||
|
1791111291.803,2026-10-04T10:54:51Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.74,103
|
||||||
|
1791111303.857,2026-10-04T10:55:03Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,18
|
||||||
|
1791111314.992,2026-10-04T10:55:14Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.85,4717
|
||||||
|
1791111321.139,2026-10-04T10:55:21Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.53,591
|
||||||
|
1791111322.357,2026-10-04T10:55:22Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.88,104
|
||||||
|
1791111333.872,2026-10-04T10:55:33Z,PC2-amd,mac-node,amd-DESKTOP-KMCV30N-20261004-113517,3.35,18
|
||||||
|
1791111345.019,2026-10-04T10:55:45Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.80,4733
|
||||||
|
1791111351.170,2026-10-04T10:55:51Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.58,609
|
||||||
|
1791111352.889,2026-10-04T10:55:52Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,105
|
||||||
|
1791111375.044,2026-10-04T10:56:15Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.81,4742
|
||||||
|
1791111381.200,2026-10-04T10:56:21Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.59,617
|
||||||
|
1791111383.436,2026-10-04T10:56:23Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.81,105
|
||||||
|
1791111405.077,2026-10-04T10:56:45Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.78,4759
|
||||||
|
1791111411.226,2026-10-04T10:56:51Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.61,635
|
||||||
|
1791111413.918,2026-10-04T10:56:53Z,PC1-amd,pc-node,amd-DESKTOP-KMCV30N-20261004-101053,2.82,105
|
||||||
|
1791111435.110,2026-10-04T10:57:15Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.78,4775
|
||||||
|
1791111441.256,2026-10-04T10:57:21Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.59,655
|
||||||
|
1791111465.219,2026-10-04T10:57:45Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,122.03,4790
|
||||||
|
1791111471.288,2026-10-04T10:57:51Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.58,669
|
||||||
|
1791111495.263,2026-10-04T10:58:15Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.74,4796
|
||||||
|
1791111501.340,2026-10-04T10:58:21Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.49,684
|
||||||
|
1791111525.276,2026-10-04T10:58:45Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.86,4810
|
||||||
|
1791111531.360,2026-10-04T10:58:51Z,PC2-nvidia,mac-node,nvidia-DESKTOP-KMCV30N-20261004-113517,124.63,697
|
||||||
|
1791111555.318,2026-10-04T10:59:15Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.74,4821
|
||||||
|
1791111585.357,2026-10-04T10:59:45Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.75,4835
|
||||||
|
1791111615.406,2026-10-04T11:00:15Z,PC1-nvidia,pc-node,nvidia-DESKTOP-KMCV30N-20261004-101053,121.72,4851
|
||||||
|
8091
sim/difficulty/records/live-2026-10-04.csv
Normal file
8091
sim/difficulty/records/live-2026-10-04.csv
Normal file
File diff suppressed because it is too large
Load diff
74
sim/difficulty/records/pull_live.py
Normal file
74
sim/difficulty/records/pull_live.py
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Export every header of the live devnet from the observer node's read-only wRPC JSON endpoint.
|
||||||
|
|
||||||
|
python3 pull_live.py [ws://127.0.0.1:28640] [out.csv]
|
||||||
|
|
||||||
|
Columns: hash, daa_score, blue_score, timestamp_ms, bits, difficulty (the node's 2^255 / target convention),
|
||||||
|
target_log2, epoch (3,600 DAA), is_chain_block, parents, selected_parent, blue_work (hex), mergeset_blues,
|
||||||
|
mergeset_reds, vote_key_hash. Read only: getBlockDagInfo and getBlocks from the pruning point, nothing else.
|
||||||
|
"""
|
||||||
|
import asyncio
|
||||||
|
import csv
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
async def rpc(url, method, params=None):
|
||||||
|
import websockets
|
||||||
|
async with websockets.connect(url, max_size=None) as ws:
|
||||||
|
await ws.send(json.dumps({"id": 1, "method": method, "params": params or {}}))
|
||||||
|
m = json.loads(await ws.recv())
|
||||||
|
if m.get("error"):
|
||||||
|
raise RuntimeError(m["error"])
|
||||||
|
return m["params"]
|
||||||
|
|
||||||
|
|
||||||
|
def bits_to_target(bits):
|
||||||
|
exp = bits >> 24
|
||||||
|
mant = bits & 0x7FFFFF
|
||||||
|
return mant >> (8 * (3 - exp)) if exp <= 3 else mant << (8 * (exp - 3))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
url = sys.argv[1] if len(sys.argv) > 1 else "ws://127.0.0.1:28640"
|
||||||
|
out = sys.argv[2] if len(sys.argv) > 2 else "live-2026-10-04.csv"
|
||||||
|
info = asyncio.run(rpc(url, "getBlockDagInfo"))
|
||||||
|
low = info["pruningPointHash"]
|
||||||
|
seen = set()
|
||||||
|
rows = []
|
||||||
|
while True:
|
||||||
|
r = asyncio.run(rpc(url, "getBlocks", {"lowHash": low, "includeBlocks": True, "includeTransactions": False}))
|
||||||
|
blocks = r.get("blocks") or []
|
||||||
|
new = 0
|
||||||
|
for b in blocks:
|
||||||
|
h = b["header"]
|
||||||
|
v = b.get("verboseData") or {}
|
||||||
|
hs = h.get("hash") or v.get("hash")
|
||||||
|
if hs in seen:
|
||||||
|
continue
|
||||||
|
seen.add(hs)
|
||||||
|
new += 1
|
||||||
|
bits = int(h["bits"])
|
||||||
|
target = bits_to_target(bits)
|
||||||
|
rows.append({
|
||||||
|
"hash": hs, "daa_score": h["daaScore"], "blue_score": h["blueScore"], "timestamp_ms": h["timestamp"],
|
||||||
|
"bits": "0x%08x" % bits, "difficulty": v.get("difficulty"), "target_log2": "%.3f" % math.log2(target) if target else "",
|
||||||
|
"epoch": int(h["daaScore"]) // 3600, "is_chain_block": 1 if v.get("isChainBlock") else 0,
|
||||||
|
"parents": len((h.get("parentsByLevel") or [[]])[0]), "selected_parent": v.get("selectedParentHash"),
|
||||||
|
"blue_work": h.get("blueWork"), "mergeset_blues": len(v.get("mergeSetBluesHashes") or []),
|
||||||
|
"mergeset_reds": len(v.get("mergeSetRedsHashes") or []), "vote_key_hash": h.get("voteKeyHash"),
|
||||||
|
})
|
||||||
|
if not blocks or new == 0 or len(blocks) < 2:
|
||||||
|
break
|
||||||
|
low = blocks[-1]["header"].get("hash") or blocks[-1]["verboseData"]["hash"]
|
||||||
|
rows.sort(key=lambda r: (int(r["blue_score"]), int(r["daa_score"]), int(r["timestamp_ms"])))
|
||||||
|
with open(out, "w", newline="") as f:
|
||||||
|
w = csv.DictWriter(f, fieldnames=list(rows[0].keys()))
|
||||||
|
w.writeheader()
|
||||||
|
w.writerows(rows)
|
||||||
|
print("wrote %d headers to %s (sink daa %s, difficulty %s)" % (len(rows), out, info.get("virtualDaaScore"), info.get("difficulty")))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
1473
sim/difficulty/records/testnet-v2-2026-10-04.csv
Normal file
1473
sim/difficulty/records/testnet-v2-2026-10-04.csv
Normal file
File diff suppressed because it is too large
Load diff
52
sim/difficulty/records/testnet-v2-2026-10-04.schedule.log
Normal file
52
sim/difficulty/records/testnet-v2-2026-10-04.schedule.log
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
12:30:45 start minutes=28 join=4 leave=19 rejoin=23 activation=900 genesis_bits=0x1f010000 bin=/Users/joshm/Projects/igneum/vendor/igneum-node-v4/target/release
|
||||||
|
12:30:45 node1 pid 54771 gRPC 29600 override override-v2.json
|
||||||
|
12:30:46 node2 pid 54782 gRPC 29610 override override-v2.json
|
||||||
|
12:30:46 node3 pid 54783 gRPC 29620 override override-v1.json
|
||||||
|
12:30:49 miners from now
|
||||||
|
12:30:49 miner A pid 54849 on 29600 threads 4 for 1680 s
|
||||||
|
12:34:50 miner B pid 58591 on 29610 threads 4 for 900 s
|
||||||
|
12:34:50 B joins (2x step under rule v1)
|
||||||
|
12:47:52 node1 virtual DAA 900 reached the activation 900 at 1022 s; node3 (v1) at DAA 900
|
||||||
|
12:49:50 stopped miner B (leave) pid 58591 code -15
|
||||||
|
12:49:50 B leaves (step down under rule v2)
|
||||||
|
12:53:50 miner B pid 64718 on 29610 threads 4 for 304 s
|
||||||
|
12:53:50 B rejoins (step up under rule v2)
|
||||||
|
14:16:34 stopped miner B pid 64718 code -15
|
||||||
|
14:16:34 stopped miner A pid 54849 code -15
|
||||||
|
14:17:01 node1: {"blockCount": 1471, "difficulty": 8953.4444361059, "virtualDaaScore": 1471, "sink": "b5f9cd2e2d1968244207706d666b59ba7d1057798dd88ce5129a14dc48805970"}, 1472 rows
|
||||||
|
14:17:06 node2: {"blockCount": 1471, "difficulty": 8953.4444361059, "virtualDaaScore": 1471, "sink": "b5f9cd2e2d1968244207706d666b59ba7d1057798dd88ce5129a14dc48805970"}, 1472 rows
|
||||||
|
14:17:08 node3: {"blockCount": 900, "difficulty": 6854.509800667103, "virtualDaaScore": 900, "sink": "ff708e8a14c14ffd15d9913ac75fe4b745bc5087c29576606d5d1b0e672315fe"}, 901 rows
|
||||||
|
14:17:08 stopped pid pid 64718 code -15
|
||||||
|
14:17:08 stopped pid pid 58591 code -15
|
||||||
|
14:17:08 stopped pid pid 54849 code -15
|
||||||
|
14:17:09 stopped pid pid 54783 code 0
|
||||||
|
14:17:09 stopped pid pid 54782 code 0
|
||||||
|
14:17:10 stopped pid pid 54771 code 0
|
||||||
|
14:17:10 end
|
||||||
|
12:30:49 t=0 s daa node1/2/3 0/0/0 difficulty 32768 blocks 0
|
||||||
|
12:31:50 t=61 s daa node1/2/3 56/56/56 difficulty 13092 blocks 56
|
||||||
|
12:32:50 t=120 s daa node1/2/3 108/108/108 difficulty 11607 blocks 108
|
||||||
|
12:33:50 t=181 s daa node1/2/3 160/160/160 difficulty 8268 blocks 160
|
||||||
|
12:34:50 t=241 s daa node1/2/3 209/209/209 difficulty 7953 blocks 209
|
||||||
|
12:35:50 t=301 s daa node1/2/3 262/262/262 difficulty 7805 blocks 262
|
||||||
|
12:36:50 t=360 s daa node1/2/3 310/310/310 difficulty 7588 blocks 310
|
||||||
|
12:37:50 t=421 s daa node1/2/3 352/352/352 difficulty 7310 blocks 352
|
||||||
|
12:38:50 t=480 s daa node1/2/3 389/389/389 difficulty 4614 blocks 389
|
||||||
|
12:39:50 t=541 s daa node1/2/3 448/448/448 difficulty 4113 blocks 448
|
||||||
|
12:40:50 t=601 s daa node1/2/3 524/524/524 difficulty 6548 blocks 524
|
||||||
|
12:42:50 t=720 s daa node1/2/3 644/644/644 difficulty 7226 blocks 644
|
||||||
|
12:43:50 t=780 s daa node1/2/3 692/692/692 difficulty 7103 blocks 692
|
||||||
|
12:44:50 t=841 s daa node1/2/3 752/752/752 difficulty 7105 blocks 752
|
||||||
|
12:45:50 t=901 s daa node1/2/3 810/810/810 difficulty 7101 blocks 810
|
||||||
|
12:46:50 t=961 s daa node1/2/3 855/855/855 difficulty 7020 blocks 855
|
||||||
|
12:47:50 t=1020 s daa node1/2/3 899/899/899 difficulty 6861 blocks 899
|
||||||
|
12:48:50 t=1081 s daa node1/2/3 980/980/900 difficulty 6130 blocks 980
|
||||||
|
12:49:50 t=1140 s daa node1/2/3 1050/1050/900 difficulty 6545 blocks 1050
|
||||||
|
12:50:50 t=1200 s daa node1/2/3 1098/1098/900 difficulty 6501 blocks 1098
|
||||||
|
12:51:50 t=1261 s daa node1/2/3 1146/1146/900 difficulty 6266 blocks 1146
|
||||||
|
12:52:50 t=1320 s daa node1/2/3 1193/1193/900 difficulty 6005 blocks 1193
|
||||||
|
12:54:20 t=1411 s daa node1/2/3 1298/1298/900 difficulty 6231 blocks 1298
|
||||||
|
12:55:19 t=1470 s daa node1/2/3 1369/1369/900 difficulty 8571 blocks 1369
|
||||||
|
12:56:20 t=1531 s daa node1/2/3 1427/1427/900 difficulty 8423 blocks 1427
|
||||||
|
1563:2026-10-04 12:47:52.839+01:00 [WARN ] HandleRelayInvsFlow flow error: block c6f1b4ea40c55a95fb0f4e8c78348fbaefa2ada6108ba91fd5496909644fe549 difficulty of 520437997 is not the expected value of 520406991, disconnecting from p
|
||||||
|
1757:2026-10-04 14:16:34.987+01:00 [INFO ] IBD with peer 127.0.0.1:29601 completed with error: block c6f1b4ea40c55a95fb0f4e8c78348fbaefa2ada6108ba91fd5496909644fe549 difficulty of 520437997 is not the expected value of 520406991
|
||||||
|
|
@ -360,3 +360,306 @@ recovery after each event (61-block centred mean of expected rate within 10% of
|
||||||
```
|
```
|
||||||
|
|
||||||
Kaspa rule, same network and genesis, 10 minutes (`testnet-kaspa-2026-10-03.csv`): 70 blocks, bits 0x1e200000 on every header, 0.08 blocks/s, worst gap 63 s, delivered 0.042 MH/s; no retarget (block 600 was about 2 hours away).
|
Kaspa rule, same network and genesis, 10 minutes (`testnet-kaspa-2026-10-03.csv`): 70 blocks, bits 0x1e200000 on every header, 0.08 blocks/s, worst gap 63 s, delivered 0.042 MH/s; no retarget (block 600 was about 2 hours away).
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Live replay, 4 October 2026 (`sim.py --live records/live-2026-10-04.csv --hashrate records/live-2026-10-04-hashrate.csv --dag-delay 0.75`)
|
||||||
|
|
||||||
|
The record's row is the live chain over the same UTC window; every other row is the DAG model with that controller. Windows: solo 09:25 to 10:04 (PC 1 + Mac), join 10:20 to 10:31 (three short windows after PC 2 joined at 10:12), rejoin 10:42 to 10:54 (after PC 2 came back at 10:35), both 10:17 to 10:32 (the whole polluted window).
|
||||||
|
|
||||||
|
## The brief's candidates and the reference-window cap
|
||||||
|
|
||||||
|
|
||||||
|
### Window solo (seeds 7, 8, 9: mean)
|
||||||
|
|
||||||
|
| rule | blocks/s | chain blocks merging 2+ % | difficulty mean M | min M | max M | std log D | peaks over 15% | mean peak/trough | blocks/min min | blocks/min max | lane flips | short lane % |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| record | 1.06 | 38.7 | 63.1 | 56.7 | 82.2 | 0.053 | 1.0 | 1.45 | 49.0 | 79.0 | none | none |
|
||||||
|
| igneum | 1.03 | 35.0 | 72.5 | 63.7 | 87.4 | 0.054 | 4.7 | 1.29 | 46.7 | 77.0 | 21.0 | 5.6 |
|
||||||
|
| igneum:ns=240 | 1.04 | 35.3 | 71.4 | 64.3 | 97.5 | 0.060 | 1.7 | 1.40 | 48.0 | 80.3 | 6.7 | 0.7 |
|
||||||
|
| igneum:ns=360 | 1.06 | 37.3 | 71.2 | 63.7 | 99.9 | 0.068 | 1.0 | 1.51 | 49.0 | 79.0 | 2.7 | 0.1 |
|
||||||
|
| igneum:ease_pct=0.03 | 1.04 | 35.5 | 71.4 | 64.0 | 92.6 | 0.062 | 2.7 | 1.35 | 47.7 | 77.0 | 13.0 | 6.2 |
|
||||||
|
| igneum:clamp_window=1000 | 1.02 | 35.0 | 72.8 | 64.0 | 95.7 | 0.067 | 2.0 | 1.37 | 46.0 | 78.3 | 25.3 | 6.2 |
|
||||||
|
| igneum:trig_exit=0.10 | 1.04 | 36.2 | 71.6 | 62.6 | 91.8 | 0.068 | 1.7 | 1.41 | 49.3 | 78.7 | 3.7 | 13.1 |
|
||||||
|
| igneum:median3=1 | 1.04 | 36.3 | 71.5 | 64.4 | 86.1 | 0.056 | 3.0 | 1.34 | 47.7 | 77.0 | 11.0 | 5.3 |
|
||||||
|
| igneum:soft=0.10/0.25 | 1.02 | 36.5 | 73.4 | 60.9 | 91.9 | 0.070 | 6.0 | 1.31 | 49.3 | 74.0 | 65.0 | 43.5 |
|
||||||
|
| igneum:ref_window=600 | 1.00 | 34.8 | 74.6 | 67.6 | 89.7 | 0.044 | 0.7 | 1.38 | 47.0 | 73.7 | 2.0 | 0.5 |
|
||||||
|
| igneum:ref_window=1200 | 1.00 | 34.0 | 74.7 | 65.3 | 86.9 | 0.038 | 1.0 | 1.32 | 47.7 | 77.0 | 5.7 | 1.0 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=600 | 1.00 | 34.1 | 74.6 | 66.2 | 89.6 | 0.050 | 1.7 | 1.26 | 46.7 | 74.7 | 72.0 | 21.2 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=600+clamp_window=1000 | 1.00 | 34.8 | 74.5 | 67.7 | 87.6 | 0.041 | 1.0 | 1.26 | 48.7 | 72.3 | 80.3 | 17.2 |
|
||||||
|
| igneum:trig_exit=0.10+ref_window=600 | 1.00 | 34.3 | 74.2 | 67.5 | 79.8 | 0.046 | 0.3 | 1.15 | 49.3 | 74.0 | 0.0 | 0.0 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=1200 | 1.00 | 35.3 | 74.3 | 64.3 | 87.2 | 0.041 | 1.7 | 1.31 | 48.7 | 71.7 | 74.7 | 25.0 |
|
||||||
|
|
||||||
|
### Window join (seeds 7, 8, 9: mean)
|
||||||
|
|
||||||
|
| rule | blocks/s | chain blocks merging 2+ % | difficulty mean M | min M | max M | std log D | peaks over 15% | mean peak/trough | blocks/min min | blocks/min max | lane flips | short lane % |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| record | 1.08 | 36.3 | 128.2 | 101.8 | 164.3 | 0.134 | 4.0 | 1.37 | 59.0 | 72.0 | none | none |
|
||||||
|
| igneum | 1.10 | 37.1 | 128.8 | 110.7 | 167.2 | 0.115 | 4.3 | 1.31 | 56.7 | 73.7 | 22.3 | 38.1 |
|
||||||
|
| igneum:ns=240 | 1.07 | 36.3 | 132.8 | 108.4 | 159.5 | 0.125 | 1.3 | 1.42 | 53.3 | 73.3 | 10.3 | 58.9 |
|
||||||
|
| igneum:ns=360 | 1.07 | 36.4 | 132.9 | 112.2 | 151.7 | 0.107 | 1.0 | 1.29 | 52.7 | 77.0 | 11.3 | 60.4 |
|
||||||
|
| igneum:ease_pct=0.03 | 1.11 | 36.9 | 127.1 | 108.7 | 164.9 | 0.113 | 3.0 | 1.34 | 56.7 | 72.7 | 20.3 | 31.5 |
|
||||||
|
| igneum:clamp_window=1000 | 1.09 | 36.3 | 129.3 | 106.1 | 164.5 | 0.132 | 4.3 | 1.34 | 57.7 | 78.7 | 20.7 | 55.2 |
|
||||||
|
| igneum:trig_exit=0.10 | 1.02 | 34.1 | 142.2 | 121.2 | 171.7 | 0.090 | 2.0 | 1.32 | 50.7 | 72.7 | 1.7 | 77.6 |
|
||||||
|
| igneum:median3=1 | 1.09 | 36.2 | 129.0 | 110.9 | 170.4 | 0.124 | 4.7 | 1.32 | 55.0 | 75.3 | 15.0 | 37.0 |
|
||||||
|
| igneum:soft=0.10/0.25 | 1.03 | 35.7 | 137.6 | 114.6 | 168.0 | 0.110 | 3.0 | 1.30 | 54.0 | 71.3 | 13.0 | 84.0 |
|
||||||
|
| igneum:ref_window=600 | 1.01 | 33.0 | 140.9 | 130.1 | 147.6 | 0.024 | 0.0 | none | 55.0 | 68.0 | 0.0 | 0.0 |
|
||||||
|
| igneum:ref_window=1200 | 1.07 | 35.4 | 133.4 | 112.5 | 166.7 | 0.108 | 3.7 | 1.31 | 54.3 | 77.0 | 14.3 | 28.3 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=600 | 1.02 | 34.7 | 139.7 | 123.1 | 159.3 | 0.047 | 1.0 | 1.29 | 53.0 | 71.3 | 27.7 | 26.1 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=600+clamp_window=1000 | 1.00 | 34.2 | 140.6 | 128.0 | 160.6 | 0.034 | 0.7 | 1.28 | 51.3 | 66.3 | 24.0 | 24.9 |
|
||||||
|
| igneum:trig_exit=0.10+ref_window=600 | 1.00 | 34.8 | 141.9 | 127.8 | 159.1 | 0.035 | 0.3 | 1.45 | 51.7 | 68.0 | 1.0 | 4.4 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=1200 | 1.04 | 35.2 | 137.6 | 112.6 | 166.0 | 0.103 | 2.7 | 1.33 | 53.0 | 70.7 | 16.7 | 77.1 |
|
||||||
|
|
||||||
|
### Window rejoin (seeds 7, 8, 9: mean)
|
||||||
|
|
||||||
|
| rule | blocks/s | chain blocks merging 2+ % | difficulty mean M | min M | max M | std log D | peaks over 15% | mean peak/trough | blocks/min min | blocks/min max | lane flips | short lane % |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| record | 1.10 | 34.6 | 121.2 | 112.5 | 150.4 | 0.067 | 3.0 | 1.31 | 55.0 | 75.0 | none | none |
|
||||||
|
| igneum | 1.07 | 35.5 | 125.0 | 118.7 | 149.6 | 0.045 | 1.7 | 1.25 | 54.7 | 75.0 | 8.7 | 4.2 |
|
||||||
|
| igneum:ns=240 | 1.10 | 37.2 | 125.2 | 118.2 | 139.4 | 0.043 | 0.3 | 1.27 | 56.3 | 76.0 | 0.7 | 0.5 |
|
||||||
|
| igneum:ns=360 | 1.09 | 34.3 | 125.6 | 117.5 | 133.7 | 0.041 | 0.0 | none | 55.7 | 75.0 | 0.0 | 0.0 |
|
||||||
|
| igneum:ease_pct=0.03 | 1.08 | 35.0 | 125.1 | 118.1 | 158.9 | 0.055 | 1.3 | 1.34 | 54.7 | 72.3 | 9.3 | 5.9 |
|
||||||
|
| igneum:clamp_window=1000 | 1.10 | 36.5 | 125.7 | 116.9 | 157.4 | 0.054 | 1.0 | 1.35 | 57.3 | 75.0 | 10.0 | 6.9 |
|
||||||
|
| igneum:trig_exit=0.10 | 1.05 | 34.2 | 130.4 | 121.7 | 145.8 | 0.054 | 0.7 | 1.26 | 53.7 | 72.0 | 1.3 | 19.2 |
|
||||||
|
| igneum:median3=1 | 1.11 | 38.1 | 126.6 | 118.4 | 156.9 | 0.056 | 2.3 | 1.28 | 59.3 | 73.7 | 7.0 | 6.7 |
|
||||||
|
| igneum:soft=0.10/0.25 | 1.06 | 36.0 | 128.5 | 120.6 | 157.7 | 0.055 | 1.0 | 1.23 | 53.7 | 71.0 | 30.0 | 52.6 |
|
||||||
|
| igneum:ref_window=600 | 1.00 | 34.0 | 137.8 | 125.6 | 144.0 | 0.028 | 0.0 | none | 52.3 | 70.0 | 0.0 | 0.0 |
|
||||||
|
| igneum:ref_window=1200 | 1.07 | 38.0 | 130.8 | 124.1 | 150.6 | 0.048 | 1.0 | 1.32 | 52.7 | 73.7 | 4.7 | 4.7 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=600 | 1.02 | 34.4 | 134.0 | 117.6 | 150.4 | 0.046 | 0.7 | 1.31 | 51.7 | 69.3 | 19.7 | 16.7 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=600+clamp_window=1000 | 1.00 | 34.7 | 133.6 | 119.2 | 146.0 | 0.040 | 0.0 | none | 48.7 | 68.0 | 22.7 | 14.6 |
|
||||||
|
| igneum:trig_exit=0.10+ref_window=600 | 1.01 | 34.8 | 135.8 | 119.9 | 152.6 | 0.044 | 0.3 | 1.44 | 52.7 | 68.0 | 1.0 | 4.3 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=1200 | 1.05 | 34.4 | 128.8 | 121.6 | 152.8 | 0.044 | 1.7 | 1.22 | 55.3 | 71.0 | 24.3 | 33.1 |
|
||||||
|
|
||||||
|
### Window both (seeds 7, 8, 9: mean)
|
||||||
|
|
||||||
|
| rule | blocks/s | chain blocks merging 2+ % | difficulty mean M | min M | max M | std log D | peaks over 15% | mean peak/trough | blocks/min min | blocks/min max | lane flips | short lane % |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| record | 1.08 | 36.3 | 129.2 | 101.8 | 164.3 | 0.123 | 5.0 | 1.33 | 54.0 | 81.0 | none | none |
|
||||||
|
| igneum | 1.08 | 36.2 | 128.1 | 104.1 | 169.2 | 0.118 | 5.3 | 1.33 | 53.7 | 77.0 | 28.0 | 43.3 |
|
||||||
|
| igneum:ns=240 | 1.04 | 36.0 | 133.4 | 108.4 | 159.5 | 0.117 | 2.0 | 1.35 | 50.7 | 75.7 | 10.3 | 64.0 |
|
||||||
|
| igneum:ns=360 | 1.05 | 36.7 | 133.5 | 112.2 | 151.7 | 0.101 | 1.7 | 1.26 | 52.3 | 77.7 | 11.7 | 66.1 |
|
||||||
|
| igneum:ease_pct=0.03 | 1.08 | 37.0 | 126.7 | 102.6 | 165.3 | 0.113 | 4.3 | 1.42 | 51.7 | 76.0 | 29.3 | 38.1 |
|
||||||
|
| igneum:clamp_window=1000 | 1.06 | 35.9 | 129.1 | 103.2 | 164.5 | 0.132 | 4.3 | 1.36 | 53.0 | 79.3 | 25.0 | 57.8 |
|
||||||
|
| igneum:trig_exit=0.10 | 1.00 | 35.4 | 140.4 | 120.3 | 173.2 | 0.095 | 2.7 | 1.32 | 49.0 | 73.0 | 1.7 | 77.8 |
|
||||||
|
| igneum:median3=1 | 1.06 | 35.1 | 129.7 | 105.7 | 170.4 | 0.123 | 5.7 | 1.35 | 52.0 | 78.3 | 17.7 | 43.2 |
|
||||||
|
| igneum:soft=0.10/0.25 | 1.01 | 34.9 | 137.8 | 114.6 | 168.0 | 0.107 | 4.3 | 1.29 | 51.0 | 73.0 | 14.7 | 84.4 |
|
||||||
|
| igneum:ref_window=600 | 1.01 | 34.2 | 138.0 | 107.6 | 152.0 | 0.066 | 0.3 | 1.57 | 47.3 | 72.0 | 5.3 | 5.7 |
|
||||||
|
| igneum:ref_window=1200 | 1.05 | 35.9 | 133.9 | 108.0 | 168.0 | 0.109 | 5.0 | 1.30 | 51.7 | 77.3 | 18.7 | 38.1 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=600 | 1.01 | 34.2 | 136.6 | 108.9 | 159.3 | 0.067 | 2.3 | 1.27 | 50.0 | 71.3 | 30.7 | 38.5 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=600+clamp_window=1000 | 0.99 | 35.0 | 139.3 | 116.6 | 160.6 | 0.053 | 1.7 | 1.31 | 47.0 | 70.0 | 26.3 | 38.4 |
|
||||||
|
| igneum:trig_exit=0.10+ref_window=600 | 0.99 | 34.8 | 140.4 | 120.4 | 162.2 | 0.047 | 1.0 | 1.29 | 48.7 | 71.0 | 1.7 | 20.8 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=1200 | 1.01 | 34.2 | 136.7 | 111.2 | 166.0 | 0.100 | 3.0 | 1.36 | 50.7 | 71.0 | 19.7 | 78.3 |
|
||||||
|
## Narrowing the cap (480 to 1,200) and the cap with hysteresis
|
||||||
|
|
||||||
|
|
||||||
|
### Window solo (seeds 7, 8, 9: mean)
|
||||||
|
|
||||||
|
| rule | blocks/s | chain blocks merging 2+ % | difficulty mean M | min M | max M | std log D | peaks over 15% | mean peak/trough | blocks/min min | blocks/min max | lane flips | short lane % |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| record | 1.06 | 38.7 | 63.1 | 56.7 | 82.2 | 0.053 | 1.0 | 1.45 | 49.0 | 79.0 | none | none |
|
||||||
|
| igneum | 1.03 | 35.0 | 72.5 | 63.7 | 87.4 | 0.054 | 4.7 | 1.29 | 46.7 | 77.0 | 21.0 | 5.6 |
|
||||||
|
| igneum:ref_window=600 | 1.00 | 34.8 | 74.6 | 67.6 | 89.7 | 0.044 | 0.7 | 1.38 | 47.0 | 73.7 | 2.0 | 0.5 |
|
||||||
|
| igneum:ref_window=720 | 1.00 | 34.2 | 75.5 | 68.3 | 87.4 | 0.053 | 1.0 | 1.33 | 46.0 | 73.3 | 3.3 | 1.2 |
|
||||||
|
| igneum:ref_window=900 | 1.00 | 35.2 | 75.1 | 69.2 | 84.7 | 0.043 | 0.3 | 1.35 | 45.3 | 75.0 | 2.7 | 0.4 |
|
||||||
|
| igneum:ref_window=600+trig_exit=0.10 | 1.00 | 34.3 | 74.2 | 67.5 | 79.8 | 0.046 | 0.3 | 1.15 | 49.3 | 74.0 | 0.0 | 0.0 |
|
||||||
|
| igneum:ref_window=480 | 1.01 | 35.0 | 74.4 | 65.9 | 81.4 | 0.052 | 0.0 | none | 46.3 | 73.0 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
### Window join (seeds 7, 8, 9: mean)
|
||||||
|
|
||||||
|
| rule | blocks/s | chain blocks merging 2+ % | difficulty mean M | min M | max M | std log D | peaks over 15% | mean peak/trough | blocks/min min | blocks/min max | lane flips | short lane % |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| record | 1.08 | 36.3 | 128.2 | 101.8 | 164.3 | 0.134 | 4.0 | 1.37 | 59.0 | 72.0 | none | none |
|
||||||
|
| igneum | 1.10 | 37.1 | 128.8 | 110.7 | 167.2 | 0.115 | 4.3 | 1.31 | 56.7 | 73.7 | 22.3 | 38.1 |
|
||||||
|
| igneum:ref_window=600 | 1.01 | 33.0 | 140.9 | 130.1 | 147.6 | 0.024 | 0.0 | none | 55.0 | 68.0 | 0.0 | 0.0 |
|
||||||
|
| igneum:ref_window=720 | 1.04 | 35.3 | 136.4 | 116.7 | 149.3 | 0.055 | 0.0 | none | 53.3 | 72.0 | 4.3 | 0.6 |
|
||||||
|
| igneum:ref_window=900 | 1.06 | 36.2 | 134.2 | 112.4 | 151.4 | 0.081 | 0.7 | 1.32 | 53.0 | 73.7 | 8.3 | 8.6 |
|
||||||
|
| igneum:ref_window=600+trig_exit=0.10 | 1.00 | 34.8 | 141.9 | 127.8 | 159.1 | 0.035 | 0.3 | 1.45 | 51.7 | 68.0 | 1.0 | 4.4 |
|
||||||
|
| igneum:ref_window=480 | 1.00 | 35.0 | 141.3 | 134.0 | 146.6 | 0.021 | 0.0 | none | 52.0 | 69.7 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
### Window rejoin (seeds 7, 8, 9: mean)
|
||||||
|
|
||||||
|
| rule | blocks/s | chain blocks merging 2+ % | difficulty mean M | min M | max M | std log D | peaks over 15% | mean peak/trough | blocks/min min | blocks/min max | lane flips | short lane % |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| record | 1.10 | 34.6 | 121.2 | 112.5 | 150.4 | 0.067 | 3.0 | 1.31 | 55.0 | 75.0 | none | none |
|
||||||
|
| igneum | 1.07 | 35.5 | 125.0 | 118.7 | 149.6 | 0.045 | 1.7 | 1.25 | 54.7 | 75.0 | 8.7 | 4.2 |
|
||||||
|
| igneum:ref_window=600 | 1.01 | 34.0 | 137.8 | 125.6 | 144.0 | 0.028 | 0.0 | none | 52.3 | 70.0 | 0.0 | 0.0 |
|
||||||
|
| igneum:ref_window=720 | 1.03 | 34.5 | 132.3 | 116.2 | 140.5 | 0.052 | 0.0 | none | 53.7 | 71.0 | 2.7 | 0.5 |
|
||||||
|
| igneum:ref_window=900 | 1.05 | 36.1 | 129.5 | 118.2 | 139.1 | 0.063 | 0.0 | none | 53.0 | 71.7 | 1.3 | 0.1 |
|
||||||
|
| igneum:ref_window=600+trig_exit=0.10 | 1.01 | 34.8 | 135.8 | 119.9 | 152.6 | 0.044 | 0.3 | 1.44 | 52.7 | 68.0 | 1.0 | 4.3 |
|
||||||
|
| igneum:ref_window=480 | 0.99 | 34.0 | 135.0 | 128.8 | 141.0 | 0.019 | 0.0 | none | 52.7 | 66.3 | 0.0 | 0.0 |
|
||||||
|
## Rule v2 (cap 600, epoch lane only) against the cap with the long lane kept
|
||||||
|
|
||||||
|
|
||||||
|
### Window solo (seeds 7, 8, 9: mean)
|
||||||
|
|
||||||
|
| rule | blocks/s | chain blocks merging 2+ % | difficulty mean M | min M | max M | std log D | peaks over 15% | mean peak/trough | blocks/min min | blocks/min max | lane flips | short lane % |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| record | 1.06 | 38.7 | 63.1 | 56.7 | 82.2 | 0.053 | 1.0 | 1.45 | 49.0 | 79.0 | none | none |
|
||||||
|
| igneum | 1.03 | 35.0 | 72.5 | 63.7 | 87.4 | 0.054 | 4.7 | 1.29 | 46.7 | 77.0 | 21.0 | 5.6 |
|
||||||
|
| igneum:ref_window=600 | 1.00 | 34.8 | 74.6 | 67.6 | 89.7 | 0.044 | 0.7 | 1.38 | 47.0 | 73.7 | 2.0 | 0.5 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 1.01 | 35.6 | 74.2 | 66.6 | 83.9 | 0.050 | 0.3 | 1.38 | 46.0 | 73.3 | 0.7 | 0.2 |
|
||||||
|
| igneum:ref_window=480+long_min=100000 | 1.01 | 35.0 | 74.4 | 65.9 | 81.4 | 0.052 | 0.0 | none | 46.3 | 73.0 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
### Window join (seeds 7, 8, 9: mean)
|
||||||
|
|
||||||
|
| rule | blocks/s | chain blocks merging 2+ % | difficulty mean M | min M | max M | std log D | peaks over 15% | mean peak/trough | blocks/min min | blocks/min max | lane flips | short lane % |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| record | 1.08 | 36.3 | 128.2 | 101.8 | 164.3 | 0.134 | 4.0 | 1.37 | 59.0 | 72.0 | none | none |
|
||||||
|
| igneum | 1.10 | 37.1 | 128.8 | 110.7 | 167.2 | 0.115 | 4.3 | 1.31 | 56.7 | 73.7 | 22.3 | 38.1 |
|
||||||
|
| igneum:ref_window=600 | 1.01 | 33.0 | 140.9 | 130.1 | 147.6 | 0.024 | 0.0 | none | 55.0 | 68.0 | 0.0 | 0.0 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 1.00 | 33.8 | 142.6 | 130.3 | 149.8 | 0.026 | 0.0 | none | 52.0 | 67.7 | 0.0 | 0.0 |
|
||||||
|
| igneum:ref_window=480+long_min=100000 | 1.00 | 35.0 | 141.3 | 134.0 | 146.6 | 0.021 | 0.0 | none | 52.0 | 69.7 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
### Window rejoin (seeds 7, 8, 9: mean)
|
||||||
|
|
||||||
|
| rule | blocks/s | chain blocks merging 2+ % | difficulty mean M | min M | max M | std log D | peaks over 15% | mean peak/trough | blocks/min min | blocks/min max | lane flips | short lane % |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| record | 1.10 | 34.6 | 121.2 | 112.5 | 150.4 | 0.067 | 3.0 | 1.31 | 55.0 | 75.0 | none | none |
|
||||||
|
| igneum | 1.07 | 35.5 | 125.0 | 118.7 | 149.6 | 0.045 | 1.7 | 1.25 | 54.7 | 75.0 | 8.7 | 4.2 |
|
||||||
|
| igneum:ref_window=600 | 1.01 | 34.0 | 137.8 | 125.6 | 144.0 | 0.028 | 0.0 | none | 52.3 | 70.0 | 0.0 | 0.0 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 1.01 | 34.2 | 136.1 | 123.0 | 143.5 | 0.031 | 0.0 | none | 51.7 | 70.0 | 0.0 | 0.0 |
|
||||||
|
| igneum:ref_window=480+long_min=100000 | 0.99 | 34.0 | 135.0 | 128.8 | 141.0 | 0.019 | 0.0 | none | 52.7 | 66.3 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
### Window both (seeds 7, 8, 9: mean)
|
||||||
|
|
||||||
|
| rule | blocks/s | chain blocks merging 2+ % | difficulty mean M | min M | max M | std log D | peaks over 15% | mean peak/trough | blocks/min min | blocks/min max | lane flips | short lane % |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| record | 1.08 | 36.3 | 129.2 | 101.8 | 164.3 | 0.123 | 5.0 | 1.33 | 54.0 | 81.0 | none | none |
|
||||||
|
| igneum | 1.08 | 36.2 | 128.1 | 104.1 | 169.2 | 0.118 | 5.3 | 1.33 | 53.7 | 77.0 | 28.0 | 43.3 |
|
||||||
|
| igneum:ref_window=600 | 1.01 | 34.2 | 138.0 | 107.6 | 152.0 | 0.066 | 0.3 | 1.57 | 47.3 | 72.0 | 5.3 | 5.7 |
|
||||||
|
| igneum:ref_window=600+long_min=100000 | 1.00 | 34.5 | 139.4 | 114.0 | 157.9 | 0.071 | 0.7 | 1.21 | 44.3 | 74.3 | 2.3 | 6.8 |
|
||||||
|
| igneum:ref_window=480+long_min=100000 | 1.00 | 34.8 | 138.5 | 112.4 | 147.7 | 0.056 | 0.0 | none | 44.0 | 73.3 | 1.0 | 0.2 |
|
||||||
|
|
||||||
|
### Seed 7 raw output of the candidate run (hash-rate schedule and every window)
|
||||||
|
|
||||||
|
# Live replay of records/live-2026-10-04.csv: 6741 headers, DAG model, seed 7, delay scale 0.75
|
||||||
|
|
||||||
|
Hash-rate schedule (from the log intake and the Mac's bench value), MH/s:
|
||||||
|
|
||||||
|
| time UTC | worker | node | MH/s |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 09:07:31 | mac-metal | mac | 26.7 |
|
||||||
|
| 09:11:03 | PC1-nvidia | pc | 121.0 |
|
||||||
|
| 09:11:04 | PC1-amd | pc | 2.5 |
|
||||||
|
| 09:11:35 | PC1-amd | pc | 2.7 |
|
||||||
|
| 09:19:13 | PC1-amd | pc | 2.8 |
|
||||||
|
| 09:45:07 | PC1-nvidia | pc | 119.7 |
|
||||||
|
| 09:45:37 | PC1-nvidia | pc | 108.1 |
|
||||||
|
| 09:51:38 | PC1-nvidia | pc | 117.6 |
|
||||||
|
| 09:52:08 | PC1-nvidia | pc | 122.1 |
|
||||||
|
| 09:53:08 | PC1-nvidia | pc | 114.9 |
|
||||||
|
| 09:54:09 | PC1-nvidia | pc | 113.2 |
|
||||||
|
| 09:54:39 | PC1-nvidia | pc | 121.2 |
|
||||||
|
| 10:03:11 | PC2-amd | mac | 3.2 |
|
||||||
|
| 10:04:12 | PC2-amd | mac | 3.5 |
|
||||||
|
| 10:04:40 | PC2-nvidia | mac | 0.0 |
|
||||||
|
| 10:05:03 | PC1-amd | pc | 1.5 |
|
||||||
|
| 10:05:15 | PC2-nvidia | mac | 0.0 |
|
||||||
|
| 10:05:28 | PC2-nvidia | mac | 0.0 |
|
||||||
|
| 10:05:34 | PC1-amd | pc | 2.8 |
|
||||||
|
| 10:06:03 | PC2-nvidia | mac | 0.0 |
|
||||||
|
| 10:06:30 | PC2-nvidia | mac | 0.0 |
|
||||||
|
| 10:07:05 | PC2-nvidia | mac | 0.0 |
|
||||||
|
| 10:07:35 | PC2-nvidia | mac | 0.0 |
|
||||||
|
| 10:08:45 | PC2-nvidia | mac | 0.0 |
|
||||||
|
| 10:09:21 | PC2-amd | mac | 0.0 |
|
||||||
|
| 10:12:17 | PC2-nvidia | mac | 122.0 |
|
||||||
|
| 10:12:17 | PC2-amd | mac | 3.2 |
|
||||||
|
| 10:12:47 | PC2-amd | mac | 3.4 |
|
||||||
|
| 10:18:22 | PC2-amd | mac | 3.1 |
|
||||||
|
| 10:18:52 | PC2-amd | mac | 3.3 |
|
||||||
|
| 10:21:42 | PC1-nvidia | pc | 116.3 |
|
||||||
|
| 10:21:59 | PC2-amd | mac | 0.0 |
|
||||||
|
| 10:22:42 | PC1-nvidia | pc | 121.7 |
|
||||||
|
| 10:31:25 | PC2-nvidia | mac | 0.0 |
|
||||||
|
| 10:35:19 | PC2-nvidia | mac | 121.6 |
|
||||||
|
| 10:35:20 | PC2-amd | mac | 3.2 |
|
||||||
|
| 10:35:50 | PC2-amd | mac | 3.4 |
|
||||||
|
| 10:36:04 | PC1-amd | pc | 2.9 |
|
||||||
|
| 10:41:54 | PC2-amd | mac | 3.4 |
|
||||||
|
| 10:54:52 | PC1-amd | pc | 2.9 |
|
||||||
|
| 10:55:38 | PC2-amd | mac | 0.0 |
|
||||||
|
| 10:56:58 | PC1-amd | pc | 0.0 |
|
||||||
|
| 10:58:56 | PC2-nvidia | mac | 0.0 |
|
||||||
|
| 11:00:20 | PC1-nvidia | pc | 0.0 |
|
||||||
|
|
||||||
|
### Window solo (09:25 to 10:04 UTC)
|
||||||
|
|
||||||
|
| source | blocks | blocks/s | chain/s | blues per chain block | chain blocks merging 2+ % | blocks with 2+ parents % | chain step median ms | difficulty mean M | min M | max M | std log D | peaks over 15% | mean peak/trough | peak spacing chain blocks | blocks/min min | blocks/min max | lane flips | short lane % |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| record | 2471 | 1.06 | 0.72 | 1.470 | 38.7 | 38.3 | 1085 | 63.1 | 56.7 | 82.2 | 0.053 | 1 | 1.45 | none | 49 | 79 | none | none |
|
||||||
|
| igneum | 2466 | 1.05 | 0.74 | 1.422 | 34.4 | 34.8 | 1107.4 | 71.6 | 58.2 | 92.5 | 0.071 | 7 | 1.26 | 125.8 | 44 | 81 | 39 | 9.1 |
|
||||||
|
| igneum:ns=240 | 2478 | 1.06 | 0.74 | 1.431 | 35.2 | 34.9 | 1121.0 | 70.6 | 61.9 | 110.0 | 0.094 | 2 | 1.46 | 1396.0 | 46 | 85 | 8 | 0.5 |
|
||||||
|
| igneum:ns=360 | 2536 | 1.08 | 0.74 | 1.457 | 37.5 | 37.8 | 1089.2 | 69.8 | 61.2 | 84.4 | 0.072 | 1 | 1.23 | none | 52 | 82 | 2 | 0.1 |
|
||||||
|
| igneum:ease_pct=0.03 | 2464 | 1.05 | 0.73 | 1.436 | 36.6 | 36.6 | 1108.0 | 72.0 | 61.8 | 96.7 | 0.087 | 3 | 1.42 | 639.0 | 49 | 79 | 19 | 11.8 |
|
||||||
|
| igneum:clamp_window=1000 | 2444 | 1.04 | 0.73 | 1.427 | 34.4 | 34.6 | 1116.5 | 72.0 | 62.5 | 101.9 | 0.088 | 2 | 1.40 | 183.0 | 48 | 83 | 43 | 9.3 |
|
||||||
|
| igneum:trig_exit=0.10 | 2415 | 1.03 | 0.71 | 1.448 | 36.9 | 35.9 | 1177.8 | 71.5 | 60.7 | 92.0 | 0.082 | 2 | 1.45 | 507.0 | 47 | 76 | 5 | 20.9 |
|
||||||
|
| igneum:median3=1 | 2451 | 1.05 | 0.73 | 1.442 | 36.8 | 36.7 | 1126.6 | 70.4 | 61.8 | 90.6 | 0.076 | 4 | 1.34 | 181.0 | 46 | 79 | 23 | 9.6 |
|
||||||
|
| igneum:soft=0.10/0.25 | 2362 | 1.01 | 0.71 | 1.425 | 35.1 | 35.6 | 1133.4 | 73.7 | 59.4 | 95.3 | 0.097 | 7 | 1.37 | 210.3 | 47 | 75 | 61 | 49.1 |
|
||||||
|
| igneum:ref_window=600 | 2365 | 1.01 | 0.71 | 1.428 | 35.1 | 34.8 | 1161.0 | 74.6 | 68.1 | 95.0 | 0.047 | 1 | 1.40 | none | 47 | 73 | 4 | 1.0 |
|
||||||
|
| igneum:ref_window=1200 | 2353 | 1.01 | 0.71 | 1.409 | 34.0 | 34.0 | 1164.9 | 74.8 | 63.0 | 92.7 | 0.035 | 2 | 1.34 | 733.0 | 49 | 75 | 9 | 2.1 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=600 | 2332 | 1.00 | 0.71 | 1.412 | 33.6 | 33.2 | 1184.4 | 75.9 | 65.2 | 93.2 | 0.056 | 2 | 1.30 | 986.0 | 46 | 74 | 72 | 24.9 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=600+clamp_window=1000 | 2342 | 1.00 | 0.70 | 1.427 | 35.3 | 36.2 | 1155.4 | 74.9 | 64.8 | 93.6 | 0.061 | 2 | 1.27 | 973.0 | 47 | 76 | 98 | 31.8 |
|
||||||
|
| igneum:trig_exit=0.10+ref_window=600 | 2351 | 1.00 | 0.71 | 1.413 | 33.9 | 34.0 | 1132.4 | 74.1 | 66.8 | 80.2 | 0.048 | 1 | 1.15 | none | 49 | 75 | 0 | 0.0 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=1200 | 2334 | 1.00 | 0.70 | 1.415 | 34.9 | 34.2 | 1140.2 | 74.5 | 64.7 | 94.8 | 0.051 | 2 | 1.40 | 776.0 | 49 | 70 | 85 | 38.8 |
|
||||||
|
|
||||||
|
### Window both (10:17 to 10:32 UTC)
|
||||||
|
|
||||||
|
| source | blocks | blocks/s | chain/s | blues per chain block | chain blocks merging 2+ % | blocks with 2+ parents % | chain step median ms | difficulty mean M | min M | max M | std log D | peaks over 15% | mean peak/trough | peak spacing chain blocks | blocks/min min | blocks/min max | lane flips | short lane % |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| record | 975 | 1.08 | 0.74 | 1.455 | 36.3 | 36.4 | 1073 | 129.2 | 101.8 | 164.3 | 0.123 | 5 | 1.33 | 132.0 | 54 | 81 | none | none |
|
||||||
|
| igneum | 952 | 1.06 | 0.73 | 1.451 | 36.0 | 34.7 | 1066.4 | 129.7 | 106.3 | 171.1 | 0.134 | 4 | 1.32 | 142.7 | 53 | 74 | 17 | 56.9 |
|
||||||
|
| igneum:ns=240 | 946 | 1.05 | 0.71 | 1.474 | 37.5 | 37.2 | 1117.2 | 129.4 | 108.7 | 154.2 | 0.115 | 1 | 1.42 | none | 53 | 73 | 9 | 55.6 |
|
||||||
|
| igneum:ns=360 | 952 | 1.06 | 0.74 | 1.427 | 34.3 | 33.3 | 1050.0 | 131.9 | 104.8 | 149.0 | 0.105 | 3 | 1.33 | 107.0 | 50 | 81 | 15 | 76.5 |
|
||||||
|
| igneum:ease_pct=0.03 | 994 | 1.10 | 0.74 | 1.495 | 38.6 | 38.7 | 1029.5 | 120.2 | 102.3 | 159.4 | 0.112 | 6 | 1.29 | 80.0 | 52 | 75 | 35 | 34.6 |
|
||||||
|
| igneum:clamp_window=1000 | 964 | 1.07 | 0.72 | 1.479 | 38.7 | 40.4 | 1078.9 | 124.8 | 101.3 | 174.0 | 0.146 | 4 | 1.39 | 92.7 | 55 | 82 | 21 | 48.3 |
|
||||||
|
| igneum:trig_exit=0.10 | 918 | 1.02 | 0.71 | 1.439 | 36.5 | 36.4 | 1050.2 | 130.6 | 113.8 | 160.1 | 0.091 | 2 | 1.30 | 162.0 | 51 | 72 | 3 | 62.2 |
|
||||||
|
| igneum:median3=1 | 941 | 1.05 | 0.73 | 1.424 | 34.6 | 34.9 | 1009.3 | 127.2 | 101.3 | 167.0 | 0.130 | 3 | 1.44 | 106.5 | 50 | 75 | 11 | 57.0 |
|
||||||
|
| igneum:soft=0.10/0.25 | 919 | 1.02 | 0.71 | 1.443 | 37.4 | 36.1 | 1106.9 | 131.6 | 112.5 | 159.5 | 0.098 | 5 | 1.25 | 126.5 | 49 | 71 | 21 | 84.9 |
|
||||||
|
| igneum:ref_window=600 | 892 | 0.99 | 0.70 | 1.425 | 34.2 | 36.1 | 1125.4 | 134.2 | 113.0 | 148.3 | 0.045 | 0 | none | none | 51 | 67 | 9 | 4.0 |
|
||||||
|
| igneum:ref_window=1200 | 962 | 1.07 | 0.75 | 1.434 | 36.1 | 36.0 | 1033.0 | 127.0 | 102.4 | 153.5 | 0.100 | 7 | 1.27 | 65.8 | 57 | 75 | 29 | 35.8 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=600 | 902 | 1.00 | 0.69 | 1.457 | 36.7 | 37.7 | 1134.0 | 137.9 | 115.0 | 176.6 | 0.071 | 3 | 1.29 | 176.5 | 52 | 70 | 24 | 39.1 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=600+clamp_window=1000 | 886 | 0.98 | 0.69 | 1.434 | 36.6 | 36.1 | 1125.5 | 136.6 | 119.6 | 165.7 | 0.054 | 2 | 1.29 | 366.0 | 47 | 70 | 33 | 35.3 |
|
||||||
|
| igneum:trig_exit=0.10+ref_window=600 | 884 | 0.98 | 0.69 | 1.417 | 34.1 | 32.6 | 1170.3 | 138.8 | 122.9 | 151.8 | 0.033 | 0 | none | none | 49 | 69 | 1 | 15.4 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=1200 | 921 | 1.02 | 0.71 | 1.446 | 36.9 | 36.9 | 1104.5 | 128.0 | 103.2 | 155.2 | 0.109 | 2 | 1.42 | 174.0 | 52 | 72 | 31 | 66.7 |
|
||||||
|
|
||||||
|
### Window join (10:20 to 10:31 UTC)
|
||||||
|
|
||||||
|
| source | blocks | blocks/s | chain/s | blues per chain block | chain blocks merging 2+ % | blocks with 2+ parents % | chain step median ms | difficulty mean M | min M | max M | std log D | peaks over 15% | mean peak/trough | peak spacing chain blocks | blocks/min min | blocks/min max | lane flips | short lane % |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| record | 711 | 1.08 | 0.74 | 1.448 | 36.3 | 35.9 | 1068 | 128.2 | 101.8 | 164.3 | 0.134 | 4 | 1.37 | 106.0 | 59 | 72 | none | none |
|
||||||
|
| igneum | 719 | 1.09 | 0.74 | 1.464 | 37.5 | 35.9 | 1065.3 | 129.7 | 106.3 | 171.1 | 0.149 | 3 | 1.35 | 127.5 | 55 | 74 | 17 | 50.5 |
|
||||||
|
| igneum:ns=240 | 709 | 1.07 | 0.72 | 1.499 | 39.1 | 38.9 | 1118.4 | 127.3 | 108.7 | 154.2 | 0.120 | 1 | 1.42 | none | 53 | 73 | 9 | 48.4 |
|
||||||
|
| igneum:ns=360 | 720 | 1.09 | 0.76 | 1.437 | 34.7 | 34.3 | 1050.0 | 130.4 | 104.8 | 149.0 | 0.114 | 2 | 1.35 | 163.0 | 50 | 81 | 14 | 71.3 |
|
||||||
|
| igneum:ease_pct=0.03 | 765 | 1.16 | 0.77 | 1.506 | 39.4 | 39.3 | 1013.8 | 117.3 | 102.3 | 158.2 | 0.109 | 4 | 1.32 | 103.7 | 56 | 75 | 32 | 23.2 |
|
||||||
|
| igneum:clamp_window=1000 | 734 | 1.11 | 0.75 | 1.477 | 39.0 | 40.3 | 1037.9 | 122.8 | 101.4 | 174.0 | 0.138 | 4 | 1.39 | 92.7 | 56 | 82 | 18 | 45.5 |
|
||||||
|
| igneum:trig_exit=0.10 | 706 | 1.07 | 0.74 | 1.444 | 36.2 | 36.3 | 1050.0 | 128.9 | 113.8 | 155.6 | 0.087 | 2 | 1.30 | 162.0 | 55 | 72 | 3 | 57.7 |
|
||||||
|
| igneum:median3=1 | 718 | 1.09 | 0.75 | 1.442 | 35.9 | 36.1 | 987.2 | 125.5 | 101.3 | 167.0 | 0.138 | 3 | 1.44 | 106.5 | 53 | 75 | 11 | 50.8 |
|
||||||
|
| igneum:soft=0.10/0.25 | 694 | 1.05 | 0.72 | 1.452 | 38.7 | 37.2 | 1050.0 | 129.8 | 112.5 | 159.5 | 0.096 | 3 | 1.28 | 118.5 | 56 | 71 | 18 | 82.6 |
|
||||||
|
| igneum:ref_window=600 | 657 | 1.00 | 0.70 | 1.413 | 34.0 | 35.2 | 1109.1 | 136.2 | 131.1 | 142.7 | 0.019 | 0 | none | none | 54 | 67 | 0 | 0.0 |
|
||||||
|
| igneum:ref_window=1200 | 735 | 1.11 | 0.77 | 1.441 | 36.7 | 36.1 | 1030.5 | 124.0 | 104.9 | 149.8 | 0.097 | 5 | 1.27 | 52.0 | 61 | 75 | 25 | 22.7 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=600 | 671 | 1.02 | 0.70 | 1.462 | 37.5 | 37.7 | 1103.6 | 140.5 | 124.6 | 176.6 | 0.059 | 2 | 1.29 | 40.0 | 53 | 70 | 22 | 30.7 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=600+clamp_window=1000 | 657 | 1.00 | 0.70 | 1.419 | 35.0 | 33.5 | 1100.9 | 136.1 | 123.9 | 165.7 | 0.042 | 1 | 1.34 | none | 47 | 65 | 32 | 26.1 |
|
||||||
|
| igneum:trig_exit=0.10+ref_window=600 | 666 | 1.01 | 0.71 | 1.417 | 34.0 | 31.8 | 1162.8 | 138.4 | 128.8 | 142.6 | 0.023 | 0 | none | none | 52 | 69 | 0 | 0.0 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=1200 | 700 | 1.06 | 0.72 | 1.464 | 38.3 | 38.1 | 1105.4 | 127.8 | 104.2 | 155.2 | 0.104 | 2 | 1.42 | 174.0 | 55 | 72 | 24 | 67.2 |
|
||||||
|
|
||||||
|
### Window rejoin (10:42 to 10:54 UTC)
|
||||||
|
|
||||||
|
| source | blocks | blocks/s | chain/s | blues per chain block | chain blocks merging 2+ % | blocks with 2+ parents % | chain step median ms | difficulty mean M | min M | max M | std log D | peaks over 15% | mean peak/trough | peak spacing chain blocks | blocks/min min | blocks/min max | lane flips | short lane % |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| record | 794 | 1.10 | 0.79 | 1.400 | 34.6 | 36.3 | 1072 | 121.2 | 112.5 | 150.4 | 0.067 | 3 | 1.31 | 206.5 | 55 | 75 | none | none |
|
||||||
|
| igneum | 790 | 1.10 | 0.76 | 1.450 | 36.9 | 34.8 | 1023.3 | 124.8 | 117.4 | 155.9 | 0.045 | 3 | 1.24 | 22.5 | 60 | 74 | 16 | 5.9 |
|
||||||
|
| igneum:ns=240 | 798 | 1.11 | 0.75 | 1.483 | 39.2 | 40.4 | 1115.3 | 124.8 | 117.2 | 148.7 | 0.045 | 1 | 1.27 | none | 59 | 74 | 2 | 1.5 |
|
||||||
|
| igneum:ns=360 | 787 | 1.09 | 0.78 | 1.405 | 32.3 | 32.7 | 1057.8 | 126.6 | 117.0 | 134.5 | 0.044 | 0 | none | none | 56 | 75 | 0 | 0.0 |
|
||||||
|
| igneum:ease_pct=0.03 | 787 | 1.09 | 0.75 | 1.457 | 34.8 | 33.8 | 1059.6 | 124.7 | 115.7 | 153.4 | 0.062 | 1 | 1.33 | none | 58 | 73 | 8 | 8.1 |
|
||||||
|
| igneum:clamp_window=1000 | 798 | 1.11 | 0.76 | 1.459 | 36.0 | 37.0 | 1050.0 | 127.7 | 117.4 | 160.6 | 0.066 | 1 | 1.37 | none | 60 | 74 | 6 | 8.4 |
|
||||||
|
| igneum:trig_exit=0.10 | 794 | 1.10 | 0.75 | 1.468 | 37.2 | 36.9 | 1078.4 | 125.6 | 121.0 | 138.4 | 0.033 | 0 | none | none | 57 | 74 | 1 | 2.8 |
|
||||||
|
| igneum:median3=1 | 826 | 1.15 | 0.75 | 1.524 | 40.8 | 42.0 | 1117.7 | 122.9 | 113.3 | 158.7 | 0.066 | 3 | 1.35 | 198.0 | 61 | 76 | 10 | 8.1 |
|
||||||
|
| igneum:soft=0.10/0.25 | 791 | 1.10 | 0.75 | 1.459 | 36.9 | 36.5 | 1130.7 | 126.6 | 117.7 | 149.8 | 0.055 | 1 | 1.20 | none | 58 | 70 | 23 | 65.5 |
|
||||||
|
| igneum:ref_window=600 | 723 | 1.00 | 0.70 | 1.432 | 34.5 | 35.8 | 1139.2 | 138.9 | 127.5 | 146.9 | 0.027 | 0 | none | none | 54 | 75 | 0 | 0.0 |
|
||||||
|
| igneum:ref_window=1200 | 766 | 1.06 | 0.72 | 1.470 | 36.9 | 35.5 | 1084.6 | 132.9 | 128.2 | 145.0 | 0.036 | 0 | none | none | 55 | 74 | 0 | 0.0 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=600 | 750 | 1.04 | 0.73 | 1.426 | 34.8 | 34.1 | 1091.6 | 137.1 | 118.5 | 156.6 | 0.050 | 1 | 1.30 | none | 52 | 72 | 19 | 17.5 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=600+clamp_window=1000 | 709 | 0.98 | 0.70 | 1.404 | 32.3 | 31.7 | 1118.5 | 135.3 | 124.7 | 144.8 | 0.033 | 0 | none | none | 48 | 69 | 28 | 14.3 |
|
||||||
|
| igneum:trig_exit=0.10+ref_window=600 | 748 | 1.04 | 0.73 | 1.430 | 35.2 | 34.5 | 1115.0 | 135.3 | 118.2 | 142.6 | 0.035 | 0 | none | none | 52 | 71 | 0 | 0.0 |
|
||||||
|
| igneum:soft=0.10/0.25+ref_window=1200 | 763 | 1.06 | 0.73 | 1.442 | 34.0 | 35.0 | 1134.7 | 130.4 | 122.6 | 160.5 | 0.057 | 2 | 1.23 | 51.0 | 57 | 72 | 22 | 33.8 |
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,10 @@ Controllers
|
||||||
igneum-literal
|
igneum-literal
|
||||||
the brief's literal trigger (fast lane engaged while the short-window RATE is more than
|
the brief's literal trigger (fast lane engaged while the short-window RATE is more than
|
||||||
25% off target) kept for the chatter measurement.
|
25% off target) kept for the chatter measurement.
|
||||||
|
igneum-v2 rule v2 (4 October 2026): the reference lane is the newest 600 blocks of the epoch (epoch lane only).
|
||||||
|
igneum:key=value+key=value
|
||||||
|
any variant of the Igneum class (ns, trig, trig_exit, soft=a/b, median3, clamp_window, ref_window,
|
||||||
|
long_min, clamp_pct, ease_pct, cap, k0, ...).
|
||||||
|
|
||||||
Profiles
|
Profiles
|
||||||
real the devnet record (--record CSV) turned into a step profile of estimated hash rate.
|
real the devnet record (--record CSV) turned into a step profile of estimated hash rate.
|
||||||
|
|
@ -27,6 +31,8 @@ Usage
|
||||||
python3 sim.py every synthetic profile, every controller, markdown out
|
python3 sim.py every synthetic profile, every controller, markdown out
|
||||||
python3 sim.py --record devnet-2026-10-03.csv adds the real profile and the exact-bits replay check
|
python3 sim.py --record devnet-2026-10-03.csv adds the real profile and the exact-bits replay check
|
||||||
python3 sim.py --tune the parameter sweep for the Igneum candidate
|
python3 sim.py --tune the parameter sweep for the Igneum candidate
|
||||||
|
python3 sim.py --live records/live-2026-10-04.csv --hashrate records/live-2026-10-04-hashrate.csv \
|
||||||
|
--controllers igneum,igneum-v2 DAG replay of the live devnet against the record (4 October 2026)
|
||||||
"""
|
"""
|
||||||
import argparse
|
import argparse
|
||||||
import csv
|
import csv
|
||||||
|
|
@ -181,11 +187,26 @@ class Igneum(Controller):
|
||||||
name = "igneum"
|
name = "igneum"
|
||||||
|
|
||||||
def __init__(self, g, ns=120, k_min=8, k0=16, long_min=600, trig=0.25, clamp_pct=0.03, ease_pct=0.10, cap=20 * T,
|
def __init__(self, g, ns=120, k_min=8, k0=16, long_min=600, trig=0.25, clamp_pct=0.03, ease_pct=0.10, cap=20 * T,
|
||||||
window=661, rate=4, literal=False, epoch_aware=True, kaspa_formula=False, lag_caps=3):
|
window=661, rate=4, literal=False, epoch_aware=True, kaspa_formula=False, lag_caps=3,
|
||||||
|
trig_exit=None, soft=None, median3=False, clamp_window=None, ref_window=None):
|
||||||
|
"""Candidates of 4 October 2026 (live oscillation, docs/analysis/difficulty-2026-10-04-oscillation.md), all off by
|
||||||
|
default so the rule of spec 2.3 is unchanged:
|
||||||
|
trig_exit hysteresis: the short lane, once engaged, stays engaged until it is within this fraction of the reference
|
||||||
|
soft (a, b): blend instead of switch; weight on the short lane rises linearly from 0 at |S/R - 1| = a to 1 at b
|
||||||
|
median3 the short lane's rate is the median of its estimates at the block, its parent and its grandparent
|
||||||
|
clamp_window ms: the clamps also bind relative to the target of the newest chain block at least this far back on
|
||||||
|
the sanitised clock, so a burst of chain blocks inside one window moves the target once
|
||||||
|
ref_window blocks: the reference lane sees at most this many newest blocks of the epoch (the long lane's samples
|
||||||
|
and the epoch lane's steps alike), so a hash-rate step inside an epoch washes out of it in that many
|
||||||
|
blocks instead of lasting the whole epoch"""
|
||||||
super().__init__(g)
|
super().__init__(g)
|
||||||
self.ns, self.k_min, self.k0, self.long_min = ns, k_min, k0, long_min
|
self.ns, self.k_min, self.k0, self.long_min = ns, k_min, k0, long_min
|
||||||
self.trig, self.clamp_pct, self.cap = trig, clamp_pct, cap
|
self.trig, self.clamp_pct, self.cap = trig, clamp_pct, cap
|
||||||
self.lag_caps = lag_caps
|
self.lag_caps = lag_caps
|
||||||
|
self.trig_exit, self.soft, self.median3 = trig_exit, soft, median3
|
||||||
|
self.clamp_window, self.ref_window = clamp_window, ref_window
|
||||||
|
self.lane = [False] # per height: the short lane ruled the block's target (index 0 = genesis)
|
||||||
|
self.flips = 0
|
||||||
self.tss = [] # sanitised clock per height
|
self.tss = [] # sanitised clock per height
|
||||||
self.sts = [] # clock step per height (the solvetime the lanes see)
|
self.sts = [] # clock step per height (the solvetime the lanes see)
|
||||||
self.ease_pct = clamp_pct if ease_pct is None else ease_pct
|
self.ease_pct = clamp_pct if ease_pct is None else ease_pct
|
||||||
|
|
@ -264,27 +285,67 @@ class Igneum(Controller):
|
||||||
parent = self.tg[-1]
|
parent = self.tg[-1]
|
||||||
epoch_start = (h // EPOCH) * EPOCH if self.epoch_aware else 0
|
epoch_start = (h // EPOCH) * EPOCH if self.epoch_aware else 0
|
||||||
k = h - epoch_start
|
k = h - epoch_start
|
||||||
|
eng = False
|
||||||
if k < self.k_min:
|
if k < self.k_min:
|
||||||
cand = parent
|
cand = parent
|
||||||
else:
|
else:
|
||||||
s_lo = max(epoch_start, h - self.ns)
|
ref_start = max(epoch_start, h - self.ref_window) if self.ref_window else epoch_start
|
||||||
|
s_lo = max(ref_start, h - self.ns)
|
||||||
r_s = self.rate_s(s_lo, h)
|
r_s = self.rate_s(s_lo, h)
|
||||||
|
if self.median3 and h - s_lo > 4:
|
||||||
|
r_s = sorted([r_s, self.rate_s(s_lo, h - 1), self.rate_s(s_lo, h - 2)])[1]
|
||||||
r_ref = None
|
r_ref = None
|
||||||
if k >= self.long_min:
|
if k >= self.long_min:
|
||||||
r_ref = self.rate_l(max(epoch_start, h - self.window * self.rate))
|
r_ref = self.rate_l(max(ref_start, h - self.window * self.rate))
|
||||||
if r_ref is None:
|
if r_ref is None:
|
||||||
r_ref = self.rate_e(epoch_start, h, k)
|
r_ref = self.rate_e(ref_start, h, h - ref_start)
|
||||||
if self.literal:
|
if self.literal:
|
||||||
n = h - s_lo
|
n = h - s_lo
|
||||||
measured = max(self.pref_st[h] - self.pref_st[s_lo + 1], 1)
|
measured = max(self.pref_st[h] - self.pref_st[s_lo + 1], 1)
|
||||||
use_s = abs(T * (n - 1) / measured - 1) > self.trig
|
eng = abs(T * (n - 1) / measured - 1) > self.trig
|
||||||
|
r = r_s if eng else r_ref
|
||||||
else:
|
else:
|
||||||
use_s = abs(r_s / r_ref - 1) > self.trig
|
r, eng = choose_rate(r_s, r_ref, self.lane[-1], self.trig, self.trig_exit, self.soft)
|
||||||
r = r_s if use_s else r_ref
|
self.engaged += 1 if eng else 0
|
||||||
self.engaged += 1 if use_s else 0
|
|
||||||
cand = ONE / (r * T)
|
cand = ONE / (r * T)
|
||||||
out = clamp(cand, parent / (1 + self.clamp_pct), parent * (1 + self.ease_pct))
|
base = None
|
||||||
return clamp(out, MIN_TARGET, ONE)
|
if self.clamp_window:
|
||||||
|
j = h - 1
|
||||||
|
while j > 0 and self.tss[h - 1] - self.tss[j] < self.clamp_window:
|
||||||
|
j -= 1
|
||||||
|
base = self.tg[j]
|
||||||
|
if eng != self.lane[-1]:
|
||||||
|
self.flips += 1
|
||||||
|
self.lane.append(eng)
|
||||||
|
return clamp_target(cand, parent, base, self.clamp_pct, self.ease_pct)
|
||||||
|
|
||||||
|
|
||||||
|
def choose_rate(r_s, r_ref, prev_engaged, trig, trig_exit=None, soft=None):
|
||||||
|
"""The trigger between the lanes. Returns (rate, short lane engaged).
|
||||||
|
Spec 2.3 rule 3: the short lane rules while it differs from the reference by more than `trig`.
|
||||||
|
trig_exit: hysteresis, an engaged short lane rules until it is within trig_exit of the reference.
|
||||||
|
soft (a, b): the output is the reference plus a share of the difference that rises linearly from 0 at a to 1 at b."""
|
||||||
|
if r_s is None:
|
||||||
|
return r_ref, False
|
||||||
|
if r_ref is None:
|
||||||
|
return r_s, True
|
||||||
|
dev = abs(r_s / r_ref - 1)
|
||||||
|
if soft is not None:
|
||||||
|
a, b = soft
|
||||||
|
w = clamp((dev - a) / (b - a), 0.0, 1.0)
|
||||||
|
return r_ref + w * (r_s - r_ref), w > 0
|
||||||
|
thr = trig_exit if (prev_engaged and trig_exit is not None) else trig
|
||||||
|
use_s = dev > thr
|
||||||
|
return (r_s if use_s else r_ref), use_s
|
||||||
|
|
||||||
|
|
||||||
|
def clamp_target(cand, parent, base, clamp_pct, ease_pct):
|
||||||
|
"""Spec 2.3 rule 4: harden by at most clamp_pct and ease by at most ease_pct against the parent, then the floor and
|
||||||
|
ceiling. `base` (the clamp-window candidate): the same bounds against the newest chain block at least one window back."""
|
||||||
|
out = clamp(cand, parent / (1 + clamp_pct), parent * (1 + ease_pct))
|
||||||
|
if base is not None:
|
||||||
|
out = clamp(out, base / (1 + clamp_pct), base * (1 + ease_pct))
|
||||||
|
return clamp(out, MIN_TARGET, ONE)
|
||||||
|
|
||||||
|
|
||||||
def make_controller(name, g, **kw):
|
def make_controller(name, g, **kw):
|
||||||
|
|
@ -302,9 +363,45 @@ def make_controller(name, g, **kw):
|
||||||
return Igneum(g, literal=True, **kw)
|
return Igneum(g, literal=True, **kw)
|
||||||
if name == "igneum-noepoch":
|
if name == "igneum-noepoch":
|
||||||
return Igneum(g, epoch_aware=False, **kw)
|
return Igneum(g, epoch_aware=False, **kw)
|
||||||
|
if name.startswith("igneum:"):
|
||||||
|
# igneum:key=value+key=value with the Igneum constructor's names; soft=a/b; v2 expands to the adopted candidate
|
||||||
|
opts = dict(kw)
|
||||||
|
opts.update(parse_variant(name[len("igneum:"):]))
|
||||||
|
return Igneum(g, **opts)
|
||||||
|
if name == "igneum-v2":
|
||||||
|
return Igneum(g, **dict(V2, **kw))
|
||||||
raise ValueError(name)
|
raise ValueError(name)
|
||||||
|
|
||||||
|
|
||||||
|
# Rule v2, adopted 4 October 2026 (docs/analysis/difficulty-2026-10-04-oscillation.md): the reference lane sees the
|
||||||
|
# newest 600 blocks of the epoch through the epoch lane only (the sampled long lane is not consulted). `igneum-v2` runs it.
|
||||||
|
V2 = {"ref_window": 600, "long_min": 1 << 62}
|
||||||
|
|
||||||
|
|
||||||
|
def parse_variant(spec):
|
||||||
|
out = {}
|
||||||
|
for part in [p for p in spec.replace(",", "+").split("+") if p]:
|
||||||
|
key, val = part.split("=")
|
||||||
|
if key == "v2" or key == "soft" and "/" in val:
|
||||||
|
if key == "v2":
|
||||||
|
out.update(V2)
|
||||||
|
else:
|
||||||
|
a, b = val.split("/")
|
||||||
|
out["soft"] = (float(a), float(b))
|
||||||
|
continue
|
||||||
|
if key in ("ns", "k_min", "k0", "long_min", "window", "rate", "lag_caps", "ref_window"):
|
||||||
|
out[key] = int(val)
|
||||||
|
elif key in ("cap", "clamp_window"):
|
||||||
|
out[key] = float(val) * T if float(val) < 1000 else float(val)
|
||||||
|
elif key in ("median3", "literal", "epoch_aware"):
|
||||||
|
out[key] = val in ("1", "true", "yes")
|
||||||
|
elif key == "trig_exit" and val in ("none", "None"):
|
||||||
|
out[key] = None
|
||||||
|
else:
|
||||||
|
out[key] = float(val)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------- profiles
|
# ---------------------------------------------------------------- profiles
|
||||||
class Profile:
|
class Profile:
|
||||||
"""Hash rate in hashes per ms as a function of (time ms, height). `steps` lists (t_ms, factor) events
|
"""Hash rate in hashes per ms as a function of (time ms, height). `steps` lists (t_ms, factor) events
|
||||||
|
|
@ -578,6 +675,444 @@ def steady(blocks, t_from, t_to):
|
||||||
return std, (cs / cm if cm else None), max(gaps) / 1000
|
return std, (cs / cm if cm else None), max(gaps) / 1000
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- DAG model (4 October 2026, the live oscillation)
|
||||||
|
# Several miners on several nodes. A miner fetches a template from its node (the node stamps it with its clock at the
|
||||||
|
# fetch and the miner never touches the stamp, as igneum-miner does), the template reaches the card `delay` later (the
|
||||||
|
# miner's job queue), and the miner refetches every `period` and right after its own block. A block carries the parents
|
||||||
|
# and the stamp of the template it was mined from, so blocks found inside one another's staleness are parallel and the
|
||||||
|
# next block merges them. GHOSTDAG with every merged block blue (k = 18 is far above the width seen here): selected
|
||||||
|
# parent = the parent with the most blue work, blue work = the selected parent's plus the work of its mergeset blues
|
||||||
|
# (the selected parent included), DAA score = the selected parent's plus the mergeset size. The rule runs exactly as
|
||||||
|
# `SampledDifficultyManager::igneum_difficulty_bits`: the chain walk from the virtual's selected parent with blue-work
|
||||||
|
# increments over sanitised-clock steps, and the sampled window (every 4th block of each mergeset, selected parent
|
||||||
|
# first then descending blue work, 661 samples) restricted to the epoch for the long lane.
|
||||||
|
class DagBlock:
|
||||||
|
__slots__ = ("id", "parents", "sp", "ms", "work", "bw", "daa", "bs", "ts", "clock", "target", "past", "lane",
|
||||||
|
"found", "miner", "samples", "children", "arrival", "engaged_frac")
|
||||||
|
|
||||||
|
def __init__(self, bid):
|
||||||
|
self.id = bid
|
||||||
|
self.parents = []
|
||||||
|
self.sp = None
|
||||||
|
self.ms = [] # mergeset without the selected parent, descending blue work
|
||||||
|
self.children = []
|
||||||
|
self.samples = [] # (ts, bw, daa) of the sampled blocks of this block's mergeset
|
||||||
|
self.lane = False
|
||||||
|
self.past = set() # ids of recent ancestors (PAST_DEPTH ids back)
|
||||||
|
|
||||||
|
|
||||||
|
PAST_DEPTH = 400
|
||||||
|
|
||||||
|
|
||||||
|
class DagRule:
|
||||||
|
"""The Igneum rule on a DAG, parameters taken from an `Igneum` controller instance (so `igneum:...` variants apply)."""
|
||||||
|
|
||||||
|
def __init__(self, ctrl):
|
||||||
|
self.c = ctrl
|
||||||
|
self.cache = {}
|
||||||
|
|
||||||
|
def mergeset(self, parents, sp):
|
||||||
|
out = []
|
||||||
|
seen = set()
|
||||||
|
stack = [p for p in parents if p is not sp]
|
||||||
|
while stack:
|
||||||
|
x = stack.pop()
|
||||||
|
if x.id in seen or x is sp or x.id in sp.past or x.id < sp.id - PAST_DEPTH:
|
||||||
|
continue
|
||||||
|
seen.add(x.id)
|
||||||
|
out.append(x)
|
||||||
|
stack.extend(x.parents)
|
||||||
|
out.sort(key=lambda b: (-b.bw, b.id))
|
||||||
|
return out
|
||||||
|
|
||||||
|
def virtual(self, tips):
|
||||||
|
sp = max(tips, key=lambda b: (b.bw, -b.id))
|
||||||
|
ms = self.mergeset(tips, sp)
|
||||||
|
daa = sp.daa + 1 + len(ms)
|
||||||
|
return sp, ms, daa
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def samples_of(sp, ms):
|
||||||
|
"""Kaspa's sampled_mergeset_iterator for a block whose selected parent is sp: index 1 = sp, then the mergeset in
|
||||||
|
descending blue work; sampled where (daa(sp) + index) % rate == 0."""
|
||||||
|
out = []
|
||||||
|
for i, b in enumerate([sp] + ms, start=1):
|
||||||
|
if (sp.daa + i) % 4 == 0:
|
||||||
|
out.append((b.ts, b.bw, b.daa))
|
||||||
|
return out
|
||||||
|
|
||||||
|
def target_for(self, tips):
|
||||||
|
"""Target, DAA score and short-lane flag of the template built on `tips`."""
|
||||||
|
key = tuple(sorted(b.id for b in tips))
|
||||||
|
hit = self.cache.get(key)
|
||||||
|
if hit is not None:
|
||||||
|
return hit
|
||||||
|
c = self.c
|
||||||
|
sp, ms, daa = self.virtual(tips)
|
||||||
|
parent = sp.target
|
||||||
|
epoch_start = (daa // EPOCH) * EPOCH
|
||||||
|
k = daa - epoch_start
|
||||||
|
eng = False
|
||||||
|
if k < c.k_min:
|
||||||
|
cand = parent
|
||||||
|
else:
|
||||||
|
ref_start = max(epoch_start, daa - c.ref_window) if c.ref_window else epoch_start
|
||||||
|
# long lane: the virtual's own sampled mergeset, then the chain's, newest first, 661 samples
|
||||||
|
r_ref = None
|
||||||
|
if k >= c.long_min:
|
||||||
|
samples = self.samples_of(sp, ms)
|
||||||
|
cur = sp
|
||||||
|
while cur.id != 0 and len(samples) < c.window and cur.daa >= ref_start:
|
||||||
|
samples.extend(cur.samples)
|
||||||
|
cur = cur.sp
|
||||||
|
samples = [s for s in samples[:c.window] if s[2] >= ref_start]
|
||||||
|
if len(samples) >= c.long_min // c.rate:
|
||||||
|
mn = min(samples, key=lambda s: s[0])
|
||||||
|
mx = max(samples, key=lambda s: s[0])
|
||||||
|
if mx[1] > mn[1] and mx[0] > mn[0]:
|
||||||
|
r_ref = (mx[1] - mn[1]) / (mx[0] - mn[0])
|
||||||
|
# chain walk: blue-work increments over sanitised-clock steps, oldest first
|
||||||
|
limit = c.ns if r_ref is not None else max(c.long_min, c.ns)
|
||||||
|
steps = []
|
||||||
|
cur = sp
|
||||||
|
while cur.id != 0 and cur.daa >= ref_start and len(steps) < limit:
|
||||||
|
p = cur.sp
|
||||||
|
steps.append((cur.bw - p.bw, min(cur.clock - p.clock, c.cap)))
|
||||||
|
cur = p
|
||||||
|
steps.reverse()
|
||||||
|
r_s = self.short(steps, c.ns)
|
||||||
|
if c.median3 and len(steps) > 4:
|
||||||
|
r_s = sorted([r_s, self.short(steps[:-1], c.ns), self.short(steps[:-2], c.ns)])[1]
|
||||||
|
if r_ref is None:
|
||||||
|
work = sum(w for w, _ in steps)
|
||||||
|
time = max(sum(s for _, s in steps), 1)
|
||||||
|
kk = daa - ref_start
|
||||||
|
r_ref = (kk * work / time + c.k0 * (ONE / parent) / T) / (kk + c.k0)
|
||||||
|
r, eng = choose_rate(r_s, r_ref, sp.lane, c.trig, c.trig_exit, c.soft)
|
||||||
|
cand = ONE / (r * T)
|
||||||
|
base = None
|
||||||
|
if c.clamp_window:
|
||||||
|
b = sp
|
||||||
|
while b.id != 0 and sp.clock - b.clock < c.clamp_window:
|
||||||
|
b = b.sp
|
||||||
|
base = b.target
|
||||||
|
out = (clamp_target(cand, parent, base, c.clamp_pct, c.ease_pct), daa, eng)
|
||||||
|
self.cache[key] = out
|
||||||
|
return out
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def short(steps, ns):
|
||||||
|
n = min(ns, len(steps))
|
||||||
|
if n == 0:
|
||||||
|
return None
|
||||||
|
wsum = 0.0
|
||||||
|
dsum = 0.0
|
||||||
|
for i, (w, s) in enumerate(steps[len(steps) - n:], start=1):
|
||||||
|
wsum += s * i
|
||||||
|
dsum += w * i
|
||||||
|
wsum = max(wsum, n * n * T / 20)
|
||||||
|
return dsum / wsum
|
||||||
|
|
||||||
|
|
||||||
|
class DagMiner:
|
||||||
|
def __init__(self, name, node, period_ms, delay_ms, rpc_ms=30):
|
||||||
|
self.name, self.node, self.period, self.delay, self.rpc = name, node, period_ms, delay_ms, rpc_ms
|
||||||
|
self.hr = 0.0 # hashes per ms
|
||||||
|
self.template = None # (tips, ts, target, daa, eng)
|
||||||
|
self.pending = [] # (apply time, template) fetched but still in the job queue
|
||||||
|
self.t_apply = None
|
||||||
|
self.t_fetch = 0
|
||||||
|
self.t_solve = None
|
||||||
|
|
||||||
|
|
||||||
|
def simulate_dag(miners, schedule, ctrl, t0, t_end, rng, genesis_d, genesis_ts, nodes=2, prop_ms=100, verify_ms=30):
|
||||||
|
"""Blocks of a DAG mined by `miners` under the hash-rate `schedule` (sorted (t_ms, miner name, hashes per ms)).
|
||||||
|
Returns (blocks, chain ids, lane flips)."""
|
||||||
|
rule = DagRule(ctrl)
|
||||||
|
c = ctrl
|
||||||
|
genesis = DagBlock(0)
|
||||||
|
genesis.ts = genesis_ts
|
||||||
|
genesis.clock = genesis_ts
|
||||||
|
genesis.target = ONE / genesis_d
|
||||||
|
genesis.work = genesis_d
|
||||||
|
genesis.bw = 0.0
|
||||||
|
genesis.daa = 0
|
||||||
|
genesis.bs = 0
|
||||||
|
genesis.sp = genesis
|
||||||
|
genesis.found = t0
|
||||||
|
genesis.arrival = [t0] * nodes
|
||||||
|
genesis.miner = "genesis"
|
||||||
|
blocks = [genesis]
|
||||||
|
views = [[(t0, genesis)] for _ in range(nodes)] # per node, (arrival, block) in arrival order
|
||||||
|
by_name = {m.name: m for m in miners}
|
||||||
|
for m in miners:
|
||||||
|
m.t_fetch = t0 + rng.random() * m.period
|
||||||
|
si = 0
|
||||||
|
t = t0
|
||||||
|
flips = 0
|
||||||
|
last_lane = False
|
||||||
|
|
||||||
|
def tips_at(node, tau):
|
||||||
|
v = views[node]
|
||||||
|
out = []
|
||||||
|
for i in range(len(v) - 1, -1, -1):
|
||||||
|
arr, b = v[i]
|
||||||
|
if arr > tau:
|
||||||
|
continue
|
||||||
|
if all(ch.arrival[node] > tau for ch in b.children):
|
||||||
|
out.append(b)
|
||||||
|
if len(v) - i > 60 and out:
|
||||||
|
break
|
||||||
|
return out
|
||||||
|
|
||||||
|
def redraw(m, now):
|
||||||
|
if m.hr > 0 and m.template is not None:
|
||||||
|
D = ONE / m.template[2]
|
||||||
|
m.t_solve = now + rng.expovariate(1.0) * D / m.hr
|
||||||
|
else:
|
||||||
|
m.t_solve = None
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# next event
|
||||||
|
t_sched = schedule[si][0] if si < len(schedule) else None
|
||||||
|
ev, tm, who = None, None, None
|
||||||
|
for m in miners:
|
||||||
|
for kind, tt in (("solve", m.t_solve), ("fetch", m.t_fetch), ("apply", m.t_apply)):
|
||||||
|
if tt is not None and (tm is None or tt < tm):
|
||||||
|
ev, tm, who = kind, tt, m
|
||||||
|
if t_sched is not None and (tm is None or t_sched <= tm):
|
||||||
|
ev, tm, who = "sched", t_sched, None
|
||||||
|
if tm is None or tm > t_end:
|
||||||
|
break
|
||||||
|
t = tm
|
||||||
|
if ev == "sched":
|
||||||
|
_, name, hr = schedule[si]
|
||||||
|
si += 1
|
||||||
|
m = by_name[name]
|
||||||
|
m.hr = hr
|
||||||
|
redraw(m, t)
|
||||||
|
elif ev == "fetch":
|
||||||
|
m = who
|
||||||
|
tips = tips_at(m.node, t)
|
||||||
|
target, daa, eng = rule.target_for(tips)
|
||||||
|
m.pending.append((t + m.delay, (tips, t, target, daa, eng)))
|
||||||
|
m.t_apply = m.pending[0][0]
|
||||||
|
m.t_fetch = t + m.period
|
||||||
|
elif ev == "apply":
|
||||||
|
m = who
|
||||||
|
m.template = m.pending.pop(0)[1]
|
||||||
|
m.t_apply = m.pending[0][0] if m.pending else None
|
||||||
|
redraw(m, t)
|
||||||
|
elif ev == "solve":
|
||||||
|
m = who
|
||||||
|
tips, ts, target, daa, eng = m.template
|
||||||
|
b = DagBlock(len(blocks))
|
||||||
|
b.parents = tips
|
||||||
|
b.sp = max(tips, key=lambda x: (x.bw, -x.id))
|
||||||
|
b.ms = rule.mergeset(tips, b.sp)
|
||||||
|
b.ts = ts
|
||||||
|
b.target = target
|
||||||
|
b.work = ONE / target
|
||||||
|
b.bw = b.sp.bw + b.sp.work + sum(x.work for x in b.ms)
|
||||||
|
b.daa = b.sp.daa + 1 + len(b.ms)
|
||||||
|
b.bs = b.sp.bs + 1 + len(b.ms)
|
||||||
|
b.clock = max(b.sp.clock + clamp(ts - b.sp.clock, -c.cap, c.cap), ts - c.lag_caps * c.cap)
|
||||||
|
b.lane = eng
|
||||||
|
b.found = t
|
||||||
|
b.miner = m.name
|
||||||
|
b.samples = rule.samples_of(b.sp, b.ms)
|
||||||
|
past = set()
|
||||||
|
for p in tips:
|
||||||
|
past.add(p.id)
|
||||||
|
past.update(p.past)
|
||||||
|
b.past = {x for x in past if x >= b.id - PAST_DEPTH}
|
||||||
|
b.arrival = [t + (verify_ms if n == m.node else prop_ms) for n in range(nodes)]
|
||||||
|
for p in tips:
|
||||||
|
p.children.append(b)
|
||||||
|
blocks.append(b)
|
||||||
|
for n in range(nodes):
|
||||||
|
v = views[n]
|
||||||
|
arr = b.arrival[n]
|
||||||
|
i = len(v)
|
||||||
|
while i > 0 and v[i - 1][0] > arr:
|
||||||
|
i -= 1
|
||||||
|
v.insert(i, (arr, b))
|
||||||
|
if eng != last_lane:
|
||||||
|
flips += 1
|
||||||
|
last_lane = eng
|
||||||
|
m.t_fetch = min(m.t_fetch, t + m.rpc)
|
||||||
|
redraw(m, t)
|
||||||
|
# the selected chain of the final virtual
|
||||||
|
tips = tips_at(0, t_end + 10 * prop_ms)
|
||||||
|
chain = set()
|
||||||
|
cur = max(tips, key=lambda x: (x.bw, -x.id)) if tips else genesis
|
||||||
|
while True:
|
||||||
|
chain.add(cur.id)
|
||||||
|
if cur.id == 0:
|
||||||
|
break
|
||||||
|
cur = cur.sp
|
||||||
|
return blocks, chain, flips
|
||||||
|
|
||||||
|
|
||||||
|
def window_stats(items, secs):
|
||||||
|
"""items: (ts_ms, is_chain, mergeset_blues, parents, D, step_ms or None), D in the node's convention (2^255 / target)
|
||||||
|
i.e. half the expected hashes. Chain items in chain order."""
|
||||||
|
ch = [x for x in items if x[1]]
|
||||||
|
if len(ch) < 10:
|
||||||
|
return {"blocks": len(items)}
|
||||||
|
D = [x[4] for x in ch]
|
||||||
|
ld = [math.log(x) for x in D]
|
||||||
|
mean_ld = sum(ld) / len(ld)
|
||||||
|
std_ld = math.sqrt(sum((x - mean_ld) ** 2 for x in ld) / len(ld))
|
||||||
|
peaks = []
|
||||||
|
trough = D[0]
|
||||||
|
up = False
|
||||||
|
peak = pi = None
|
||||||
|
for i, x in enumerate(D):
|
||||||
|
if not up:
|
||||||
|
trough = min(trough, x)
|
||||||
|
if x >= trough * 1.15:
|
||||||
|
up, peak, pi = True, x, i
|
||||||
|
else:
|
||||||
|
if x > peak:
|
||||||
|
peak, pi = x, i
|
||||||
|
if x <= peak / 1.15:
|
||||||
|
peaks.append((pi, peak / trough))
|
||||||
|
up, trough = False, x
|
||||||
|
mins = {}
|
||||||
|
for x in items:
|
||||||
|
mins[int(x[0] // 60000)] = mins.get(int(x[0] // 60000), 0) + 1
|
||||||
|
counts = sorted(mins.values())[1:-1] if len(mins) > 2 else list(mins.values())
|
||||||
|
steps = sorted(x[5] for x in ch if x[5] is not None)
|
||||||
|
return {"blocks": len(items), "blocks_s": len(items) / secs, "chain_s": len(ch) / secs, "blues_per_chain": len(items) / len(ch),
|
||||||
|
"merge2_pct": 100.0 * sum(1 for x in ch if x[2] >= 2) / len(ch), "parents2_pct": 100.0 * sum(1 for x in items if x[3] >= 2) / len(items),
|
||||||
|
"step_median_ms": steps[len(steps) // 2] if steps else None,
|
||||||
|
"D_mean_M": sum(D) / len(D) / 1e6, "D_min_M": min(D) / 1e6, "D_max_M": max(D) / 1e6, "std_logD": std_ld,
|
||||||
|
"peaks15": len(peaks), "peak_ratio": (sum(p[1] for p in peaks) / len(peaks)) if peaks else None,
|
||||||
|
"peak_spacing_blocks": ((peaks[-1][0] - peaks[0][0]) / (len(peaks) - 1)) if len(peaks) > 1 else None,
|
||||||
|
"bpm_min": min(counts) if counts else None, "bpm_max": max(counts) if counts else None}
|
||||||
|
|
||||||
|
|
||||||
|
LIVE_COLS = [("blocks", "blocks"), ("blocks_s", "blocks/s"), ("chain_s", "chain/s"), ("blues_per_chain", "blues per chain block"),
|
||||||
|
("merge2_pct", "chain blocks merging 2+ %"), ("parents2_pct", "blocks with 2+ parents %"), ("step_median_ms", "chain step median ms"),
|
||||||
|
("D_mean_M", "difficulty mean M"), ("D_min_M", "min M"), ("D_max_M", "max M"), ("std_logD", "std log D"),
|
||||||
|
("peaks15", "peaks over 15%"), ("peak_ratio", "mean peak/trough"), ("peak_spacing_blocks", "peak spacing chain blocks"),
|
||||||
|
("bpm_min", "blocks/min min"), ("bpm_max", "blocks/min max"), ("flips", "lane flips"), ("engaged_pct", "short lane %")]
|
||||||
|
|
||||||
|
|
||||||
|
def record_items(rows, t_lo, t_hi):
|
||||||
|
by = {r["hash"]: r for r in rows}
|
||||||
|
out = []
|
||||||
|
for r in sorted(rows, key=lambda r: (int(r["blue_score"]), int(r["daa_score"]))):
|
||||||
|
ts = int(r["timestamp_ms"])
|
||||||
|
if int(r["daa_score"]) == 0 or not (t_lo <= ts < t_hi):
|
||||||
|
continue
|
||||||
|
p = by.get(r.get("selected_parent"))
|
||||||
|
step = (ts - int(p["timestamp_ms"])) if (p and r["is_chain_block"] == "1") else None
|
||||||
|
out.append((ts, r["is_chain_block"] == "1", int(r.get("mergeset_blues") or 1), int(r["parents"]), float(r["difficulty"]), step))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def dag_items(blocks, chain, t_lo, t_hi):
|
||||||
|
out = []
|
||||||
|
for b in blocks[1:]:
|
||||||
|
if not (t_lo <= b.ts < t_hi):
|
||||||
|
continue
|
||||||
|
is_chain = b.id in chain
|
||||||
|
out.append((b.ts, is_chain, 1 + len(b.ms), len(b.parents), b.work / 2.0, (b.ts - b.sp.ts) if is_chain else None, b.lane))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def live_schedule(path, t0, metal_mhs):
|
||||||
|
"""Hash-rate events from the records CSV (STATUS lines: the last 30 s of every worker): (t_ms, worker, hashes/ms).
|
||||||
|
A worker is off from 5 s after its last report when the next one is more than 45 s away. The Mac Metal miner has
|
||||||
|
no upload; it mines `metal_mhs` from t0."""
|
||||||
|
rows = list(csv.DictReader(open(path)))
|
||||||
|
byw = {}
|
||||||
|
for r in rows:
|
||||||
|
byw.setdefault(r["worker"], []).append((float(r["t_unix"]) * 1000, float(r["mh_s_last_30s"]) * 1e3))
|
||||||
|
ev = [(t0, "mac-metal", metal_mhs * 1e3)]
|
||||||
|
nodes = {"mac-metal": 1}
|
||||||
|
for w, pts in byw.items():
|
||||||
|
nodes[w] = 0 if rows[[r["worker"] for r in rows].index(w)]["node"] == "pc-node" else 1
|
||||||
|
pts.sort()
|
||||||
|
prev = None
|
||||||
|
for t, hr in pts:
|
||||||
|
if prev is None or t - prev > 45000:
|
||||||
|
if prev is not None:
|
||||||
|
ev.append((prev + 5000, w, 0.0))
|
||||||
|
ev.append((t - 30000, w, hr))
|
||||||
|
elif abs(hr - prev_hr) > 0.03 * max(prev_hr, 1):
|
||||||
|
ev.append((t - 30000, w, hr))
|
||||||
|
prev, prev_hr = t, hr
|
||||||
|
ev.append((prev + 5000, w, 0.0))
|
||||||
|
ev.sort()
|
||||||
|
return ev, nodes
|
||||||
|
|
||||||
|
|
||||||
|
def run_live(args, names):
|
||||||
|
import datetime
|
||||||
|
rows = list(csv.DictReader(open(args.live)))
|
||||||
|
rows.sort(key=lambda r: (int(r["blue_score"]), int(r["daa_score"])))
|
||||||
|
genesis = rows[0]
|
||||||
|
first = next(r for r in rows if int(r["daa_score"]) > 0 or int(r["blue_score"]) == 1)
|
||||||
|
t0 = int(first["timestamp_ms"]) - 1000
|
||||||
|
day = datetime.datetime.utcfromtimestamp(t0 / 1000).strftime("%Y-%m-%d")
|
||||||
|
|
||||||
|
def at(hhmm):
|
||||||
|
return int(datetime.datetime.fromisoformat("%sT%s:00+00:00" % (day, hhmm)).timestamp() * 1000)
|
||||||
|
|
||||||
|
windows = []
|
||||||
|
for w in args.live_windows.split(","):
|
||||||
|
name, span = w.split("=")
|
||||||
|
a, b = span.split("-")
|
||||||
|
windows.append((name, at(a), at(b)))
|
||||||
|
t_end = at(args.live_end) if args.live_end else max(int(r["timestamp_ms"]) for r in rows)
|
||||||
|
genesis_d = ONE / bits_to_target(int(genesis["bits"], 16))
|
||||||
|
schedule, node_of = live_schedule(args.hashrate, t0, args.metal_mhs)
|
||||||
|
print("# Live replay of %s: %d headers, DAG model, seed %d, delay scale %.2f\n" % (args.live, len(rows), args.seed, args.dag_delay))
|
||||||
|
print("Hash-rate schedule (from the log intake and the Mac's bench value), MH/s:\n")
|
||||||
|
print("| time UTC | worker | node | MH/s |")
|
||||||
|
print("|---|---|---|---|")
|
||||||
|
for t, w, hr in schedule:
|
||||||
|
print("| %s | %s | %s | %.1f |" % (datetime.datetime.utcfromtimestamp(t / 1000).strftime("%H:%M:%S"), w, "pc" if node_of[w] == 0 else "mac", hr / 1e3))
|
||||||
|
results = {}
|
||||||
|
for name, lo, hi in windows:
|
||||||
|
results.setdefault("record", {})[name] = window_stats(record_items(rows, lo, hi), (hi - lo) / 1000)
|
||||||
|
for cn in names:
|
||||||
|
ctrl = make_controller(cn, ONE / genesis_d)
|
||||||
|
if not isinstance(ctrl, Igneum):
|
||||||
|
continue
|
||||||
|
rng = random.Random(args.seed)
|
||||||
|
miners = []
|
||||||
|
for w, n in node_of.items():
|
||||||
|
if w == "mac-metal":
|
||||||
|
miners.append(DagMiner(w, n, 630, int(900 * args.dag_delay)))
|
||||||
|
else:
|
||||||
|
miners.append(DagMiner(w, n, 150, int(350 * args.dag_delay)))
|
||||||
|
blocks, chain, flips = simulate_dag(miners, schedule, ctrl, t0, t_end, rng, genesis_d, int(genesis["timestamp_ms"]), prop_ms=int(100 * args.dag_delay) + 20)
|
||||||
|
for name, lo, hi in windows:
|
||||||
|
items = dag_items(blocks, chain, lo, hi)
|
||||||
|
st = window_stats([x[:6] for x in items], (hi - lo) / 1000)
|
||||||
|
seg = [b for b in blocks[1:] if lo <= b.ts < hi and b.id in chain]
|
||||||
|
st["flips"] = sum(1 for a, b in zip(seg, seg[1:]) if a.lane != b.lane)
|
||||||
|
st["engaged_pct"] = 100.0 * sum(1 for b in seg if b.lane) / len(seg) if seg else None
|
||||||
|
results.setdefault(cn, {})[name] = st
|
||||||
|
if args.live_dump:
|
||||||
|
with open(args.live_dump % cn.replace(":", "_").replace("/", "_") if "%s" in args.live_dump else args.live_dump, "w") as f:
|
||||||
|
f.write("id,found_ms,ts_ms,daa,blue_score,chain,parents,mergeset_blues,difficulty,miner,lane\n")
|
||||||
|
for b in blocks[1:]:
|
||||||
|
f.write("%d,%d,%d,%d,%d,%d,%d,%d,%.0f,%s,%d\n" % (b.id, b.found, b.ts, b.daa, b.bs, b.id in chain, len(b.parents), 1 + len(b.ms), b.work / 2, b.miner, b.lane))
|
||||||
|
for name, lo, hi in windows:
|
||||||
|
print("\n### Window %s (%s to %s UTC)\n" % (name, datetime.datetime.utcfromtimestamp(lo / 1000).strftime("%H:%M"), datetime.datetime.utcfromtimestamp(hi / 1000).strftime("%H:%M")))
|
||||||
|
cols = [(k, h) for k, h in LIVE_COLS if any(k in results[r].get(name, {}) for r in results)]
|
||||||
|
print("| source | " + " | ".join(h for _, h in cols) + " |")
|
||||||
|
print("|---|" + "---|" * len(cols))
|
||||||
|
for r in results:
|
||||||
|
st = results[r].get(name, {})
|
||||||
|
print("| %s | " % r + " | ".join(fmt(st.get(k), 3 if k in ("std_logD", "blues_per_chain") else (2 if k in ("blocks_s", "chain_s", "peak_ratio") else 1)) for k, _ in cols) + " |")
|
||||||
|
|
||||||
|
|
||||||
def fmt(x, nd=1):
|
def fmt(x, nd=1):
|
||||||
if x is None:
|
if x is None:
|
||||||
return "none"
|
return "none"
|
||||||
|
|
@ -715,6 +1250,13 @@ def main():
|
||||||
ap.add_argument("--events", default="", help="real record: comma list of ISO times of miner events")
|
ap.add_argument("--events", default="", help="real record: comma list of ISO times of miner events")
|
||||||
ap.add_argument("--dump", default="", help="profile:controller, write per-block trajectory to stdout as CSV and exit")
|
ap.add_argument("--dump", default="", help="profile:controller, write per-block trajectory to stdout as CSV and exit")
|
||||||
ap.add_argument("--custom", default="", help="extra profile: name=genesis_bits_hex,base_MHs,duration_s,t_s:factor,t_s:factor,...")
|
ap.add_argument("--custom", default="", help="extra profile: name=genesis_bits_hex,base_MHs,duration_s,t_s:factor,t_s:factor,...")
|
||||||
|
ap.add_argument("--live", default="", help="DAG replay of a live record (records/live-2026-10-04.csv) against the controllers")
|
||||||
|
ap.add_argument("--hashrate", default="", help="live replay: the hash-rate CSV from the log intake (records/live-2026-10-04-hashrate.csv)")
|
||||||
|
ap.add_argument("--live-windows", default="solo=09:25-10:04,both=10:17-10:32,late=10:37-10:54", help="live replay: name=HH:MM-HH:MM UTC windows to compare")
|
||||||
|
ap.add_argument("--live-end", default="", help="live replay: stop at HH:MM UTC (default: the record's last stamp)")
|
||||||
|
ap.add_argument("--live-dump", default="", help="live replay: write every simulated block to this CSV (%s = controller name)")
|
||||||
|
ap.add_argument("--dag-delay", type=float, default=1.0, help="live replay: scale of the miners' template staleness and propagation (1 = fitted)")
|
||||||
|
ap.add_argument("--metal-mhs", type=float, default=26.7, help="live replay: the Mac Metal miner's hash rate (no upload; bench-log value)")
|
||||||
ap.add_argument("--quick", action="store_true",
|
ap.add_argument("--quick", action="store_true",
|
||||||
help="smoke run for CI: profiles up50 and warmup-hard, controllers kaspa and igneum (about a minute); --profiles and --controllers still override")
|
help="smoke run for CI: profiles up50 and warmup-hard, controllers kaspa and igneum (about a minute); --profiles and --controllers still override")
|
||||||
args = ap.parse_args()
|
args = ap.parse_args()
|
||||||
|
|
@ -724,6 +1266,9 @@ def main():
|
||||||
if args.controllers == "kaspa,monero,lwma60,lwma120,igneum,igneum-literal":
|
if args.controllers == "kaspa,monero,lwma60,lwma120,igneum,igneum-literal":
|
||||||
args.controllers = "kaspa,igneum"
|
args.controllers = "kaspa,igneum"
|
||||||
names = args.controllers.split(",")
|
names = args.controllers.split(",")
|
||||||
|
if args.live:
|
||||||
|
run_live(args, names)
|
||||||
|
return
|
||||||
profiles = synthetic_profiles(args.seed)
|
profiles = synthetic_profiles(args.seed)
|
||||||
if args.profiles != "all":
|
if args.profiles != "all":
|
||||||
want = args.profiles.split(",")
|
want = args.profiles.split(",")
|
||||||
|
|
|
||||||
247
sim/difficulty/testnet_v2.py
Normal file
247
sim/difficulty/testnet_v2.py
Normal file
|
|
@ -0,0 +1,247 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""3-node CPU test network for difficulty rule v2 and its height switch (4 October 2026).
|
||||||
|
|
||||||
|
Ports 29600 and above, appdir /tmp/igneum-diffv2, binaries from vendor/igneum-node-v4/target/release (the devnet-v4
|
||||||
|
line with `difficulty_v2_activation_daa`). Never touches the live devnet (26610/26611, 26640/26641, 28640).
|
||||||
|
|
||||||
|
Profile: infra/fast-time/override-60x.json plus genesis bits 0x1f010000 (2^16 hashes per block, the CPU difficulty),
|
||||||
|
the devnet's program epoch (pow_epoch_blocks 3,600, lead 600: the 60x file's one-minute epoch would empty the
|
||||||
|
reference window every minute and hide the pollution this test is about), and `difficulty_v2_activation_daa` at the
|
||||||
|
given height. Node 1 (gRPC 29600, P2P 29601, wRPC JSON 29602) and node 2 (29610/29611) carry the activation; node 3
|
||||||
|
(29620/29621) is started WITHOUT it (rule v1 for ever) and follows only: it must stall at the activation height,
|
||||||
|
which shows the switch is consensus-critical and takes effect at that block and no other.
|
||||||
|
|
||||||
|
Schedule (minutes from the first miner): A (4 CPU threads) on node 1 all run; B (4 threads) on node 2 from `--join`
|
||||||
|
(a 2x step inside epoch 0, the live devnet's case), off at `--leave`, back at `--rejoin`. The activation height is
|
||||||
|
chosen so the first step runs under rule v1 and the leave and rejoin under v2.
|
||||||
|
|
||||||
|
python3 testnet_v2.py --minutes 28 --join 4 --activation 900 --leave 19 --rejoin 23 --out /tmp/igneum-diffv2/run1
|
||||||
|
python3 testnet_v2.py --analyse /tmp/igneum-diffv2/run1
|
||||||
|
"""
|
||||||
|
import argparse
|
||||||
|
import csv
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
sys.path.insert(0, os.path.join(HERE, "attacks"))
|
||||||
|
import testnet as TN # noqa: E402 (node/miner helpers, wRPC export)
|
||||||
|
|
||||||
|
ROOT = os.path.abspath(os.path.join(HERE, "..", ".."))
|
||||||
|
BIN = os.environ.get("IGNEUM_BIN", os.path.join(ROOT, "vendor", "igneum-node-v4", "target", "release"))
|
||||||
|
FAST = os.path.join(ROOT, "infra", "fast-time", "override-60x.json")
|
||||||
|
GENESIS_BITS = 0x1f010000
|
||||||
|
NODES = [
|
||||||
|
{"name": "node1", "grpc": 29600, "p2p": 29601, "json": 29602},
|
||||||
|
{"name": "node2", "grpc": 29610, "p2p": 29611, "json": 29612},
|
||||||
|
{"name": "node3", "grpc": 29620, "p2p": 29621, "json": 29622},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def write_override(out, name, activation):
|
||||||
|
o = json.load(open(FAST))
|
||||||
|
o["genesis_bits"] = GENESIS_BITS
|
||||||
|
o["pow_epoch_blocks"] = 3600
|
||||||
|
o["pow_epoch_lead"] = 600
|
||||||
|
if activation is not None:
|
||||||
|
o["difficulty_v2_activation_daa"] = activation
|
||||||
|
else:
|
||||||
|
o.pop("difficulty_v2_activation_daa", None)
|
||||||
|
path = os.path.join(out, name)
|
||||||
|
with open(path, "w") as f:
|
||||||
|
json.dump(o, f)
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def start_node(n, out, override):
|
||||||
|
appdir = os.path.join(out, n["name"])
|
||||||
|
args = [os.path.join(BIN, "igneumd"), "--devnet", "--devnet-suffix=960", "--nodnsseed", "--disable-upnp",
|
||||||
|
"--enable-unsynced-mining", "--nologfiles", "--override-params-file=" + override, "--appdir=" + appdir,
|
||||||
|
"--rpclisten=127.0.0.1:%d" % n["grpc"], "--listen=127.0.0.1:%d" % n["p2p"],
|
||||||
|
"--rpclisten-json=127.0.0.1:%d" % n["json"], "--loglevel=info"]
|
||||||
|
if n["name"] != "node1":
|
||||||
|
args.append("--connect=127.0.0.1:%d" % NODES[0]["p2p"])
|
||||||
|
else:
|
||||||
|
args.append("--outpeers=0")
|
||||||
|
lf = open(os.path.join(out, n["name"] + ".log"), "w")
|
||||||
|
p = subprocess.Popen(["nice", "-n", "19"] + args, stdout=lf, stderr=subprocess.STDOUT)
|
||||||
|
TN.started.append(p)
|
||||||
|
TN.log(out, "%s pid %d gRPC %d override %s" % (n["name"], p.pid, n["grpc"], os.path.basename(override)))
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
def start_miner(out, label, grpc, threads, secs):
|
||||||
|
lf = open(os.path.join(out, "miner-%s.log" % label), "a")
|
||||||
|
args = ["nice", "-n", "19", os.path.join(BIN, "igneum-miner"), "mine", "grpc://127.0.0.1:%d" % grpc, str(threads), str(secs),
|
||||||
|
label, "--engine", "igneum-pow", "--payout-label", label, "--status-secs", "10"]
|
||||||
|
env = dict(os.environ)
|
||||||
|
env["IGNEUM_POW_DAY_MS"] = "1440000"
|
||||||
|
p = subprocess.Popen(args, stdout=lf, stderr=subprocess.STDOUT, env=env)
|
||||||
|
TN.started.append(p)
|
||||||
|
TN.log(out, "miner %s pid %d on %d threads %d for %d s" % (label, p.pid, grpc, threads, secs))
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
def daa_of(port):
|
||||||
|
try:
|
||||||
|
return int(TN.dag_info(port)["virtualDaaScore"])
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def run(args):
|
||||||
|
out = args.out
|
||||||
|
os.makedirs(out, exist_ok=True)
|
||||||
|
total = args.minutes * 60
|
||||||
|
TN.log(out, "start minutes=%d join=%d leave=%d rejoin=%d activation=%d genesis_bits=%#x bin=%s" % (
|
||||||
|
args.minutes, args.join, args.leave, args.rejoin, args.activation, GENESIS_BITS, BIN))
|
||||||
|
ov_v2 = write_override(out, "override-v2.json", args.activation)
|
||||||
|
ov_v1 = write_override(out, "override-v1.json", None)
|
||||||
|
try:
|
||||||
|
start_node(NODES[0], out, ov_v2)
|
||||||
|
TN.wait_grpc(out, NODES[0])
|
||||||
|
start_node(NODES[1], out, ov_v2)
|
||||||
|
start_node(NODES[2], out, ov_v1)
|
||||||
|
for n in NODES[1:]:
|
||||||
|
TN.wait_grpc(out, n)
|
||||||
|
time.sleep(3)
|
||||||
|
t0 = time.time()
|
||||||
|
TN.log(out, "miners from now")
|
||||||
|
a = start_miner(out, "A", NODES[0]["grpc"], args.threads, total)
|
||||||
|
b = None
|
||||||
|
phase = "solo"
|
||||||
|
last_daa = {}
|
||||||
|
switched = None
|
||||||
|
while time.time() - t0 < total:
|
||||||
|
m = (time.time() - t0) / 60.0
|
||||||
|
if phase == "solo" and m >= args.join:
|
||||||
|
b = start_miner(out, "B", NODES[1]["grpc"], args.threads, int((args.leave - args.join) * 60))
|
||||||
|
phase = "joined"
|
||||||
|
TN.log(out, "B joins (2x step under rule v1)")
|
||||||
|
elif phase == "joined" and m >= args.leave:
|
||||||
|
TN.stop(b, out, "miner B (leave)")
|
||||||
|
phase = "left"
|
||||||
|
TN.log(out, "B leaves (step down under rule v2)")
|
||||||
|
elif phase == "left" and m >= args.rejoin:
|
||||||
|
b = start_miner(out, "B", NODES[1]["grpc"], args.threads, int(total - (time.time() - t0)) + 5)
|
||||||
|
phase = "rejoined"
|
||||||
|
TN.log(out, "B rejoins (step up under rule v2)")
|
||||||
|
d = {n["name"]: daa_of(n["json"]) for n in NODES}
|
||||||
|
if d != last_daa and int(m * 6) % 3 == 0:
|
||||||
|
last_daa = d
|
||||||
|
if switched is None and d.get("node1") is not None and d["node1"] >= args.activation:
|
||||||
|
switched = time.time() - t0
|
||||||
|
TN.log(out, "node1 virtual DAA %d reached the activation %d at %.0f s; node3 (v1) at DAA %s" % (d["node1"], args.activation, switched, d.get("node3")))
|
||||||
|
if int(time.time() - t0) % 30 == 0:
|
||||||
|
try:
|
||||||
|
info = TN.dag_info(NODES[0]["json"])
|
||||||
|
TN.log(out, "t=%.0f s daa node1/2/3 %s/%s/%s difficulty %.0f blocks %s" % (
|
||||||
|
time.time() - t0, d.get("node1"), d.get("node2"), d.get("node3"), float(info["difficulty"]), info["blockCount"]))
|
||||||
|
except Exception as e:
|
||||||
|
TN.log(out, "dag info failed: %s" % e)
|
||||||
|
time.sleep(1)
|
||||||
|
if b is not None:
|
||||||
|
TN.stop(b, out, "miner B")
|
||||||
|
TN.stop(a, out, "miner A")
|
||||||
|
time.sleep(2)
|
||||||
|
for n in NODES:
|
||||||
|
try:
|
||||||
|
rows, info = TN.export(n["json"], os.path.join(out, "record-%s.csv" % n["name"]))
|
||||||
|
TN.log(out, "%s: %s, %d rows" % (n["name"], json.dumps({k: info.get(k) for k in ("blockCount", "difficulty", "virtualDaaScore", "sink")}), len(rows)))
|
||||||
|
except Exception as e:
|
||||||
|
TN.log(out, "%s export failed: %s" % (n["name"], e))
|
||||||
|
finally:
|
||||||
|
for p in reversed(TN.started):
|
||||||
|
TN.stop(p, out, "pid")
|
||||||
|
TN.log(out, "end")
|
||||||
|
|
||||||
|
|
||||||
|
def analyse(out):
|
||||||
|
sched = open(os.path.join(out, "schedule.log")).read().splitlines()
|
||||||
|
rows = list(csv.DictReader(open(os.path.join(out, "record-node1.csv"))))
|
||||||
|
rows = [r for r in rows if int(r["blue_score"]) > 0]
|
||||||
|
chain = sorted([r for r in rows if r["is_chain_block"] == "1"], key=lambda r: int(r["blue_score"]))
|
||||||
|
t0 = int(chain[0]["timestamp_ms"]) / 1000.0
|
||||||
|
marks = {}
|
||||||
|
for line in sched:
|
||||||
|
for key, pat in (("join", "B joins"), ("leave", "B leaves"), ("rejoin", "B rejoins"), ("switch", "reached the activation")):
|
||||||
|
if pat in line:
|
||||||
|
hms = line.split()[0]
|
||||||
|
marks[key] = hms
|
||||||
|
print("blocks %d, chain blocks %d; schedule marks %s" % (len(rows), len(chain), marks))
|
||||||
|
print("\n| from s | chain blocks | chain/s | all blocks | mean difficulty | min | max | DAA at end |")
|
||||||
|
print("|---|---|---|---|---|---|---|---|")
|
||||||
|
bins = {}
|
||||||
|
for r in rows:
|
||||||
|
b = int((int(r["timestamp_ms"]) / 1000.0 - t0) // 30)
|
||||||
|
d = bins.setdefault(b, {"n": 0, "c": 0, "D": [], "daa": 0})
|
||||||
|
d["n"] += 1
|
||||||
|
if r["is_chain_block"] == "1":
|
||||||
|
d["c"] += 1
|
||||||
|
d["D"].append(float(r["difficulty"]))
|
||||||
|
d["daa"] = max(d["daa"], int(r["daa_score"]))
|
||||||
|
for b in sorted(bins):
|
||||||
|
d = bins[b]
|
||||||
|
if not d["D"]:
|
||||||
|
continue
|
||||||
|
print("| %d | %d | %.2f | %d | %s | %s | %s | %d |" % (b * 30, d["c"], d["c"] / 30.0, d["n"], "{:,.0f}".format(sum(d["D"]) / len(d["D"])),
|
||||||
|
"{:,.0f}".format(min(d["D"])), "{:,.0f}".format(max(d["D"])), d["daa"]))
|
||||||
|
# phases by DAA score of the chain: std of log difficulty and peaks over 15%
|
||||||
|
def phase_stats(lo_s, hi_s):
|
||||||
|
seg = [float(r["difficulty"]) for r in chain if lo_s <= int(r["timestamp_ms"]) / 1000.0 - t0 < hi_s]
|
||||||
|
if len(seg) < 10:
|
||||||
|
return None
|
||||||
|
ld = [math.log(x) for x in seg]
|
||||||
|
m = sum(ld) / len(ld)
|
||||||
|
std = math.sqrt(sum((x - m) ** 2 for x in ld) / len(ld))
|
||||||
|
peaks = 0
|
||||||
|
trough = seg[0]
|
||||||
|
up = False
|
||||||
|
peak = None
|
||||||
|
for x in seg:
|
||||||
|
if not up:
|
||||||
|
trough = min(trough, x)
|
||||||
|
if x >= trough * 1.15:
|
||||||
|
up, peak = True, x
|
||||||
|
else:
|
||||||
|
peak = max(peak, x)
|
||||||
|
if x <= peak / 1.15:
|
||||||
|
peaks += 1
|
||||||
|
up, trough = False, x
|
||||||
|
return len(seg), std, peaks, min(seg), max(seg)
|
||||||
|
return phase_stats
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
ap = argparse.ArgumentParser()
|
||||||
|
ap.add_argument("--minutes", type=int, default=28)
|
||||||
|
ap.add_argument("--join", type=int, default=4)
|
||||||
|
ap.add_argument("--leave", type=int, default=19)
|
||||||
|
ap.add_argument("--rejoin", type=int, default=23)
|
||||||
|
ap.add_argument("--activation", type=int, default=900)
|
||||||
|
ap.add_argument("--threads", type=int, default=4)
|
||||||
|
ap.add_argument("--out", default="/tmp/igneum-diffv2/run")
|
||||||
|
ap.add_argument("--analyse", default="")
|
||||||
|
ap.add_argument("--phases", default="", help="analyse: name=lo_s-hi_s,... windows for std of log difficulty")
|
||||||
|
args = ap.parse_args()
|
||||||
|
if args.analyse:
|
||||||
|
ps = analyse(args.analyse)
|
||||||
|
if args.phases:
|
||||||
|
print("\n| phase | chain blocks | std log D | peaks over 15% | min | max |")
|
||||||
|
print("|---|---|---|---|---|---|")
|
||||||
|
for w in args.phases.split(","):
|
||||||
|
name, span = w.split("=")
|
||||||
|
lo, hi = span.split("-")
|
||||||
|
st = ps(float(lo), float(hi))
|
||||||
|
if st:
|
||||||
|
print("| %s | %d | %.3f | %d | %s | %s |" % (name, st[0], st[1], st[2], "{:,.0f}".format(st[3]), "{:,.0f}".format(st[4])))
|
||||||
|
return
|
||||||
|
run(args)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
Reference in a new issue