fix: a miner's hashrate is the work it did, not its share of today's network
Reported against a Grafana panel showing roughly a sixth of what the site did. Grafana was closer to the truth. The estimate was `share of blocks in the window × current network hashrate`. That is only correct while the network is the same size across the whole window. Measured on mainnet's launch day it was nowhere near: difficulty rose 346-fold inside one 14,400-block window, from 96.4B to 33.4T. A miner that won its blocks early — when a block cost a three-hundredth of what it costs now — had that share multiplied by today's network. For this observer's own node the site reported 25.4 GH/s against an actual 2.5 GH/s. Difficulty is expected hashes per block by definition, so the difficulty of the blocks a miner won, summed and divided by the time they spanned, is its hashrate directly — with no reference to the network's size, and immune to that size changing underneath, because every block carries the difficulty in force when it was won. The observer has recorded per-block difficulty correctly since the parent-state fix, so the data was already there. `miner_series` had the same flaw and is fixed the same way: summed work per bucket over the bucket's own duration. The window's duration is taken from `authored_at`, not `observed_at`. A stretch this process caught up on carries observation times seconds apart for blocks minutes apart, and dividing real work by that would invent hashrate — the same trap the history series was built to avoid. The headline network figure is unchanged. It divides current difficulty by the measured interval because it answers a different question: how hard is a block to win right now, not what did this miner do over the last twelve hours. The two no longer sum to each other, which is correct and is what the footer now says. `standings_rank_by_blocks_then_recency` asserted 400.0 from the old formula; its third argument is now the window's duration, so it asserts the work-based figure. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jp6a8EDar9ueEhAxzep4V5
This commit is contained in:
+4
-2
@@ -240,8 +240,10 @@ export default function App() {
|
||||
header — no registration, no opt-in, no way to be left out.
|
||||
</span>
|
||||
<span>
|
||||
Hashrates are estimates from blocks won over a finite window, not measurements of anyone's
|
||||
hardware.
|
||||
Hashrates are estimates over a finite window, not measurements of anyone's hardware. A
|
||||
miner's figure is the difficulty of the blocks it won — expected hashes, by definition —
|
||||
divided by the time they spanned, so a miner that won while the network was smaller is
|
||||
credited with the work it actually did rather than a share of what the network is now.
|
||||
</span>
|
||||
<span>
|
||||
Node names are a best-effort mapping, inferred from which node reported a block to
|
||||
|
||||
@@ -135,7 +135,7 @@ export function MinerPanel({
|
||||
<div className="stat">
|
||||
<div className="stat-label">Est. hashrate</div>
|
||||
<div className="stat-value">{hashrate(row?.hashrate_estimate)}</div>
|
||||
<div className="stat-note">from share of blocks won</div>
|
||||
<div className="stat-note">from work its blocks cost</div>
|
||||
</div>
|
||||
<div className="stat">
|
||||
<div className="stat-label">Blocks observed</div>
|
||||
|
||||
Reference in New Issue
Block a user