From bf63a555622f4b4d33518b8fd5f1b1c5d1a7cc4f Mon Sep 17 00:00:00 2001 From: Mehran Mazhar Date: Mon, 14 Sep 2026 18:50:25 +0400 Subject: [PATCH] fix(node): publish latest_block{block_hash} at startup, not only on import `latest_block_index` was already republished from the stored block at boot, after a synced node holding 24,000 blocks reported height 0 until the next block arrived. The hash-labelled `latest_block` series was left behind in that fix and is still written only by `add_block_to_chain`. That matters more than it sounds, because the explorer's indexer reads BOTH series and refuses the chain head unless it has both (`explorer/ingestion.rs::fetch_head` -> "latest_block metrics missing"). On a healthy chain the gap closes within one slot. On a halted chain it never does: a restart leaves the indexer permanently blind, so the explorer shows nothing regardless of what the chain is doing. That is how the stage halt of 2026-09-14 was first reported -- three layers below the actual fault. Co-Authored-By: Claude Opus 5 --- src/node/blockchain.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/node/blockchain.rs b/src/node/blockchain.rs index e726732..2d20405 100644 --- a/src/node/blockchain.rs +++ b/src/node/blockchain.rs @@ -183,6 +183,17 @@ impl Blockchain { // here are an i64 next to the error arm's unit and will not compile. Ok(Some(b)) => { metric::LATEST_BLOCK_INDEX.set(b.index as i64); + // The hash-labelled series needs the same treatment, and for a sharper reason: the + // explorer's indexer reads BOTH `latest_block_index` and `latest_block{block_hash}` + // and refuses the head if either is missing. Published only by `add_block_to_chain`, + // it was absent from boot until this node next imported a block -- so a restart + // during a halted chain left the indexer permanently blind and the explorer empty, + // which is how the stage outage of 2026-09-14 was first reported. + metric::LATEST_BLOCK + .get_or_create(&metric::BlockLabels { + block_hash: b.hash.to_string(), + }) + .set(b.index as i64); } // No block yet is genuinely 0. A read FAILURE is not, so it is left alone rather than // published as an empty chain.