igneum/infra/fast-time
igneum-labs 6b72c3b3e6 Fast time: the devnet at 60x for test networks (override-60x.json, --fast-time in both harnesses, proof script)
infra/fast-time/override-60x.json is the devnet with every clock-like consensus parameter divided by 60 and every
block count unchanged (finality window, ban and min_daa 120 DAA; merge depth 60; Kaspa finality depth 720; pruning
depth at the anticone bound 13,838; coinbase maturity 2; the hourly program epoch 60 blocks with a 10-block lead;
the dataset day 24 minutes). The epoch length, lead and day are consensus parameters of the node since devnet-v4
a5ef8b07, carried by the override file. README lists each field, why it scales or not, the flags and the numbers.

Measured (simnet.mjs, three devnet-v4 nodes, three vmine voters at 1 block/s, one real-hash CPU miner): next
epoch seed in the template at 56.1 s, program swap at 65.1 s wall (DAA 60), first finality lock at 185.5 s wall
(checkpoint 5, DAA 149). Both harnesses take --fast-time: finality-attacks s3 PASS in 113 s wall with 16 locks
per node (the devnet rule needs 20 min of warm-up at 6 blocks/s before any lock); harness s3 partition and heal
43 s wall for three cuts against 983 s for four on the devnet profile with the same binary. Bench-log entry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 10:34:19 +00:00
..
override-60x.json Fast time: the devnet at 60x for test networks (override-60x.json, --fast-time in both harnesses, proof script) 2026-10-04 10:34:19 +00:00
README.md Fast time: the devnet at 60x for test networks (override-60x.json, --fast-time in both harnesses, proof script) 2026-10-04 10:34:19 +00:00
simnet.mjs Fast time: the devnet at 60x for test networks (override-60x.json, --fast-time in both harnesses, proof script) 2026-10-04 10:34:19 +00:00

Fast time: the devnet at 60x for test networks

override-60x.json is the Igneum devnet with every clock-like consensus parameter divided by 60 and every block count unchanged. A test network on it reaches its first finality lock in about three minutes instead of two hours and crosses an hourly program epoch every minute, so a scenario that took hours of wall time takes minutes. 4 October 2026.

Flags

Node (devnet-v4 line, vendor/igneum-node-v4, built in vendor/igneum-node/target-integration):

igneumd --devnet --devnet-suffix=950 --override-params-file=infra/fast-time/override-60x.json ...

The file is complete: every field OverrideParams accepts is present (consensus/core/src/config/params.rs), so a reader sees the whole profile in one place. Merge it with skip_proof_of_work: true for a network without miners (the harnesses do this), or lower genesis_bits for CPU miners (the devnet value 0x1d100000 is the GPU difficulty).

Harnesses: node tools/finality-attacks/run.mjs s3 --fast-time, node tools/harness/run.mjs s3 s4 --fast-time (or IGNEUM_FAST_TIME=1). Both then take the node from vendor/igneum-node/target-integration/release because the file carries the PoW schedule fields that only the devnet-v4 line knows; IGNEUMD=... overrides. The in-process simulator takes the same file: igneum-harness-sim --override-params-file infra/fast-time/override-60x.json.

Proof script: node infra/fast-time/simnet.mjs (3 nodes on ports 29500 and up, igneum-devnet-950, data /tmp/igneum-fast-time; records the first lock and the first program swap; see "Measured" below).

Miners: igneum-miner follows the epoch length and lead its node reports in every template (pow_epoch), no flag. The dataset day is not in the template, so a real-hash miner on a fast-time network takes IGNEUM_POW_DAY_MS=1440000 in its environment (the node reads it from the file). The environment variables IGNEUM_POW_EPOCH_BLOCKS, IGNEUM_POW_EPOCH_LEAD and IGNEUM_POW_DAY_MS remain the fallback for a node without a params file; the file wins.

What scales and what does not

Time parameters, divided by 60 (devnet value, 60x value):

Parameter Devnet 60x Note
finality.weight_window (W2, DAA s) 7,200 120 the 2-hour weight window becomes 2 minutes
finality.min_daa (C5, F1, DAA s) 7,200 120 equal to the window on every network, so the first lock waits for a full window
finality.equivocation_ban (3.6, DAA s) 7,200 120
finality.aggregator_fallback (DAA s) 15 1 15/60 rounds up to the floor of one second
finality.presence_window (Q1, checkpoints) 20 1 a count of checkpoints, but it stands for 20 x 30 = 600 DAA s of presence; 10 s is under one checkpoint, so the floor of one
pow_epoch_blocks (DAA s) 3,600 60 the hourly program epoch becomes a minute (new in the node, 4 Oct 2026: a consensus param carried by the override file; before, only an environment variable)
pow_epoch_lead (DAA s) 600 10 the seed is knowable one lead before the boundary; the miner confirms it a quarter of the lead later (3 DAA s at 60x, 150 on the devnet)
pow_day_ms (ms) 86,400,000 1,440,000 the dataset day of the 256 MiB cache becomes 24 minutes (new consensus param, same change)
blockrate.merge_depth (DAA s) 3,600 60 Kaspa's merge-depth bound, one hour of DAA score
blockrate.finality_depth (DAA s) 43,200 720 Kaspa's pruning-side finality, 12 hours
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
deflationary_phase_daa_score 0 0 the devnet has no deflationary phase

Unchanged, and why:

Parameter Value Why it stays
blockrate.target_time_per_block 1,000 ms the unit: a 60x network still makes one block per second; 60 blocks per second is a different DAG (k, parents, mergeset) and not what is being tested
blockrate.ghostdag_k, max_block_parents, mergeset_size_limit 18, 10, 180 DAG shape at 1 block/s
finality.checkpoint_interval, checkpoint_depth 30, 20 blue-score counts: a checkpoint every 30 blocks, determined 20 blocks later
finality.dust, aggregators 5, 8 a block count and a count of keys
difficulty_window_size, min_difficulty_window_size, difficulty_sample_rate 661, 150, 4 sample counts of Kaspa's sampled DAA (the reference lane of the dual rule); the controller needs its samples to estimate hash rate, and the 120-block LWMA lane, the 8-block warm-up, the 600-block reference start and the per-block clamps (igneum::difficulty) are block counts by design
past_median_time_window_size, past_median_time_sample_rate, timestamp_deviation_tolerance 27, 10, 132 the past-median rule's window in samples; Igneum's own 10 s future and back bounds are constants of the rule
genesis_bits 0x1d100000 the devnet's GPU difficulty; a CPU test network sets its own (0x1f010000 = 2^16 hashes per block)
skip_proof_of_work false the harnesses turn it on themselves
mass, lane, script and payload limits, pruning_proof_m, max_block_level, crescendo_activation, storage_mass_parameter, pre_deflationary_phase_base_subsidy devnet sizes and rule switches, not clocks

Consequences to remember when reading a fast-time result: the merge depth (60 s) is now far under the difficulty window (2,641 s), so a low-difficulty side chain older than a minute cannot merge, which the devnet tolerates for an hour; the presence window of one checkpoint means "finality active" needs a lock within the last checkpoint; the partition bound of spec 3.3.1 is W / (3R) = 13 s at 1 block/s per side (200 s on the devnet), so a split longer than that locks on both sides as the arithmetic says (docs/bench-log.md, 4 Oct 2026, 6A long heal).

The node unit test fast_time_60x_file_is_the_devnet_at_60x (consensus/core/src/config/params.rs) reads this file and checks every rule above against DEVNET_PARAMS; override_params_carry_the_pow_schedule and pow_schedule_defaults_and_clamps check the new fields and that the devnet defaults are untouched.

Measured (4 October 2026, Apple M5 Max shared with four other agents and the live devnet, load 40 to 60)

node infra/fast-time/simnet.mjs --secs 240: three devnet-v4 nodes (target-integration/release/igneumd, built from devnet-v4 a5ef8b07), three vmine voters sharing 1 block/s, one real-hash CPU miner thread on node 0.

Event Wall time from the first node's start Chain position
next epoch seed reported in the template 56.1 s DAA 53 (boundary 60, lead 10, quarter-lead confirm 3)
first hourly program swap: template epoch index 0 to 1 65.1 s DAA 60
CPU miner's new program and 256 MiB cache ready for the new seed 66.1 s (397 ms compile) DAA 60
first finality lock 185.5 s checkpoint 5, blue score 150, DAA 149 (checkpoint 4 sat at DAA 119, one under min_daa 120, so it could not certify)

Sinks agreed on all three nodes at the end (DAA 171). On the devnet the same two events come at DAA 3,600 (one hour) and DAA 7,200 plus a checkpoint (two hours and change).

Harness scenarios, same binaries, before and after:

Run Devnet profile 60x profile
tools/finality-attacks s3 (dishonest aggregators, six voters at 6 blocks/s) 32 min for the seven-scenario catalogue at SCALE 0.6 on the 3 Oct node (bench log 4 Oct 2026, s3 alone 180 s plus bring-up); on today's rule (min_daa = window) the window fills at DAA 7,200 = 20 min at 6 blocks/s, so s3 at full scale shows no lock inside its 300 s 113 s wall, 16 locks per node, 0 conflicting certificates, lock hashes agree across nodes, median lock latency 1,018 ms: PASS
tools/harness s3 (partition and heal in the in-process simulator, igneum-harness-sim of the devnet-v4 line) 983 s wall for the four cuts (120, 600, 1,800 and 3,700 s virtual: 46, 151, 400 and 831 s wall, two at a time), all PASS 43 s wall for the three cuts (10, 30 and 62 s virtual: 18, 20 and 26 s wall), all PASS, the 62-s cut beyond the 60-s merge depth converged with a 34-block reorg

The 3 Oct catalogue run reported 3 to 47 s wall per s3 cut on the ordering-layer-only harness branch; the devnet-v4 simulator carries the execution layer and costs about 70 ms per block on this loaded machine, hence the 983 s. The before and after above are the same binary on the same day.