Skip to content

feat(dashboard): add validator score history view (issue #76) - #87

Merged
flo2517 merged 1 commit into
mainfrom
feat/issue-76-validator-score-history
Aug 7, 2026
Merged

feat(dashboard): add validator score history view (issue #76)#87
flo2517 merged 1 commit into
mainfrom
feat/issue-76-validator-score-history

Conversation

@flo2517

@flo2517 flo2517 commented Aug 7, 2026

Copy link
Copy Markdown
Owner

What

Reads pallet-network-validator's Rounds StorageNMap directly (never read from Go before this PR) and surfaces it as a new dashboard endpoint and UI panel — the first concrete piece of #76's validator-facing views, unblocked by #85's committee/evidence work.

internal/blockchainbridge/roundresult.go

  • RoundResult/RoundStatus mirror the pallet's struct/enum exactly (fixed-width SCALE, no compact encoding), verified directly against blockchain/pallets/network-validator/src/lib.rs.
  • roundResultStorageKey builds Rounds' 3-key StorageNMap key (Blake2_128Concat AccountId, Twox64Concat u64, Twox64Concat ScoreDimension) — this codebase's first NMap key; everything prior only needed the single-key mapStorageKey helper. Evidence uses the identical key shape if a future caller needs it.
  • twox64 is twox128's 8-byte single-pass sibling (Twox64Concat's hash component).
  • FinalizedRoundResult reads one (provider, round, dimension) point; found=false means the round hasn't closed yet — a normal state, not an error.
  • ConfidenceBps turns submissions/committee_target into a display figure so a thin, low-confidence round can't be confused with a well-attested one.

internal/dashboard/validatorscores.go

  • GET /api/v1/validator-scores/{provider_id}: for each of the 5 score dimensions, concurrently scans the last 12 rounds back from the current round (derived via the existing internal/networkvalidator.RoundLength helper) for closed rounds, returning up to 8 per dimension.
  • Unauthenticated and rate-limited, matching agentEndpoint's reasoning — this is a narrower view over reputation data already public in /api/v1/overview, not a new trust boundary.

Dashboard UI

A new "Historique des rounds de scoring" panel — on-demand lookup by provider_id, not folded into the periodic overview poll, since each load is real per-round chain I/O.

Testing

  • Unit tests for the storage-key construction, decode, and confidence math.
  • Live-chain integration tests (OPENINFRA_TEST_SUBSTRATE_RPC_URL) proving the whole read path against the running local dev node, including the concurrent per-dimension scan end to end via the HTTP handler.
  • As with every pallet-network-validator interaction this session, the local dev chain's wasm predates the pallet, so only the "not found" path is live-verified, not a real closed-round decode — documented in the test comments, not hidden.
  • gofmt, go vet, go build ./..., and the full control-plane test suite all ran clean.

This leaves #76 open: operator views, RBAC, pagination beyond hardcoded LIMITs, accessibility review, E2E tests, and the decentralized-hosting migration doc are still outstanding.

🤖 Generated with Claude Code

Reads pallet-network-validator's Rounds StorageNMap directly (never
read from Go before this) and surfaces it as a new dashboard endpoint
and UI panel, the first concrete piece of #76's validator-facing views
unblocked by #85's committee/evidence work.

internal/blockchainbridge/roundresult.go:
- RoundResult/RoundStatus mirror the pallet's struct/enum exactly
  (fixed-width SCALE, no compact encoding), verified directly against
  blockchain/pallets/network-validator/src/lib.rs.
- roundResultStorageKey builds Rounds' 3-key StorageNMap key
  (Blake2_128Concat AccountId, Twox64Concat u64, Twox64Concat
  ScoreDimension) -- this codebase's first NMap key, everything prior
  only needed the single-key mapStorageKey helper. Evidence uses the
  identical key shape if a future caller needs it.
- twox64 is twox128's 8-byte single-pass sibling (Twox64Concat's hash
  component).
- FinalizedRoundResult reads one (provider, round, dimension) point;
  found=false means the round hasn't closed yet, a normal state, not
  an error.
- ConfidenceBps turns submissions/committee_target into a display
  figure so a thin, low-confidence round can't be confused with a
  well-attested one.

internal/dashboard/validatorscores.go:
- GET /api/v1/validator-scores/{provider_id}: for each of the 5 score
  dimensions, concurrently scans the last 12 rounds back from the
  current round (derived via the existing
  internal/networkvalidator.RoundLength helper) for closed rounds,
  returning up to 8 per dimension. Unauthenticated and rate-limited,
  matching agentEndpoint's reasoning -- this is a narrower view over
  reputation data already public in /api/v1/overview, not a new trust
  boundary.

Dashboard UI: a new "Historique des rounds de scoring" panel (on-demand
lookup by provider_id, not folded into the periodic overview poll,
since each load is real per-round chain I/O).

Tested: unit tests for the storage-key construction, decode, and
confidence math; live-chain integration tests
(OPENINFRA_TEST_SUBSTRATE_RPC_URL) proving the whole read path against
the running local dev node, including the concurrent per-dimension
scan end to end via the HTTP handler. As with every
pallet-network-validator interaction this session, the local dev
chain's wasm predates the pallet, so only the "not found" path is
live-verified, not a real closed-round decode -- documented in the
test comments, not hidden.

Leaves #76 open: operator views, RBAC, pagination beyond hardcoded
LIMITs, accessibility review, E2E tests, and the decentralized-hosting
migration doc are still outstanding.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@flo2517
flo2517 merged commit 570dcac into main Aug 7, 2026
4 checks passed
@flo2517
flo2517 deleted the feat/issue-76-validator-score-history branch August 7, 2026 12:00
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