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 (65)
May 27, 8-9 AM (38)
May 27, 9-10 AM (74)
May 27, 10-11 AM (83)
May 27, 11-12 PM (30)
May 27, 12-1 PM (50)
May 27, 1-2 PM (39)
May 27, 2-3 PM (53)
May 27, 3-4 PM (37)
May 27, 4-5 PM (11)
May 27, 5-6 PM (18)
May 27, 6-7 PM (21)
May 27, 7-8 PM (25)
May 27, 8-9 PM (17)
May 27, 9-10 PM (15)
May 27, 10-11 PM (29)
May 27, 11-12 AM (27)
May 28, 12-1 AM (9)
May 28, 1-2 AM (3)
May 28, 2-3 AM (5)
May 28, 3-4 AM (2)
May 28, 4-5 AM (9)
May 28, 5-6 AM (34)
May 28, 6-7 AM (31)
May 28, 7-8 AM (84)
May 28, 8-9 AM (33)
May 28, 9-10 AM (54)
May 28, 10-11 AM (50)
May 28, 11-12 PM (21)
May 28, 12-1 PM (46)
May 28, 1-2 PM (50)
May 28, 2-3 PM (23)
May 28, 3-4 PM (43)
May 28, 4-5 PM (86)
May 28, 5-6 PM (13)
May 28, 6-7 PM (31)
May 28, 7-8 PM (43)
May 28, 8-9 PM (34)
May 28, 9-10 PM (17)
May 28, 10-11 PM (36)
May 28, 11-12 AM (32)
May 29, 12-1 AM (12)
May 29, 1-2 AM (13)
May 29, 2-3 AM (4)
May 29, 3-4 AM (3)
May 29, 4-5 AM (0)
May 29, 5-6 AM (2)
May 29, 6-7 AM (5)
May 29, 7-8 AM (16)
May 29, 8-9 AM (37)
May 29, 9-10 AM (34)
May 29, 10-11 AM (69)
May 29, 11-12 PM (25)
May 29, 12-1 PM (44)
May 29, 1-2 PM (66)
May 29, 2-3 PM (60)
May 29, 3-4 PM (25)
May 29, 4-5 PM (26)
May 29, 5-6 PM (79)
May 29, 6-7 PM (11)
May 29, 7-8 PM (19)
May 29, 8-9 PM (9)
May 29, 9-10 PM (8)
May 29, 10-11 PM (27)
May 29, 11-12 AM (7)
May 30, 12-1 AM (9)
May 30, 1-2 AM (2)
May 30, 2-3 AM (1)
May 30, 3-4 AM (5)
May 30, 4-5 AM (2)
May 30, 5-6 AM (11)
May 30, 6-7 AM (0)
May 30, 7-8 AM (2)
May 30, 8-9 AM (11)
May 30, 9-10 AM (13)
May 30, 10-11 AM (10)
May 30, 11-12 PM (5)
May 30, 12-1 PM (8)
May 30, 1-2 PM (5)
May 30, 2-3 PM (18)
May 30, 3-4 PM (5)
May 30, 4-5 PM (1)
May 30, 5-6 PM (9)
May 30, 6-7 PM (9)
May 30, 7-8 PM (1)
May 30, 8-9 PM (5)
May 30, 9-10 PM (4)
May 30, 10-11 PM (27)
May 30, 11-12 AM (12)
May 31, 12-1 AM (17)
May 31, 1-2 AM (0)
May 31, 2-3 AM (1)
May 31, 3-4 AM (1)
May 31, 4-5 AM (0)
May 31, 5-6 AM (0)
May 31, 6-7 AM (7)
May 31, 7-8 AM (4)
May 31, 8-9 AM (10)
May 31, 9-10 AM (3)
May 31, 10-11 AM (4)
May 31, 11-12 PM (4)
May 31, 12-1 PM (1)
May 31, 1-2 PM (2)
May 31, 2-3 PM (24)
May 31, 3-4 PM (16)
May 31, 4-5 PM (2)
May 31, 5-6 PM (1)
May 31, 6-7 PM (2)
May 31, 7-8 PM (2)
May 31, 8-9 PM (2)
May 31, 9-10 PM (7)
May 31, 10-11 PM (25)
May 31, 11-12 AM (11)
Jun 01, 12-1 AM (14)
Jun 01, 1-2 AM (7)
Jun 01, 2-3 AM (3)
Jun 01, 3-4 AM (10)
Jun 01, 4-5 AM (13)
Jun 01, 5-6 AM (16)
Jun 01, 6-7 AM (10)
Jun 01, 7-8 AM (14)
Jun 01, 8-9 AM (46)
Jun 01, 9-10 AM (50)
Jun 01, 10-11 AM (19)
Jun 01, 11-12 PM (27)
Jun 01, 12-1 PM (49)
Jun 01, 1-2 PM (40)
Jun 01, 2-3 PM (44)
Jun 01, 3-4 PM (34)
Jun 01, 4-5 PM (54)
Jun 01, 5-6 PM (5)
Jun 01, 6-7 PM (32)
Jun 01, 7-8 PM (37)
Jun 01, 8-9 PM (9)
Jun 01, 9-10 PM (12)
Jun 01, 10-11 PM (30)
Jun 01, 11-12 AM (22)
Jun 02, 12-1 AM (13)
Jun 02, 1-2 AM (8)
Jun 02, 2-3 AM (5)
Jun 02, 3-4 AM (14)
Jun 02, 4-5 AM (10)
Jun 02, 5-6 AM (43)
Jun 02, 6-7 AM (32)
Jun 02, 7-8 AM (58)
Jun 02, 8-9 AM (47)
Jun 02, 9-10 AM (10)
3,730 commits this week May 26, 2026 - Jun 02, 2026
Optimal non-builtin valueOf in plutus-ledger-api Data.Value (#7797)
Rewrites `PlutusLedgerApi.V1.Data.Value.valueOf` so the non-builtin lookup
path walks the underlying `BuiltinList` directly via `unsafeDataAsMap` /
`unsafeDataAsB` / `unsafeDataAsI`, compares keys with `equalsByteString`,
and short-circuits on the first match. No `Maybe` is materialised: the
"absent" answer is `0`, returned in-place by the `nilCase` of each
traversal. Avoids `withCurrencySymbol`'s continuation + `Map.lookup`'s
`Maybe`-wrapping, and bypasses the `ToData k`/`UnsafeFromData a` dictionary
work that `AssocMap.lookup` does per element. Semantics preserved.

Adds `Spec.Data.Value.test_valueOf`: a QuickCheck property that compiles
`valueOf` via TH, evaluates it on the CEK machine, and compares the result
against the host-Haskell `valueOf` for the same inputs. Differential test
against the Plinth compiler — any divergence is a compilation bug, not a
semantics bug.

Budget evidence (lookup matrix, `unsafeDataAsValue` baseline) lives on the
companion experimental branch `yura/issue-2242-valueof-evidence`, kept out
of this PR to avoid carrying ~96 golden files that would only ever regenerate
on upstream plugin/cost-model changes.

For IntersectMBO/plutus-private#2242.
Unify headId guard in aggregateNodeState
  Move the cross-head contamination guard from the HeadState-only
  `aggregate` function into `aggregateNodeState`, so that the entire
  NodeState (including pendingDeposits) is protected on headId mismatch.

  This removes the redundant inline `| headId == ourHeadId` guards from
  the DepositRecovered and CommitFinalized cases, which previously still
  modified pendingDeposits in their fallthrough branch even when the
  headId didn't match.

  Also makes `eventHeadId` fully explicit — no wildcard catch-all — so
  every StateChanged constructor is deliberately accounted for. Events
  with a head-specific headId now return Just headId; IgnoredHeadInitializing
  returns Nothing because its headId is the other head's id, not ours.
Validate headId in aggregate to prevent cross-head event contamination
  The SQLite event store accumulates events from all head lifecycles without
  rotation. On restart, `aggregate` replays every persisted StateChanged event
  but unlike the live `handleChainInput` path, never checked that an event's
  headId matched the current state — so a HeadClosed or HeadFannedOut event
  from a previous head could silently drive an unrelated Open/Closed head into
  the wrong state.

  Fix: add `eventHeadId` and `headIdOf` helpers and a single pre-check at the
  top of `aggregate`. Any event whose headId does not match the current state's
  headId is silently dropped. Events that carry no headId are always applied,
  preserving existing behaviour for TransactionReceived, ChainRolledBack, etc.

  Regression tests cover the two critical cross-phase transitions:
  Open→Closed via HeadClosed and Closed→Idle via HeadFannedOut from a
  mismatched head.
Fix recovered deposit leaking into new L2 snapshot utxo
The root cause was in confirmedUTxO inside onOpenNetworkReqSn: it always
  included utxoToCommit unconditionally. When a new ReqSn with no deposit
  arrived after recovery, the recovered deposit was still part of the base
  UTxO used to apply transactions, and with no withoutUTxO to strip it
  back out, it baked into the new snapshot's utxo field.
Use dynamic binary search to find largest fitting fanout chunk
  Replace the hardcoded numToDistribute = totalUTxO - 1 in the partial
  fanout benchmarks with a binary search that finds the largest chunk
  actually fitting within both the tx size and execution budget, mirroring
  findFittingFanoutTx in the real node. The Remaining column in the output
  table now carries meaningful information instead of always showing 1.

  Also add ContestationDeadlineOutsideTimeHorizon to the PostTxError
  oneOf in api.yaml, which was defined in Chain.hs but missing from the
  schema, causing ServerOutputSpec to fail.

Signed-off-by: Sasha Bogicevic <[email protected]>
Replace UTxO hash verification with BLS accumulator commitment
  Remove utxoHash/alphaUTxOHash/omegaUTxOHash from ClosedDatum, all
  Close/Contest redeemers, and the snapshot signing tuple. The BLS
  accumulator already commits to the full UTxO set (utxo ∪ alpha ∪
  omega), making the three separate SHA256 hashes redundant.

  Full fanout now verifies outputs via a KZG membership proof (same as
  partial fanout) rather than hash comparison. The Fanout redeemer gains
  proof and crsRef fields; the three output-count fields are dropped.

  Snapshot signing shrinks from a 7-tuple to a 4-tuple
  (headId, version, snapshotNumber, accumulatorHash).

Signed-off-by: Sasha Bogicevic <[email protected]>
Fix tx-cost bench: drop fanoutChunkSize, widen FinalPartialFanout range
  computeFinalPartialFanOutCost was capped at 7 (fanoutChunkSize), hiding
  the real tx-size limit for the terminal fanout step. Now it sweeps a wide
  range and searches for the actual maximum, using a single preceding output
  as minimal setup to reach FanoutProgress.

  computePartialFanOutMixedCost also dropped its fanoutChunkSize cap and
  now distributes all-but-one outputs, consistent with the nominal benchmark.
  The stale description mentioning fanoutChunkSize is corrected accordingly.

Signed-off-by: Sasha Bogicevic <[email protected]>
Consolidate fanout test constants and fix uncaught exception in postTx
  fanoutChunkSize and fanoutOutputThreshold are now defined once in
  Test.Hydra.Tx.Fixture and imported wherever needed, removing the
  per-file duplicates.

  prepareTxToPost gains explicit FanoutTx/FinalPartialFanoutTx branches
  (error) so GHC's exhaustiveness checker catches any future unhandled
  constructor, instead of silently falling through a wildcard.

  The two deadline-slot conversions in mkChain.postTx now throw
  FailedToConstructFanoutTx (a PostTxError Tx) instead of userError,
  so the exception is caught by Node.hs's PostTxError handler rather
  than propagating uncaught and crashing the node.
Remove hardcoded fanout chunk/threshold constants; make fanout sizing fully dynamic
  HeadLogic no longer uses fanoutChunkSize or fanoutOutputThreshold to decide
  which tx type to emit. For a fresh fanout it always emits FanoutTx; for an
  in-progress fanout it always emits FinalPartialFanoutTx. Handlers now owns the
  sizing decision: it tries the preferred tx first, then falls back to
  PartialFanoutTx with a decreasing chunk size (starting at N-1) until one fits
  within the execution budget, using a single shared findFittingFanoutTx helper.

  PartialFanoutTx is removed from PostChainTx — it is now an internal Handlers
  detail, never emitted by HeadLogic. fanoutChunkSize and fanoutOutputThreshold
  are removed from KZGTrustedSetup and all call sites.