testnet-object harness: the miners outlive the run (the stop hook ends them) and the final finality read is taken as the run ends, while every voter signs (pod 2's false pause, 8 October 2026)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
igneum-labs 2026-10-08 09:45:26 +00:00
parent 2aa4f1c5d1
commit 99ff23493d

View file

@ -203,7 +203,9 @@ const START_LINES = {
};
for (const n of nodes) log(`n${n.i}: ${Object.entries(START_LINES).map(([k, re]) => `${k}=${n.grepLog(re).length > 0}`).join(' ')} | digest ${(n.grepLog(START_LINES.digest)[0] || '').replace(/^.*?digest: /, '').slice(0, 16)}`);
// n0 and n1 vote (the key is the payout label's identity); n2 never votes: the silent key
const miners = nodes.map((n, i) => miner(CPU_MINER, ['mine', n.grpc, '1', String(SECS), `cpu${i}`, '--engine', 'igneum-pow', '--payout-label', LABELS[i], '--evm-address', EVM[i], '--dev-fee', '0', '--status-secs', '30', '--stall-secs', '0', ...(i === SILENT ? ['--no-vote'] : [])], `cpu${i}`, { IGNEUM_POW_DAY_MS: String(DAY_MS) }));
// the miners (and so the voters) outlive the run by five minutes and are stopped by the stop hook, so the final finality
// read never sees a table nobody signs (pod 2 of 8 October 2026 read "0.00% signing" after the voters had exited with the run)
const miners = nodes.map((n, i) => miner(CPU_MINER, ['mine', n.grpc, '1', String(SECS + 300), `cpu${i}`, '--engine', 'igneum-pow', '--payout-label', LABELS[i], '--evm-address', EVM[i], '--dev-fee', '0', '--status-secs', '30', '--stall-secs', '0', ...(i === SILENT ? ['--no-vote'] : [])], `cpu${i}`, { IGNEUM_POW_DAY_MS: String(DAY_MS) }));
const pay = devAddress('fast-time-testnet-object');
const epochs = new Map();
@ -250,6 +252,8 @@ while (Date.now() - t0 < SECS * 1000) {
samples.push({ t: +since(), daa, epoch, class: cls, step, reps, locked: r?.latestLockedIndex ?? null, active: r?.finalityActive ?? null, nodes: counts });
}
}
// the final finality read, taken the moment the run ends and while every voter still signs
const finalReports = await Promise.all(nodes.map(n => report(n, 3)));
await sleep(3000);
// the chain: every block with its coinbase outputs by address, and the execution layer's segment rewards by miner
@ -397,7 +401,6 @@ const sinks = dag.map(d => String(d.sink || '?').slice(0, 16));
const counts = dag.map(d => d.blockCount ?? '?');
const accepted = LABELS.map((_, i) => minerLog(i).filter(l => /ACCEPTED block/.test(l)).length);
const rejectedNode = nodes.map(n => n.grepLog(/PoW rejected|Rejected block|rejected block/i).length);
const finalReports = await Promise.all(nodes.map(n => report(n, 3)));
// the report's reason flickers for one read at every new lock (the table frozen at the lock reads 0.00 percent signing
// for a second); a pause is consecutive inactive reads, measured in seconds of the 1-s poll, never one read
function longestInactiveStretchAfter(daa) {