Home / Input Output / hydra-poc
Apr 06, 2-3 PM (1)
Apr 06, 3-4 PM (0)
Apr 06, 4-5 PM (0)
Apr 06, 5-6 PM (0)
Apr 06, 6-7 PM (0)
Apr 06, 7-8 PM (0)
Apr 06, 8-9 PM (0)
Apr 06, 9-10 PM (0)
Apr 06, 10-11 PM (0)
Apr 06, 11-12 AM (0)
Apr 07, 12-1 AM (0)
Apr 07, 1-2 AM (0)
Apr 07, 2-3 AM (0)
Apr 07, 3-4 AM (0)
Apr 07, 4-5 AM (0)
Apr 07, 5-6 AM (0)
Apr 07, 6-7 AM (0)
Apr 07, 7-8 AM (1)
Apr 07, 8-9 AM (1)
Apr 07, 9-10 AM (0)
Apr 07, 10-11 AM (0)
Apr 07, 11-12 PM (0)
Apr 07, 12-1 PM (0)
Apr 07, 1-2 PM (0)
Apr 07, 2-3 PM (1)
Apr 07, 3-4 PM (0)
Apr 07, 4-5 PM (0)
Apr 07, 5-6 PM (0)
Apr 07, 6-7 PM (0)
Apr 07, 7-8 PM (0)
Apr 07, 8-9 PM (0)
Apr 07, 9-10 PM (0)
Apr 07, 10-11 PM (0)
Apr 07, 11-12 AM (0)
Apr 08, 12-1 AM (0)
Apr 08, 1-2 AM (0)
Apr 08, 2-3 AM (0)
Apr 08, 3-4 AM (0)
Apr 08, 4-5 AM (0)
Apr 08, 5-6 AM (0)
Apr 08, 6-7 AM (0)
Apr 08, 7-8 AM (0)
Apr 08, 8-9 AM (2)
Apr 08, 9-10 AM (0)
Apr 08, 10-11 AM (1)
Apr 08, 11-12 PM (0)
Apr 08, 12-1 PM (3)
Apr 08, 1-2 PM (0)
Apr 08, 2-3 PM (0)
Apr 08, 3-4 PM (0)
Apr 08, 4-5 PM (0)
Apr 08, 5-6 PM (0)
Apr 08, 6-7 PM (0)
Apr 08, 7-8 PM (0)
Apr 08, 8-9 PM (0)
Apr 08, 9-10 PM (0)
Apr 08, 10-11 PM (0)
Apr 08, 11-12 AM (0)
Apr 09, 12-1 AM (0)
Apr 09, 1-2 AM (0)
Apr 09, 2-3 AM (0)
Apr 09, 3-4 AM (0)
Apr 09, 4-5 AM (0)
Apr 09, 5-6 AM (0)
Apr 09, 6-7 AM (0)
Apr 09, 7-8 AM (2)
Apr 09, 8-9 AM (1)
Apr 09, 9-10 AM (0)
Apr 09, 10-11 AM (1)
Apr 09, 11-12 PM (1)
Apr 09, 12-1 PM (0)
Apr 09, 1-2 PM (0)
Apr 09, 2-3 PM (5)
Apr 09, 3-4 PM (1)
Apr 09, 4-5 PM (0)
Apr 09, 5-6 PM (0)
Apr 09, 6-7 PM (0)
Apr 09, 7-8 PM (0)
Apr 09, 8-9 PM (0)
Apr 09, 9-10 PM (0)
Apr 09, 10-11 PM (0)
Apr 09, 11-12 AM (0)
Apr 10, 12-1 AM (0)
Apr 10, 1-2 AM (0)
Apr 10, 2-3 AM (0)
Apr 10, 3-4 AM (0)
Apr 10, 4-5 AM (0)
Apr 10, 5-6 AM (0)
Apr 10, 6-7 AM (0)
Apr 10, 7-8 AM (0)
Apr 10, 8-9 AM (0)
Apr 10, 9-10 AM (0)
Apr 10, 10-11 AM (0)
Apr 10, 11-12 PM (0)
Apr 10, 12-1 PM (0)
Apr 10, 1-2 PM (0)
Apr 10, 2-3 PM (0)
Apr 10, 3-4 PM (0)
Apr 10, 4-5 PM (0)
Apr 10, 5-6 PM (1)
Apr 10, 6-7 PM (0)
Apr 10, 7-8 PM (0)
Apr 10, 8-9 PM (0)
Apr 10, 9-10 PM (0)
Apr 10, 10-11 PM (0)
Apr 10, 11-12 AM (0)
Apr 11, 12-1 AM (0)
Apr 11, 1-2 AM (0)
Apr 11, 2-3 AM (0)
Apr 11, 3-4 AM (0)
Apr 11, 4-5 AM (0)
Apr 11, 5-6 AM (0)
Apr 11, 6-7 AM (0)
Apr 11, 7-8 AM (0)
Apr 11, 8-9 AM (0)
Apr 11, 9-10 AM (0)
Apr 11, 10-11 AM (0)
Apr 11, 11-12 PM (0)
Apr 11, 12-1 PM (0)
Apr 11, 1-2 PM (0)
Apr 11, 2-3 PM (0)
Apr 11, 3-4 PM (0)
Apr 11, 4-5 PM (0)
Apr 11, 5-6 PM (0)
Apr 11, 6-7 PM (0)
Apr 11, 7-8 PM (0)
Apr 11, 8-9 PM (0)
Apr 11, 9-10 PM (0)
Apr 11, 10-11 PM (0)
Apr 11, 11-12 AM (0)
Apr 12, 12-1 AM (0)
Apr 12, 1-2 AM (0)
Apr 12, 2-3 AM (0)
Apr 12, 3-4 AM (0)
Apr 12, 4-5 AM (0)
Apr 12, 5-6 AM (0)
Apr 12, 6-7 AM (0)
Apr 12, 7-8 AM (0)
Apr 12, 8-9 AM (0)
Apr 12, 9-10 AM (0)
Apr 12, 10-11 AM (0)
Apr 12, 11-12 PM (0)
Apr 12, 12-1 PM (0)
Apr 12, 1-2 PM (0)
Apr 12, 2-3 PM (0)
Apr 12, 3-4 PM (0)
Apr 12, 4-5 PM (0)
Apr 12, 5-6 PM (0)
Apr 12, 6-7 PM (0)
Apr 12, 7-8 PM (0)
Apr 12, 8-9 PM (0)
Apr 12, 9-10 PM (0)
Apr 12, 10-11 PM (0)
Apr 12, 11-12 AM (0)
Apr 13, 12-1 AM (0)
Apr 13, 1-2 AM (0)
Apr 13, 2-3 AM (0)
Apr 13, 3-4 AM (0)
Apr 13, 4-5 AM (0)
Apr 13, 5-6 AM (0)
Apr 13, 6-7 AM (0)
Apr 13, 7-8 AM (0)
Apr 13, 8-9 AM (0)
Apr 13, 9-10 AM (0)
Apr 13, 10-11 AM (0)
Apr 13, 11-12 PM (0)
Apr 13, 12-1 PM (0)
Apr 13, 1-2 PM (0)
Apr 13, 2-3 PM (0)
22 commits this week Apr 06, 2026 - Apr 13, 2026
Cache signible bytes (#2571)
fix #2570 


  Summary

During snapshot signing rounds, each incoming AckSn triggers
verifyMultiSignature which internally calls getSignableRepresentation on
the Snapshot to get the bytes to verify against. This serializes and
hashes the entire UTxO set. In a cluster of N parties, the same
expensive computation was repeated N times per snapshot.

This PR caches the result as signableBytes :: ByteString inside the
SeenSnapshot constructor, computed once when the snapshot is first seen
and reused for all subsequent AckSn verifications.

  Changes

- SeenSnapshot gains a signableBytes field with manual ToJSON/FromJSON
instances that exclude it from serialization — it is recomputed from
snapshot on deserialization, so persistence and state recovery are
unaffected
- verifyMultiSignatureBytes added to Crypto — like verifyMultiSignature
but takes pre-computed bytes; verifyMultiSignature now delegates to it,
eliminating code duplication
- mkSeenSnapshot smart constructor added to enforce the invariant that
signableBytes always equals getSignableRepresentation snapshot — direct
record construction is replaced at all call sites

  Benchmark Results (3-node cluster with growing UTxO set)

```

| Metric                | master   | fix (cache-signible-bytes) | Delta          |
| --------------------- | -------- | -------------------------- | -------------- |
| Avg confirmation (ms) | 465.8    | **430.2**                  | **-7.6%**      |
| P50                   | 406.7ms  | **384.3ms**                | **-5.5%**      |
| P95                   | 919.8ms  | **864.0ms**                | **-6.1%**      |
| P99                   | 1301.1ms | 1475.4ms                   | +13.4% (noise) |
| Invalid txs           | 0        | 0                          | —              |
| Fanout outputs        | 1503     | 1503                       | —              |
```
---

<!-- Consider each and tick it off one way or the other -->
* [x] CHANGELOG updated or not needed
* [x] Documentation updated or not needed
* [x] Haddocks updated or not needed
* [x] No new TODOs introduced or explained herafter
Enforce signableBytes invariant via smart constructor
  Add `mkSeenSnapshot` as the single correct way to construct the
  `SeenSnapshot` variant, ensuring `signableBytes` is always derived
  from `snapshot`. Direct record construction could silently produce a
  stale bytes/snapshot mismatch, causing incorrect signature verification.

  Also remove code duplication in `verifyMultiSignatureBytes` by having
  `verifyMultiSignature` delegate to it after computing the bytes.

Signed-off-by: Sasha Bogicevic <[email protected]>
Simplify CardanoClient API to use LocalNodeConnectInfo directly
  Remove the CardanoNodeT/EraT monad transformer stack from CardanoClient
  in favour of plain functions that take LocalNodeConnectInfo as an explicit
  argument. All query and submission functions now have the form
  `LocalNodeConnectInfo -> ... -> IO a`, eliminating the need for
  runCardanoNode at call sites. Update all callers across hydra-node,
  hydra-cluster, hydra-tui, and hydra-chain-observer accordingly.

Signed-off-by: Sasha Bogicevic <[email protected]>
Slim down persisted StateChanged events (#2539)
  Remove redundant fields from three StateChanged constructors:

  - SnapshotRequested: drop requestedTxIds (derivable from map txId snapshot.confirmed)
  - SnapshotConfirmed: change snapshot to Maybe (Nothing on normal AckSn path where the snapshot is already tracked in seenSnapshot; Just only on side-load path)
  - DecommitRecorded: drop utxoToDecommit (derivable from utxoFromTx decommitTx)
  - PartySignedSnapshot: replace snapshot :: Snapshot tx with snapshotNumber :: SnapshotNumber

  The API server reconstructs SnapshotConfirmed outputs by threading the seenSnapshot through a stateful mapAccum conduit for history replay and reading nodeStateP before updating for live events.

Signed-off-by: Sasha Bogicevic <[email protected]>
Replace file-based persistence with SQLite event store
  Events are now persisted in a SQLite database (hydra.db) instead of a
  plain append-only JSON file (state). On first startup after upgrade,
  existing state files are automatically migrated into the database and
  renamed to state.migrated.

  Key changes:
  - Add Hydra.Events.SQLiteBased with mkSQLiteEventStore and
    migrateFromFileBased
  - WAL mode, synchronous=NORMAL, 64MB page cache for fast reads/writes
  - rotate uses a single transaction (atomic delete + checkpoint insert)
  - Migration batches all inserts in one transaction
  - Update Run.hs to wire up the SQLite store
  - Update docs to reflect SQLite backend and hydra.db filename
  - Add Hydra.Events.SQLiteBasedSpec mirroring FileBasedSpec
Simplify CardanoClient API to use LocalNodeConnectInfo directly
  Remove the CardanoNodeT/EraT monad transformer stack from CardanoClient
  in favour of plain functions that take LocalNodeConnectInfo as an explicit
  argument. All query and submission functions now have the form
  `LocalNodeConnectInfo -> ... -> IO a`, eliminating the need for
  runCardanoNode at call sites. Update all callers across hydra-node,
  hydra-cluster, hydra-tui, and hydra-chain-observer accordingly.

Signed-off-by: Sasha Bogicevic <[email protected]>
Refactor ChainBackend into a monad-style type class
  Replace the data-passing ChainBackend class (where each method received
  an explicit backend value) with a monad-style class `ChainBackend m`
  where `m` is the computation monad. Each backend is now a newtype over
  ReaderT: DirectBackend wraps ReaderT DirectOptions IO and BlockfrostBackend
  wraps ReaderT BlockfrostOptions IO. Callers use runDirectBackend /
  runBlockfrostBackend runners to execute backend actions in IO.

Signed-off-by: Sasha Bogicevic <[email protected]>
Refactor ChainBackend into a monad-style type class
  Replace the data-passing ChainBackend class (where each method received
  an explicit backend value) with a monad-style class `ChainBackend m`
  where `m` is the computation monad. Each backend is now a newtype over
  ReaderT: DirectBackend wraps ReaderT DirectOptions IO and BlockfrostBackend
  wraps ReaderT BlockfrostOptions IO. Callers use runDirectBackend /
  runBlockfrostBackend runners to execute backend actions in IO.

Signed-off-by: Sasha Bogicevic <[email protected]>