feat(cardano): shard RUPD reward computation by credential key
RUPD was the boundary path's worst memory spike: a single load built
the full per-account `accounts_by_pool` + `registered_accounts` plus
an O(N) `RewardMap`. Mirror the Estart/Ewrap pattern — hoist
pool-bounded globals into `initialize()` (pots, incentives, pparams,
pool snapshots, pool_stake totals) and shard the per-credential leg
across the same `account_shards` partitions: each shard streams
`AccountState` over its two key ranges only, builds a shard-scoped
delegator + registered set, runs `define_rewards` over every pool
but emits only in-range credentials, and writes the in-range
`PendingRewardState` entities.
Leader-reward emission gates on a new default-true
`RewardsContext::should_include`, so the shard whose range contains
the operator credential is the sole emitter for that pool's leader
reward. Delegator emissions are filtered naturally via
`pool_delegators` returning only in-range creds, with a defensive
`should_include` check at the merge site.
Per-shard progress is tracked by a new `RupdProgress` delta on
`EpochState.rupd_progress`, with the same idempotency + ordering +
total-mismatch guards as `EWrapProgress` / `EStartProgress`.
`EpochTransition` rollback now also captures and clears
`rupd_progress`. `EpochState.incentives` and per-pool `StakeLog`
archive entries move to `finalize()` (one-shot, after every shard
has committed) so concurrent shard commits can't race; the per-pool
reward + delegator-count contributions accumulate on the work unit
as O(pools) state.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>