igneum/sim/difficulty/attacks/results.md
igneum-labs c01b9544a4 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>
2026-10-04 13:26:23 +00:00

37 KiB

Raw simulator output behind README.md (4 October 2026)

Seeds 7, 8, 9 unless stated. Tables are attacks.py output; the candidate igneum-san is the sanitised clock with the 60 s lag bound (README.md, Part B) unless stated.

Full suite, Kaspa's timestamp rules (the forger under 132 s and the past median)

Difficulty attacks, seeds [7, 8, 9], rules ['igneum', 'igneum-san', 'kaspa']

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 10 0 0.015 0.015 0.432 301.0 0.072 12.7 0.998 3
igneum 10 60 0.013 0.014 0.437 227.0 0.072 12.6 0.998 3
igneum 30 0 0.010 0.011 0.216 492.0 0.135 12.8 0.994 3
igneum 30 60 0.001 0.003 0.283 394.0 0.140 13.9 0.992 3
igneum 50 0 0.009 0.010 0.149 616.7 0.197 13.8 0.992 3
igneum 50 60 -0.017 -0.022 0.283 544.7 0.211 13.8 0.984 3
igneum 100 0 0.007 0.007 0.085 741.0 0.339 13.3 0.990 3
igneum 100 60 -0.040 -0.054 0.378 818.0 0.349 16.9 0.968 3
igneum-san 10 0 0.015 0.015 0.432 301.0 0.072 12.7 0.998 3
igneum-san 10 60 0.013 0.014 0.437 227.0 0.072 12.6 0.998 3
igneum-san 30 0 0.010 0.011 0.216 492.0 0.135 12.8 0.994 3
igneum-san 30 60 0.001 0.003 0.283 394.0 0.140 13.9 0.992 3
igneum-san 50 0 0.009 0.010 0.149 616.7 0.197 13.8 0.992 3
igneum-san 50 60 -0.017 -0.022 0.283 544.7 0.211 13.8 0.984 3
igneum-san 100 0 0.007 0.007 0.085 741.0 0.339 13.3 0.990 3
igneum-san 100 60 -0.040 -0.054 0.378 818.0 0.349 16.9 0.968 3
kaspa 10 0 0.008 0.009 0.367 63.7 0.054 11.8 1.000 3
kaspa 10 60 0.008 0.009 0.367 63.7 0.054 11.8 1.000 3
kaspa 30 0 0.006 0.007 0.181 88.0 0.124 12.3 1.001 3
kaspa 30 60 0.006 0.007 0.181 88.0 0.124 12.3 1.001 3
kaspa 50 0 0.005 0.006 0.116 112.3 0.180 12.7 1.001 3
kaspa 50 60 0.005 0.006 0.115 111.3 0.179 12.6 1.001 3
kaspa 100 0 0.005 0.006 0.061 122.7 0.304 12.5 1.001 3
kaspa 100 60 0.004 0.005 0.068 132.0 0.315 12.5 1.001 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 3600 -0.963 -0.964 0.263 0.267 -0.977 -0.375 0.234 0.893 183.7 152.5 0.824 3
igneum 1000000 -0.971 -0.972 0.131 0.138 -0.976 -0.186 0.106 0.806 177.0 81.3 0.920 3
igneum-san 3600 -0.964 -0.965 0.262 0.267 -0.977 -0.362 0.234 0.893 182.3 221.4 0.823 3
igneum-san 1000000 -0.971 -0.972 0.130 0.136 -0.976 -0.179 0.105 0.806 177.0 78.4 0.927 3
kaspa 3600 -0.145 -0.159 0.983 0.984 -0.898 -0.880 0.878 0.893 1734.0 102.7 0.979 3
kaspa 1000000 -0.432 -0.443 0.871 0.879 -0.884 -0.796 0.703 0.806 1734.0 68.4 0.686 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 kaspa 30 future 132.0 0.994 0.656 0.658 -0.344 -0.350 1.549 0.136 15.6 0.000 3
igneum kaspa 30 past -439.1 0.994 0.415 0.428 -0.585 -0.597 2.421 0.243 44.8 0.000 3
igneum kaspa 30 alt -70.3 0.994 0.514 0.513 -0.486 -0.545 1.966 0.381 37.0 0.000 3
igneum kaspa 50 future 132.0 0.994 0.563 0.573 -0.437 -0.449 1.796 0.103 17.1 0.000 3
igneum kaspa 50 past -2122.9 0.994 0.116 0.119 -0.884 -0.925 9.886 0.186 233.8 0.000 3
igneum kaspa 50 alt -289.0 0.994 0.231 0.221 -0.769 -0.804 4.393 0.257 83.5 0.000 3
igneum-san kaspa 30 future 132.0 0.994 0.091 0.100 -0.909 -0.911 10.9 0.055 119.1 0.000 3
igneum-san kaspa 30 past -195.5 0.994 0.931 0.874 -0.069 -0.092 1.084 0.228 20.4 0.000 3
igneum-san kaspa 30 alt -786.0 0.994 0.087 0.091 -0.913 -0.918 11.6 0.058 126.6 0.000 3
igneum-san kaspa 50 future 132.0 0.994 0.166 0.188 -0.834 -0.860 6.046 0.173 102.4 0.000 3
igneum-san kaspa 50 past -4510.6 0.994 0.033 0.009 -0.967 -0.992 64.0 0.098 607.0 0.000 3
igneum-san kaspa 50 alt -2039.9 0.994 0.038 0.036 -0.962 -0.968 25.6 0.024 439.2 0.000 3
kaspa kaspa 30 future 132.0 0.993 1.049 1.049 0.049 0.052 0.959 0.018 8.825 0.000 3
kaspa kaspa 30 past -170.2 0.993 1.069 1.073 0.069 0.072 0.941 0.021 8.675 0.000 3
kaspa kaspa 30 alt 6.993 0.993 1.090 1.092 0.090 0.092 0.923 0.023 8.463 0.000 3
kaspa kaspa 50 future 132.0 0.993 1.050 1.052 0.050 0.054 0.958 0.018 8.840 0.000 3
kaspa kaspa 50 past -235.6 0.993 1.113 1.113 0.113 0.116 0.904 0.027 8.353 0.000 3
kaspa kaspa 50 alt 8.892 0.993 1.098 1.100 0.098 0.100 0.916 0.021 8.451 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 25 120 0.045 0.160 3.753 4.815 0.143 8.789 11.0 0.980 -0.014 3
igneum-san 25 120 0.045 0.160 3.753 4.815 0.143 8.789 11.0 0.980 -0.014 3
kaspa 25 120 0.010 0.147 16.4 23.5 0.143 8.906 10.3 1.001 0.000 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 dodge 0.000 0.000 0.997 0.054 9.598 1.002 3
igneum flood 0.007 0.024 0.000 0.470 9.986 0.995 3
igneum flood30 0.003 0.021 0.001 0.054 9.811 0.997 3
igneum-san dodge 0.000 0.000 0.997 0.054 9.598 1.002 3
igneum-san flood 0.007 0.024 0.000 0.470 9.986 0.995 3
igneum-san flood30 0.003 0.021 0.001 0.054 9.811 0.997 3
kaspa dodge 0.000 0.000 0.997 0.026 9.360 1.001 3
kaspa flood 0.000 0.005 0.000 0.482 9.293 1.001 3
kaspa flood30 -0.001 0.004 0.002 0.030 9.278 1.001 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 0 600 88.6 134.8 303.1 303.1 16.9 55.3 0.000 3
igneum 480 600 none none 291.9 291.9 15.2 50.3 0.000 3
igneum 480 720 76.3 58.3 321.4 321.4 28.4 56.7 0.000 3
igneum 0 1200 88.6 134.8 312.2 334.0 24.5 56.7 0.000 3
igneum-san 0 600 88.6 134.8 296.8 296.8 16.4 55.3 0.000 3
igneum-san 480 600 none none 286.7 286.7 14.8 47.3 0.000 3
igneum-san 480 720 76.3 58.3 312.0 312.0 28.4 54.3 0.000 3
igneum-san 0 1200 88.6 134.8 304.7 328.7 24.5 55.7 0.000 3
kaspa 0 600 none none 2910.0 2910.0 9.954 0.000 0.000 3
kaspa 480 600 none none 0.000 0.000 8.600 0.000 0.000 3
kaspa 480 720 none none 135.3 135.3 8.838 0.000 0.000 3
kaspa 0 1200 none none 3539.6 3539.6 13.1 0.000 0.000 3

Timestamp stretching under the tight rules (README.md, Part A: 10 s ahead, selected parent minus 10 s)

Difficulty attacks, seeds [7, 8, 9], rules ['igneum', 'igneum-san', 'kaspa']

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 tight 30 future 10.0 0.994 1.008 1.006 0.008 0.018 0.999 0.067 9.662 0.000 3
igneum tight 30 past -16.6 0.994 0.636 0.649 -0.364 -0.381 1.597 0.201 32.5 0.000 3
igneum tight 30 alt 1.012 0.994 0.975 0.968 -0.025 -0.035 1.030 0.067 10.7 0.000 3
igneum tight 50 future 10.0 0.994 1.009 1.001 0.009 0.021 0.997 0.071 9.792 0.000 3
igneum tight 50 past -30.3 0.994 0.170 0.132 -0.830 -0.850 5.917 0.115 106.0 0.000 3
igneum tight 50 alt 1.975 0.994 0.949 0.936 -0.051 -0.057 1.059 0.088 11.6 0.000 3
igneum-san tight 30 future 10.0 0.994 1.008 1.006 0.008 0.018 0.999 0.067 9.662 0.000 3
igneum-san tight 30 past -15.8 0.994 1.008 1.006 0.008 0.024 0.998 0.077 9.920 0.000 3
igneum-san tight 30 alt 1.036 0.994 1.004 1.001 0.004 0.012 1.001 0.052 9.826 0.000 3
igneum-san tight 50 future 10.0 0.994 1.009 1.001 0.009 0.021 0.997 0.071 9.792 0.000 3
igneum-san tight 50 past -21.9 0.994 1.007 1.012 0.007 0.027 1.000 0.147 10.1 0.000 3
igneum-san tight 50 alt 2.017 0.994 1.011 1.005 0.011 0.022 0.995 0.071 9.996 0.000 3
kaspa tight 30 future 10.0 0.993 1.000 1.003 0.000 0.005 1.005 0.017 9.249 0.000 3
kaspa tight 30 past -15.8 0.993 1.002 1.002 0.002 0.007 1.002 0.018 9.239 0.000 3
kaspa tight 30 alt 1.036 0.993 1.001 1.003 0.001 0.005 1.004 0.017 9.220 0.000 3
kaspa tight 50 future 10.0 0.993 1.001 1.002 0.001 0.005 1.004 0.017 9.252 0.000 3
kaspa tight 50 past -21.9 0.993 1.009 1.012 0.009 0.015 0.996 0.019 9.152 0.000 3
kaspa tight 50 alt 1.987 0.993 1.001 1.002 0.001 0.005 1.004 0.017 9.238 0.000 3

Base profiles (sim.py metrics) through each rule

Difficulty attacks, seeds [7, 8, 9], rules ['igneum', 'igneum-san', 'kaspa']

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 up50 56.1 154.4 none 9.719 0.042 none none 3
igneum down50 782.3 782.3 none 78.3 0.042 none none 3
igneum epoch30 44.6 87.6 none 10.8 0.039 none 0.000 3
igneum walk10 none none 3 10.7 0.058 none none 3
igneum hop10 213.8 239.4 none 31.9 0.042 none 0.000 3
igneum polluted 70.1 70.1 none 10.2 0.041 7.969 none 3
igneum warmup-hard 381.3 381.3 none 34.6 0.039 none none 3
igneum-san up50 56.1 154.4 none 9.719 0.042 none none 3
igneum-san down50 728.5 762.2 none 73.9 0.042 none none 3
igneum-san epoch30 44.6 87.6 none 10.8 0.039 none 0.000 3
igneum-san walk10 none none 3 10.7 0.058 none none 3
igneum-san hop10 210.3 245.1 none 35.6 0.042 none 0.000 3
igneum-san polluted 74.9 74.9 none 10.2 0.041 11.4 none 3
igneum-san warmup-hard 305.8 326.5 none 34.6 0.039 none none 3
kaspa up50 1764.8 1764.8 none 9.869 0.014 none none 3
kaspa down50 12306.2 12306.2 none 155.2 0.014 none none 3
kaspa epoch30 1663.5 1663.5 none 10.9 0.023 none 0.000 3
kaspa walk10 none none 3 10.8 0.044 none none 3
kaspa hop10 none none 3 45.6 0.014 none 12.0 3
kaspa polluted 695.0 2713.3 none 11.4 0.013 8.225 none 3
kaspa warmup-hard 5975.0 none 3 68.8 43.4 none none 3

Lag bound of the sanitised clock (older naming: igneum-san = 120 s bound, igneum-san-j60 = 60 s bound; 60 s was adopted)

Difficulty attacks, seeds [7, 8, 9], rules ['igneum-san', 'igneum-san-j60']

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-san up50 56.1 154.4 none 9.719 0.042 none none 3
igneum-san down50 720.9 758.9 none 73.9 0.042 none none 3
igneum-san epoch30 44.6 87.6 none 10.8 0.039 none 0.000 3
igneum-san walk10 none none 3 10.7 0.058 none none 3
igneum-san hop10 210.3 245.1 none 35.6 0.042 none 0.000 3
igneum-san polluted 83.6 83.6 none 10.2 0.041 17.8 none 3
igneum-san warmup-hard 305.8 326.5 none 34.6 0.039 none none 3
igneum-san-j60 up50 56.1 154.4 none 9.719 0.042 none none 3
igneum-san-j60 down50 728.5 762.2 none 73.9 0.042 none none 3
igneum-san-j60 epoch30 44.6 87.6 none 10.8 0.039 none 0.000 3
igneum-san-j60 walk10 none none 3 10.7 0.058 none none 3
igneum-san-j60 hop10 210.3 245.1 none 35.6 0.042 none 0.000 3
igneum-san-j60 polluted 74.9 74.9 none 10.2 0.041 11.4 none 3
igneum-san-j60 warmup-hard 305.8 326.5 none 34.6 0.039 none none 3

Difficulty attacks, seeds [7], rules ['igneum-san', 'igneum-san-j60']

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-san tight 30 future 10.0 0.978 1.010 0.998 0.010 0.010 0.989 0.084 10.3 0.000 1
igneum-san tight 30 past -15.9 0.978 1.014 1.000 0.014 0.014 0.984 0.097 11.1 0.000 1
igneum-san tight 30 alt 1.051 0.978 1.009 0.999 0.009 0.009 0.989 0.068 10.9 0.000 1
igneum-san tight 50 future 10.0 0.978 1.009 0.986 0.009 0.009 0.989 0.086 10.7 0.000 1
igneum-san tight 50 past -22.1 0.978 1.040 1.030 0.040 0.040 0.960 0.190 10.7 0.000 1
igneum-san tight 50 alt 2.023 0.978 1.014 0.991 0.014 0.014 0.984 0.097 11.3 0.000 1
igneum-san-j60 tight 30 future 10.0 0.978 1.010 0.998 0.010 0.010 0.989 0.084 10.3 0.000 1
igneum-san-j60 tight 30 past -15.9 0.978 1.012 0.995 0.012 0.012 0.986 0.096 11.1 0.000 1
igneum-san-j60 tight 30 alt 1.051 0.978 1.009 0.999 0.009 0.009 0.989 0.068 10.9 0.000 1
igneum-san-j60 tight 50 future 10.0 0.978 1.009 0.986 0.009 0.009 0.989 0.086 10.7 0.000 1
igneum-san-j60 tight 50 past -22.2 0.978 1.002 1.013 0.002 0.002 0.999 0.181 10.7 0.000 1
igneum-san-j60 tight 50 alt 2.023 0.978 1.014 0.991 0.014 0.014 0.984 0.097 11.3 0.000 1

Clock without a lag bound (first candidate): base profiles, seed 7 to 9

Difficulty attacks, seeds [7, 8, 9], rules ['igneum', 'igneum-san']

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 up50 56.1 154.4 none 9.719 0.042 none none 3
igneum down50 782.3 782.3 none 78.3 0.042 none none 3
igneum epoch30 44.6 87.6 none 10.8 0.039 none 0.000 3
igneum walk10 none none 3 10.7 0.058 none none 3
igneum hop10 213.8 239.4 none 31.9 0.042 none 0.000 3
igneum polluted 70.1 70.1 none 10.2 0.041 7.969 none 3
igneum warmup-hard 381.3 381.3 none 34.6 0.039 none none 3
igneum-san up50 56.1 154.4 none 9.719 0.042 none none 3
igneum-san down50 718.8 757.2 none 73.9 0.042 none none 3
igneum-san epoch30 44.6 87.6 none 10.8 0.039 none 0.000 3
igneum-san walk10 none none 3 10.7 0.058 none none 3
igneum-san hop10 210.3 245.1 none 35.6 0.042 none 0.000 3
igneum-san polluted 75.5 75.5 none 10.2 0.041 274.4 none 3
igneum-san warmup-hard 305.8 326.5 none 34.6 0.039 none none 3

Early variant study, clock without a lag bound, Kaspa's timestamp rules, seed 7 (flat weights, lag, 10 T cap)

Difficulty attacks, seeds [7], rules ['igneum-san-flat-lag0', 'igneum-san-flat-lag1', 'igneum-san-flat-lag2', 'igneum-san-lwma-lag1', 'igneum-san-lwma-lag2', 'igneum-san-flat-lag1-cap10']

3. Timestamp stretching inside the rules: block rate after 1 h of forging (drift = rate - 1), 6 h runs

rule share stamp forger_offset_s rate_pre rate_post rate_last_hour drift drift_worst D_ratio std worst_gap forger_adv seeds
igneum-san-flat-lag0 30 future 132.0 0.979 1.070 1.049 0.070 0.070 0.935 0.204 9.132 0.000 1
igneum-san-flat-lag0 30 past -168.4 0.979 1.072 1.073 0.072 0.072 0.939 0.244 13.1 0.000 1
igneum-san-flat-lag0 30 alt 5.685 0.979 1.070 1.059 0.070 0.070 0.936 0.118 11.0 0.000 1
igneum-san-flat-lag0 50 future 132.0 0.979 1.063 1.042 0.063 0.063 0.943 0.438 12.5 0.000 1
igneum-san-flat-lag0 50 past -285.0 0.979 0.823 0.536 -0.177 -0.177 1.229 14.5 77.4 0.000 1
igneum-san-flat-lag0 50 alt 8.669 0.979 1.094 1.081 0.094 0.094 0.918 0.161 11.1 0.000 1
igneum-san-flat-lag1 30 future 132.0 0.979 1.070 1.048 0.070 0.070 0.935 0.200 9.312 0.000 1
igneum-san-flat-lag1 30 past -168.4 0.979 1.072 1.072 0.072 0.072 0.939 0.243 12.8 0.000 1
igneum-san-flat-lag1 30 alt 5.639 0.979 1.069 1.058 0.069 0.069 0.936 0.117 10.7 0.000 1
igneum-san-flat-lag1 50 future 132.0 0.979 1.063 1.040 0.063 0.063 0.943 0.435 12.1 0.000 1
igneum-san-flat-lag1 50 past -285.8 0.979 0.823 0.527 -0.177 -0.177 1.238 14.5 72.7 0.000 1
igneum-san-flat-lag1 50 alt 8.666 0.979 1.093 1.081 0.093 0.093 0.918 0.163 10.8 0.000 1
igneum-san-flat-lag2 30 future 132.0 0.979 1.069 1.047 0.069 0.069 0.936 0.199 9.121 0.000 1
igneum-san-flat-lag2 30 past -168.5 0.979 1.071 1.071 0.071 0.071 0.939 0.243 15.5 0.000 1
igneum-san-flat-lag2 30 alt 5.651 0.979 1.069 1.058 0.069 0.069 0.936 0.117 10.9 0.000 1
igneum-san-flat-lag2 50 future 132.0 0.979 1.061 1.031 0.061 0.061 0.944 0.431 13.4 0.000 1
igneum-san-flat-lag2 50 past -285.2 0.979 0.823 0.528 -0.177 -0.177 1.234 13.0 78.7 0.000 1
igneum-san-flat-lag2 50 alt 8.680 0.979 1.094 1.079 0.094 0.094 0.918 0.161 10.5 0.000 1
igneum-san-lwma-lag1 30 future 132.0 0.978 1.098 1.091 0.098 0.098 0.911 0.353 9.727 0.000 1
igneum-san-lwma-lag1 30 past -162.2 0.978 1.114 1.139 0.114 0.114 0.904 0.290 12.2 0.000 1
igneum-san-lwma-lag1 30 alt 5.272 0.978 1.065 1.053 0.065 0.065 0.942 0.132 10.7 0.000 1
igneum-san-lwma-lag1 50 future 132.0 0.978 1.233 1.258 0.233 0.233 0.823 0.709 10.2 0.000 1
igneum-san-lwma-lag1 50 past -270.0 0.978 0.934 0.609 -0.066 -0.066 1.076 1396.5 102.2 0.000 1
igneum-san-lwma-lag1 50 alt 8.250 0.978 1.089 1.081 0.089 0.089 0.921 0.144 11.4 0.000 1
igneum-san-lwma-lag2 30 future 132.0 0.978 1.096 1.095 0.096 0.096 0.912 0.349 9.663 0.000 1
igneum-san-lwma-lag2 30 past -162.3 0.978 1.113 1.136 0.113 0.113 0.905 0.288 13.4 0.000 1
igneum-san-lwma-lag2 30 alt 5.288 0.978 1.064 1.055 0.064 0.064 0.943 0.131 10.7 0.000 1
igneum-san-lwma-lag2 50 future 132.0 0.978 1.229 1.257 0.229 0.229 0.826 0.699 10.8 0.000 1
igneum-san-lwma-lag2 50 past -270.4 0.978 0.931 0.600 -0.069 -0.069 1.085 1068.9 97.6 0.000 1
igneum-san-lwma-lag2 50 alt 8.606 0.978 1.097 1.111 0.097 0.097 0.916 0.155 9.717 0.000 1
igneum-san-flat-lag1-cap10 30 future 132.0 0.979 1.052 1.024 0.052 0.052 0.950 0.113 9.696 0.000 1
igneum-san-flat-lag1-cap10 30 past -175.7 0.979 1.031 0.999 0.031 0.031 0.974 0.185 13.3 0.000 1
igneum-san-flat-lag1-cap10 30 alt 5.566 0.979 1.068 1.058 0.068 0.068 0.938 0.119 10.7 0.000 1
igneum-san-flat-lag1-cap10 50 future 132.0 0.979 0.938 0.918 -0.062 -0.062 1.071 0.404 22.1 0.000 1
igneum-san-flat-lag1-cap10 50 past -853.2 0.979 0.226 0.019 -0.774 -0.774 4.585 40314.5 268.5 0.000 1
igneum-san-flat-lag1-cap10 50 alt 7.507 0.979 1.077 1.071 0.077 0.077 0.932 0.135 11.0 0.000 1

First run, realised-count estimator (superseded; shows the block-count noise on the epoch flooders)

Difficulty attacks, seeds [7, 8, 9], rules ['igneum', 'kaspa']

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 10 0 0.011 0.013 0.432 301.0 0.072 12.7 0.998 3
igneum 10 60 0.010 0.011 0.437 227.0 0.072 12.6 0.998 3
igneum 30 0 0.006 0.014 0.216 492.0 0.135 12.8 0.994 3
igneum 30 60 -0.002 -0.008 0.283 394.0 0.140 13.9 0.992 3
igneum 50 0 0.006 0.015 0.149 616.7 0.197 13.8 0.992 3
igneum 50 60 -0.015 -0.022 0.283 544.7 0.211 13.8 0.984 3
igneum 100 0 0.012 0.024 0.085 741.0 0.339 13.3 0.990 3
igneum 100 60 -0.038 -0.050 0.378 818.0 0.349 16.9 0.968 3
kaspa 10 0 0.005 0.009 0.367 63.7 0.054 11.8 1.000 3
kaspa 10 60 0.005 0.009 0.367 63.7 0.054 11.8 1.000 3
kaspa 30 0 0.006 0.008 0.181 88.0 0.124 12.3 1.001 3
kaspa 30 60 0.006 0.008 0.181 88.0 0.124 12.3 1.001 3
kaspa 50 0 0.012 0.015 0.116 112.3 0.180 12.7 1.001 3
kaspa 50 60 0.014 0.019 0.115 111.3 0.179 12.6 1.001 3
kaspa 100 0 0.010 0.029 0.061 122.7 0.304 12.5 1.001 3
kaspa 100 60 0.006 0.019 0.068 132.0 0.315 12.5 1.001 3

2. Pulsed hash rate: 50x for 10 min every hour, blocks per hash of the pulser against steady mining

rule pulse_vs_steady pulse_vs_steady_worst base_vs_steady pulse_vs_base pulse_block_share pulse_hash_share peak_blocks_per_min worst_gap blocks_per_s seeds
igneum -0.977 -0.977 -0.346 -0.964 0.228 0.862 182.3 100.9 0.841 3
kaspa -0.896 -0.897 -0.879 -0.139 0.878 0.862 1741.0 102.1 0.979 3

3. Timestamp stretching inside the rules: block rate after 1 h of forging (drift = rate - 1)

rule share stamp forger_offset_s rate_pre rate_post rate_last_hour drift drift_worst D_ratio std worst_gap seeds
igneum 30 future 132.0 0.994 0.656 0.658 -0.344 -0.350 1.549 0.136 15.6 3
igneum 30 past -439.1 0.994 0.415 0.428 -0.585 -0.597 2.421 0.243 44.8 3
igneum 30 alt -70.3 0.994 0.514 0.513 -0.486 -0.545 1.966 0.381 37.0 3
igneum 50 future 132.0 0.994 0.563 0.573 -0.437 -0.449 1.796 0.103 17.1 3
igneum 50 past -2122.9 0.994 0.116 0.119 -0.884 -0.925 9.886 0.186 233.8 3
igneum 50 alt -289.0 0.994 0.231 0.221 -0.769 -0.804 4.393 0.257 83.5 3
kaspa 30 future 132.0 0.993 1.049 1.049 0.049 0.052 0.959 0.018 8.825 3
kaspa 30 past -170.2 0.993 1.069 1.073 0.069 0.072 0.941 0.021 8.675 3
kaspa 30 alt 6.993 0.993 1.090 1.092 0.090 0.092 0.923 0.023 8.463 3
kaspa 50 future 132.0 0.993 1.050 1.052 0.050 0.054 0.958 0.018 8.840 3
kaspa 50 past -235.6 0.993 1.113 1.113 0.113 0.116 0.904 0.027 8.353 3
kaspa 50 alt 8.892 0.993 1.098 1.100 0.098 0.100 0.916 0.021 8.451 3

4. Short-lane oscillation: 25% miner on and off every 120 blocks

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 25 120 0.045 0.160 3.753 4.815 0.143 8.789 11.0 0.980 -0.015 3
kaspa 25 120 0.010 0.147 16.4 23.5 0.143 8.906 10.3 1.001 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 dodge -0.000 0.001 0.997 0.054 9.598 1.002 3
igneum flood 0.136 0.276 0.000 0.470 9.986 0.995 3
igneum flood30 0.131 0.272 0.001 0.054 9.811 0.997 3
kaspa dodge -0.000 -0.000 0.997 0.026 9.360 1.001 3
kaspa flood 0.111 0.264 0.000 0.482 9.293 1.001 3
kaspa flood30 0.110 0.263 0.002 0.030 9.278 1.001 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 0 600 88.6 134.8 303.1 303.1 16.9 55.3 0.000 3
igneum 480 600 none none 291.9 291.9 15.2 50.3 0.000 3
igneum 480 720 76.3 none 321.4 321.4 28.4 56.7 0.000 3
igneum 0 1200 88.6 134.8 312.2 334.0 24.5 56.7 0.000 3
kaspa 0 600 none none 2910.0 2910.0 9.954 0.000 0.000 3
kaspa 480 600 none none 0.000 0.000 8.600 0.000 0.000 3
kaspa 480 720 none none 135.3 135.3 8.838 0.000 0.000 3
kaspa 0 1200 none none 3539.6 3539.6 13.1 0.000 0.000 3

Scenario 7, flood test output (cargo test -p kaspa-consensus --lib igneum_flood -- --nocapture, diff-attacks branch)

target below 2^64 at block 4142 (epoch start 3600), bits 0x900fe5b
thread 'processes::difficulty::tests::igneum_flood_at_85_blocks_per_second_drives_the_target_below_block_work_range' (36166563) panicked at consensus/src/processes/difficulty.rs:431:20:
Work should not exceed 2**192: TryFromIntError
test processes::difficulty::tests::igneum_flood_at_85_blocks_per_second_drives_the_target_below_block_work_range - should panic ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 81 filtered out; finished in 0.01s

Ease clamp against the hopper (igneum-ease6 and igneum-ease3: the spec rule with a 6% or 3% ease clamp), seed 7, 24 h

Difficulty attacks, seeds [7], rules ['igneum-ease6', 'igneum-ease3']

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-ease6 10 0 0.015 0.015 0.517 330.0 0.073 12.7 1.000 1
igneum-ease6 10 60 0.014 0.014 0.505 240.0 0.073 12.7 1.000 1
igneum-ease6 30 0 0.010 0.010 0.271 565.0 0.143 11.7 0.995 1
igneum-ease6 30 60 0.002 0.002 0.336 445.0 0.144 13.7 0.993 1
igneum-ease6 50 0 0.009 0.009 0.185 718.0 0.209 13.6 0.992 1
igneum-ease6 50 60 -0.011 -0.011 0.309 576.0 0.214 12.2 0.986 1
igneum-ease6 100 0 0.006 0.006 0.107 861.0 0.362 13.9 0.990 1
igneum-ease6 100 60 -0.032 -0.032 0.396 841.0 0.346 17.0 0.970 1
igneum-ease3 10 0 0.015 0.015 0.529 308.0 0.072 11.7 0.999 1
igneum-ease3 10 60 0.015 0.015 0.515 238.0 0.073 12.8 0.999 1
igneum-ease3 30 0 0.009 0.009 0.284 566.0 0.142 11.7 0.994 1
igneum-ease3 30 60 0.002 0.002 0.342 446.0 0.143 13.7 0.993 1
igneum-ease3 50 0 0.008 0.008 0.190 698.0 0.208 12.7 0.991 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 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