From 7594f0cc99ddbf6e7439bd859b98da10b0f7ce10 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Wed, 7 Oct 2026 14:01:11 +0000 Subject: [PATCH] Genesis forward-compatibility: the suite row closed (114 passed twice on build-2 at f95178a1) and section 6a, the two-node UnexpectedDifficulty class found and fixed Co-Authored-By: Claude Fable 5.1 --- docs/design/genesis-forward.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/design/genesis-forward.md b/docs/design/genesis-forward.md index 357b2f27..e70f32e0 100644 --- a/docs/design/genesis-forward.md +++ b/docs/design/genesis-forward.md @@ -72,13 +72,13 @@ Flagged in spec 04 section 4.8, not sized: Shor computes the class-group order, | The codec | `scheme_byte_and_succession_items_round_trip_and_an_older_decoder_stops_at_them` | green in the suite runs | | The digest, cross-binary | igneumd 75810130 against the 0.3.20 base dc141409 (bs0319's build), both with no file, devnet suffix 973 | both `079d8a7e736abbd4` (`digest-no-file.log`, `digest-base-dc141409.log`): the three fields at never move nothing; the ladder alone at 0 reads `772f9f8e3ef59ca1`, the testnet-shaped file (ladder at 0, scheme switch at 0, succession at 0, the cache rung) `60e842a738c7dea0`, on devnet params; the testnet lane's own number comes from `TESTNET_PARAMS` at its cut. The 0.3.18 line's `c562d70e` is behind the decimals, tail-emission and subsidy fields of the 0.3.19 and 0.3.20 lines, not behind these | | The gate build | `tools/build-remote.sh --priority gate` on build-1 at bdb34f62 | igneumd 57,554,336 B sha256 6d0aa37b..., igneum-miner 10,240,768 B sha256 69fc3c63... (commit string carried) | -| The consensus suite | `cargo test --release -p kaspa-consensus` on build-2 | 114 passed, 0 failed, 3 ignored at 13:16 UK (bdb34f62's code); two later runs at 14:2x UK failed 1 of 114 on the pre-existing two-node F23 test (`ban_is_decided_by_the_carrying_block...`: node 1 refuses block 61 at DAA 60 with `UnexpectedDifficulty`, bits apart by about 17,000 in the mantissa), the same shape the succession test showed once at 13:0x UK before it passed; the refusal moves between the two-node tests and between runs, and no static on the bits path was found (the memos are keyed by block hash and sit on the class, ladder and era paths), so it is OPEN as a test-binary class, probed as F23 alone three times and the two-node tests together three times (section 6a) | +| The consensus suite | `cargo test --release -p kaspa-consensus` (all targets) on build-2 at f95178a1, twice | 114 passed, 0 failed, 3 ignored in the lib binary both times, the two moved targets 1 each; `cargo check -p kaspad` clean. Before the fix below the lib binary failed 1 of 114 on one of the two-node tests in three of four runs (the succession test once, the pre-existing F23 test twice), node 1 refusing block 61 at DAA 60 with `UnexpectedDifficulty`, the two nodes' bits about 17,000 apart in the mantissa | Faults found on the way, both mine: (1) rule v3's frozen table stood at the lock before the carrier, where the old key still weighed and signed nothing, so nothing locked after the fold (fixed in `frozen_table`, 9322cc1d); (2) the template read the explicit-form switch from the process-wide static that only the daemon installs, so `TestConsensus` wrote the plain form (the manager holds the activation now, daa61847). -### 6a. The two-node refusal probe +### 6a. The two-node refusal: found and fixed (f95178a1) -Filled from `probe.out` (F23 alone three times, the three two-node tests together three times, build-2). +The probe on build-2: F23 alone three times, green each time; the three two-node tests together three times, green each time; so the refusal needed the rest of the lib binary. The cause: `consensus/src/consensus/services.rs` built the difficulty manager with `igneum::pow_epoch_blocks()`, the process-wide static, where every other argument of that constructor comes from `params`; two pruning-proof tests in the same binary (`igneum_m20_tests.rs:27`, `igneum_pow.rs:346`) install a 60-block schedule process-wide, so a `TestConsensus` built inside that window read a 60-block epoch into its difficulty manager while its partner read 3,600, the two disagreed on `reference_window` from DAA 60, and the second node refused block 61, the exact block of every refusal. The fix is the manager's own field, `params.pow_epoch_blocks`. The node's behaviour is unchanged (the daemon installs the static from the same params before building the consensus); the class is the static-at-construction read, the sibling of the signal-table race the node lane moved two installing tests for on 7 October 2026. The test helper now names the node and the block it refuses, which is what found it. ## 7. For the testnet lane