class v5 harness: the pairing rule's fixed attempt-3 seed read on every run (kaspa-pow program-id beside the run's CLI, attempt and id against the record; an unreadable side fails the check); the seed's inputs pinned under the harness dir; the page row
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
9e84c33af2
commit
cd23554835
4 changed files with 37 additions and 0 deletions
11
docs/design/class-v5-harness/attempt-3-seed/seed.json
Normal file
11
docs/design/class-v5-harness/attempt-3-seed/seed.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"what": "The class v5 pairing rule's fixed attempt-3 seed (8 October 2026, 14:1x UK): the 0.3.25 pin d5b68fae's FAIL seed from the cross harness run cross-0325-d5b68fae, epoch 9 of that run, whose draw lands at attempt 3 under the freeze's rule. Every harness run reads it through the pair's engine path (kaspa-pow program-id) and the run's CLI (igneum-pow show) and compares attempt and id; a difference is FAILED CHECK attempt_3_seed_reads_equal.",
|
||||
"epoch_hex": "ec0a8cf9e1c6874fc3bc7f9e5a2d8113f2b2353fced8bf293e9d451a48d68212",
|
||||
"era_hex": "234e082d653dc69db36d875b256d0f5f4a123b353d6aa069c3c7aa9aa6c46062",
|
||||
"day": 1244071,
|
||||
"genesis_day": 1243740,
|
||||
"genesis_log2": 28,
|
||||
"state_file": "state.igsd1",
|
||||
"state_root": "3046a7c17feb51c91b30f29d26e1b0de1",
|
||||
"expected": { "class": "v5", "attempt": 3, "id": "1f1cf82877f46ee6", "read_by": "igneum-pow at exactly 1c420786 and kaspa-pow program-id on class-v5-node f912e614, build-1, 14:07 UK" }
|
||||
}
|
||||
BIN
docs/design/class-v5-harness/attempt-3-seed/state.igsd1
Normal file
BIN
docs/design/class-v5-harness/attempt-3-seed/state.igsd1
Normal file
Binary file not shown.
|
|
@ -50,6 +50,7 @@ Clock rule for this page: every time is UK time (UK time tonight, UTC+1). The bu
|
|||
| 13:4x | The shipper's STOP on the 0.3.25 pin d5b68fae (13:42 UK): the fast-time pair's `v5_ids_equal_the_cli_v5_id` FAILED on epoch 9's attempt-3 seed ec0a8cf9 (the freeze CLI 1c420786 draws ebf64b32e2d84c5b, the pin's miner 65b57e3b847d362e, its nodes accepting 4 of 4 on it); every 0.3.25 node binary embeds "igneum-pow-v5/src", not the freeze's crate: rule 7's pairing broken in the node lane's build path, a chain-split class. PAIRING RULE, added: the fast-time set carries an attempt-3 seed on every run (an attempt-0 seed cannot tell two acceptance rules apart). The node lane folds the freeze pairing and the ceiling re-cut into one commit; this lane's read-back on the rebuilt pair: the freeze CLI built at exactly 1c420786 on build-1 (/srv/builds/_scratch/v5-freeze-cli) against the new sha's miner, id for id and attempt for attempt on every v5 epoch of the flip case (the harness's POW_BIN override, 8c810148), and the live network's path: the 0.3.24 miner's epoch-19 read 3d375a55029e7e60 against the freeze CLI |
|
||||
| 13:5x | The pairing read-back on the rebuilt pair 6ccaf9e9 (release-0.3.25-node, igneumd's IGNEUM_POW_FINGERPRINT=cbc5bd0a..., the same PoW code as the print-only c9ad753a): the flip case on build-1 (13:44 to 13:56 UK, `class-v5-harness/readback-0325.{log,json}`) with the CLI side igneum-pow built at exactly 1c420786 (/srv/builds/_scratch/v5-freeze-cli, sha256 7ba781db...): SUMMARY PASS; every v5 epoch id for id, miners 3 of 3 against the freeze CLI: epoch 8 13a54a0dd793ca79 (attempt 2), epoch 9 d35cd0e9cb186d00 (attempt 1), epoch 10 6104176723170d72 (attempt 2). The gap: the run's seeds are its block hashes and drew no attempt-3 seed, so the case that caught the pin d5b68fae is not exercised by this read; the seeded attempt-3 case (a fixed seed through the freeze CLI and the pair's miner pack path, one line per run) is the next harness item |
|
||||
| 14:1x | The pin's FAIL seed re-read (ec0a8cf9...8212, its era 234e082d...6062, day 1244071, the run's own epoch-9 stream from /tmp/igneum-fast-time-v5x-cross-0325-d5b68fae): igneum-pow at exactly 1c420786 draws attempt 3, program id 1f1cf82877f46ee6 (8f481459 the same). Neither id of the FAIL was the freeze's: the cross harness's "cli v5 ebf64b32e2d84c5b" came from the release worktree's pre-freeze igneum-pow copy and the pin miner's 65b57e3b847d362e from "igneum-pow-v5/src"; rule 19's fingerprint pairing catches both. The miner's side of a past seed cannot be re-read (igneum-miner reads ids from a node's template only), so the pin goes on the fingerprint equality and the record says the attempt-3 seed's miner id was not re-read; the seeded attempt-3 case (a miner `program-id` read on a given seed, era, day and stream, asked of the node lane by 15:00 UK, default a kaspa-pow test binary on class-v5-node) is the next harness item |
|
||||
| 14:1x | The seeded attempt-3 case closed EQUAL: kaspa-pow `program-id` (class-v5-node f912e614, consensus/pow/src/bin: the template prepare's own path on a given seed, era, day, genesis day and stream file; a stream-less v5 read refuses with the engine's line, exit 3) reads the pin's FAIL seed ec0a8cf9...8212 (era 234e082d...6062, day 1244071, genesis day 1243740, the run's epoch-9 stream) as attempt 3, id 1f1cf82877f46ee6, equal to igneum-pow at exactly 1c420786 (build-1, 14:07 UK); the class v4 control reads attempt 0, 17d03dc8ddfe865c. The harness now reads that seed on every run (`class-v5-harness/attempt-3-seed/{seed.json,state.igsd1}`, check `attempt_3_seed_reads_equal`: the engine path beside the run's CLI, attempt and id against the record's expectation; an unreadable side is a FAILED CHECK, never a skip); the node lane lifts the read into `igneum-miner program-id` on its next line |
|
||||
|
||||
## 1. The claim, in one paragraph
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
import { spawn, spawnSync } from 'node:child_process';
|
||||
import { mkdirSync, rmSync, writeFileSync, readFileSync, openSync, existsSync } from 'node:fs';
|
||||
import { dirname } from 'node:path';
|
||||
import { connectRpc } from '../../tools/finality-attacks/lib/rpc.mjs';
|
||||
import { devAddress } from '../../tools/harness/lib/address.mjs';
|
||||
|
||||
|
|
@ -429,8 +430,32 @@ if (EXPECT === 'flip') {
|
|||
stateless_node_stops_at_the_flip: !statelessNode || (counts[statelessNode.i] <= before.length && counts[statelessNode.i] >= before.length - 5),
|
||||
};
|
||||
}
|
||||
// The pairing rule's fixed attempt-3 seed (8 October 2026, 14:1x UK; the 0.3.25 pin d5b68fae's FAIL seed): read on every
|
||||
// run through the pair's engine path (kaspa-pow `program-id`, beside the node binary or in the fork worktree's target) and
|
||||
// through the run's CLI (igneum-pow show), attempt and id compared with each other and with the record's expectation.
|
||||
// A run's own seeds are its block hashes and rarely land at attempt 3, which is where two acceptance rules show; this
|
||||
// read does not wait for the chain to draw one. An unreadable side is a FAILED CHECK, never a skip.
|
||||
const A3_DIR = `${ROOT}docs/design/class-v5-harness/attempt-3-seed`;
|
||||
const a3 = (() => {
|
||||
try {
|
||||
const j = JSON.parse(readFileSync(`${A3_DIR}/seed.json`, 'utf8'));
|
||||
const state = `${A3_DIR}/${j.state_file}`;
|
||||
const dayHex = Buffer.concat([Buffer.from('igneum-day/'), Buffer.from(BigInt(j.day).toString(16).padStart(16, '0'), 'hex').reverse()]).toString('hex');
|
||||
const cli = IGNEUM_POW && existsSync(IGNEUM_POW) ? spawnSync(IGNEUM_POW, ['show', '--program-class', 'v5', '--epoch-hex', j.epoch_hex, '--era-hex', j.era_hex, '--day-hex', dayHex, '--state', state], { encoding: 'utf8' }).stdout || '' : '';
|
||||
const cm = /attempt (\d+) program id ([0-9a-f]{16})/.exec(cli);
|
||||
const pidBin = [`${dirname(IGNEUMD)}/program-id`, `${ROOT}vendor/igneum-node-class-v5/target/release/program-id`].find(p => existsSync(p));
|
||||
const eng = pidBin ? spawnSync(pidBin, ['--epoch-hex', j.epoch_hex, '--era-hex', j.era_hex, '--day', String(j.day), '--class', 'v5', '--state', state, '--genesis-day', String(j.genesis_day), '--genesis-log2', String(j.genesis_log2)], { encoding: 'utf8' }) : null;
|
||||
const em = eng ? /attempt (\d+) id ([0-9a-f]{16})/.exec(eng.stdout || '') : null;
|
||||
const row = { seed: j.epoch_hex.slice(0, 16), expected: j.expected, cli: cm ? { attempt: +cm[1], id: cm[2] } : null, engine: em ? { attempt: +em[1], id: em[2], binary: pidBin } : null, engine_refusal: eng && !em ? (eng.stderr || '').trim().slice(0, 200) : null };
|
||||
row.equal = !!(cm && em && cm[1] === em[1] && cm[2] === em[2] && +cm[1] === j.expected.attempt && cm[2] === j.expected.id);
|
||||
log(`ATTEMPT-3 SEED ${row.seed}: cli ${cm ? `attempt ${cm[1]} id ${cm[2]}` : 'UNREAD'} | engine ${em ? `attempt ${em[1]} id ${em[2]}` : `UNREAD${row.engine_refusal ? ` (${row.engine_refusal})` : pidBin ? '' : ' (no program-id binary)'}`} | expected attempt ${j.expected.attempt} id ${j.expected.id} | ${row.equal ? 'EQUAL' : 'DIFFER'}`);
|
||||
return row;
|
||||
} catch (e) { log(`ATTEMPT-3 SEED: ${e.message}`); return { equal: false, error: e.message }; }
|
||||
})();
|
||||
checks.attempt_3_seed_reads_equal = !!a3.equal;
|
||||
const pass = Object.values(checks).every(Boolean);
|
||||
const summary = {
|
||||
attempt_3_seed: a3,
|
||||
pass, expect: EXPECT, signals: SIGNAL, checks, window: WINDOW, windows: WINDOWS, floor: FLOOR ?? 'never', v4_floor: V4_FLOOR ?? 'never', v3_activation: V3_ACTIVATION ?? 'never', epoch_blocks: EPOCH, lead: LEAD, first_full_window_epoch: FIRST_FULL_EPOCH, floor_epoch: FLOOR_EPOCH,
|
||||
stale_miner: STALE, stale_accepted_after_first_refresh: staleAcceptedAfterRefresh, honest_accepted_after_flip: honestAcceptedAfterFlip, stale_rejected: staleRejected, stateless_node: statelessNode ? statelessNode.i : null, stateless_accepted_after_flip: statelessAcceptedAfterFlip, stateless_refusal_lines: statelessRefusals,
|
||||
state_roots_at_flip: rootsAtFlip, streams, days_seen: daysSeen, day_boundary_crossed: daysSeen.length > 1,
|
||||
|
|
|
|||
Loading…
Reference in a new issue