Apr 14, 7-8 PM (14)
Apr 14, 8-9 PM (10)
Apr 14, 9-10 PM (11)
Apr 14, 10-11 PM (24)
Apr 14, 11-12 AM (24)
Apr 15, 12-1 AM (3)
Apr 15, 1-2 AM (9)
Apr 15, 2-3 AM (8)
Apr 15, 3-4 AM (1)
Apr 15, 4-5 AM (1)
Apr 15, 5-6 AM (32)
Apr 15, 6-7 AM (7)
Apr 15, 7-8 AM (25)
Apr 15, 8-9 AM (49)
Apr 15, 9-10 AM (40)
Apr 15, 10-11 AM (127)
Apr 15, 11-12 PM (53)
Apr 15, 12-1 PM (60)
Apr 15, 1-2 PM (43)
Apr 15, 2-3 PM (45)
Apr 15, 3-4 PM (29)
Apr 15, 4-5 PM (44)
Apr 15, 5-6 PM (21)
Apr 15, 6-7 PM (33)
Apr 15, 7-8 PM (15)
Apr 15, 8-9 PM (17)
Apr 15, 9-10 PM (5)
Apr 15, 10-11 PM (20)
Apr 15, 11-12 AM (16)
Apr 16, 12-1 AM (12)
Apr 16, 1-2 AM (6)
Apr 16, 2-3 AM (7)
Apr 16, 3-4 AM (3)
Apr 16, 4-5 AM (4)
Apr 16, 5-6 AM (8)
Apr 16, 6-7 AM (33)
Apr 16, 7-8 AM (32)
Apr 16, 8-9 AM (31)
Apr 16, 9-10 AM (27)
Apr 16, 10-11 AM (50)
Apr 16, 11-12 PM (56)
Apr 16, 12-1 PM (58)
Apr 16, 1-2 PM (30)
Apr 16, 2-3 PM (40)
Apr 16, 3-4 PM (46)
Apr 16, 4-5 PM (47)
Apr 16, 5-6 PM (56)
Apr 16, 6-7 PM (17)
Apr 16, 7-8 PM (68)
Apr 16, 8-9 PM (38)
Apr 16, 9-10 PM (11)
Apr 16, 10-11 PM (23)
Apr 16, 11-12 AM (23)
Apr 17, 12-1 AM (12)
Apr 17, 1-2 AM (8)
Apr 17, 2-3 AM (3)
Apr 17, 3-4 AM (4)
Apr 17, 4-5 AM (3)
Apr 17, 5-6 AM (9)
Apr 17, 6-7 AM (26)
Apr 17, 7-8 AM (96)
Apr 17, 8-9 AM (70)
Apr 17, 9-10 AM (53)
Apr 17, 10-11 AM (41)
Apr 17, 11-12 PM (58)
Apr 17, 12-1 PM (64)
Apr 17, 1-2 PM (39)
Apr 17, 2-3 PM (46)
Apr 17, 3-4 PM (36)
Apr 17, 4-5 PM (13)
Apr 17, 5-6 PM (10)
Apr 17, 6-7 PM (25)
Apr 17, 7-8 PM (22)
Apr 17, 8-9 PM (3)
Apr 17, 9-10 PM (16)
Apr 17, 10-11 PM (24)
Apr 17, 11-12 AM (16)
Apr 18, 12-1 AM (2)
Apr 18, 1-2 AM (2)
Apr 18, 2-3 AM (6)
Apr 18, 3-4 AM (1)
Apr 18, 4-5 AM (2)
Apr 18, 5-6 AM (2)
Apr 18, 6-7 AM (1)
Apr 18, 7-8 AM (2)
Apr 18, 8-9 AM (4)
Apr 18, 9-10 AM (4)
Apr 18, 10-11 AM (1)
Apr 18, 11-12 PM (6)
Apr 18, 12-1 PM (7)
Apr 18, 1-2 PM (8)
Apr 18, 2-3 PM (9)
Apr 18, 3-4 PM (0)
Apr 18, 4-5 PM (2)
Apr 18, 5-6 PM (6)
Apr 18, 6-7 PM (2)
Apr 18, 7-8 PM (2)
Apr 18, 8-9 PM (4)
Apr 18, 9-10 PM (9)
Apr 18, 10-11 PM (21)
Apr 18, 11-12 AM (23)
Apr 19, 12-1 AM (1)
Apr 19, 1-2 AM (4)
Apr 19, 2-3 AM (1)
Apr 19, 3-4 AM (0)
Apr 19, 4-5 AM (0)
Apr 19, 5-6 AM (2)
Apr 19, 6-7 AM (0)
Apr 19, 7-8 AM (2)
Apr 19, 8-9 AM (1)
Apr 19, 9-10 AM (1)
Apr 19, 10-11 AM (4)
Apr 19, 11-12 PM (7)
Apr 19, 12-1 PM (6)
Apr 19, 1-2 PM (8)
Apr 19, 2-3 PM (22)
Apr 19, 3-4 PM (7)
Apr 19, 4-5 PM (4)
Apr 19, 5-6 PM (3)
Apr 19, 6-7 PM (8)
Apr 19, 7-8 PM (3)
Apr 19, 8-9 PM (8)
Apr 19, 9-10 PM (6)
Apr 19, 10-11 PM (25)
Apr 19, 11-12 AM (23)
Apr 20, 12-1 AM (4)
Apr 20, 1-2 AM (5)
Apr 20, 2-3 AM (2)
Apr 20, 3-4 AM (7)
Apr 20, 4-5 AM (1)
Apr 20, 5-6 AM (6)
Apr 20, 6-7 AM (11)
Apr 20, 7-8 AM (29)
Apr 20, 8-9 AM (42)
Apr 20, 9-10 AM (37)
Apr 20, 10-11 AM (95)
Apr 20, 11-12 PM (42)
Apr 20, 12-1 PM (39)
Apr 20, 1-2 PM (53)
Apr 20, 2-3 PM (68)
Apr 20, 3-4 PM (47)
Apr 20, 4-5 PM (40)
Apr 20, 5-6 PM (31)
Apr 20, 6-7 PM (24)
Apr 20, 7-8 PM (10)
Apr 20, 8-9 PM (7)
Apr 20, 9-10 PM (16)
Apr 20, 10-11 PM (28)
Apr 20, 11-12 AM (18)
Apr 21, 12-1 AM (24)
Apr 21, 1-2 AM (5)
Apr 21, 2-3 AM (13)
Apr 21, 3-4 AM (4)
Apr 21, 4-5 AM (3)
Apr 21, 5-6 AM (8)
Apr 21, 6-7 AM (15)
Apr 21, 7-8 AM (44)
Apr 21, 8-9 AM (119)
Apr 21, 9-10 AM (36)
Apr 21, 10-11 AM (35)
Apr 21, 11-12 PM (98)
Apr 21, 12-1 PM (57)
Apr 21, 1-2 PM (71)
Apr 21, 2-3 PM (60)
Apr 21, 3-4 PM (31)
Apr 21, 4-5 PM (27)
Apr 21, 5-6 PM (25)
Apr 21, 6-7 PM (36)
Apr 21, 7-8 PM (11)
3,853 commits this week
Apr 14, 2026
-
Apr 21, 2026
fix(ledger): add stake snapshot and leader observability metrics
Signed-off-by: cryptodj413 <[email protected]>
Artifacts generated from 117e827519565336aafdf7a74e76f6ede38e0422
Use physical path in run-fourmolu.sh
`fd --full-path` matches the regex against the canonicalized path (with symlinks resolved). When the script is invoked from a directory reached via a symlink, `$(pwd)` returns the logical path and the regex matches zero files — the script succeeds silently without formatting anything. Using `pwd -P` produces the physical path, so the regex and the paths `fd` walks agree.
Fix error "impossible!" in Leios Prototype's fetch decision logic (#1996)
## Summary
Fixes `error "impossible!"` crashes observed in the Leios ThreadNet test
suite (tracked in
[ouroboros-leios#862](https://github.com/input-output-hk/ouroboros-leios/issues/862)),
plus a silent wrong-size charge in the same code path.
Per @nfrisby's clarification on this PR: the silent wrong-size bug has
existed since [commit
9c5584f8e](https://github.com/IntersectMBO/ouroboros-consensus/commit/9c5584f8e)
(the commit where the fetch-decision logic was first added, 2025-10-26).
The crash bug was introduced later by
[#1859](https://github.com/IntersectMBO/ouroboros-consensus/pull/1859)
(commit
[ce6324695](https://github.com/IntersectMBO/ouroboros-consensus/commit/ce6324695),
2026-02-10), which removed the `EbId` intermediate naming scheme for
EBs.
## Diagnosis
`goTx2` extracted the transaction's byte size via three nested lookups
starting with `Map.lookupMax txOffsets'` where `txOffsets' :: Map EbHash
Int`.
`lookupMax` picks by lexicographic order of Blake2b-256 hash bytes —
effectively arbitrary with respect to the current `point`.
The offset returned belongs to the picked EB's body-coordinate system.
The code then used this offset as a key into `missingEbTxs[point]`'s
IntMap, assuming the two coordinate systems coincide.
They only do so if the picked EB happens to equal `point`.
Two observable failure modes:
- **Crash.** `IntMap.lookup` returns `Nothing` and fires `error
"impossible!"`.
- **Silent wrong size.** The offset coincidentally indexes a different
tx in `point`'s body; its size is adopted for `txHash` without any
`TxHash` equality check. `requestedBytesSize` /
`requestedBytesSizePerPeer` / the `accNew'` tuple drift.
### Example — crash case
- Tx T1 at offset 0 in EB A (body `[T1, X]`).
- Tx T1 at offset 2 in EB B (body `[Y, Z, T1]`).
- `point = A`; peer offers closure of B only.
- `txOffsets' = {B |-> 2}`; `lookupMax` returns `(B, 2)`.
- `IntMap.lookup 2 v_A` returns `Nothing` — A's body has only offsets 0
and 1. Fires `error "impossible!"`.
### Example — silent wrong-size case
- Tx T1 at offset 0 in EB A, **body `[T1, X, Y]`** (three entries).
- Tx T1 at offset 2 in EB B.
- Same `point`, same peer, same `txOffsets'`.
- `IntMap.lookup 2 v_A` returns `Just (Y, 300)` — Y's size, not T1's.
The code takes Y's size as `txBytesSize` for T1.
## Fix (four commits)
### 1. `Add type signature for goTx2`
Non-behavioral; documents the shape that the refactor touches.
### 2. `Thread txBytesSize into goTx2; drop three-layer lookup`
Capture the tx's byte size at target construction in `expand` — it is
already paired with the tx hash in the IntMap value extracted from
`missingEbTxs[point]`.
Thread it through the `Right` target tuple and as an explicit `goTx2`
argument.
The three-layer lookup and all three `error "impossible!"` branches
disappear.
The size charged against `requestedBytesSize` and
`requestedBytesSizePerPeer` is `point`'s own claim — sourced directly
from where `missingEbTxs[point]` was already handing it to us.
### 3. `Carry byte size in txOffsetss`
Enrich the inverse index to `Map TxHash (Map EbHash (Int, BytesSize))`,
capturing the size already in scope at EB-body ingest time (previously
discarded as `_txBytesSize`).
Non-behavioral on its own: `choosePeerTx` strips the size in its return,
so the `accNew'` DList payload, `LeiosFetchDecisions`, and
`packRequests` see the same shape as before.
### 4. `Require an offered EB's size to match the target in
choosePeerTx`
Per @nfrisby's review: `choosePeerTx` takes `targetBytesSize ::
BytesSize` and inspects one arbitrary entry in `txOffsets'`
(`Map.lookupMax`), requiring its claimed size to equal the target.
An honest peer wouldn't offer EbClosures for EBs that assign different
sizes to the same tx, so every entry in `txOffsets'` has the same size
and a single-entry check is representative.
For an adversarial peer it's inevitable that they could send a different
amount of bytes than requested, so the accuracy of `requestedBytesSize`
/ `requestedBytesSizePerPeer` is not particularly important or
achievable — the single-entry check is sufficient.
## Why the fix is correct
For any decision recorded by `goTx2`:
1. The charged size (`txBytesSize`) and the tx hash (`txHash`) come from
the same IntMap entry in `missingEbTxs[point]`, which is hash-committed
and validated by us — no foreign-offset lookup.
2. The chosen peer has offered at least one EB whose validated body
claims the same size (single-entry check via `Map.lookupMax`).
Both crash and silent-wrong-size paths are eliminated.
Addresses https://github.com/input-output-hk/ouroboros-leios/issues/862
cardano-testnet: disable ExperimentalHardForksEnabled in default config
After ProtVer 12 became the experimental-gated version, Conway-era testnets forged blocks with PV 12 in the header, which the Conway BBody rule rejects (max PV = 11). Dropping the unconditional flag from hardforkViaConfig makes the node fall back to ProtVer 11, which Conway accepts, so the testnet chain progresses.
Artifacts generated from 6da1679b2b95494e32b07459415ccfd9d4f888b1
Unify Dijkstra-era placeholder messages under TODO Dijkstra
All Dijkstra-era placeholder `error` messages and `TODO` comments in `cardano-api/src/` now share the greppable token `TODO Dijkstra:`, so a single `grep -r 'TODO Dijkstra'` locates every site that needs attention when Dijkstra-era support lands. No behaviour change; this is a pure message/comment unification across 30 sites in 16 files. The runtime invariant assertion at `Tx/Internal/Body.hs:2858` (`toScriptIndexDijkstra: unexpected DijkstraGuarding`) is intentionally untouched — it is an impossible-case assertion, not a pending-implementation stub. The PlutusV4 placeholder at `Plutus/Internal/Script.hs:1302` (`toShelleyScript: PlutusV4 not implemented yet.`) is tracked separately as it blocks on ledger exposing a PlutusV4 constructor.
Set PR number in changelog fragment
remove obsolete code
Rewrite re-exported type links to original defining package
Haddock resolves re-exports to the local re-export page (e.g. a reference to cardano-ledger-byron's Address via Cardano.Api.Byron becomes href="Cardano-Api-Byron.html#t:Address", not an external link). The Haddock-emitted "Source" link, however, points to the cabal store path for the original defining package. Phase 2b uses that as ground truth to rewrite local re-export hrefs to the upstream doc site. Also extend dead-link handling in Phase 3: before annotating a 404 as unclickable, probe for the page under doc-site subdirectories (api/, protocols/, framework/ — ouroboros-network's layout) and under parent modules (Cardano-Ledger-Api-State-Query-CommitteeMembersState.html -> Cardano-Ledger-Api-State-Query.html#t:CommitteeMembersState). If the parent resolves, rewrite to it with a reconstructed #t: fragment so the browser still scrolls to the definition. On a full cardano-api build this rewrites 205 of 208 re-exported types (up from 0) and rescues 182 of 233 previously-annotated dead links.
fix ipv6 parser and other minor stuff
fix(ledger): wire into the response for past (closed) eras so their EraEnd reflects confirmed boundaries rather than the raw epoch-end slot
Signed-off-by: Chris Guiney <[email protected]>
automatic signing mode
chore(minibf): Add /pools/pool_id/metadata endpoint
cardano: preserve managed kupo authenticated host
Snapshot of Frisby's SQLite latency investigation during 2026 March
cardano: tighten managed provider diagnostics
fix(ledger): wire into the response for past (closed) eras so their EraEnd reflects confirmed boundaries rather than the raw epoch-end slot
Signed-off-by: Chris Guiney <[email protected]>
fix: bootstrap proposal deposits in accounts_state
Signed-off-by: William Hankins <[email protected]>
[Dijkstra] CIP-159-10: Apply batch-wide direct deposits in LEDGER rule (#1122)
After all sub-rule transitions (`SUBLEDGERS`, `CERTS`, `GOVS`, `UTXOW`), apply batch-wide direct deposits to the final CertState via `applyDirectDeposits` and `allDirectDeposits`. `Ledger.lagda.md`: + Update `LEDGER-V` output: compute `certStateFinal` by applying `allDirectDeposits` to `certState₂`, use `certStateFinal` in the output `LedgerState` and in `rmOrphanDRepVotes`; + `LEDGER-I` unchanged (invalid batches don't apply deposits); + Document direct deposit application ordering and phantom asset prevention rationale. `Ledger/Properties/Computational.lagda.md`: + Update `computeProof` valid branch to compute `certStateFinal` and use it in the output `LedgerState`.
CIP-159-11: Initial PoV property module skeletons (#1123)
Add preservation-of-value property modules for the Dijkstra era, adapted from the Conway PoV proof structure for CIP-159 (partial withdrawals and direct deposits). New modules: - Certs.Properties.PoVLemmas: CERT-pov, POST-CERT-pov, sts-pov, PRE-CERT-pov (adapted for applyWithdrawals subtraction semantics) - Certs.Properties.PoV: CERTS-pov top-level theorem - Certs.Properties.ApplyWithdrawalsPov: Key new lemma showing applyWithdrawals decreases rewardsBalance by exactly getCoin wdrls - Ledger.Properties.PoV: HasCoin instances, LEDGER-pov statement with proof sketch for direct deposit cancellation Design notes: - PRE-CERT-pov delegates to applyWithdrawals-pov (fold induction) instead of Conway's constMap/res-decomp/sumConstZero chain - LEDGER-pov identifies the applyDirectDeposits cancellation as the main new proof obligation vs Conway - applyWithdrawals-pov is structured as three layers: single-step (applyOne-pov), fold induction (foldl-applyOne-pov), top-level Status: Skeleton with holes; does not yet fully typecheck.
CIP-159-11: LEDGER-pov structure with LEDGER-I proved (#1123)
State and partially prove the Dijkstra LEDGER preservation-of-value theorem with the corrected HasCoin-LedgerState that includes deposits. - LEDGER-I (invalid case): Fully proved via utxow-pov-invalid. - LEDGER-V (valid case): Equational chain with holes, to be filled. The HasCoin-LedgerState total is: getCoin utxoSt + rewardsBalance(certState) + coinFromDeposits(certState) Key insight: SUBLEDGERS-pov cannot be proved independently because individual SUBUTXO rules have no balance premise — only the batch-level consumedBatch ≡ producedBatch constrains the total. The LEDGER-V proof must reason about the entire step at once.
`indexedSumᵛ'-∪` and `sumConstZero` have proofs!
There were unresolved proof obligations from Conway.
[Dijkstra] CIP-159-08: Phantom asset attack prevention (#1120)
Add batch-wide withdrawal bound check to prevent phantom asset attacks when nested transactions combine deposits and withdrawals. `Transaction.lagda.md`: + Define allWithdrawals batch aggregation helper (mirrors allDirectDeposits) `Utxo.lagda.md`: + Define NoPhantomWithdrawals predicate using allWithdrawals + Add NoPhantomWithdrawals premise to UTXO rule + Document phantom asset attack and spend-side safety analogy `Utxo/Properties/Computational.lagda.md`: + Update Computational-UTXO for new premise tuple arity (21+h → 22+h)