Mar 18, 11-12 PM (64)
Mar 18, 12-1 PM (72)
Mar 18, 1-2 PM (49)
Mar 18, 2-3 PM (130)
Mar 18, 3-4 PM (44)
Mar 18, 4-5 PM (26)
Mar 18, 5-6 PM (33)
Mar 18, 6-7 PM (43)
Mar 18, 7-8 PM (39)
Mar 18, 8-9 PM (23)
Mar 18, 9-10 PM (32)
Mar 18, 10-11 PM (40)
Mar 18, 11-12 AM (31)
Mar 19, 12-1 AM (30)
Mar 19, 1-2 AM (13)
Mar 19, 2-3 AM (6)
Mar 19, 3-4 AM (4)
Mar 19, 4-5 AM (4)
Mar 19, 5-6 AM (1)
Mar 19, 6-7 AM (29)
Mar 19, 7-8 AM (58)
Mar 19, 8-9 AM (118)
Mar 19, 9-10 AM (73)
Mar 19, 10-11 AM (199)
Mar 19, 11-12 PM (54)
Mar 19, 12-1 PM (61)
Mar 19, 1-2 PM (48)
Mar 19, 2-3 PM (76)
Mar 19, 3-4 PM (138)
Mar 19, 4-5 PM (29)
Mar 19, 5-6 PM (19)
Mar 19, 6-7 PM (31)
Mar 19, 7-8 PM (19)
Mar 19, 8-9 PM (36)
Mar 19, 9-10 PM (13)
Mar 19, 10-11 PM (41)
Mar 19, 11-12 AM (18)
Mar 20, 12-1 AM (4)
Mar 20, 1-2 AM (4)
Mar 20, 2-3 AM (8)
Mar 20, 3-4 AM (9)
Mar 20, 4-5 AM (10)
Mar 20, 5-6 AM (4)
Mar 20, 6-7 AM (51)
Mar 20, 7-8 AM (27)
Mar 20, 8-9 AM (29)
Mar 20, 9-10 AM (38)
Mar 20, 10-11 AM (33)
Mar 20, 11-12 PM (22)
Mar 20, 12-1 PM (33)
Mar 20, 1-2 PM (91)
Mar 20, 2-3 PM (19)
Mar 20, 3-4 PM (52)
Mar 20, 4-5 PM (24)
Mar 20, 5-6 PM (20)
Mar 20, 6-7 PM (14)
Mar 20, 7-8 PM (15)
Mar 20, 8-9 PM (15)
Mar 20, 9-10 PM (16)
Mar 20, 10-11 PM (22)
Mar 20, 11-12 AM (18)
Mar 21, 12-1 AM (8)
Mar 21, 1-2 AM (2)
Mar 21, 2-3 AM (5)
Mar 21, 3-4 AM (2)
Mar 21, 4-5 AM (1)
Mar 21, 5-6 AM (2)
Mar 21, 6-7 AM (6)
Mar 21, 7-8 AM (3)
Mar 21, 8-9 AM (9)
Mar 21, 9-10 AM (7)
Mar 21, 10-11 AM (5)
Mar 21, 11-12 PM (4)
Mar 21, 12-1 PM (3)
Mar 21, 1-2 PM (8)
Mar 21, 2-3 PM (3)
Mar 21, 3-4 PM (9)
Mar 21, 4-5 PM (7)
Mar 21, 5-6 PM (12)
Mar 21, 6-7 PM (12)
Mar 21, 7-8 PM (2)
Mar 21, 8-9 PM (1)
Mar 21, 9-10 PM (5)
Mar 21, 10-11 PM (24)
Mar 21, 11-12 AM (21)
Mar 22, 12-1 AM (0)
Mar 22, 1-2 AM (6)
Mar 22, 2-3 AM (5)
Mar 22, 3-4 AM (0)
Mar 22, 4-5 AM (1)
Mar 22, 5-6 AM (6)
Mar 22, 6-7 AM (6)
Mar 22, 7-8 AM (1)
Mar 22, 8-9 AM (1)
Mar 22, 9-10 AM (2)
Mar 22, 10-11 AM (3)
Mar 22, 11-12 PM (5)
Mar 22, 12-1 PM (1)
Mar 22, 1-2 PM (1)
Mar 22, 2-3 PM (2)
Mar 22, 3-4 PM (6)
Mar 22, 4-5 PM (6)
Mar 22, 5-6 PM (17)
Mar 22, 6-7 PM (32)
Mar 22, 7-8 PM (48)
Mar 22, 8-9 PM (7)
Mar 22, 9-10 PM (1)
Mar 22, 10-11 PM (21)
Mar 22, 11-12 AM (23)
Mar 23, 12-1 AM (5)
Mar 23, 1-2 AM (4)
Mar 23, 2-3 AM (9)
Mar 23, 3-4 AM (7)
Mar 23, 4-5 AM (2)
Mar 23, 5-6 AM (4)
Mar 23, 6-7 AM (1)
Mar 23, 7-8 AM (7)
Mar 23, 8-9 AM (33)
Mar 23, 9-10 AM (36)
Mar 23, 10-11 AM (17)
Mar 23, 11-12 PM (97)
Mar 23, 12-1 PM (62)
Mar 23, 1-2 PM (53)
Mar 23, 2-3 PM (73)
Mar 23, 3-4 PM (67)
Mar 23, 4-5 PM (86)
Mar 23, 5-6 PM (65)
Mar 23, 6-7 PM (21)
Mar 23, 7-8 PM (18)
Mar 23, 8-9 PM (16)
Mar 23, 9-10 PM (16)
Mar 23, 10-11 PM (35)
Mar 23, 11-12 AM (31)
Mar 24, 12-1 AM (1)
Mar 24, 1-2 AM (3)
Mar 24, 2-3 AM (14)
Mar 24, 3-4 AM (4)
Mar 24, 4-5 AM (3)
Mar 24, 5-6 AM (4)
Mar 24, 6-7 AM (3)
Mar 24, 7-8 AM (102)
Mar 24, 8-9 AM (40)
Mar 24, 9-10 AM (30)
Mar 24, 10-11 AM (167)
Mar 24, 11-12 PM (26)
Mar 24, 12-1 PM (42)
Mar 24, 1-2 PM (129)
Mar 24, 2-3 PM (12)
Mar 24, 3-4 PM (40)
Mar 24, 4-5 PM (47)
Mar 24, 5-6 PM (110)
Mar 24, 6-7 PM (16)
Mar 24, 7-8 PM (9)
Mar 24, 8-9 PM (14)
Mar 24, 9-10 PM (14)
Mar 24, 10-11 PM (27)
Mar 24, 11-12 AM (14)
Mar 25, 12-1 AM (1)
Mar 25, 1-2 AM (2)
Mar 25, 2-3 AM (13)
Mar 25, 3-4 AM (2)
Mar 25, 4-5 AM (10)
Mar 25, 5-6 AM (5)
Mar 25, 6-7 AM (7)
Mar 25, 7-8 AM (14)
Mar 25, 8-9 AM (22)
Mar 25, 9-10 AM (43)
Mar 25, 10-11 AM (10)
Mar 25, 11-12 PM (1)
4,447 commits this week Mar 18, 2026 - Mar 25, 2026
Make sure we're using indexes during rollbacks
Fixes https://github.com/IntersectMBO/cardano-db-sync/issues/2083

The `queryMinRefId` query uses
```sql
SELECT id FROM <table> WHERE <field> >= $1 ORDER BY id ASC LIMIT 1.
```

The planner sometimes picks a bad plan:

```sql
Index Scan using tx_pkey on tx
  Filter: (block_id >= $1)
```

the filter is not Index Cond, so this ends up in a sequential scan.
The index refers to the primary key and is only used for sorting.

Instead we use a simpler query without ORDER BY:

SELECT id FROM <table> WHERE <field> >= $1 LIMIT 10000
This forces the planner to use the field's index.
The results are fetched and the minimum is found in Haskell.
Near the tip this returns only a handful of rows.

If there are more than 10000 matching rows (large rollback),
we fall back to the original ORDER BY id ASC LIMIT 1 query.
net-rs: add Leios per-peer task integration (Phase 4d)
Wire LeiosNotify (ID 18) and LeiosFetch (ID 19) into the per-peer task
architecture behind a `leios_enabled` config flag (default false).

- LeiosStore: content-addressed blob store for EBs/votes (separate from
  ChainStore since Leios data is keyed by (slot, hash), not a linear chain)
- Client tasks: spawn_leios_notify (continuous request_next loop),
  spawn_leios_fetch (command-driven, like BlockFetch)
- Server handlers: serve_leios_notify (from LeiosStore + subscribe),
  serve_leios_fetch (block/txs/vote lookups)
- Types: 6 PeerEvent, 2 PeerCommand, 5 NetworkEvent, 3 NetworkCommand variants
- Coordinator: stub-forwards Leios events, populates LeiosStore on fetch
- Wiring: peer_task, responder_task, duplex_task all conditionally register
  and spawn Leios protocol sub-tasks
- CLI: --leios flag on serve (synthetic EB/vote generation) and multi-follow
  (logs Leios notifications) for local end-to-end testing

247 total tests (9 new). Locally tested: serve --leios -> multi-follow --leios.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Added JSONField type class
To avoid `extraField: true` in `ToJSON` instance of `LocalRootPeers`,
`JSONField` type class is added.  With it `PeerTrustable` is encoded as
`peerTrustable: true`, e.g. instead of

```
{"at":"2026-03-25T10:28:46.923707499Z","ns":"Startup.NetworkConfig","data":{"kind":"NetworkConfig","localRoots":[[1,1,[[{"address":"13.39.54.80","port":3001},{"behindFirewall":true,"diffusionMode":"InitiatorAndResponderDiffusionMode","extraFlags":false,"peerAdvertise":false}]]]],"peerSnapshotFile":null,"publicRoots":[],"useLedgerAfter":150828233},"sev":"Info","thread":"11","host":"waldorf"}
```
we get
```
{"at":"2026-03-25T10:53:33.412251964Z","ns":"Startup.NetworkConfig","data":{"kind":"NetworkConfig","localRoots":[[1,1,[[{"address":"13.39.54.80","port":3001},{"behindFirewall":false,"diffusionMode":"InitiatorAndResponderDiffusionMode","peerAdvertise":false,"peerTrustable":false}]]]],"peerSnapshotFile":null,"publicRoots":[],"useLedgerAfter":150828233},"sev":"Info","thread":"11","host":"waldorf"}
```
Add conformance tests between model and real WFA implementation
This commits adds conformance tests between the WFALS model and Haskell
implementation using randomly generated stake distributions and target
committee sizes.

Additionally, it breaks the test utilities for the model into a separate
module Test.Consensus.WFALS.Model.Utils.

Co-authored-by: Nicolas BACQUEY <[email protected]>
Co-authored-by: Thomas BAGREL <[email protected]>
Co-authored-by: Agustin Mista <[email protected]>
Add Flat encoding test coverage across all packages
Pay down test coverage debt for Flat serialization instances.
This ensures encoding stability is verified by tests before
we attempt to fix the Generic derivation bug in a follow-up PR.

Adds roundtrip and stable byte encoding tests for:
- Flat library types (Maybe, Either, NonEmpty, Complex, Ratio,
  Set, Tree, Map, Seq, DList, Filler, PreAligned, and
  monoid/semigroup wrappers)
- TPLC types (Version, Name, Kind, DeBruijn, NamedDeBruijn,
  SrcSpan, SrcSpans, DefaultFun, DefaultUni, and all newtype
  wrappers including TyName, Unique, TyDeBruijn, etc.)
- PIR types (Recursivity, Strictness)
- UPLC types (Binder variants, FakeNamedDeBruijn, minimal
  Program encoding)
- Value types (K encodes as ByteString, Quantity as Integer)

Also adds a standalone encoding generator executable
(cabal run flat-encoding-generator) for reproducing expected
byte constants.
net-rs: move codec.rs to mux/ and protocol.rs to protocols/
codec.rs wraps mux channels with CBOR framing — belongs in mux/.
protocol.rs defines the protocol state machine framework — belongs
in protocols/. Re-export from parent modules so imports become
crate::mux::{CodecSend,CodecRecv} and crate::protocols::{Protocol,
Runner,Agency,Role,ProtocolError}. Update all ~40 import sites.
238 tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>