Skip to content

Node PR #876 — Governance hash-mismatch diagnostics + isCoherent dump #879

@linear

Description

@linear

PR: #876
Branch: diag/governance-hash-mismatch-v2feat-stabilisation-test
Head: 49dd4e79

What it does

Four diagnostic pieces for the governance hash mismatch on dev.node2:

  1. scripts/dev-node-battery.ts — single-command smoke test (pay → stake → validators list → governance propose → vote → unstake → final state), with per-stage tx polling via getTransactionStatus nodeCall and a self-contained markdown report writer.
  2. test-reports/dev-node-battery-FINAL.md — clean run captured against dev.node2.demos.sh:53552 (node v0.9.8 / a0957941, dirty=true, osDenomination active).
  3. test-reports/governance-hash-mismatch-analysis.md — root-cause analysis + why the existing test suite missed it (every governance test bypasses the SDK builder).
  4. src/libs/blockchain/transaction.tsisCoherent mismatch dump (sibling of PR debug(validation): emit raw gcr_edits dump on mismatch + version canary (DEBUG-ONLY) #870's GCREdit dump). When the full content hash diverges, emits tx type, both hashes, and the serialized bytes at log.warn level so the next dev.node2 repro pinpoints the diverging byte from logs.

Why diagnostic, not fix

Without log access to dev.node2 + the binary being dirty=true, a speculative serializer fix would chase the wrong asymmetry. The two known divergences (node doesn't walk gcr_edits[], node rebuilds transaction_fee without spread) both produce identical bytes for both PAY and PROPOSE in pure local round-trips, so the dev.node2-specific divergence is not yet pinned. The battery + log dump close that gap on next repro cycle.

CI status

All green:

  • Greptile Review: success
  • SonarCloud Code Analysis: success
  • claude-review: success

AI feedback addressed (6 rounds)

# Source Severity Issue Commit
1 Greptile P1 log.error × 4 would page on-call on every mismatch 2b9aa96c — collapsed to single log.warn
2 Greptile P2 unused existsSync import 2b9aa96c
3 Greptile P2 skipped stages counted as failures in summary 2b9aa96c — added skipped?: boolean
4 TS6 error demos.confirm(tx, demos) passed wrong arg count f961fcdc — dropped spurious 2nd arg, 8 call sites
5 SonarCloud hotspot http:// URL in default RPC c9373c9f// NOSONAR with rationale
6 Greptile P1 proposalId = randomUUID() set before await, Stage 5 ran on failed propose 49dd4e79 — mint local id, promote only after included

Verified locally

  • bunx tsx scripts/dev-node-battery.ts end-to-end against dev.node2: 6/7 stages + 2 skipped (clean — Stage 5 properly ⏭️ after Stage 4 failure)
  • npx tsc --noEmit --skipLibCheck clean for transaction.ts and battery script

Also fixed in this PR

  • Added stress-test-mnemonic to .gitignore — was almost leaked via git checkout stash@{N} side-effect during the session. Caught locally before push.

Next step

Reviewer approval. mergeable=MERGEABLE. After merge: redeploy dev.node2 → re-run battery → grep node logs for [TX] isCoherent mismatch → pinpoint diverging byte → targeted serializer fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions