Skip to content

Tombstones for deleted contracts#155

Open
githoboman wants to merge 2 commits into
Miracle656:mainfrom
githoboman:Tombstones-for-deleted-contracts
Open

Tombstones for deleted contracts#155
githoboman wants to merge 2 commits into
Miracle656:mainfrom
githoboman:Tombstones-for-deleted-contracts

Conversation

@githoboman

Copy link
Copy Markdown
Contributor

mplemented contract liveness tracking with tombstone emission on storage TTL expiry, matching the codebase's existing conventions (modeled closely on sac-detect.ts).
Closes #143

Files changed
New: src/indexer/tombstones.ts — the core module:

isExpired(liveUntilLedger, currentLedger) — pure expiry rule. A contract is live through its liveUntilLedger, so it's only expired once currentLedger > liveUntilLedger. A null/unknown TTL is never tombstoned.
tombstoneFor(liveness, currentLedger) — pure: builds a tombstone record or returns null.
fetchLiveUntilLedger — reads the contract instance entry's liveUntilLedgerSeq via getRpc().getContractData(...), exactly like SAC detection reads the executable. Wrapped in an injectable TtlFetcher type for testing.
fetchLiveness / detectExpiredContracts — de-duplicate contract IDs, one RPC call per unique contract.
insertTombstones — idempotent createMany({ skipDuplicates: true }) keyed by the unique contractId (first expiry detection wins).
tombstoneExpiredContracts — the end-to-end entry point: detect + persist.
New: src/tests/tombstones.test.ts — 15 tests over a TTL fixture (live / expired / border / unknown contracts) with an injected fetcher and a mocked Prisma client. No network, no DB.

Schema + migration — added the ContractTombstone model to schema.prisma (unique contractId, liveUntilLedger, detectedLedger, indexed by detectedLedger) plus the matching SQL migration.

Acceptance criteria
✅ Tombstones inserted on expiry detection — tombstoneExpiredContracts / insertTombstones.
✅ Tested with fixture — fixture-driven suite, 15/15 passing.
Verification
npx jest src/tests/tombstones.test.ts → 15 passed
npx tsc --noEmit (and the test tsconfig) → clean, exit 0
npx prisma generate → client regenerated for the new model

@drips-wave

drips-wave Bot commented Jun 29, 2026

Copy link
Copy Markdown

@githoboman Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Miracle656 Miracle656 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

The tombstone model is nicely designed — contractId-unique so first-detection-wins and re-detection is a no-op, createMany with skipDuplicates for idempotency, the "unknown liveUntilLedger is never treated as expired" guard, and thorough unit tests on tombstoneFor / detectExpiredContracts. But there's a gap that blocks merge:

The feature is never invoked — it's dead code. detectExpiredContracts / tombstoneExpiredContracts are only referenced by their own tests; this PR doesn't modify src/indexer.ts (or any poll/cron path), so nothing ever calls them against live ledgers. As shipped, the migration adds a ContractTombstone table that stays permanently empty and downstream consumers watching it never get a signal.

To land this, please wire the detection into the indexing loop:

  • Call tombstoneExpiredContracts(contracts, currentLedger) from pollOnce (or a periodic job), sourcing each tracked contract's instance liveUntilLedger. If that requires an RPC/getLedgerEntries call that isn't available in the poll path yet, that's the missing piece — either add it or split it into a follow-up and note the intended trigger here.
  • A small test asserting a row actually lands in the table when an expired contract flows through the wired path.

Also please rebase onto latest main#154 landed with the lockfile (@emnapi/core) reconciled, so rebasing will clear the npm ci desync this branch inherits. Solid foundation; it just needs to actually run.

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.

Tombstones for deleted contracts

2 participants