implemented cleanup pda script#36
Conversation
zkr99
left a comment
There was a problem hiding this comment.
Solid shape - matches the blueprint. Discriminator + offset memcmp filtering is the right approach, the summary output is informative, and the signer-must-match-target check is correct from a Solana mechanics standpoint (the program's close instructions require the owner to sign, so an operator can't run this for someone else's wallet).
Three blockers before merge, plus a few inline polish notes.
Blockers:
- Branch is stale. Your
cleanup-pdasbranch predates Pluto's recent PRs (#29, #30, #31, #32, #35) and the org rebrand (#33, #34). package.json showslitesvm-initialandtrustscore.tswhich were renamed in PR #29. Rebase against current develop:
git fetch origin develop
git rebase origin/develop
git push --force-with-lease-
IDL path doesn't exist on current develop. The Rust crate was renamed
iam_verifier->entros_verifierin PR #33, so Anchor outputs the IDL attarget/idl/entros_verifier.json, notiam_verifier.json. Script throws ENOENT at runtime as written. Inline note on the line. -
Filter logic contradicts the program's
close_challengeconstraint. Closing an expired-but-unused challenge fails on-chain withChallengeNotUsed, becauseclose_challengerequireschallenge.used == true. Your filterused || expiresAt <= nowTsincludes the unused-expired case, which silently fails in the try/catch and logs spurious errors. Fix inline.
Polish items inline. Once the three blockers land, ready to take another look.
| import * as fs from "fs"; | ||
| import * as path from "path"; | ||
|
|
||
| const IAM_VERIFIER_PROGRAM_ID = new anchor.web3.PublicKey( |
There was a problem hiding this comment.
Stale naming from before the org rebrand. Pluto's PR #35 swept all IAM_* references to ENTROS_* across the codebase. Rename to ENTROS_VERIFIER_PROGRAM_ID. The pubkey itself stays the same (programs were upgraded in place during the rebrand), just the variable name changes.
| ); | ||
| } | ||
|
|
||
| const idlPath = path.resolve(__dirname, "../target/idl/iam_verifier.json"); |
There was a problem hiding this comment.
This file doesn't exist on current develop. The Rust crate was renamed in PR #33, so Anchor outputs the IDL at target/idl/entros_verifier.json. Script throws ENOENT at runtime. After rebasing:
const idlPath = path.resolve(__dirname, '../target/idl/entros_verifier.json');| const closeableChallenges = challengeAccounts.filter(({ account }) => { | ||
| const expiresAt = readI64LE(account.data, EXPIRES_AT_OFFSET); | ||
| const used = readBool(account.data, USED_OFFSET); | ||
| return used || expiresAt <= nowTs; |
There was a problem hiding this comment.
This filter doesn't match the program's contract. close_challenge at programs/entros-verifier/src/lib.rs:205 constrains challenge.used and returns ChallengeNotUsed (6005) for unused challenges regardless of expiry. The current logic flags expired-unused challenges as closeable, which silently fails in the try/catch below and logs spurious errors. Fix:
return used;Expired-unused challenges are a known protocol gap (no instruction exists to close them) - not this script's job to solve.
| return used || expiresAt <= nowTs; | ||
| }); | ||
|
|
||
| const verificationAccounts = await provider.connection.getProgramAccounts( |
There was a problem hiding this comment.
VR closes every result owned by the signer with no filter. The program doesn't constrain this (just the ownership check at programs/entros-verifier/src/lib.rs:218), so it works, but a fresh VR still bound to the current identity.current_commitment represents an unspent proof - closing it discards work the user paid CU for.
Consider filtering for either:
- VRs whose
commitment_prev(offset 56, 32 bytes) no longer matches the current identity state'scurrent_commitment- i.e. already consumed byupdate_anchor - VRs whose
verified_at(offset 49, 8 bytes i64) is older thanMAX_PROOF_AGE_SECS(600s) and therefore expired anyway
At minimum, add a header comment noting the script is destructive to unspent proofs.
| "private": true, | ||
| "scripts": { | ||
| "test": "anchor test", | ||
| "cleanup-pdas": "npx --yes tsx scripts/cleanup-pdas.ts", |
There was a problem hiding this comment.
npx --yes tsx silently installs tsx at runtime - slow on first run, no version pinning, and the --yes skips the install confirmation prompt. Add tsx to devDependencies and use it directly:
"cleanup-pdas": "tsx scripts/cleanup-pdas.ts"
Implemented cleanup pdas script