You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Part of #2588. Do NOT start this until Phase 1 (#2921) and Phase 2 (#2922) have shipped. This is the risky phase — real production data, may not be fully feasible, requires staging rehearsal before any live execution.
Context
Every row written before Phase 1 lands is already lossy, via one of two mechanisms:
Mechanism A (neurons.stake_tao/emission_tao, neuron_daily.stake_tao, subnet_snapshots.total_stake_tao): the exact rao value was discarded inside the Bittensor SDK's Balance.__float__() before this repo's code ever ran. Recovering it requires re-querying the chain at the exact historical block height for every affected row — this is not a code fix, it's a full re-derivation project, and it may not even be possible for the oldest rows if an archive node isn't reachable that far back.
Mechanism B (neuron_daily.emission_tao from the backfill script, account_events.amount_tao/alpha_amount): also already-lossy, but since these came from SCALE-decoded raw chain events, re-deriving exact values is more mechanical (same event-decode logic, just skip the premature division) — IF the raw source blocks/events are still replayable, which again depends on archive-node reachability.
Requirements — go/no-go gate before any implementation
Confirm archive-node reachability at historical block heights. This project now runs a self-hosted full-archive node (JSO-1926/infra(archive-node): bare-metal buildout — provision → sync → first-party RPC origin #2111) — check whether it (or the public archive RPC fallback) can actually serve state queries far enough back to cover the oldest affected rows in neurons/neuron_daily/account_events. If not reachable that far back, full recovery for the oldest data may be impossible — this must be established and documented before deciding to proceed, not discovered mid-implementation.
Rehearse against a staging D1 copy first, never live. This directly matters given a live incident earlier in this project's timeline from an under-verified schema/data assumption on a large production table (neuron_daily alone is 10M+ rows) — do not repeat that failure mode here.
Explicit rollback/verification plan before any live run: row-count diffs before/after, spot-checks against independently-known-correct values (e.g. cross-check a handful of known large validators' stake against a manual chain query), and a clear way to abort/roll back mid-run if something looks wrong.
Decide whether backfill is even worth doing. Per the audit: today's actual magnitudes are nowhere near the ~9M TAO precision ceiling, so the practical impact of NOT backfilling is small (low-order-bit imprecision on old rows, not a functionally broken product). Weigh the real engineering cost (a full re-derivation project against chain history) against that low practical impact before committing to it.
Deliverables
Archive-node reachability confirmed (or ruled out) for the full historical range needing backfill
Explicit go/no-go decision documented, with reasoning, on whether to backfill at all
If go: a staging-rehearsed migration/backfill plan with rollback strategy, executed only after rehearsal succeeds
If no-go: the historical imprecision documented as a known, accepted limitation (e.g. in docs/adr/ or this repo's data-integrity documentation), so it isn't rediscovered as a "mystery bug" later
Expected outcome
Either: historical rows are corrected via a carefully-rehearsed, low-risk backfill; or: a clear, documented decision that backfill isn't worth the cost/risk given today's magnitudes, with the limitation recorded for future reference.
Explicitly out of scope
Any live schema/data change without a prior staging rehearsal.
Changing the REAL column types to INTEGER/TEXT as part of this issue (that's Phase 4/a separate decision if the contract itself ever needs to change).
Part of #2588. Do NOT start this until Phase 1 (#2921) and Phase 2 (#2922) have shipped. This is the risky phase — real production data, may not be fully feasible, requires staging rehearsal before any live execution.
Context
Every row written before Phase 1 lands is already lossy, via one of two mechanisms:
neurons.stake_tao/emission_tao,neuron_daily.stake_tao,subnet_snapshots.total_stake_tao): the exact rao value was discarded inside the Bittensor SDK'sBalance.__float__()before this repo's code ever ran. Recovering it requires re-querying the chain at the exact historical block height for every affected row — this is not a code fix, it's a full re-derivation project, and it may not even be possible for the oldest rows if an archive node isn't reachable that far back.neuron_daily.emission_taofrom the backfill script,account_events.amount_tao/alpha_amount): also already-lossy, but since these came from SCALE-decoded raw chain events, re-deriving exact values is more mechanical (same event-decode logic, just skip the premature division) — IF the raw source blocks/events are still replayable, which again depends on archive-node reachability.Requirements — go/no-go gate before any implementation
neurons/neuron_daily/account_events. If not reachable that far back, full recovery for the oldest data may be impossible — this must be established and documented before deciding to proceed, not discovered mid-implementation.neuron_dailyalone is 10M+ rows) — do not repeat that failure mode here.Deliverables
docs/adr/or this repo's data-integrity documentation), so it isn't rediscovered as a "mystery bug" laterExpected outcome
Either: historical rows are corrected via a carefully-rehearsed, low-risk backfill; or: a clear, documented decision that backfill isn't worth the cost/risk given today's magnitudes, with the limitation recorded for future reference.
Explicitly out of scope
REALcolumn types toINTEGER/TEXTas part of this issue (that's Phase 4/a separate decision if the contract itself ever needs to change).maintainer-only (owner)