Skip to content

Make all page models SSZ compatible for the frontend cache - #915

Merged
pk910 merged 5 commits into
masterfrom
pk910/model-ssz-fixes
Oct 23, 2026
Merged

pk910 merged 5 commits into
masterfrom
pk910/model-ssz-fixes

Conversation

@pk910

@pk910 pk910 commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Summary

The tiered page cache SSZ-encodes page models and silently falls back to JSON (logging page model not ssz compatible) for models that fail dynssz validation. The transaction page was one of 14 cached models affected. This PR makes every cached model SSZ compatible and adds tests that keep it that way.

  • Unsized ints → sized integers in the transaction, transactions, address, token, transfers, slot arrival, slot waves and bid-seen models and in services.SlotInclusionListsView.
  • Maps → slices: []UrlParam for the builders and MEV blocks pagers, []uint8 filter sets (rendered via a new inUint8List template func), a sorted slice with an explicit slot for epoch arrivals, and a []*SlotDutyName list for the slot duties endpoint (the two in-repo JS consumers are updated).
  • Pointer fields tagged ssz-type:"optional" on every non-list pointer in cached models, so nil survives the SSZ round trip. The arrival and waves models were previously kept on the JSON path on the assumption that SSZ had no optionals; the existing nil-fidelity tests now pass on the SSZ path.
  • Search-ahead cache value (searchAheadCached) held its result as interface{} and had both fields tagged json:"-", so the JSON fallback stored an empty object and cache hits answered the search box with null. It now carries one typed slice per search type and the handler picks the queried one.

Tests

  • handlers/page_models_ssz_test.go: registry of every value handed to the frontend cache (all top-level page models, checked for completeness against the models package, plus the handler- and service-local cached types). Each is stored through the public cache API and must be counted as SSZ compatible, survive a round trip, and declare every pointer field reachable through nested types as an SSZ optional. A separate round trip pins the search-ahead value.
  • Each guard was negative-checked (an int field, an unregistered model, an untagged nested pointer).

Notes

  • /validators?json now emits filter_cred_types as an array instead of an object.
  • make api-docs produced no changes.

The tiered page cache falls back to JSON and logs "page model not ssz
compatible" for models that fail dynssz validation. 14 cached models were
affected, through unsized int fields and map fields.

- replace int fields with sized integers in the transaction, transactions,
  address, token, transfers, slot arrival, slot waves and bid-seen models
  and in the services inclusion-lists view
- replace map fields with slices: []UrlParam for the builders and mev
  blocks pagers, []uint8 filter sets rendered via a new inUint8List
  template func, a slice with an explicit slot for epoch arrivals and a
  []*SlotDutyName list for the slot duties endpoint
- tag every non-list pointer field in cached models ssz-type:"optional"
  so nil survives the SSZ round trip; the arrival and waves models no
  longer need the JSON-path workaround and their nil-fidelity tests now
  pass on the SSZ path
- add cache/page_models_ssz_test.go: registry of all top-level page
  models with a completeness check, dynssz validation, a zero-value round
  trip and a static walk requiring the optional tag on every reachable
  pointer field; handlers/page_models_ssz_test.go covers cached values
  outside the models package

@redpandabot redpandabot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Summary

Makes all cached page models SSZ-compatible: sized ints replace unsized ones, maps become slices with updated templates/JS consumers, and every pointer field in cached models gets ssz-type:"optional" so nil survives the round trip, backed by a registry test with a parser-based completeness check. I traced all writers and consumers of the changed fields, verified the template func semantics and the dynssz v1.4.0 optional/pointer behavior, and confirmed stale-JSON cache entries safely fall back to a rebuild. The change looks correct; the only gap is one handler-local cached value (search_ahead) that remains on the JSON path and is missed by the new guard test.

Issues

  • 🟢 handlers/page_models_ssz_test.go:25 — search_ahead cached value stays on the JSON path, uncovered by the new guard — see the thread on that line

Reviewed @ 7d80953e
"Refactoring is just regret with a roadmap."

Comment thread handlers/page_models_ssz_test.go Outdated
@redpandabot

This comment has been minimized.

searchAheadCached held the result as interface{}, which dynssz rejects,
so it stayed on the JSON path. Both of its fields were also tagged
json:"-", so the JSON fallback stored an empty object and every cache hit
answered the search box with null. The value now carries one typed slice
per search type, the handler picks the queried one, and a round-trip
test pins that a cache hit serves the built entries. The type is added
to the handlers SSZ guard.

The models test used go/parser.ParseDir, which staticcheck flags as
deprecated (SA1019); it now parses the package files individually.

@redpandabot redpandabot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Makes all cached page models SSZ compatible: sized ints, map-to-slice conversions, optional tags on pointer fields, and a typed SSZ-compatible searchAheadCached value replacing the interface{} field that previously cached an empty object on the JSON fallback. The follow-up commit fixes the last open finding — the search-ahead cache value is now covered by the SSZ-compat guard (via the cache's incompatible-type counter, so a dynssz failure fails CI rather than silently falling back to JSON) and by a round-trip test. Demux via result() covers every allowed search type and the JSON response shape is unchanged; error results now persist correctly instead of being cached as empty. No remaining issues found.


Reviewed 48 changed file(s) @ 93817889 — no blocking issues found.
"Refactoring is just regret with a roadmap."

pk910 added 2 commits October 20, 2026 19:35
The models registry, completeness check and optional-pointer walk move
from the cache package into handlers/page_models_ssz_test.go, which
already covered the handler-local cached values through the public cache
API, so one test file guards every value handed to the frontend cache.
@redpandabot

This comment has been minimized.

@pk910
pk910 merged commit d38980e into master Oct 23, 2026
6 checks passed
@pk910
pk910 deleted the pk910/model-ssz-fixes branch October 23, 2026 14:32
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