diff --git a/tools/fleet/base-unit-gate.sh b/tools/fleet/base-unit-gate.sh index 5d41411e..9eeb9022 100755 --- a/tools/fleet/base-unit-gate.sh +++ b/tools/fleet/base-unit-gate.sh @@ -62,7 +62,7 @@ done if [ -n "$WORKER" ]; then say "nodes up; exporting the first pack from A, then mining $SECS s on the GPU worker $WORKER, payout to 0x$EVM_ADDR" mkdir -p "$ROOT/packs/first" "$ROOT/packs/prepare" - "$BIN/igneum-miner" export-pack grpc://127.0.0.1:$A_RPC "$ROOT/packs/first" > "$ROOT/pack.log" 2>&1 || say "export-pack exit $?" + "$BIN/igneum-miner" export-pack grpc://127.0.0.1:$A_RPC "$ROOT/packs/first" > "$ROOT/pack.log" 2>&1 || say "export-pack exit $? (the testnet address prefix; the miner prepares the pack itself)" "$BIN/igneum-miner" mine grpc://127.0.0.1:$A_RPC 1 "$SECS" gate --worker "$WORKER" --worker-args "--pack $ROOT/packs/first" --prepare-packs "$ROOT/packs/prepare" --network testnet --payout-label gate --evm-address "$EVM_ADDR" --dev-fee 0 --status-secs 60 > "$ROOT/miner.log" 2>&1 || say "miner exit $?" else say "nodes up; mining $SECS s with $THREADS CPU threads on A, payout to 0x$EVM_ADDR" @@ -86,10 +86,23 @@ say "check 3: the UTXO side over the last 30 blocks on both nodes" grep -c "same_on_all_nodes=true" "$ROOT/inspect.log" | sed 's/^/ blocks identical on both nodes: /' if grep -q "MISMATCH" "$ROOT/inspect.log"; then die "80/20 mismatch: $(grep -m1 MISMATCH "$ROOT/inspect.log")"; fi if grep -q "same_on_all_nodes=false" "$ROOT/inspect.log"; then die "a block differs between the nodes"; fi -LOW=$(grep -o "subsidy_in_payload=[0-9]*" "$ROOT/inspect.log" | cut -d= -f2 | sort -n | head -1) -say "smallest payload subsidy seen: $LOW (u64::MAX is 18446744073709551615)" -python3 - "$LOW" <<'PY' || die "a payload subsidy fits a u64: not an 18-decimal chain" -import sys; assert int(sys.argv[1]) > 18446744073709551615 +python3 - "$ROOT/inspect.log" "${GATE_EXPECT_DECIMALS:-18}" <<'PY' || die "a coinbase payload subsidy is not the 18-decimal schedule (see above)" +import re, sys +decimals = int(sys.argv[2]); UNIT = 10 ** decimals +launch_rate = 100 * UNIT; ramp_seconds = 90 * 86400; start = 10; bps = 1 +def subsidy(daa): + s = daa // bps; full = launch_rate // bps + return full if s >= ramp_seconds else full * (start * ramp_seconds + (100 - start) * s) // (100 * ramp_seconds) +n = bad = 0 +for line in open(sys.argv[1]): + m = re.search(r" daa=(\d+) .*subsidy_in_payload=(\d+)", line) + if not m: continue + n += 1; daa, got = int(m.group(1)), int(m.group(2)) + if got != subsidy(daa): + bad += 1 + if bad <= 3: print(f" daa {daa}: payload subsidy {got} != schedule {subsidy(daa)}") +print(f" payload subsidies checked {n}, wrong {bad}; one IGN = {UNIT}; day-0 block = {subsidy(0)} base units") +assert n > 0 and bad == 0 PY tail -1 "$ROOT/inspect.log" | cut -c1-200 @@ -98,7 +111,7 @@ BAL_A=$(evm $A_EVM eth_getBalance "[\"0x$EVM_ADDR\",\"latest\"]" | jq -r .result say "balances: A $BAL_A B $BAL_B" [ "$BAL_A" = "$BAL_B" ] || die "balances differ between the nodes" : > "$ROOT/segments.jsonl" -for n in $(seq 1 "$BLOCKS"); do evm $A_EVM igneum_getSegment "[$n]" >> "$ROOT/segments.jsonl"; echo >> "$ROOT/segments.jsonl"; done +for n in $(seq 1 "$BLOCKS"); do evm $A_EVM igneum_getSegment "[\"$(printf '0x%x' "$n")\"]" >> "$ROOT/segments.jsonl"; echo >> "$ROOT/segments.jsonl"; done python3 - "$ROOT/segments.jsonl" "$BAL_A" "$EVM_ADDR" "${GATE_EXPECT_DECIMALS:-18}" <<'PY' || die "the execution layer does not match the schedule (see above)" import json, sys path, bal_hex, addr, decimals = sys.argv[1], sys.argv[2], sys.argv[3].lower(), int(sys.argv[4]) @@ -118,10 +131,12 @@ for line in open(path): line = line.strip() if not line: continue r = json.loads(line).get("result") - if not r: continue + 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: continue + 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)) blues = [m for m in r["mergeset"] if m["blue"]] for w in r["rewards"]: @@ -130,7 +145,7 @@ for line in open(path): if wei != expect: bad += 1 if bad <= 3: print(f" segment {r['number']}: reward {wei} != expected {expect} (daa {daa})") - if w["miner"].lower().lstrip("0x") == addr: total += wei + 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}") print(f" balance in IGN (8 visible digits): {bal // UNIT}.{(bal % UNIT) // (UNIT // 10**8):08d}")