From e0bd6fe73cd1518986525b2aa91edcdd9a8f3bdd Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Tue, 6 Oct 2026 22:48:42 +0000 Subject: [PATCH] tools/ci/base-unit-pending-check.sh (O-2.6 phase B): counts the fork's Amount::pending_u64() narrowing sites and refuses a tree whose IMPLEMENTED_DECIMALS carries 18 while any is left; self-test on a known-failed, a known-good and an in-progress tree; in the pre-push gate Co-Authored-By: Claude Fable 5.1 --- tools/ci/base-unit-pending-check.sh | 49 +++++++++++++++++++++++++++++ tools/ci/pre-push.sh | 1 + 2 files changed, 50 insertions(+) create mode 100755 tools/ci/base-unit-pending-check.sh diff --git a/tools/ci/base-unit-pending-check.sh b/tools/ci/base-unit-pending-check.sh new file mode 100755 index 000000000..488aa3836 --- /dev/null +++ b/tools/ci/base-unit-pending-check.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# The base-unit widening's phase B marker (O-2.6, docs/design/base-unit.md section 8). While a path of the node fork +# still carries a u64 amount it narrows through `Amount::pending_u64()`; every such site is removed by its own step +# (B3 stores, B4 p2p, B5 RPC, B6 mempool, B7 exec, B8 txscript, B9 wallet and tools). This check counts the sites in a +# fork tree and fails when any are left in a tree that claims 18 decimals implemented (`IMPLEMENTED_DECIMALS` carrying +# 18), so B10 cannot flip the list over a half-widened tree; in a tree that still claims only 8 it prints the inventory +# and passes. +# +# tools/ci/base-unit-pending-check.sh # a vendor/igneum-node-* worktree +# tools/ci/base-unit-pending-check.sh --self-test # fails on a known-failed tree, passes on a known-good one +set -euo pipefail + +count_sites() { # every call site, the definition in unit.rs excluded + grep -rn --include='*.rs' -F '.pending_u64()' "$1" 2>/dev/null | grep -v '/target' | grep -v 'consensus/core/src/unit.rs' || true +} +claims_18() { # IMPLEMENTED_DECIMALS carries 18 + grep -E 'pub const IMPLEMENTED_DECIMALS: &\[u8\] = &\[[^]]*\b18\b' "$1/consensus/core/src/unit.rs" >/dev/null 2>&1 +} +check() { + local tree=$1 sites n + sites=$(count_sites "$tree"); n=$(printf '%s' "$sites" | grep -c . || true) + if claims_18 "$tree"; then + if [ "$n" -gt 0 ]; then + echo "base-unit-pending: $n pending_u64() site(s) left while IMPLEMENTED_DECIMALS carries 18:"; printf '%s\n' "$sites" + return 1 + fi + echo "base-unit-pending: no pending_u64() site; 18 decimals implemented end to end" + else + echo "base-unit-pending: $n pending_u64() site(s) in a tree at 8 decimals (phase B in progress)" + printf '%s\n' "$sites" | awk -F: '{print $1}' | sort | uniq -c | sort -rn + fi +} + +if [ "${1:-}" = --self-test ]; then + t=$(mktemp -d) + mkdir -p "$t/bad/consensus/core/src" "$t/bad/rpc/src" "$t/good/consensus/core/src" "$t/wip/consensus/core/src" "$t/wip/rpc/src" + echo 'pub const IMPLEMENTED_DECIMALS: &[u8] = &[DEVNET_DECIMALS, EVM_DECIMALS]; // 8, 18' > "$t/bad/consensus/core/src/unit.rs" + echo 'pub const IMPLEMENTED_DECIMALS: &[u8] = &[8, 18];' > "$t/bad/consensus/core/src/unit.rs" + echo 'let v = amount.pending_u64();' > "$t/bad/rpc/src/x.rs" + echo 'pub const IMPLEMENTED_DECIMALS: &[u8] = &[8, 18];' > "$t/good/consensus/core/src/unit.rs" + echo 'pub const IMPLEMENTED_DECIMALS: &[u8] = &[8];' > "$t/wip/consensus/core/src/unit.rs" + echo 'let v = amount.pending_u64();' > "$t/wip/rpc/src/x.rs" + if check "$t/bad" >/dev/null 2>&1; then echo "self-test: the known-failed tree passed"; exit 1; fi + check "$t/good" >/dev/null || { echo "self-test: the known-good tree failed"; exit 1; } + check "$t/wip" >/dev/null || { echo "self-test: the in-progress tree failed"; exit 1; } + rm -rf "$t"; echo "base-unit-pending self-test ok (fails on a site under 18, passes clean and in-progress trees)"; exit 0 +fi +[ -d "${1:-}" ] || { sed -n '2,12p' "$0"; exit 2; } +check "$1" diff --git a/tools/ci/pre-push.sh b/tools/ci/pre-push.sh index c6364234d..d9f4ea8fe 100755 --- a/tools/ci/pre-push.sh +++ b/tools/ci/pre-push.sh @@ -70,6 +70,7 @@ tree_checks() { run "pinned guest programs match their manifest" bash tools/ci/pinned-guests-check.sh run "root prover playbooks kill the GPU server and unlink its socket" bash tools/ci/prover-socket-check.sh run "commit-string gate self-test" bash tools/ci/commit-string-check.sh --self-test + run "base-unit pending-narrowing check self-test (O-2.6 phase B)" bash tools/ci/base-unit-pending-check.sh --self-test run "build server remote checkout self-test" bash infra/build-server/remote-run.sh --self-test run "no shell assignment hides behind a trailing comment (the swallowed-defaults class)" bash -c 'bash tools/ci/defaults-line-check.sh --self-test && bash tools/ci/defaults-line-check.sh' run "the identity check's own self-test (excluded research path passes, exported leak fails)" bash tools/ci/identity-check.sh --self-test