S4 — Lottery / redistribution

Three panes covering the storage incentives game (the redistribution lottery): round timeline, anchor summary, and a six-state stake card. Plus an on-demand rchash benchmark.

Why this screen exists

Bee earns BZZ through the redistribution lottery — every 152 blocks, eligible nodes commit a hash of a sample of their reserve, reveal it, and (if they win the round) claim the reward. The mechanics span four scattered RedistributionState booleans (is_frozen, is_healthy, has_sufficient_funds, is_fully_synced), the staked amount, and the per-round LastWonRound / LastPlayedRound / LastSelectedRound / LastFrozenRound anchors.

When an operator asks "why am I not earning rewards?", neither /redistributionstate nor /stake alone answers. S4 reduces it all to a single screen with explicit reasoning trees.

Pane 1 — Round timeline

ROUND 4127   block 234,512  ·  in round 87/152
  commit  ████████████░░░░░░░░░░░░  blocks 1-38
  reveal  ████████████████████████  blocks 39-76
  claim   ████████████░░░░░░░░░░░░  blocks 77-114
  idle                              blocks 115-152

The 152-block round is split into three on-chain phases per pkg/storageincentives/agent.go:

  • Commit (blocks 1-38): submit a hash of your reserve sample
  • Reveal (blocks 39-76): reveal the sample
  • Claim (blocks 77-114): if won, claim the reward
  • Idle (blocks 115-152): wait for next round

The progress bar shows where the current round is. Whether you committed / revealed depends on your stake state + RedistributionState booleans — see the stake card below.

Pane 2 — Anchor summary

ANCHORS
  Last won            round 4115     12 rounds ago
  Last played         round 4126     this round
  Last selected       round 4126     this round
  Last frozen         round —        never

Four anchors with human Δ strings:

  • Last won: the most recent round you claimed a reward
  • Last played: the most recent round you committed a hash
  • Last selected: the most recent round Bee said the network selected your sample (precondition for winning)
  • Last frozen: the most recent round you were frozen out (penalty for misbehaviour)

The Δ string ("12 rounds ago", "never", "this round") calibrates the cadence. A fresh node should be playing every round once warm; if Last played is many rounds behind Last selected, you're missing commits.

Pane 3 — Stake card

The most operator-relevant pane. Six states, each with an explicit reason:

StateWhenWhat to do
Healthy ✓Stake > 0, not frozen, healthy, sufficient fundsNothing. You're playing rounds correctly.
Unstaked ·Stake = 0Run bee stake deposit <amount> to enter the lottery.
Frozen ✗is_frozen = truePenalty round. Wait it out (variable duration; check Last frozen anchor for the round you got frozen).
InsufficientGas ⚠has_sufficient_funds = falseNative balance too low to play. Top up the operator wallet.
Unhealthy ⚠is_healthy = false, other booleans OKReserve isn't filled / depth not stable / fully synced still false. Most common during warmup; see S5.
Unknown ·Snapshot not loadedCold start.

The reasoning tree fires the first match top-to-bottom, so "InsufficientGas + Unhealthy" reads as InsufficientGas (more actionable).

Pane 4 — Rchash benchmark (on-demand)

Press r to fire GET /rchash/<depth>/<anchor1>/<anchor2> where:

  • depth = current storage_radius
  • anchor1, anchor2 = deterministic so repeat measurements compare cleanly

The result shows the duration vs the 95-second commit window deadline:

RCHASH BENCHMARK
  duration   3.4s
  hash       0xabcd12ef…
    hash 0xabcd12ef3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d
  budget     ✓ well under 95s commit deadline

The hash 0x<full> continuation line below the truncated form is from v1.9.1 — before that, only the 8-char prefix was visible, which made copying the full hash for a Bee bug report or block-explorer search a non-starter. The truncated form stays in the table column for visual scan; the full hex is one line below.

If duration approaches or exceeds 95 s, your reserve is too slow to commit in time. The lottery will silently skip your node every round. Possible causes:

  • Reserve is on a slow disk (HDD, network-attached storage)
  • Bee is competing with other I/O (database, video)
  • Storage node has very high committedDepth

Lifecycle is owned by an internal mpsc inside the Lottery component, not a global Action — so r doesn't pollute other screens, and a benchmark already in flight is no-op'd by re-pressing r.

The "why am I not earning rewards?" decision tree

  1. Stake card says Unstaked → deposit stake
  2. Stake card says InsufficientGas → top up native balance
  3. Stake card says Frozen → wait it out
  4. Stake card says Unhealthy → check S1 for which gate is failing; if Reserve isn't filled, see S5 Warmup
  5. Stake card says Healthy but Last won is many rounds behind Last played → press r and check the rchash duration; if it's near 95 s, your reserve is too slow
  6. Healthy + good rchash + still not winning → the lottery is stochastic; some rounds you don't get selected. Watch Last selected vs Last won — if Selected is recent but Won is old, the network reveals didn't include your sample (rare but possible).

Snapshot cadence

S4 polls two streams:

  • /redistributionstate (existing 2 s health stream — shared)
  • /stake (30 s, low-rate)

The rchash benchmark is on-demand only.

Keys

KeyEffect
rFire / re-fire rchash benchmark
?Toggle help overlay

No selection cursor (yet) — the screen is mostly cards, not a list.