From 5f3db40fe09f47c0ad5f5c15b8a39130d2a5d43e Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Wed, 7 Oct 2026 08:51:31 +0000 Subject: [PATCH] base-unit gate: check 5 reads each blue block's own DAA (the per-block subsidy rule from genesis on the testnet); the pod run of 09:4x UK read 165 of 561 segments one ramp step low against the chain block's DAA Co-Authored-By: Claude Fable 5.1 --- tools/fleet/base-unit-gate.sh | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/tools/fleet/base-unit-gate.sh b/tools/fleet/base-unit-gate.sh index 9eeb90227..ac09b1345 100755 --- a/tools/fleet/base-unit-gate.sh +++ b/tools/fleet/base-unit-gate.sh @@ -14,8 +14,9 @@ # the outputs split 80/20 exactly (the UTXO side), identical on both nodes # 4. the execution layer: eth_getBalance of the miner's EVM address is equal on both nodes and equals the sum of the # producer shares the segments paid (igneum_getSegment over every chain block), which is the identity bridge -# 5. every reward in a segment equals producer_share(block_subsidy(daa of the chain block)) under the testnet schedule -# at 18 decimals (100 IGN a second, the 90-day ramp from 10%), computed here in exact integers +# 5. every reward in a segment equals producer_share(block_subsidy(daa of the rewarded block itself)) under the testnet +# schedule at 18 decimals (100 IGN a second, the 90-day ramp from 10%), computed here in exact integers (each merged +# block its own DAA: subsidy_per_block_activation_daa 0 on the testnet since the re-cut of 7 October 2026) # # CPU note (7 October 2026, 01:5x UK): the testnet genesis bits are 2^28 expected hashes a block and the box's CPU engine # does 0.147 MH/s on 32 threads, so a block takes 10 to 30 minutes on CPU; the ten-minute, hundreds-of-blocks form of @@ -133,18 +134,25 @@ for line in open(path): r = json.loads(line).get("result") if not r: print(" segment query failed:", line[:120]); bad += 1; continue - chain_hash = r["hash"] - daa = next((int(m["daaScore"], 16) if isinstance(m["daaScore"], str) else int(m["daaScore"]) for m in r["mergeset"] if m["hash"] == chain_hash), None) - if daa is None: - print(f" segment {r['number']}: the chain block is not in its own mergeset list"); bad += 1; continue - expect = producer(subsidy(daa)) + # each blue block of the mergeset is credited the subsidy of ITS OWN DAA (subsidy_per_block_activation_daa 0 on + # the testnet, ledger N8, 7 October 2026); the rewards list runs in the mergeset's blue order, one entry per blue + # block. Before N8 every reward was the chain block's subsidy and 165 of 561 segments read one ramp step low + # (the pod run of 09:4x UK, 7 October 2026: the known-failed shape of this check). + def daa_of(m): + return int(m["daaScore"], 16) if isinstance(m["daaScore"], str) else int(m["daaScore"]) blues = [m for m in r["mergeset"] if m["blue"]] - for w in r["rewards"]: + if len(blues) != len(r["rewards"]): + print(f" segment {r['number']}: {len(blues)} blue blocks but {len(r['rewards'])} rewards"); bad += 1; continue + for m, w in zip(blues, r["rewards"]): + if w["miner"].lower() != m["miner"].lower(): + print(f" segment {r['number']}: reward {w['miner']} is not the blue block's miner {m['miner']}"); bad += 1; continue + daa = daa_of(m) + expect = producer(subsidy(daa)) wei = int(w["wei"], 16) if isinstance(w["wei"], str) else int(w["wei"]) checked += 1 if wei != expect: bad += 1 - if bad <= 3: print(f" segment {r['number']}: reward {wei} != expected {expect} (daa {daa})") + if bad <= 3: print(f" segment {r['number']}: reward {wei} != expected {expect} (block daa {daa})") if w["miner"].lower().removeprefix("0x") == addr: total += wei bal = int(bal_hex, 16) print(f" rewards checked {checked}, wrong {bad}; sum of our rewards {total}; eth_getBalance {bal}; one IGN = {UNIT}")