Skip to content

Ingest and store the epoch schedule so the epoch methods are correct off mainnet #47

Description

@Mctursh

Follow-up from #30.

Three methods compute epoch fields from a hardcoded mainnet schedule (DEFAULT_SLOTS_PER_EPOCH = 432000, warmup off), so on any cluster whose genesis enables warmup they're silently wrong. Example from that thread: at slot 1,000,000 real Solana is on epoch 15, superbank reports epoch 2.

Affected methods

They all assume mainnet because the RPC layer has no source for the cluster's real schedule. Scoped to the epoch schedule only (no leader-schedule method exists today).

Approach (ingest-and-store, per #30)

  • Ingest: the ingestor already fetches the real schedule in one path (it builds an RPC client and calls get_epoch_schedule() in the bigtable epoch-range resolution). Generalize it: when --rpc-url is set, fetch the schedule once at startup and store it. --rpc-url is a global optional arg, so this covers the rpc source (which requires it) and anything else run with one; sources without it just get no schedule.
  • Store: a small epoch_schedule table holding the five fields (slots_per_epoch, leader_schedule_slot_offset, warmup, first_normal_epoch, first_normal_slot) as a single row. This would be the first config-style (single-row) table in the repo, so the engine/shape is worth a quick look (local/cluster/replicated variants).
  • Read: the RPC server loads it once at startup (natural fit next to discover_bucket_moduli) into AppState, and the three methods derive their epoch fields from it (warmup included) instead of the hardcoded constant.

Open questions

  1. Gate mechanism. You mentioned a feature flag. Compile-time Cargo feature (like grpc-head-cache), or a runtime gate on whether the schedule is present (or a plain config flag)? Runtime feels closer for per-deployment data availability, but your call.
  2. No-schedule behavior, and getInflationReward rollout. When the schedule isn't available I'd rather gate the methods off than silently fall back to the mainnet default, since that silent fallback is the exact thing this fixes. An explicit "assume mainnet" opt-in works too if you prefer. The wrinkle: getInflationReward is already live on main, so gating it removes a method from deployments that don't set --rpc-url or the opt-in. Fine, or should the "assume mainnet" opt-in default to on to preserve today's behavior?

@notwedtm

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions