Skip to content

Evaluate miner active state per-block in scoring replay#56

Merged
anderdc merged 2 commits intotestfrom
fix/scoring-historical-active-state
Apr 16, 2026
Merged

Evaluate miner active state per-block in scoring replay#56
anderdc merged 2 commits intotestfrom
fix/scoring-historical-active-state

Conversation

@LandynDev
Copy link
Copy Markdown
Collaborator

Summary

  • Scoring previously filtered candidates by event_watcher.active_miners (scoring-time snapshot), so a miner who was active + top-rate throughout the window but deactivated before scoring got zero credit. Active state is now replayed per-block alongside collateral/rate/busy. Only metagraph membership is evaluated at scoring time.
  • New ActiveEvent log in ContractEventWatcher with get_active_miners_at / get_active_events_in_range helpers. initialize() seeds an anchor event at the cursor so pre-cursor state mirrors the collateral bootstrap pattern. Prune retains the latest event per hotkey as a reconstruction anchor.
  • Scoring: eligible_hotkeysrewardable_hotkeys (= current metagraph). EventKind.ACTIVE orders first at shared blocks — active is the tell-all, applies before busy/collateral/rate transitions.
  • 17 new tests covering mid-window deactivation/activation, the headline "deactivated at scoring time but active during window" case, pre-window reconstruction, multi-cycle toggles, crown-inherits-on-deactivation, same-block event ordering, and event-watcher helper units.

Test plan

  • pytest tests/test_scoring_v1.py — 46/46 pass
  • pytest tests/ — 289/289 pass
  • ruff format . + ruff check . — clean
  • E2E smoke: cd alw-utils/dev-environment && ./down.sh --force && ./up.sh --chains btc && ./tests/run.sh --chains btc --suite 02
  • Manual: miner calls set_active(false) between window_end and next scoring tick — confirm they still receive the reward cycle they were active for

Scoring previously filtered candidates by event_watcher.active_miners — the
current (scoring-time) active set — so a miner who was active + top-rate
throughout the window but deactivated before scoring got zero credit.
Active state is now replayed per-block alongside collateral, rate, and
busy, via a new ActiveEvent log in ContractEventWatcher. A miner's
status at scoring time is irrelevant beyond metagraph membership.

- ActiveEvent log + get_active_miners_at / get_active_events_in_range
- initialize() seeds an anchor event at cursor for bootstrap-active miners
- prune keeps the latest active event per hotkey as a reconstruction anchor
- scoring: eligible_hotkeys → rewardable_hotkeys (= metagraph); active
  evaluated via replay. EventKind.ACTIVE orders first at shared blocks
- 17 new tests covering mid-window transitions, deactivated-at-scoring-time,
  pre-window reconstruction, same-block event ordering, and watcher helpers
Same class of bug as the prior active-flag fix: scoring used the
watcher's current scalar for min_collateral, ignored max_collateral
entirely, and had no concept of a halted contract. An admin config
change retroactively applied to every historical block in the window.

- ConfigEvent log + config_current / config_initial mirrors for
  min_collateral, max_collateral, halted
- ConfigUpdated handler now routes through record_config_transition
  for all tracked keys (previously only min_collateral)
- initialize() reads max_collateral + halted from the contract and
  seeds anchor ConfigEvents at cursor
- prune keeps the latest config event per key as a reconstruction anchor
- scoring: EventKind.CONFIG ordered first; replay mutates min/max/halted;
  crown_holders_at_instant returns [] when halted; enforces
  min_collateral <= collateral <= max_collateral (max=0 disables cap,
  matching contract semantics)
- drop min_collateral kwarg from replay_crown_time_window — replay
  reconstructs it from config history
- 16 new tests: mid-window min raised/lowered, max over-cap exclusion,
  max lowered mid-window, max=0 no cap, halt mid-window recycles that
  interval, halt entire window recycles full pool, same-block CONFIG
  transitions, unknown-key ignored, duplicate no-op, fallback semantics
@anderdc anderdc merged commit 9cc7c04 into test Apr 16, 2026
2 checks passed
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