replay gate: the devnet-window row in 7.6 (rule checks pass, the harness's sync clause corrected for a pruning A), the idle-network note in 7.7
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
9b6af9fc9f
commit
6bac2b15bd
2 changed files with 7 additions and 1 deletions
|
|
@ -262,6 +262,7 @@ Harness `infra/fast-time/vote-or-burn.mjs`: node A's miner votes, node B's runs
|
|||
| `--rule burn --expect burn --replay`, binaries at 812c3ac2 (igneumd 19670ddd..., igneum-miner ef51249c...) | 00:16 to 00:24Z | PASS: the late node C synced every block in 5 s (313 against 313, one sink fb054883), 0 rule error lines; the payout unchanged (ratio 0.8000, B's pool 0.2500 of A's producer, 65 and 54 pairs) | `vote-or-burn-rule-burn-expect-burn-replay.json` |
|
||||
| `--rule bonus --expect bonus --replay`, 812c3ac2 | 00:24 to 00:30Z | PASS: C synced in 5 s (331 against 331, one sink 20e976eb), 0 rule error lines; the payout unchanged (ratio 0.9000, B's pool 0.3500 of A's producer, 48 and 71 pairs) | `vote-or-burn-rule-bonus-expect-bonus-replay.json` |
|
||||
| `--rule bonus --expect bonus --replay --secs 660` (a span past two 120-DAA weight windows), 812c3ac2 | 00:31 to 00:42Z | PASS: C synced the 697-block span from genesis in 5 s (697 against 697, one sink fc4d942d), 0 rule error lines; the payout unchanged (ratio 0.9000, the pool 0.3500, 58 and 61 pairs over DAA 566 to 686) | `vote-or-burn-rule-bonus-expect-bonus-replay-long.json` |
|
||||
| `--rule bonus --expect bonus --replay --secs 14700 --finality devnet` (the devnet's own finality object: weight window 7,200 DAA, presence 20, interval 30, depth 20; a span past two devnet windows), 812c3ac2 binaries | 01:00 to 05:19Z | the rule checks PASS: 65 pairs paying A and 55 paying B over DAA 14,419 to 14,538, producer ratio 0.9000 (want 0.9), B's pool 0.3500 of A's producer (want 0.35), 0 rule error lines on C; the harness's own sync check read FAIL and was wrong: A pruned at the moment C joined (the chain had passed the 13,838 pruning depth; "pruning points in history: 13" at 04:49:28Z), so A's count at C's start (the whole chain) is not reachable by a C that prunes too; by the logs C took A's 13,843 blocks and A's sink in 20 s (IBD done 04:49:25Z, C started 04:49:05Z). Clause corrected in the harness (C against A's current count) | `vote-or-burn-rule-bonus-expect-bonus-replay-devnet-window.json` (the json carries the harness's FAIL; the reading above is the gate's) |
|
||||
|
||||
### 7.7 The miner's stall guard and the node's idle-peer drop (ledger N4)
|
||||
|
||||
|
|
@ -290,6 +291,8 @@ The node half's gate, `infra/fast-time/peer-drop.mjs` (7 October 2026, 01:03 to
|
|||
|
||||
The 720 s is the rule's span (600 s) plus one ping interval (120 s): the verdict is read after each pong.
|
||||
|
||||
An idle network (the devnet-window replay, 7 October 2026, 05:12 to 05:14Z): once the harness miner stopped, A and C dropped each other at 720 s as idle peers and reconnected at once, and will every 12 minutes on a network where nothing mines at all. Harmless on the live devnet (the tip moves) and noisy on an idle testnet before go. A 0.3.19 refinement: hold the drop while our own sink is older than the span, since a peer cannot show a block that nobody mined.
|
||||
|
||||
The 0.3.17 canary (7 October 2026, 04:0x to 04:53 UK) found the node half's blind spot: a fresh node syncing 155,700 headers over a headers-proof IBD got no BLOCK for 12 minutes (the headers stage delivers headers, a proof and trusted data, none of which the relay flow stamps), so the drop closed every peer at 12 minutes and the 17-minute join died; and the class-signal "window below epoch ... is incomplete" line printed about 1,900 times a minute through the same IBD (the floor decision is not memoised, so every header asked again). Fixed on both trees:
|
||||
|
||||
| Commit (release branch ca3-v4-0317-fix, on 12153428) | Twin on ca3-v4-0318 | What it does |
|
||||
|
|
|
|||
|
|
@ -192,7 +192,10 @@ if (REPLAY) {
|
|||
while (Date.now() - started_at < REPLAY_WAIT * 1000) {
|
||||
await sleep(5000);
|
||||
try { lastC = await c.rpc.call('getBlockDagInfo'); lastA = await a.rpc.call('getBlockDagInfo'); } catch { continue; }
|
||||
if (lastC.blockCount >= atStart.blockCount && Math.abs(lastC.blockCount - lastA.blockCount) <= 3 && lastC.sink === lastA.sink) { synced = true; break; }
|
||||
// C holds what A holds now, with A's sink. Not A's count at C's start: the devnet-window run (7 October 2026,
|
||||
// 04:49Z) had A prune at the moment C joined (its count fell from the whole chain to 13,843), so a C that
|
||||
// prunes too can never reach the old count; it held A's 13,843 and A's sink 20 s after its start.
|
||||
if (Math.abs(lastC.blockCount - lastA.blockCount) <= 3 && lastC.sink === lastA.sink) { synced = true; break; }
|
||||
if ((Date.now() - started_at) % 30000 < 5000) log(`replay: C ${lastC.blockCount} blocks sink ${String(lastC.sink).slice(0, 8)}; A ${lastA.blockCount} sink ${String(lastA.sink).slice(0, 8)}`);
|
||||
}
|
||||
const ruleErrors = c.grepLog(/BadCoinbase|WrongSubsidy|Rule error|rule error|invalid block|Banning/);
|
||||
|
|
|
|||
Loading…
Reference in a new issue