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:
| State | When | What to do |
|---|---|---|
| Healthy ✓ | Stake > 0, not frozen, healthy, sufficient funds | Nothing. You're playing rounds correctly. |
| Unstaked · | Stake = 0 | Run bee stake deposit <amount> to enter the lottery. |
| Frozen ✗ | is_frozen = true | Penalty round. Wait it out (variable duration; check Last frozen anchor for the round you got frozen). |
| InsufficientGas ⚠ | has_sufficient_funds = false | Native balance too low to play. Top up the operator wallet. |
| Unhealthy ⚠ | is_healthy = false, other booleans OK | Reserve isn't filled / depth not stable / fully synced still false. Most common during warmup; see S5. |
| Unknown · | Snapshot not loaded | Cold 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= currentstorage_radiusanchor1,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
- Stake card says Unstaked → deposit stake
- Stake card says InsufficientGas → top up native balance
- Stake card says Frozen → wait it out
- Stake card says Unhealthy → check S1 for which gate is failing; if Reserve isn't filled, see S5 Warmup
- Stake card says Healthy but Last won is many rounds
behind Last played → press
rand check the rchash duration; if it's near 95 s, your reserve is too slow - 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
| Key | Effect |
|---|---|
r | Fire / re-fire rchash benchmark |
? | Toggle help overlay |
No selection cursor (yet) — the screen is mostly cards, not a list.