igneum/infra/fast-time
2026-10-07 09:13:13 +00:00
..
class-v3.mjs counter-asic-2-node.md: gate run 4, a real Metal miner across the v3 boundary (3 v3 prepares and prepared lines, swap with no pause, 124 blocks on v3, 0 re-check mismatches); class-v3.mjs judges the Metal checks from the first v3 prepare on 2026-10-05 22:32:45 +00:00
class-v4-signal.mjs Counter ASIC 3.0 gates (node): the two cut preconditions: the fleet rehearsal plan (counter-asic-3-rehearsal.md, the publish and rehearsal override objects with their digests ac8e60ce... and bc2142b1...), the PROPOSED miner-signalled activation (node doc section 6), the fast-time signal gate class-v4-signal.mjs, the signal window in override-60x.json (120) and the README 2026-10-06 17:27:50 +00:00
class-v4.mjs Counter ASIC 3.0 gates (node): the program id carries the class. A class v4 program is generator 4 wherever it is made: the CLI's --era path stamps the generator from the class (era_generator_of: 4 on V4_CLASS, 3 otherwise; ProgramClass::of_load_class), show honours --program-class and --era-hex; the shadow block marks class v4 in packcheck, packfile.h and the Metal worker (a generator 3 pack with IGNEUM_SHADOW_INSTRS is refused as a v4 program stamped v3, a generator 4 pack without it is refused; generator 2 ladder packs unchanged); the seven gate packs re-exported (generator 4, id c120d7963abdcd96 against the v3 control's 73bcbfe8ccf988f1, every other line byte-identical); class-v4.mjs asserts every v4 epoch's id against the CLI's same-seed v3 and v4 ids (--id-check-against v4 is the assertion's failed case); v2 and v3 ids byte-identical (60 + 7 + 4 + 19 + 7, the pinned packs) 2026-10-06 16:24:02 +00:00
class-v5-signal.mjs class v5 harness: the previous run's survivors (two nodes of the known-failed case were still bound at 08:49Z and the flip run read a stranger's chain): a pid file per data dir killed at start, a node whose log says a port was in use fails the run at once, a port base per case (IGNEUM_V5_BASE, BASE= in harness-remote.sh) 2026-10-07 09:13:13 +00:00
latency-ladder.mjs igneum-pow and the fast-time profile from release-0.3.18 (the ladder's b0af074f and 0bc76818: v4_class_at, chain_program_shadow, the three ladder fields of the 60x file, the ladder harness and bench script), which the 0.3.18 fork builds against and master does not yet carry 2026-10-07 07:38:08 +00:00
override-60x.json class v5: the fast-time gate infra/fast-time/class-v5-signal.mjs (the class v4 signal gate's shape: three signalling nodes with their executors on loopback ports, a fourth node with --evm-disable that must mine nothing after the flip, a --stale miner that keeps its first stream and must fall off at the first refresh, the v5 floor far away so the signal decides, the no-flip, flip, object-off, floor and known-failed cases, every node's state root for the flip epoch compared), the v5 floor in the 60x profile (never), proto-newpow/class-v5/bench.cu (one pack-generic 4090 bench: cache, leaves, build, the pack's self-test and vector warps, hash rate, watts), DatasetSource::refreshed_or_clone 2026-10-07 08:13:33 +00:00
README.md Counter ASIC 3.0 gates (node): the two cut preconditions: the fleet rehearsal plan (counter-asic-3-rehearsal.md, the publish and rehearsal override objects with their digests ac8e60ce... and bc2142b1...), the PROPOSED miner-signalled activation (node doc section 6), the fast-time signal gate class-v4-signal.mjs, the signal window in override-60x.json (120) and the README 2026-10-06 17:27:50 +00:00
simnet.mjs fast-time: the override file is merged as text, never through JSON.parse (a never height, 18446744073709551615, becomes 1.8446744073709552e+19 and the node refuses the file; first gate run 5 October 2026 21:30Z); class-v3.mjs and simnet.mjs 2026-10-05 21:32:09 +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).

Class switch gate (Counter ASIC 2.0 rollout G4): node infra/fast-time/class-v3.mjs (3 nodes on ports 29600 and up, igneum-devnet-960, data /tmp/igneum-fast-time-v3, CPU difficulty genesis_bits 0x1f010000, real CPU mining on every node, program_class_v3_activation_daa a few epochs ahead; reports blocks on both sides of the boundary, the program id and class before and after, rejected blocks, forks, and every node's switch line; see docs/plans/counter-asic-2-node.md).

Class v4 switch gate (Counter ASIC 3.0 G4): node infra/fast-time/class-v4.mjs (the same shape on ports 29660 and up, igneum-devnet-966, data /tmp/igneum-fast-time-v4, program_class_v3_activation_daa at 60 and program_class_v4_activation_daa at 150 by default, so one run crosses v2, v3 and v4; --activation never is the known-failed case, which must report FAIL with no v4 epoch; --metal <igneum-bench> puts a real Metal miner on node 0 for G4b; see docs/plans/counter-asic-3-node.md).

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
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)
proving_v0_activation_daa never never a height: proving v0 payouts (spec 7.7) switch on at this DAA score; tools/proving-v0/run.mjs sets 60 in its merged file
finality_v3_activation_daa never never a height, not a clock: finality rule v3 (the frozen weight table of ledger F21 and the certificate fold of F22, 4 Oct 2026 evening) applies to checkpoints at or above this DAA score; tools/finality-attacks/v3.mjs sets 0 in its merged file
pow_genesis_dataset_log2 28 28 a size, not a clock: the dataset at genesis (2^28 words, 1 GiB); the cache growth rule (ca2-mixer) doubles it with the days since the genesis day
proving_v1_activation_daa never never a height: proving v1 (the fork's proving-v1 branch, 5 Oct 2026) switches on at this DAA score
proving_v1_segment_blocks, proving_v1_aggregator_share_bps 8, 1,000 8, 1,000 a block count and a share
proving_v1_unproven_daa 600 10 a DAA clock (the unproven allowance), divided by 60; the proving agent confirms the value
program_class_v3_activation_daa never never a height, not a clock: the lottery hash draws programs from class v3 (Counter ASIC 2.0, 5 Oct 2026) from the first EPOCH whose start is at or above this DAA score (rounded up to an epoch boundary: at 60 DAA per epoch, 150 means epoch 3 at DAA 180); infra/fast-time/class-v3.mjs sets it a few epochs ahead in its merged file
program_class_v4_activation_daa never never a height, not a clock: the lottery hash draws programs from class v4 (Counter ASIC 3.0, 6 Oct 2026: class v3 plus the latency-shadow block) from the first EPOCH whose start is at or above this DAA score, rounded up like the v3 switch; infra/fast-time/class-v4.mjs sets it a few epochs ahead in its merged file
program_class_v4_signal_window_daa 86,400 120 a DAA window (one day of blocks), divided by 60 and rounded to two epochs: the class v4 signal tally (PROPOSED, docs/plans/counter-asic-3-node.md section 6) over the blue blocks below each epoch's seed block; 0 = off; infra/fast-time/class-v4-signal.mjs is its gate
proving_v1_fresh_rule_daa, exec_restart_number, exec_restart_trust_daa, exec_restart_hash never, never, never, "" the same heights and a hash, not clocks (the 0.3.12 and 0.3.13 switches); present so the fork's every-field test (fast_time_60x_file_is_the_devnet_at_60x) holds; added 6 Oct 2026 with the class v4 field

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
finality.certificate_fold 3 DAA seconds after a checkpoint's determination at which a node holding a certificate rebuilds it from every vote seen (rule v3, F22): a relay-latency allowance measured on the 12-node cloud devnet (the last of 12 votes issued median 1.45 s, p90 2.36 s after the first determination), not a clock of the protocol, so it is not divided; absent from a file, the node takes the devnet value
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.