Skip to content

Record zero-rate opt-outs in crown-time accounting#381

Merged
anderdc merged 1 commit into
testfrom
fix/zero-rate-optout-crown-accounting
May 26, 2026
Merged

Record zero-rate opt-outs in crown-time accounting#381
anderdc merged 1 commit into
testfrom
fix/zero-rate-optout-crown-accounting

Conversation

@LandynDev
Copy link
Copy Markdown
Collaborator

Closes #379.

Problem

A miner posting rate 0 for a direction means "no longer offered" (#37 semantics, enforced by the rate > 0 filter in crown_holders_at_instant). But refresh_miner_rates continued on r <= 0 before writing a rate event, so the opt-out never reached the persisted rate_events stream. Scoring's get_latest_rate_before kept returning the stale positive rate, and the leaving miner kept its crown — displacing miners still offering the direction.

Fix

When a direction with a previously-positive rate drops to 0, persist a terminating 0.0 rate event. The check reads the persisted latest rate (via get_latest_rate_before) rather than only the in-memory last_known_rates, so:

  • a never-offered direction (latest is None) records nothing — unchanged behavior;
  • a zero posted while the validator was down still reconciles on the first poll after restart (poll_commitments runs before score_and_reward_miners in the same forward step);
  • the terminator is written once; repeat zero polls are no-ops.

Single-function change in allways/validator/forward.py. No schema, API, UI, or contract changes — the existing prune logic already preserves the latest row per (hotkey, direction) as an anchor, so the zero survives as the terminator.

Tests

  • test_poll_commitments.py: positive→zero records the opt-out; recorded once not per-poll; positive→zero→positive re-enables; zero-during-downtime reconciles against the persisted rate.
  • test_scoring_v1.py: replay regression mirroring the issue — {hk_a: 500, hk_b: 500} after opt-out instead of {hk_a: 1000}.

Full suite: 563 passed. ruff format + ruff check clean.

A miner posting rate 0 means "no longer offering this direction," but
refresh_miner_rates skipped r<=0 before persisting anything, so the
stale positive rate stayed latest and kept earning crown credit.

Persist a terminating zero event when a previously-offered direction
drops to 0. Read the persisted latest rate so a zero posted during
validator downtime reconciles on the next poll, and only record once.
@LandynDev LandynDev force-pushed the fix/zero-rate-optout-crown-accounting branch from 91b560b to 1b699ad Compare May 26, 2026 18:51
@anderdc anderdc merged commit ac06c75 into test May 26, 2026
3 checks passed
@anderdc anderdc deleted the fix/zero-rate-optout-crown-accounting branch May 26, 2026 18:55
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.

[Bug] Zero-rate opt-outs keep previous rates active in crown-time accounting

2 participants