May 20, 6-7 PM (17)
May 20, 7-8 PM (23)
May 20, 8-9 PM (15)
May 20, 9-10 PM (5)
May 20, 10-11 PM (34)
May 20, 11-12 AM (16)
May 21, 12-1 AM (16)
May 21, 1-2 AM (9)
May 21, 2-3 AM (11)
May 21, 3-4 AM (7)
May 21, 4-5 AM (4)
May 21, 5-6 AM (27)
May 21, 6-7 AM (14)
May 21, 7-8 AM (22)
May 21, 8-9 AM (34)
May 21, 9-10 AM (45)
May 21, 10-11 AM (37)
May 21, 11-12 PM (27)
May 21, 12-1 PM (63)
May 21, 1-2 PM (68)
May 21, 2-3 PM (60)
May 21, 3-4 PM (53)
May 21, 4-5 PM (20)
May 21, 5-6 PM (27)
May 21, 6-7 PM (27)
May 21, 7-8 PM (25)
May 21, 8-9 PM (23)
May 21, 9-10 PM (3)
May 21, 10-11 PM (29)
May 21, 11-12 AM (10)
May 22, 12-1 AM (16)
May 22, 1-2 AM (6)
May 22, 2-3 AM (8)
May 22, 3-4 AM (4)
May 22, 4-5 AM (11)
May 22, 5-6 AM (10)
May 22, 6-7 AM (21)
May 22, 7-8 AM (13)
May 22, 8-9 AM (38)
May 22, 9-10 AM (12)
May 22, 10-11 AM (18)
May 22, 11-12 PM (25)
May 22, 12-1 PM (24)
May 22, 1-2 PM (34)
May 22, 2-3 PM (56)
May 22, 3-4 PM (13)
May 22, 4-5 PM (29)
May 22, 5-6 PM (13)
May 22, 6-7 PM (19)
May 22, 7-8 PM (20)
May 22, 8-9 PM (12)
May 22, 9-10 PM (12)
May 22, 10-11 PM (41)
May 22, 11-12 AM (12)
May 23, 12-1 AM (9)
May 23, 1-2 AM (0)
May 23, 2-3 AM (3)
May 23, 3-4 AM (1)
May 23, 4-5 AM (1)
May 23, 5-6 AM (4)
May 23, 6-7 AM (12)
May 23, 7-8 AM (1)
May 23, 8-9 AM (3)
May 23, 9-10 AM (1)
May 23, 10-11 AM (1)
May 23, 11-12 PM (5)
May 23, 12-1 PM (1)
May 23, 1-2 PM (6)
May 23, 2-3 PM (5)
May 23, 3-4 PM (5)
May 23, 4-5 PM (4)
May 23, 5-6 PM (0)
May 23, 6-7 PM (3)
May 23, 7-8 PM (23)
May 23, 8-9 PM (1)
May 23, 9-10 PM (9)
May 23, 10-11 PM (21)
May 23, 11-12 AM (27)
May 24, 12-1 AM (9)
May 24, 1-2 AM (0)
May 24, 2-3 AM (1)
May 24, 3-4 AM (1)
May 24, 4-5 AM (0)
May 24, 5-6 AM (3)
May 24, 6-7 AM (1)
May 24, 7-8 AM (2)
May 24, 8-9 AM (2)
May 24, 9-10 AM (4)
May 24, 10-11 AM (4)
May 24, 11-12 PM (1)
May 24, 12-1 PM (7)
May 24, 1-2 PM (46)
May 24, 2-3 PM (5)
May 24, 3-4 PM (3)
May 24, 4-5 PM (18)
May 24, 5-6 PM (2)
May 24, 6-7 PM (4)
May 24, 7-8 PM (13)
May 24, 8-9 PM (10)
May 24, 9-10 PM (15)
May 24, 10-11 PM (33)
May 24, 11-12 AM (42)
May 25, 12-1 AM (9)
May 25, 1-2 AM (4)
May 25, 2-3 AM (6)
May 25, 3-4 AM (1)
May 25, 4-5 AM (6)
May 25, 5-6 AM (14)
May 25, 6-7 AM (17)
May 25, 7-8 AM (17)
May 25, 8-9 AM (32)
May 25, 9-10 AM (43)
May 25, 10-11 AM (64)
May 25, 11-12 PM (33)
May 25, 12-1 PM (43)
May 25, 1-2 PM (40)
May 25, 2-3 PM (20)
May 25, 3-4 PM (27)
May 25, 4-5 PM (16)
May 25, 5-6 PM (6)
May 25, 6-7 PM (7)
May 25, 7-8 PM (11)
May 25, 8-9 PM (12)
May 25, 9-10 PM (16)
May 25, 10-11 PM (43)
May 25, 11-12 AM (25)
May 26, 12-1 AM (11)
May 26, 1-2 AM (11)
May 26, 2-3 AM (8)
May 26, 3-4 AM (11)
May 26, 4-5 AM (6)
May 26, 5-6 AM (9)
May 26, 6-7 AM (26)
May 26, 7-8 AM (43)
May 26, 8-9 AM (39)
May 26, 9-10 AM (42)
May 26, 10-11 AM (45)
May 26, 11-12 PM (59)
May 26, 12-1 PM (34)
May 26, 1-2 PM (50)
May 26, 2-3 PM (50)
May 26, 3-4 PM (18)
May 26, 4-5 PM (20)
May 26, 5-6 PM (13)
May 26, 6-7 PM (20)
May 26, 7-8 PM (12)
May 26, 8-9 PM (15)
May 26, 9-10 PM (15)
May 26, 10-11 PM (35)
May 26, 11-12 AM (30)
May 27, 12-1 AM (16)
May 27, 1-2 AM (8)
May 27, 2-3 AM (9)
May 27, 3-4 AM (5)
May 27, 4-5 AM (32)
May 27, 5-6 AM (9)
May 27, 6-7 AM (49)
May 27, 7-8 AM (63)
May 27, 8-9 AM (37)
May 27, 9-10 AM (72)
May 27, 10-11 AM (83)
May 27, 11-12 PM (30)
May 27, 12-1 PM (50)
May 27, 1-2 PM (35)
May 27, 2-3 PM (52)
May 27, 3-4 PM (36)
May 27, 4-5 PM (6)
May 27, 5-6 PM (6)
May 27, 6-7 PM (0)
3,342 commits this week
May 20, 2026
-
May 27, 2026
fix: explicit rewrite for /dashboard-api/ index
The `/dashboard-api/:path*` pattern alone doesn't match the bare trailing-slash request (Vercel's path matcher treats `:path*` as "one or more segments" in practice, not zero-or-more), so visiting `/dashboard-api/` produced a Vercel NOT_FOUND. Adding an explicit rewrite for the index path makes the root work; the wildcard rule continues to handle nested paths (`/openapi.yaml`, etc.). Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
feat: initial dijkstra era support
Signed-off-by: Chris Gianelloni <[email protected]>
refactor: pull types out of amaru-plutus, leaving just the serialization logic
Signed-off-by: yHSJ <[email protected]>
feat: serve dashboard-api docs at /dashboard-api/
Adds a Vercel rewrite forwarding `docs.blockfrost.io/dashboard-api/*` to the standalone dashboard-api docs project (https://blockfrost-dashboard-api-docs.vercel.app), and a 308 redirect from the bare `/dashboard-api` path to the trailing-slash form — matching the existing `/midnight` pattern. The dashboard-api spec + docs live in the blockfrost-dashboard-api repo and deploy independently. This repo just proxies the path under the shared `docs.blockfrost.io` host. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
chore(stm): change log and crates version
fix(stm): address suggestions
feat: add traces and metrics for the mempool.
Signed-off-by: Eric Torreborre <[email protected]>
Update srp for consensus and network
feat: propagate consensus spans
Signed-off-by: Eric Torreborre <[email protected]> feat: add an environment variable to control the metric export interval Signed-off-by: Eric Torreborre <[email protected]>
Merge pull request #913 from input-output-hk/prc/net-node-memory
net-node memory + per-message size enforcement
feat(chainsync): prunce seenHeaders during normal operation
Signed-off-by: cryptodj413 <[email protected]>
bump ProtVer to match node (12/11) for Dijkstra
net-core: front-prune LeiosStore notifications alongside slot eviction
`LeiosStore::notifications: Vec<LeiosNotification>` was never pruned. Every `inject_block` / `inject_block_txs` / `inject_votes` pushed an entry that lived forever, even though the blocks/votes those entries point at get slot-window-evicted by the same `bump_version` call. Over a long-running cluster the vec grows monotonically with the total inject rate. Switch storage to `VecDeque` and add a `notifications_pruned_count` so logical (caller-facing) cursors stay monotonic across pruning. At slot-window eviction, front-prune notifications whose every referenced slot is below the cutoff — those refer to data the store no longer holds, so re-sending them to a subscriber would be a wasted round trip. Stop at the first non-evictable front entry: notifications arrive in roughly slot order, so the leak past the cutoff is bounded by out-of-order arrivals (next bump catches up). `notifications_after` now takes `&mut usize`. Callers track a monotonic logical cursor; if it lags the prune frontier the call bumps it forward so subsequent `*after += 1` increments stay aligned with the items actually consumed. `notification_count` reports the all-time logical total. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
net-node, shared-consensus: demote per-tx / per-event spam to debug
Three info! lines fire once per item under steady cluster load and together accounted for ~600K of the ~660K info-level log lines in a 27-minute test run, dominating disk usage: - `transaction received` (net-node) 366K lines - `network event` (net-node, default arm) 155K lines - `mempool: evicting oldest tx` (shared) 71K lines At a 1 tx/s/node generation rate with a 10K-cap mempool, the eviction line fires on every admit once the cap is reached. At RUST_LOG=info on a 25-node cluster these saturate disk in roughly half a day. None of the three is useful at info: the per-tx and per-event lines are item-level traces (debug territory) and eviction at cap is a steady-state condition, not a notable event. Periodic `mempool state sizes` / `praos state sizes` / `leios_store: stats` lines remain at info — those carry the diagnostic signal. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
net-core: BlockFetch demuxer cap uses INGRESS_LIMIT, not per-message cap
The demuxer enforces `set_ingress_limit` as a *buffer* cap on the
per-protocol ingress queue, not as a per-message cap. Under server
pipelining (`MsgStartBatch` immediately followed by `MsgBlock`) both
segments can land in the buffer before the codec processes
`MsgStartBatch` and bumps the limit for `StStreaming`. With the
prior per-state caps that race manifested two ways:
1. `StBusy` at `SIZE_LIMIT_SMALL = 65_535` rejected the pipelined
block body outright (a 65K+ block was already enough to trip
it).
2. Even with `StBusy` raised to `SIZE_LIMIT_STREAMING = 2.5 MB`,
a real Praos block body — particularly the post-EB-overflow
fallback path where txs the EB couldn't carry get inlined into
the RB — can legitimately exceed 2.5 MB. Overnight one landed
at 2,506,268 bytes and tripped the new cap, cascading SDU
timeouts and freezing the cluster.
The spec defines `INGRESS_LIMIT = 230 MB` as the per-protocol
ingress buffer cap exactly for this case. Use it for both `StBusy`
and `StStreaming`. Spec per-message rejection at
`SIZE_LIMIT_SMALL` / `SIZE_LIMIT_STREAMING` belongs in the codec at
decode time (not yet wired); the framework's `size_limit` callback
controls buffer sizing only.
`StIdle` keeps `SIZE_LIMIT_SMALL` — the client never receives in
that state, so the tighter cap stands.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
net-core: enforce per-message size limits at codec decode time
Two distinct size guards on the receive path are now correctly layered: 1. **Demuxer buffer cap** (DoS protection): fixed at protocol registration via `ProtocolConfig::ingress_limit`, never narrowed at runtime. Sized to bound runaway accumulation when a protocol consumer falls behind. 2. **Codec per-message cap** (protocol conformance): `Runner::recv` passes `P::size_limit(state)` to `CodecRecv::recv`; after a CBOR value decodes, the consumed-bytes count is checked against the per-state spec limit and `MuxError::MessageTooLarge` is returned (and the connection torn down) for spec-violating peers. The previous design conflated these — `Runner` overrode the demuxer's buffer cap with the current state's per-message cap on every transition, so a fast peer pipelining `MsgStartBatch` + `MsgBlock` into one TCP read could legitimately overflow before the local runner advanced the state. Reverts `BlockFetch::size_limit` to spec (`SIZE_LIMIT_SMALL` for StIdle/StBusy, `SIZE_LIMIT_STREAMING` for StStreaming); the values are now actually enforced at decode time rather than misused as buffer caps. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
shared-consensus: O(log P) idle peek via per-peer "unannounced" set
`MempoolState::peek_unannounced_for_peer` used to scan the entire `txs` queue on every call, doing a `BTreeSet<TxId>::contains` check per element to find the few ids the peer hadn't yet been told about. Under steady TxSubmission pull traffic with a caught-up peer that's `O(N · log A · 32)` per poll for no useful work — the dominant mempool-CPU symptom under cluster load. Flip the polarity: keep a per-peer "still owed to this peer" `BTreeSet<TxId>` that's the inverse partition of `peer_advertised` over the current mempool. Lazily seed it from `tx_index` on first peer-facing call; admit fan-out inserts the new id into every known peer's owed set; pruning (`drain_*`, `on_block_applied`, capacity eviction) drops the id from both sides; `forget_peer` clears both. The hot path becomes: look up the peer's owed set (`O(log P)`), return immediately if empty, otherwise drain up to `max_count` and resolve bodies. The remaining `for tx in &self.txs` scan only runs when there's actually unannounced work — the empty-poll case (which dominates under steady-state cluster traffic) returns without touching the queue. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
net-core: drop empty VotesOffer notifications from LeiosStore
Empty vote batches were enqueued by `inject_votes` but flagged non-evictable by `notification_evictable`, so they accumulated past slot pruning. Skip the enqueue and let `all(...)` decide eviction on its own vacuous-truth semantics. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
[Leios prototype] Implement NTC chainsync (#2050)
Dijkstra cert blocks are deserialised, resolved (txs spliced from the announcer's EB), and reencoded. Relies on the protocol invariant that a cert block always immediately follows an announcer. Added a new `resolveLeiosBlockHdr` rather than overloading the existing `resolveLeiosBlock`, to avoid conflicts No integration was needed in network/node, except srps.
Merge pull request #907 from input-output-hk/prc/tcp-model
tcp-model: analytic TCP envelope for sim-rs links
tcp-model: guard config footguns surfaced by Copilot review
Reject mss_bytes == 0 and loss_prob_per_segment outside [0, 1] at the YAML override layer, with a matching early-return in msg_loss_prob so the library can't be panicked from configuration. Add a debug_assert when add_edge sees a tcp_envelope but the rng_oracle hasn't been wired. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
sim-core: thread tcp-envelope through the sequential/turbo engine
sequential.rs builds Connections directly (it doesn't route through NetworkCoordinator), so the envelope wiring added earlier was only reaching the actor engine. Fix: construct an EnvelopeWiring at link- build time whenever `LinkConfiguration.tcp_envelope` is `Some`, using the same `Rng::new(config.seed)` stateless oracle already used by other sequential-engine machinery. Caught by a NA,0.200 / top-stake-fraction / 750n sanity run with loss-prob-per-segment 0.01: the turbo-engine output was byte-identical to baseline because the envelope cfg was being discarded at the Connection::new call site. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>