Conversation
`identity.keyRecords` was cast to a bare `Codec` and read as JSON, which hid that `KeyRecord` has three variants. `MultiSigSignerKey` names the multisig account, not a DID, so the JSON read created an `Identity` keyed by an SS58 address, an `Account` pointing at it, and a portfolio 0 for it. A signer key has no identity and no permissions, so it now resolves to no `Account` at all; `ledgerAccount` still creates a bare one if the address holds POLYX. The same cast is gone from the two `system.account` reads and the reconciliation script, narrowed to the balance fields - the only part that must stay spec-agnostic, since `frozen` is `miscFrozen`/`feeFrozen` on older runtimes. The script loads the chain-type augmentation itself now: only `tsconfig.test.json` includes `scripts/**/*`, so an editor was type-checking it against a different, unaugmented type than CI. The event-data casts are load-bearing and stay: two physical copies of `@polkadot/types-codec`, which `subql build` resolves differently from `tsc`. Separately, the per-block account cache held the resolved `Account`, so a hit skipped the store read as well as the chain read. The chain read cannot change within a block - `api` serves the block's end-of-block state - but the row can, when a handler links or unlinks a key. A cached negative therefore shadowed a row another handler had just written, and `ledgerAccount` went on to overwrite it. The cache now holds only the key record; `Account` is read from the store on every lookup.
F-OBrien
force-pushed
the
fix/key-record-typing-and-block-cache
branch
from
September 10, 2026 09:05
6734e4f to
924d6ec
Compare
F-OBrien
marked this pull request as ready for review
September 10, 2026 09:05
|
Contributor
|
I have added this commit in #353 (comment) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Found while reviewing #349. Draft — #349 is still under review.
The bug
identity.keyRecordswas cast to a bareCodecand read via.toJSON(), which hid thatKeyRecordhas three variants.MultiSigSignerKeycarries the multisig's account, not a DID, so a signer key produced:Identityrow keyed by an SS58 addressAccountpointing at that fabricated identityA signer key has no identity and no permissions, so it now resolves to no
Accountat all.ledgerAccountstill creates a bare one if the address ever holds POLYX, which is the same row it creates for a pallet or system address. No DID is resolved for a signer on purpose: the signer→multisig and multisig→identity links rebind independently, andmultiSig.adminDidis the admin, not the identity the multisig is joined to.MultiSigSignerrows are left to the multisig event handlers and the genesis/seed scan — neitherstatusnorcreatedBlockis derivable from a key record.The cache
BlockContext.accountsheld the resolvedAccount, so a cache hit skipped the store read as well as the chain read. The chain read cannot change within a block (apiisapi.at(blockHash)of the block being indexed, so it serves end-of-block state), but the row can — a handler links or unlinks a key partway through. So a cached negative shadowed a row another handler had just written, andledgerAccountthen overwrote it, dropping itsidentityId.It now caches only the key record.
Accountis read from the store on every lookup. Two regression tests cover both staleness modes; they fail if entity caching is put back.Casts
Removed where they were discarding real augmented types: both
system.accountreads andscripts/reconcile-polyx.ts, narrowed to the balance fields — the only part that must stay spec-agnostic, sincefrozenismiscFrozen/feeFrozenon older runtimes.Kept where they are load-bearing: every
event.event.data[i]/extrinsic.args[0]site. Those passtscand failsubql build— two physical copies of@polkadot/types-codec(cjs/types/codecvstypes/codec) that the two toolchains resolve differently. They mask nothing: event data isCodec[], so there are no augmented types on that path.scripts/reconcile-polyx.tsnow loads the chain-type augmentation itself. Onlytsconfig.test.jsonincludesscripts/**/*, so an editor was type-checking it against a different, unaugmented type than CI — worth closing regardless of this PR. The other two chain-reading scripts still have that gap.Verified
tsc --noEmit -p tsconfig.test.jsonclean,eslint src scripts testsclean,subql buildexits 0, 409/409 unit tests pass.Not included
Pre-existing rows in any already-synced database still have the fabricated identities; that needs a reindex or migration.