Repository navigation
Conversation
f08aacd to
6e8ad07
Compare
|
| config.cleanupOldDutiesAfterHours = Math.ceil( | ||
| (Number((offset + lifetime + 1n) * roundSize) * Number(slotDuration)) / 3600, | ||
| ); |
There was a problem hiding this comment.
Existing duties lose grace period
When an upgraded validator starts with the default retention setting, its first cleanup applies the new slashing-window age to records already in the database. Signed duties older than that window are deleted immediately, rather than receiving the promised 30-day grace period. The cleanup needs to distinguish pre-upgrade records before applying the new limit.
Knowledge Base Used: Validator services
There was a problem hiding this comment.
this is addressed through the migration.
There was a problem hiding this comment.
You're right — migration 3 adds expires_at with a CURRENT_TIMESTAMP + INTERVAL '30 days' default, so existing rows receive the intended grace period before expiry-based cleanup runs. This addresses my concern.
| AND rollup_address = $2 | ||
| AND completed_at < CURRENT_TIMESTAMP - ($1 || ' milliseconds')::INTERVAL; |
There was a problem hiding this comment.
The cleanup query now filters by rollup address and completed_at, but the existing cleanup index covers status and started_at. As signing history grows in a shared database, each replica's periodic cleanup may have to examine many unrelated signed rows. An index matching the new filter would keep this maintenance work efficient.
Knowledge Base Used: Operations and deployment
| // Clean up duties older than 1 hour | ||
| const maxAgeMs = 60 * 60 * 1000; // 1 hour | ||
| const numCleaned = await spDb.cleanupOldDuties(maxAgeMs); | ||
| const numCleaned = await spDb.cleanupOldDuties(ROLLUP_ADDRESS, maxAgeMs); |
There was a problem hiding this comment.
Rollup cleanup isolation lacks coverage
This test cleans up records for only one rollup. The new cross-rollup startup test checks that records survive startup, but not that aged records for another rollup survive cleanup. Add two-rollup cleanup cases for PostgreSQL and LMDB so a regression in the central isolation guarantee is caught.
Knowledge Base Used: Validator services
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
6e8ad07 to
fc3bca6
Compare
spalladino
left a comment
There was a problem hiding this comment.
Why do we need a new column for this? Can't we just use started_at plus the max age?
Also, why does the expires_at use the slashing window time? Strictly speaking, we only need to hold the row in place for the duration of a slot, which is when double-signing could occur. After that, we don't really care. So holding a row for a few minutes is good enough, anything in the order of days is plenty.
| DELETE FROM validator_duties | ||
| WHERE status = 'signed' | ||
| AND started_at < CURRENT_TIMESTAMP - ($1 || ' milliseconds')::INTERVAL; | ||
| WHERE expires_at <= CURRENT_TIMESTAMP; |
There was a problem hiding this comment.
This cleanup no longer filters on status = 'signed', and lmdb.ts:278 is the same. So it also deletes rows still in signing, which are live locks.
DELETE FROM validator_duties WHERE expires_at <= CURRENT_TIMESTAMP;You can reach this with VALIDATOR_HA_OLD_DUTIES_MAX_AGE_H=0. The config accepts it (parseSafeInteger, zod .min(0) in stdlib/src/ha-signing/config.ts:87), so the row is inserted with expires_at = now. Any replica's cleanup then removes it while the owner is still signing, and a peer polling the row inserts a fresh one and signs. The owner's recordSuccess fails and it doesn't broadcast, so this is a lost duty rather than a double signature. Cleanup should still never remove a lock.
Reject 0 in config (.positive() in zod plus a > 0 check on the env value) and always default to a positive retention.
written by claude
| ); | ||
|
|
||
| describe('cleanupOldDuties', () => { | ||
| it('should only clean up old signed duties', async () => { |
There was a problem hiding this comment.
"should only clean up old signed duties" still asserts the signing row survives, but it now survives for a different reason. The shared test config (lines 54-60) has no cleanupOldDutiesAfterHours, so the row is inserted with a NULL expires_at.
postgres.test.ts (~line 1500) has the same problem: the signing fixtures omit expires_at and inherit the +30 days column default. The cleanupOldDutiesAfterHours: 0.5 and 0.000001 settings on the cleanup services no longer affect what cleanup deletes.
So no test covers a signing row whose deadline has passed, which is the case in the schema.ts cleanup. Add a case with an expired signing row on both backends, so a test pins down what cleanup does with a live lock.
written by claude
|
new column so that we can avoid deleting rows that are in the db at migration time. Otherwise we'd delete everything of the old rollup. There's no reason to choosing the slashing period other than it's jsut a number 🙂 |
My understanding is we'd delete everything that's expired, right? Why is this a problem? I may be missing something though. |
|
if there are two versions of the node (v5 and v6) both sharing a database:
If we add a column which says "it's safe to delete this row no sooner than this " than all future versions could encode the same rule. |
|
Hmm I still push back (sorry for being annoying on a low severity issue, but hey, sometimes it's fun to have real discussions with a real dev about real code rather than via agents!). We are setting N ridiculously large, whereas it's only needed for a handful of slots. Even if slot time changes a lot between versions, we should be covered. |
|
sure, I can reduce the number. I just needed a value. It felt natural to have it around for a slashing round |
|
Sorry, my comment was not about reducing the number, but that since it's ridiculously large, there's no need to have the expires-at column, since any deviations in the actual time we need to keep the signature (which is in the order of a few minutes) across node versions won't really matter. So we can drop the new column altogether. |
The node no longer deletes signing history for other rollups, instead which signing duty records an 'expiry time' and jobs get deleted once they're stale. Existing jobs in the db will get 30d grace period, new jobs get the slashing window as a lifetime.
Fix A-2184