Mar 25, 11-12 PM (36)
Mar 25, 12-1 PM (86)
Mar 25, 1-2 PM (29)
Mar 25, 2-3 PM (28)
Mar 25, 3-4 PM (65)
Mar 25, 4-5 PM (30)
Mar 25, 5-6 PM (16)
Mar 25, 6-7 PM (37)
Mar 25, 7-8 PM (10)
Mar 25, 8-9 PM (9)
Mar 25, 9-10 PM (6)
Mar 25, 10-11 PM (25)
Mar 25, 11-12 AM (16)
Mar 26, 12-1 AM (3)
Mar 26, 1-2 AM (9)
Mar 26, 2-3 AM (21)
Mar 26, 3-4 AM (10)
Mar 26, 4-5 AM (1)
Mar 26, 5-6 AM (14)
Mar 26, 6-7 AM (4)
Mar 26, 7-8 AM (8)
Mar 26, 8-9 AM (18)
Mar 26, 9-10 AM (33)
Mar 26, 10-11 AM (21)
Mar 26, 11-12 PM (34)
Mar 26, 12-1 PM (33)
Mar 26, 1-2 PM (77)
Mar 26, 2-3 PM (46)
Mar 26, 3-4 PM (51)
Mar 26, 4-5 PM (40)
Mar 26, 5-6 PM (19)
Mar 26, 6-7 PM (19)
Mar 26, 7-8 PM (15)
Mar 26, 8-9 PM (9)
Mar 26, 9-10 PM (17)
Mar 26, 10-11 PM (38)
Mar 26, 11-12 AM (11)
Mar 27, 12-1 AM (3)
Mar 27, 1-2 AM (1)
Mar 27, 2-3 AM (26)
Mar 27, 3-4 AM (12)
Mar 27, 4-5 AM (6)
Mar 27, 5-6 AM (3)
Mar 27, 6-7 AM (10)
Mar 27, 7-8 AM (18)
Mar 27, 8-9 AM (38)
Mar 27, 9-10 AM (26)
Mar 27, 10-11 AM (38)
Mar 27, 11-12 PM (26)
Mar 27, 12-1 PM (57)
Mar 27, 1-2 PM (31)
Mar 27, 2-3 PM (60)
Mar 27, 3-4 PM (40)
Mar 27, 4-5 PM (20)
Mar 27, 5-6 PM (30)
Mar 27, 6-7 PM (29)
Mar 27, 7-8 PM (15)
Mar 27, 8-9 PM (17)
Mar 27, 9-10 PM (13)
Mar 27, 10-11 PM (24)
Mar 27, 11-12 AM (17)
Mar 28, 12-1 AM (2)
Mar 28, 1-2 AM (2)
Mar 28, 2-3 AM (12)
Mar 28, 3-4 AM (1)
Mar 28, 4-5 AM (2)
Mar 28, 5-6 AM (1)
Mar 28, 6-7 AM (0)
Mar 28, 7-8 AM (2)
Mar 28, 8-9 AM (7)
Mar 28, 9-10 AM (7)
Mar 28, 10-11 AM (7)
Mar 28, 11-12 PM (7)
Mar 28, 12-1 PM (4)
Mar 28, 1-2 PM (5)
Mar 28, 2-3 PM (12)
Mar 28, 3-4 PM (3)
Mar 28, 4-5 PM (5)
Mar 28, 5-6 PM (5)
Mar 28, 6-7 PM (0)
Mar 28, 7-8 PM (2)
Mar 28, 8-9 PM (0)
Mar 28, 9-10 PM (1)
Mar 28, 10-11 PM (21)
Mar 28, 11-12 AM (21)
Mar 29, 12-1 AM (2)
Mar 29, 1-2 AM (6)
Mar 29, 2-3 AM (6)
Mar 29, 3-4 AM (6)
Mar 29, 4-5 AM (3)
Mar 29, 5-6 AM (5)
Mar 29, 6-7 AM (0)
Mar 29, 7-8 AM (0)
Mar 29, 8-9 AM (13)
Mar 29, 9-10 AM (0)
Mar 29, 10-11 AM (0)
Mar 29, 11-12 PM (2)
Mar 29, 12-1 PM (13)
Mar 29, 1-2 PM (2)
Mar 29, 2-3 PM (2)
Mar 29, 3-4 PM (4)
Mar 29, 4-5 PM (6)
Mar 29, 5-6 PM (8)
Mar 29, 6-7 PM (9)
Mar 29, 7-8 PM (6)
Mar 29, 8-9 PM (4)
Mar 29, 9-10 PM (10)
Mar 29, 10-11 PM (24)
Mar 29, 11-12 AM (17)
Mar 30, 12-1 AM (5)
Mar 30, 1-2 AM (5)
Mar 30, 2-3 AM (7)
Mar 30, 3-4 AM (7)
Mar 30, 4-5 AM (3)
Mar 30, 5-6 AM (12)
Mar 30, 6-7 AM (3)
Mar 30, 7-8 AM (36)
Mar 30, 8-9 AM (27)
Mar 30, 9-10 AM (10)
Mar 30, 10-11 AM (67)
Mar 30, 11-12 PM (47)
Mar 30, 12-1 PM (30)
Mar 30, 1-2 PM (39)
Mar 30, 2-3 PM (63)
Mar 30, 3-4 PM (33)
Mar 30, 4-5 PM (20)
Mar 30, 5-6 PM (41)
Mar 30, 6-7 PM (17)
Mar 30, 7-8 PM (18)
Mar 30, 8-9 PM (13)
Mar 30, 9-10 PM (28)
Mar 30, 10-11 PM (44)
Mar 30, 11-12 AM (28)
Mar 31, 12-1 AM (16)
Mar 31, 1-2 AM (5)
Mar 31, 2-3 AM (15)
Mar 31, 3-4 AM (6)
Mar 31, 4-5 AM (4)
Mar 31, 5-6 AM (7)
Mar 31, 6-7 AM (12)
Mar 31, 7-8 AM (43)
Mar 31, 8-9 AM (47)
Mar 31, 9-10 AM (30)
Mar 31, 10-11 AM (37)
Mar 31, 11-12 PM (29)
Mar 31, 12-1 PM (38)
Mar 31, 1-2 PM (34)
Mar 31, 2-3 PM (52)
Mar 31, 3-4 PM (37)
Mar 31, 4-5 PM (47)
Mar 31, 5-6 PM (39)
Mar 31, 6-7 PM (36)
Mar 31, 7-8 PM (16)
Mar 31, 8-9 PM (13)
Mar 31, 9-10 PM (9)
Mar 31, 10-11 PM (24)
Mar 31, 11-12 AM (15)
Apr 01, 12-1 AM (1)
Apr 01, 1-2 AM (2)
Apr 01, 2-3 AM (8)
Apr 01, 3-4 AM (5)
Apr 01, 4-5 AM (8)
Apr 01, 5-6 AM (9)
Apr 01, 6-7 AM (3)
Apr 01, 7-8 AM (81)
Apr 01, 8-9 AM (40)
Apr 01, 9-10 AM (22)
Apr 01, 10-11 AM (21)
Apr 01, 11-12 PM (3)
3,173 commits this week Mar 25, 2026 - Apr 01, 2026
fix(ledger): fix pipeline restart race conditions causing permanent stalls (#1783)
Three fixes for chainsync pipeline stalls found during deep concurrency audit:

1. Iterator rollback signal missed on new iterators (chain/chain.go):
   rollbackLocked() checked iter.lastPoint.Slot > point.Slot, but new
   iterators have zero-value lastPoint. Use startPoint as fallback
   reference so newly created iterators receive rollback signals.

2. Pipeline reader reads currentTip without lock (ledger/state.go):
   ledgerReadChain() read ls.currentTip.Point without RLock, racing with
   concurrent rollbacks. Snapshot under lock and handle FromPoint failure
   gracefully — the outer loop retries after rollback updates the tip.

3. Rollback doesn't wake blocked iterators (chain/chain.go):
   rollbackLocked() set needsRollback but never called
   notifyWaitingIterators(). Blocked iterators would sleep until new
   blocks arrived, stalling indefinitely if connections died after
   rollback.

Also includes defer close(resultCh) and cached batch done-channel fix
from the pipeline deadlock PR.

Signed-off-by: wcatz <[email protected]>
fix(ledger): fix pipeline restart race conditions causing permanent stalls
Three fixes for chainsync pipeline stalls found during deep concurrency audit:

1. Iterator rollback signal missed on new iterators (chain/chain.go):
   rollbackLocked() checked iter.lastPoint.Slot > point.Slot, but new
   iterators have zero-value lastPoint. Use startPoint as fallback
   reference so newly created iterators receive rollback signals.

2. Pipeline reader reads currentTip without lock (ledger/state.go):
   ledgerReadChain() read ls.currentTip.Point without RLock, racing with
   concurrent rollbacks. Snapshot under lock and handle FromPoint failure
   gracefully — the outer loop retries after rollback updates the tip.

3. Rollback doesn't wake blocked iterators (chain/chain.go):
   rollbackLocked() set needsRollback but never called
   notifyWaitingIterators(). Blocked iterators would sleep until new
   blocks arrived, stalling indefinitely if connections died after
   rollback.

Also includes defer close(resultCh) and cached batch done-channel fix
from the pipeline deadlock PR.

Signed-off-by: wcatz <[email protected]>
net-rs: add chain tree visualization to node inspector
Display the node's consensus chain tree in the inspector panel as an
SVG diagram of linked blocks. The main chain is shown in blue with the
tip in green; fork blocks appear in orange. Fork blocks share the main
lane when their column is free, and only get their own lane when there
is a collision — descendants inherit their parent's lane.

Backend: add ChainTreeEntry type and ChainTree::snapshot() which walks
backward from the adopted tip for up to 10 blocks, collecting fork
blocks within the window and extending to include fork points. The
snapshot is included in the stats POST to the cluster server and
forwarded to the UI via the stats API.

Cluster: mirror ChainTreeEntry in net-cluster types with serde(default)
for backward compatibility with older net-node binaries.

UI: new ChainTreeView SVG component with auto-scroll to latest blocks.
Integrated into InspectorPanel below the tip display. Dark-themed
scrollbars across all components via MUI CssBaseline overrides.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Make `ContextError` constructors from Alonzo to Dijkstra era lazy
Since `ContextError`s are never stored and their reporting doesn't need
to be efficient (we always optimize for the positive case with valid
transactions, as invalid transactions don't propagate through the
network), there's no need for strictness annotations on the error
constructors.

This change removes the bang patterns (!) from:
- AlonzoContextError
- BabbageContextError
- ConwayContextError
- DijkstraContextError