Skip to content

fix(dag): clearCanonicalState wipes all canonical tables (closes post-snapshot Merkle divergence)#72

Merged
t-bhendarkar merged 2 commits into
mainfrom
fix/clear-canonical-state-missed-tables
Jun 4, 2026
Merged

fix(dag): clearCanonicalState wipes all canonical tables (closes post-snapshot Merkle divergence)#72
t-bhendarkar merged 2 commits into
mainfrom
fix/clear-canonical-state-missed-tables

Conversation

@t-bhendarkar

Copy link
Copy Markdown
Collaborator

Summary

Fixes audit finding C-1 from my-notes/audit-report.md (2026-06-03).

clearCanonicalState was missing 3 tables in all three store implementations (MemoryStore, SQLiteStore, KnexAdapter). The missing tables — domain_bindings, prescan_reviews, interests_registry — are yielded by iterateCanonicalState and therefore contribute to state_merkle_root. Any node that had ever processed BIND_DOMAIN, PRESCAN_REVIEW_TRIGGERED, or INTEREST_REGISTERED would compute a different merkle root than a fresh snapshot author after install → permanent consensus halt with no recovery path.

What changed

  • node/src/dag.js MemoryStore.clearCanonicalState — clears _domainBindings, _prescanReviews, _interestsRegistry
  • node/src/dag.js SQLiteStore.clearCanonicalState — adds 3 DELETE FROM inside the existing db.transaction() block
  • node/src/db/knex-adapter.js KnexAdapter.clearCanonicalState — adds 3 .delete() to the existing Promise.all([...]) flush
  • New regression test node/tests/dag/clear-canonical-state.test.js (5 tests)

Why this slipped through

The 3 tables were added to iterateCanonicalState when their features landed, but clearCanonicalState was never updated in lockstep. There was no regression test asserting the two stay in sync. This PR adds one.

Test plan

  • node/tests/dag/clear-canonical-state.test.js (5 tests, all green):
    • After clearCanonicalState, iterateCanonicalState yields zero rows
    • domain_bindings is cleared (was missed pre-fix)
    • prescan_reviews is cleared (was missed pre-fix)
    • interests_registry is cleared (was missed pre-fix)
    • Two DAGs with different seed paths produce IDENTICAL state_merkle_root after clear — proves zero canonical state survives, which directly closes the consensus-halt-after-snapshot-install bug
  • No existing tests broken
  • Manual verification: seed BIND_DOMAIN + PRESCAN_REVIEW + INTEREST_REGISTERED on node A, snapshot-install onto node B that was previously empty, compare state_merkle_root (separate manual smoke test, follow-up if desired)

Backwards compatibility

None required — the fix is local to each store's clear path. Already-running federations are unaffected (the bug only fires during a snapshot install, which is rare; this fix just ensures it stops being silent when it does).

Pairs with

  • Audit finding C-1 from my-notes/audit-report.md
  • Remaining audit items (C-2, C-3, C-4, C-6, C-8 through C-12 + AG-7) to follow as separate PRs

@vrkothekar vrkothekar left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: APPROVED ✅

Reviewed against AUDIT_CROSSREF_2026-06-03.md finding C-1. Fix is correct and complete.

Verified locally

  • All 5 new regression tests pass (clear-canonical-state.test.js)
  • 209 existing tests pass — zero regressions
  • Full iterateCanonicalState cross-checked: all 12 yielded tables are now cleared across all 3 store implementations (MemoryStore, SQLiteStore, KnexAdapter)
  • state_merkle_root identity test (test 5) proves no canonical row survives clear regardless of seed history — directly closes the consensus-halt-after-snapshot-install bug

Non-blocking note addressed

The stale comment "Wipe the 7 canonical-state tables" in snapshot-handler.js:860 has been updated in this branch (pushed as 3533e81) — count removed, now reads "Wipe all canonical-state tables".

Scope

Correctly scoped to C-1 only. Remaining audit items (C-2, C-3, C-4, C-6, C-8–C-12) to follow as separate PRs on this branch as described.

Ready to merge.

@t-bhendarkar t-bhendarkar merged commit bb47074 into main Jun 4, 2026
@t-bhendarkar t-bhendarkar deleted the fix/clear-canonical-state-missed-tables branch June 4, 2026 06:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants