Files
observer/web
rob thijssen f9ea292a70
All checks were successful
deploy / build (push) Successful in 7m25s
deploy / deploy-web (push) Successful in 4s
deploy / deploy-api (push) Successful in 15s
fix: a hashrate estimate now carries its error bar
The leaderboard credited a miner with "1.55 GH/s" on the strength of one block,
last seen four hours earlier, to three significant figures. Block finding is
Poisson: k blocks carries a relative standard error of 1/√k, so one block is
±100% and it takes twenty-five to reach ±20%. The estimator was unbiased and the
presentation was not honest, which is the half that matters to a reader.

`miner_hashrate` now returns the count's uncertainty with the figure, and the
leaderboard and miner page render it — dimmed below four blocks, where the error
bar is wider than half the value.

Checked first that the arithmetic itself is sound, because the obvious
suspicion was the formula. It is the chain's own: `qpow-math::is_valid_nonce`
accepts when `hash < U512::MAX / difficulty`, `verify_nonce_internal` passes it
what `get_difficulty()` returns, and the hash is uniform — 200,000 samples of
`hash_squeeze_twice` gave 0.4995 of 2^512 against a uniform 0.5, and 12.48%
below 2^509 against 12.5%. Acceptance is 1/difficulty, so expected trials is
difficulty, exactly. The two network estimators — difficulty over tip interval,
and summed work over window span — also agree within 5% on live data.

What that leaves is recorded in CLAUDE.md and is not an observer bug: our three
miners measure 1.66 GH/s (1.39 instantaneous), while the chain credited the same
preimage 5.3 GH/s over 29 blocks. Sampling does not explain 14 sigma.
`miner_cpu_hash_rate` is 0 on all three — every hash is on GPU — and the miner's
CPU path calls `qpow_math::get_nonce_hash` directly while the CUDA kernel is a
separate implementation with its own counter.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jp6a8EDar9ueEhAxzep4V5
2026-09-09 19:48:51 +03:00
..