This release introduces Partial Fanout.
Until now, the number of UTxOs a Hydra head could hold was effectively capped by what fits in a single fanout transaction. With partial fanout, a head holding an arbitrarily large UTxO set can be closed out across multiple steps: each PartialFanoutTx distributes as many outputs as fit in one transaction, and a final FinalPartialFanoutTx burns the head tokens to complete the process. Every step is verified on-chain with a BLS accumulator membership proof, and the chunk size is determined dynamically rather than by a hardcoded limit. This removes the long-standing per-head UTxO ceiling.
This release also ships a substantially revised hydra-tui, event-store size reductions, and a set of correctness fixes. Note the breaking API and persisted-state changes below before upgrading.
CHANGELOG
[2.2.0] - 2026.06.12
-
Extend the end-to-end benchmark with real-world TPS metrics (end-to-end and per-snapshot quantiles), a new
MixedUTxO generator that grows then contracts the head state, an opt-in interleaved incremental commit/decommit cycle (--incremental-ops), and a newmatrixsub-command that iterates over cluster sizes, UTxO shapes, and incremental modes. CI publishes the matrix output as a new scenario benchmarks page. -
Heads with large UTxO sets can now be fanned out in multiple steps using
PartialFanoutTxandFinalPartialFanoutTxtransactions #2324.
Each step distributes as many outputs as fit in a single transaction (determined dynamically via binary search #2617) and uses a BLS accumulator membership proof to verify correctness on-chain. The final step burns the head tokens and completes the fanout. This removes the previous limit of UTxOs per head. -
BREAKING Several fields renamed or retype-changed across the API and persisted state #2324:
HeadIsFinalizedserver output:utxorenamed tofinalizedUTxO; type changed from a UTxO map (object keyed byTxIn) to an array ofTxOutvalues, since intermediate partial fanout outputs do not carry spending references.ClosedState(persistedStateChangedevent):remainingFanoutUTxOrenamed toremainingFanoutOutputs;distributedFanoutUTxOrenamed todistributedFanoutOutputs. Both changed from a UTxO map to an array ofTxOutvalues in JSON.StateChangedevents (Hydra.HeadLogic.Outcome):TransactionAppliedToLocalUTxO:newLocalUTxOfield removed.SnapshotRequested:newLocalUTxOfield removed.DecommitRecorded:newLocalUTxOfield removed.
-
Reduce on-disk event-store growth by removing redundant
newLocalUTxOfields from per-tx and per-snapshotStateChangedevents; aggregate recomputes the post-tx UTxO via pure arithmetic, no ledger needed. -
Significantly revised hydra-tui #2590:
- Pending-deposit recovery from both
OpenandClosed/Finalhead states (r). - Dark/light theme toggle (
F3) persisted to$XDG_CONFIG_HOME/hydra/tui-config.yaml. - Event-history filter — show all messages or errors only (
e). - Tab navigation (
1/2/3and ←/→) and event-detail toggle (d). - Refactored rendering into per-tab modules and a dedicated message renderer.
- Pending-deposit recovery from both
-
Fix a bug where replaying persisted events from a previous head could corrupt the state of a newly opened head.
-
Fix a bug where a recovered incremental-commit deposit could reappear in the L2 UTxO after sideloading a snapshot, making the same UTxO spendable on both L1 and L2 simultaneously #2629.
-
Add
mustNotMintOrBurnguard toIncrementandDecrementvalidator transitions, consistent with all other head transitions #2697. -
The node now dynamically determines the largest chunk of UTxOs it can distribute in a single partial fanout step, replacing a hardcoded limit.
findFittingFanoutTxuses binary search over all valid chunk sizes and tries the preferred transaction first, falling back to progressively smaller chunks until one fits within the script #2619
Build artifacts
- 📦 Binaries for Linux x86_64 and MacOS ARM64
- 🐋 Docker image
Hydra Scripts
-
preview:52c84ab10de4872478446059d997f91f0ec52e6a9432a97efc02b604e799ad6c,dd4b39205a1f529f5034cc64b1e518db44c9e824fa7b3656a2180bd6afb95f41 -
preprod:2c01bf787fff78ffe96fb0722e7a9549565ac25d11a76ffb07fd6e809ea00b03,395ecc511b7f05485165da08646ae3224ae0e3905a795bcee408a28eaf4696dd -
mainnet:17fb77e1f8ac87587033c884f55adca8646c570843bcb40b404037bb29d276b9,906ecc6e55503aa70450ee62c80c4194b98d43d156ea4b1a290ddca76dbfc4a3
See also networks.json
Compatible / tested with
cardano-node:11.0.1cardano-cli:11.0.0mithril:2617
What's Changed
- Use liburing only on Linux by @vrom911 in #2609
- Use Strict Map instead of Lazy one by @vrom911 in #2599
- Fix hoogle shell by @noonio in #2612
- Reduce disk usage in hydra-node by @v0d1ch in #2601
- Set utxoCostPerByte to zero as well; then we can do 1-lovelace NewTx's. by @noonio in #2613
- Partial fanout by @vrom911 in #2324
- bump rust-accumulator to fix musl issues by @noonio in #2622
- Switch to tasty for tests by @noonio in #2620
- Simple claude.md ;
just lintuses separate directory by @noonio in #2625 - Refactor of the hydra-tui by @noonio in #2590
- Disable nix store optimisation on CI to fix macOS dyld issue by @vrom911 in #2626
- Calculate utxo to fanout dynamically by @v0d1ch in #2617
- Resolve pumba-style test failure by more resilient etcd writes by @noonio in #2627
- Validate headId in aggregate to prevent cross-head event contamination by @v0d1ch in #2618
- Fix recovered deposit leaking into new L2 snapshot utxo by @vrom911 in #2630
- Update docs and changelog to reflect partial fanout implementation by @vrom911 in #2631
- Add unit tests for Accumulator UTxO membership proofs by @vrom911 in #2632
- Add partialFanout and finalPartialFanout into the tx-cost-diff report by @vrom911 in #2633
- Fix publish-docs by copying build/ output into nix derivation result by @vrom911 in #2634
- Fix flakey tui tests by @noonio in #2708
- Some simple tui fixes by @noonio in #2710
- Deposit and recover transition tests, tidy up some other tests by @noonio in #2711
- Remove CollectCom/Abort by @noonio in #2709
- validator fixes by @noonio in #2712
- A handful of simple fixes by @noonio in #2715
- Add mustNotMintOrBurn to checkIncrement and checkDecrement by @vrom911 in #2718
- Bit more benchmarking information on PRs by @noonio in #2635
- Unify membership checks by @v0d1ch in #2619
- Add etcd to exes shell so smoke tests can run system etcd by @vrom911 in #2722
Full Changelog: 2.1.0...2.2.0