class v5 harness: the 0.3.23 bytes (7 = class v4 sub-version 3, 6 = class v5 counted exactly)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
8fbcd43520
commit
e402f868cd
2 changed files with 7 additions and 6 deletions
|
|
@ -11,17 +11,17 @@
|
|||
// template, which the harness counts. Ports 29760 and up, network igneum-devnet-976, data /tmp/igneum-fast-time-v5s.
|
||||
//
|
||||
// The cases and the known-failed cases:
|
||||
// --signal 6,6,5 --expect no-flip two of three signal v5: 67 percent, the class must stay v4 (run 11 epochs)
|
||||
// --signal 6,6,7 --expect no-flip two of three signal v5: 67 percent, the class must stay v4 (run 11 epochs)
|
||||
// --signal 6,6,6 --expect flip all three: v5 from epoch 8, the first boundary with seven full windows; every
|
||||
// miner's v5 id equals the CLI's --program-class v5 id and differs from the same
|
||||
// seed's v4 id; the stateless node's miner accepts 0 blocks after the flip; 0 rejected
|
||||
// --signal 6,6,6 --floor never --expect no-flip the object off: byte 6 counts as v4 only
|
||||
// --signal 5,5,5 --floor 600 --expect floor nobody signals v5: it flips at the floor (epoch 10) and not before
|
||||
// --signal 7,7,7 --floor 600 --expect floor nobody signals v5: it flips at the floor (epoch 10) and not before
|
||||
// --signal 6,6,6 --expect flip --stale 2 proof of following's known-failed case: miner 2 keeps the first stream it
|
||||
// fetched (--freeze-state); from the epoch after the flip every block it mines is
|
||||
// rejected (accepted after the first refresh 0, rejected above 0); PASS means the
|
||||
// chain threw the stale miner off
|
||||
// --signal 6,6,5 --expect flip the known-failed case of the harness itself: it must report FAIL (no flip)
|
||||
// --signal 6,6,7 --expect flip the known-failed case of the harness itself: it must report FAIL (no flip)
|
||||
//
|
||||
// node infra/fast-time/class-v5-signal.mjs --signal a,b,c --expect flip|no-flip|floor [--floor <daa>|never]
|
||||
// [--v4-floor 120] [--window 60] [--v3-activation 60] [--secs 780] [--epochs 11] [--stale <miner index>] [--no-stateless-node]
|
||||
|
|
@ -57,6 +57,7 @@ const STALE = sflag('stale') == null ? null : +sflag('stale');
|
|||
const STATELESS_NODE = !args.includes('--no-stateless-node');
|
||||
const WINDOWS = 7;
|
||||
const SIGNAL = (sflag('signal') || '6,6,6').split(',').map(Number);
|
||||
// since the 0.3.23 node line the bytes are not ordered by class: 7 = class v4 sub-version 3, 6 = class v5 (counted exactly)
|
||||
const EXPECT = sflag('expect') || 'flip';
|
||||
if (!['flip', 'no-flip', 'floor'].includes(EXPECT) || SIGNAL.length !== 3) { console.error('usage: --signal a,b,c --expect flip|no-flip|floor'); process.exit(2); }
|
||||
const started = [];
|
||||
|
|
@ -221,7 +222,7 @@ const before = blocks.filter(b => b.daa < BOUNDARY), after = blocks.filter(b =>
|
|||
// the signal bytes on the chain: the share of blocks whose version high byte is 4
|
||||
const versionBytes = blocks.reduce((m, b) => { const v = b.version >> 8; m[v] = (m[v] || 0) + 1; return m; }, {});
|
||||
const V5_BYTE = 6;
|
||||
const signalShareOnChain = blocks.length ? Math.round(10000 * (blocks.filter(b => (b.version >> 8) >= V5_BYTE).length) / blocks.length) : 0;
|
||||
const signalShareOnChain = blocks.length ? Math.round(10000 * (blocks.filter(b => (b.version >> 8) === V5_BYTE).length) / blocks.length) : 0;
|
||||
|
||||
const programs = new Map();
|
||||
for (const i of nodes.map(n => n.i)) for (const l of minerLog(i)) {
|
||||
|
|
@ -378,7 +379,7 @@ const summary = {
|
|||
sinks, block_counts: counts, signal_lines: signalLines, floor_lines: floorLines, samples,
|
||||
};
|
||||
writeFileSync(`${TMP}/summary.json`, JSON.stringify(summary, null, 2));
|
||||
log(`SUMMARY ${pass ? 'PASS' : 'FAIL'} (expect ${EXPECT}, signals ${SIGNAL.join('/')}, stale ${STALE ?? 'none'}): ${firstV4 ? `v5 from epoch ${firstV4.epoch} at DAA ${firstV4.daa}` : 'no v5 epoch'}; epochs seen ${[...epochs.entries()].map(([e, v]) => `e${e}:${v.class}:${v.bps5}bps:d${v.day}`).join(' ')}; chain bytes ${JSON.stringify(versionBytes)} (${signalShareOnChain} bps at byte ${V5_BYTE}+); blocks ${before.length} / ${after.length}; rejected miners ${rejectedMiner.map(r => r.length).join('/')} nodes ${rejectedNode.map(r => r.length).join('/')}; sinks ${sinks.join(' ')} (${checks.sinks_agree ? 'agree' : 'DIFFER'}); counts ${counts.join('/')}; signal lines ${signalLines.filter(Boolean).length}/3 (epochs ${signalEpochs.join('/')}, shares ${signalShares.join('/')}); floor lines ${floorLines.filter(Boolean).length}/3; state roots at the flip ${rootsAtFlip.map(r => String(r).slice(0, 18)).join(' ')}; stateless node accepted after the flip ${statelessAcceptedAfterFlip} (refusal lines ${statelessRefusals}); stale miner accepted after the first refresh ${staleAcceptedAfterRefresh ?? 'n/a'} rejected ${staleRejected ?? 'n/a'}; days ${daysSeen.join('/')}`);
|
||||
log(`SUMMARY ${pass ? 'PASS' : 'FAIL'} (expect ${EXPECT}, signals ${SIGNAL.join('/')}, stale ${STALE ?? 'none'}): ${firstV4 ? `v5 from epoch ${firstV4.epoch} at DAA ${firstV4.daa}` : 'no v5 epoch'}; epochs seen ${[...epochs.entries()].map(([e, v]) => `e${e}:${v.class}:${v.bps5}bps:d${v.day}`).join(' ')}; chain bytes ${JSON.stringify(versionBytes)} (${signalShareOnChain} bps at byte ${V5_BYTE}); blocks ${before.length} / ${after.length}; rejected miners ${rejectedMiner.map(r => r.length).join('/')} nodes ${rejectedNode.map(r => r.length).join('/')}; sinks ${sinks.join(' ')} (${checks.sinks_agree ? 'agree' : 'DIFFER'}); counts ${counts.join('/')}; signal lines ${signalLines.filter(Boolean).length}/3 (epochs ${signalEpochs.join('/')}, shares ${signalShares.join('/')}); floor lines ${floorLines.filter(Boolean).length}/3; state roots at the flip ${rootsAtFlip.map(r => String(r).slice(0, 18)).join(' ')}; stateless node accepted after the flip ${statelessAcceptedAfterFlip} (refusal lines ${statelessRefusals}); stale miner accepted after the first refresh ${staleAcceptedAfterRefresh ?? 'n/a'} rejected ${staleRejected ?? 'n/a'}; days ${daysSeen.join('/')}`);
|
||||
for (const r of idRows) log(`PROGRAM ID epoch ${r.epoch} seed ${r.seed}: miners ${r.miners_id} (${r.miners} of 3) cli v5 ${r.cli_v5} cli v4 ${r.cli_v4}; state root ${r.state_root} (${r.state_records} records)`);
|
||||
for (const [k, v] of Object.entries(checks)) if (!v) log(`FAILED CHECK ${k}`);
|
||||
log(`summary: ${TMP}/summary.json`);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
# no build slot and no measure hold (the Mac rule's `run` kind).
|
||||
#
|
||||
# tools/class-v5/harness-remote.sh <case-name> -- <class-v5-signal.mjs arguments>
|
||||
# tools/class-v5/harness-remote.sh failed-case -- --signal 6,6,5 --expect flip
|
||||
# tools/class-v5/harness-remote.sh failed-case -- --signal 6,6,7 --expect flip
|
||||
# BASE=29830 tools/class-v5/harness-remote.sh flip-stale -- --signal 6,6,6 --expect flip --stale 2 (another port base per
|
||||
# case, so two cases never share ports; the harness kills the previous run's pids of its own data dir first)
|
||||
set -euo pipefail
|
||||
|
|
|
|||
Loading…
Reference in a new issue