55 lines
3.7 KiB
Markdown
55 lines
3.7 KiB
Markdown
# sim/difficulty
|
|
|
|
Difficulty controller simulator for Igneum (3 October 2026). Model, candidates, results and the
|
|
devnet record behind `docs/analysis/difficulty-2026-10-03.md` and section 2.3 of `docs/spec/02-consensus.md`.
|
|
|
|
## Files
|
|
|
|
| File | What |
|
|
|---|---|
|
|
| `sim.py` | the simulator: block production from a hash-rate profile through six controllers, metrics as markdown |
|
|
| `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 |
|
|
| `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 |
|
|
|
|
## Model
|
|
|
|
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
|
|
(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.
|
|
|
|
Metrics per step: first time the 121-block centred mean of the expected block rate is within 10% of
|
|
target; "settled" = the first time it then stays within 10% for 100 blocks; overshoot past target on
|
|
the far side; blocks spent above 2x and below 0.5x target rate; worst inter-block gap. Steady state:
|
|
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).
|
|
|
|
## Controllers
|
|
|
|
| Name | Rule |
|
|
|---|---|
|
|
| `kaspa` | KIP-4 sampled DAA exactly as the fork runs it: samples at every 4th block, 661 samples, average target of the window without its earliest block, times measured over expected, genesis bits held until 150 samples (600 blocks) |
|
|
| `monero` | Monero `next_difficulty`: 720 blocks, timestamps sorted, 60 cut from each end, lag 15 |
|
|
| `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-literal` | the same with the brief's literal trigger (short-window rate off target by 25%), kept to show the chatter |
|
|
|
|
## Runs
|
|
|
|
python3 sim.py synthetic set, every controller
|
|
python3 sim.py --ts-noise 500 the same with +-500 ms timestamp jitter
|
|
python3 sim.py --tune parameter sweep for the Igneum rule
|
|
python3 sim.py --record devnet-2026-10-03.csv --events 2026-10-03T19:28:05+00:00,2026-10-03T19:42:40+00:00
|
|
exact replay check of Kaspa's rule on the record,
|
|
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)
|
|
|
|
Requirements: Python 3 only (numpy not needed). The full synthetic set takes about two minutes.
|
|
|
|
## Limits
|
|
|
|
No DAG (one chain, no parallel blocks, no reds), no network latency, no miner template refresh
|
|
delay, honest timestamps unless `--ts-noise`. 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
|
|
second, because a chain-only replay cannot see the merged blocks that the sampled window includes.
|