chore: say what the window actually holds, for #13
Static reading cannot settle #13. Warm start logs restoring 19,910 blocks for mainnet and the board it serves divides every share by 1,065, and every explanation that would reconcile the two is ruled out in the code: the deque is only ever pushed and popped at a capacity of 100,800, `tail(n)` yields `min(n, len)`, `tally` counts every entry it walks, nothing filters rows, the board recomputes every five seconds, and there is exactly one non-test `ChainRuntime` and one `RollingWindow` per chain, shared by `Arc`. So: log the length. `warm start: window restored` now carries `held` beside `blocks` — the two must agree, and when they did not, every share on the site was computed over the difference with nothing saying so. `recompute_leaderboard` logs what it asked for, what was held and what it tallied at debug. The new test pins the half of the contradiction that lives in `blackbeard-core`: a window pushed 19,910 blocks holds 19,910, tallies 3,600 for a 3,600 window, and tallies 19,910 when asked for more than it holds. That is the arithmetic the served response contradicts, so an investigation upstream of it does not have to re-establish that a deque holds what was pushed. Refs #13 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jp6a8EDar9ueEhAxzep4V5
This commit is contained in:
@@ -189,7 +189,13 @@ pub async fn warm_start(chain: &Arc<ChainRuntime>, store: &Store, ticker_blocks:
|
||||
// interval.
|
||||
inner.window.push(block, false);
|
||||
}
|
||||
tracing::info!(chain = %id, blocks = count, "warm start: window restored");
|
||||
// `held` as well as `blocks`: the two must agree, and when they did
|
||||
// not, every share on the site was computed over the difference
|
||||
// without anything saying so. See #13.
|
||||
tracing::info!(
|
||||
chain = %id, blocks = count, held = inner.window.len(),
|
||||
"warm start: window restored"
|
||||
);
|
||||
}
|
||||
Err(e) => tracing::warn!(chain = %id, error = %e, "warm start: no window restored"),
|
||||
}
|
||||
|
||||
@@ -364,6 +364,13 @@ impl ChainRuntime {
|
||||
pub fn recompute_leaderboard(&self, window: Window) -> (Vec<LeaderboardRow>, bool) {
|
||||
let mut inner = self.write();
|
||||
let (tallies, total) = inner.window.tally(window.blocks() as usize);
|
||||
// The denominator of every share on the board, against what the window
|
||||
// actually holds. See #13: these disagreed with the warm-start count by
|
||||
// two orders of magnitude and nothing on the page said so.
|
||||
tracing::debug!(
|
||||
window = ?window, asked = window.blocks(), held = inner.window.len(), tallied = total,
|
||||
"leaderboard recomputed"
|
||||
);
|
||||
// The window's own duration, by the chain's clock. Every per-miner
|
||||
// hashrate is its summed work over this — not its share of the current
|
||||
// network, which credits a miner that won while the network was small
|
||||
|
||||
@@ -338,6 +338,40 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// The window keeps everything it is given up to capacity, and the tally
|
||||
/// reads the newest `n` of them.
|
||||
///
|
||||
/// Filed as #13: warm start reported restoring 19,910 blocks and the board
|
||||
/// it served divided by 1,065. One of the two had to be wrong, and this
|
||||
/// pins the half that lives in this crate — so an investigation upstream of
|
||||
/// it does not have to re-establish that a deque holds what was pushed.
|
||||
#[test]
|
||||
fn a_restored_window_tallies_the_whole_requested_span() {
|
||||
let mut w = RollingWindow::new(100_800);
|
||||
for h in 1..=19_910u64 {
|
||||
w.push(
|
||||
Observed {
|
||||
height: h,
|
||||
miner: MinerId(format!("m{}", h % 7)),
|
||||
observed_at: Utc::now(),
|
||||
authored_at: None,
|
||||
difficulty: None,
|
||||
},
|
||||
false,
|
||||
);
|
||||
}
|
||||
assert_eq!(w.len(), 19_910);
|
||||
|
||||
let (_, total) = w.tally(3_600);
|
||||
assert_eq!(total, 3_600, "a full window must tally the whole window");
|
||||
|
||||
let (_, total) = w.tally(100_800);
|
||||
assert_eq!(
|
||||
total, 19_910,
|
||||
"asking for more than is held tallies what is held"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_window_drops_the_oldest_block_when_full() {
|
||||
let mut w = RollingWindow::new(3);
|
||||
|
||||
Reference in New Issue
Block a user