From c34715441bfdbc69e3db4d6961be1e7d623e1980 Mon Sep 17 00:00:00 2001 From: Sasha Bogicevic Date: Wed, 14 Jan 2026 14:41:27 +0100 Subject: [PATCH 01/11] Use StrictData in hydra-node This reduces the memory usage significantly (1.7 GB vs. 137 MB for the stress-test I was running) Signed-off-by: Sasha Bogicevic --- hydra-node/hydra-node.cabal | 1 + 1 file changed, 1 insertion(+) diff --git a/hydra-node/hydra-node.cabal b/hydra-node/hydra-node.cabal index 90205b097b8..dfa40a10031 100644 --- a/hydra-node/hydra-node.cabal +++ b/hydra-node/hydra-node.cabal @@ -38,6 +38,7 @@ common project-config PatternSynonyms TypeFamilies ViewPatterns + StrictData ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates From b331582f25217847ff7d276f0e9399f278dea8de Mon Sep 17 00:00:00 2001 From: Jack Chan Date: Tue, 6 Jan 2026 08:07:23 +0800 Subject: [PATCH 02/11] ci: add disk cleanup step to prevent space exhaustion GitHub Actions runners have limited disk space (~14GB available). When building uncached Nix derivations (like our modified hydra-node), the build can exhaust disk space during compilation. This adds a cleanup step that removes unused tools before the build: - .NET SDK (~1.8GB) - Android SDK (~9GB) - GHC (~5GB) - CodeQL (~2.5GB) - Unused Docker images This frees up ~20GB of disk space, ensuring builds complete successfully. --- .github/actions/nix-cachix-setup/action.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/actions/nix-cachix-setup/action.yml b/.github/actions/nix-cachix-setup/action.yml index fcf19333bb5..6c24c24a284 100644 --- a/.github/actions/nix-cachix-setup/action.yml +++ b/.github/actions/nix-cachix-setup/action.yml @@ -9,6 +9,21 @@ runs: using: composite steps: + - name: ๐Ÿงน Free disk space + if: runner.os == 'Linux' + shell: bash + run: | + echo "Disk space before cleanup:" + df -h / + # Remove unnecessary tools to free up disk space + sudo rm -rf /usr/share/dotnet + sudo rm -rf /usr/local/lib/android + sudo rm -rf /opt/ghc + sudo rm -rf /opt/hostedtoolcache/CodeQL + sudo docker image prune --all --force || true + echo "Disk space after cleanup:" + df -h / + - name: โ„ Prepare nix uses: cachix/install-nix-action@v30 with: From 4f243fafb58bae95ecd0b835d27778654cb99a95 Mon Sep 17 00:00:00 2001 From: Jack Chan Date: Sat, 3 Jan 2026 19:21:30 +0800 Subject: [PATCH 03/11] ci: enable Docker builds for pull requests - Add pull_request trigger for PRs targeting master branch - Tag PR builds as pr- for easy identification - Use PR head SHA as version for traceability --- .github/workflows/docker.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index e0021638606..b716d2bcba0 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -13,6 +13,8 @@ on: push: branches: [ "master" ] tags: [ "*.*.*" ] + pull_request: + branches: [ "master" ] workflow_dispatch: inputs: ref_name: @@ -73,6 +75,12 @@ jobs: # And the version as the git commit. VERSION=${{github.sha}} + # For PRs, tag as pr- + if [[ "${{github.event_name}}" == "pull_request" ]]; then + IMAGE_LABEL=pr-${{github.event.pull_request.number}} + VERSION=${{github.event.pull_request.head.sha}} + fi + # Determine whether we are building a tag and if yes, set the label # name to be the tag name, and the version to be the tag. BUILDING_TAG=${{github.ref_type == 'tag'}} From 7c12876b2b9bb7148e0d74cd14c31f1dd1be8375 Mon Sep 17 00:00:00 2001 From: Jack Chan Date: Tue, 6 Jan 2026 17:59:37 +0800 Subject: [PATCH 04/11] ci: trigger CI and Docker builds for v1.2.0-base branch --- .github/workflows/ci-nix.yaml | 4 ++++ .github/workflows/docker.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-nix.yaml b/.github/workflows/ci-nix.yaml index 8477afbd02d..d3843fa4815 100644 --- a/.github/workflows/ci-nix.yaml +++ b/.github/workflows/ci-nix.yaml @@ -11,7 +11,11 @@ on: branches: - master - release + - v1.2.0-base pull_request: + branches: + - master + - v1.2.0-base schedule: # Everyday at 4:00 AM - cron: "0 4 * * *" diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index b716d2bcba0..f9262c0609f 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -11,10 +11,10 @@ concurrency: on: push: - branches: [ "master" ] + branches: [ "master", "v1.2.0-base" ] tags: [ "*.*.*" ] pull_request: - branches: [ "master" ] + branches: [ "master", "v1.2.0-base" ] workflow_dispatch: inputs: ref_name: From 67cdf89367bf36a435162cc1153677262c617d65 Mon Sep 17 00:00:00 2001 From: Jack Chan Date: Thu, 15 Jan 2026 10:43:54 +0800 Subject: [PATCH 05/11] fix: treefmt --- hydra-node/hydra-node.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hydra-node/hydra-node.cabal b/hydra-node/hydra-node.cabal index dfa40a10031..2ff54fa1451 100644 --- a/hydra-node/hydra-node.cabal +++ b/hydra-node/hydra-node.cabal @@ -36,9 +36,9 @@ common project-config OverloadedStrings PartialTypeSignatures PatternSynonyms + StrictData TypeFamilies ViewPatterns - StrictData ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates From 1f5003eca2fad9fb4609b4ab2e481d5bd9dc85a0 Mon Sep 17 00:00:00 2001 From: twwu123 Date: Fri, 16 Jan 2026 21:53:53 +0800 Subject: [PATCH 06/11] increase mainnet limit --- hydra-node/src/Hydra/Chain.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hydra-node/src/Hydra/Chain.hs b/hydra-node/src/Hydra/Chain.hs index 21f63c9e792..7b79cffc7f5 100644 --- a/hydra-node/src/Hydra/Chain.hs +++ b/hydra-node/src/Hydra/Chain.hs @@ -47,7 +47,7 @@ import Test.QuickCheck.Instances.Time () -- | Hardcoded limit for commit tx on mainnet maxMainnetLovelace :: Coin -maxMainnetLovelace = Coin 100_000_000 +maxMainnetLovelace = Coin 1_000_000_000 -- | Hardcoded limit for maximum number of parties in a head protocol The value -- is obtained from calculating the costs of running the scripts and on-chan From 3b3b7b961552ed81582afa4d4929dae53522cec4 Mon Sep 17 00:00:00 2001 From: hinsonsidan Date: Wed, 21 Jan 2026 14:17:34 +0800 Subject: [PATCH 07/11] fix: icid tx version race condition --- hydra-node/src/Hydra/HeadLogic.hs | 40 ++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/hydra-node/src/Hydra/HeadLogic.hs b/hydra-node/src/Hydra/HeadLogic.hs index ab4c088c702..809035bf68f 100644 --- a/hydra-node/src/Hydra/HeadLogic.hs +++ b/hydra-node/src/Hydra/HeadLogic.hs @@ -462,7 +462,7 @@ onOpenNetworkReqSn env ledger pendingDeposits currentSlot st otherParty sv sn re } where requireReqSn continue - | sv /= version = + | sv /= version && not allowStaleVersion = Error $ RequireFailed $ ReqSvNumberInvalid{requestedSv = sv, lastSeenSv = version} | sn /= seenSn + 1 = Error $ RequireFailed $ ReqSnNumberInvalid{requestedSn = sn, lastSeenSn = seenSn} @@ -470,6 +470,12 @@ onOpenNetworkReqSn env ledger pendingDeposits currentSlot st otherParty sv sn re Error $ RequireFailed $ ReqSnNotLeader{requestedSn = sn, leader = otherParty} | otherwise = continue + where + -- Allow version-1 only if ReqSn has no IC/ID content (safe stale request) + allowStaleVersion = + sv == version - 1 + && isNothing mDecommitTx + && isNothing mDepositTxId waitNoSnapshotInFlight continue | confSn == seenSn = @@ -690,11 +696,30 @@ onOpenNetworkAckSn Environment{party} pendingDeposits openState otherParty snaps maybeRequestNextSnapshot previous outcome = do let nextSn = previous.number + 1 - if isLeader parameters party nextSn && not (null localTxs) + -- Clear if just processed (prevents stale reference after IC/ID) + nextDepositTxId = + if isJust (utxoToCommit previous) + then Nothing + else currentDepositTxId + nextDecommitTx = + if isJust (utxoToDecommit previous) + then Nothing + else decommitTx + -- Pick active deposit if available + depositToInclude = + if isNothing nextDepositTxId && isNothing nextDecommitTx + then getNextActiveDeposit pendingDeposits + else nextDepositTxId + -- Trigger on ANY pending work (fixes P1, P2) + hasPendingWork = + not (null localTxs) + || isJust nextDecommitTx + || isJust depositToInclude + if isLeader parameters party nextSn && hasPendingWork then outcome <> newState SnapshotRequestDecided{snapshotNumber = nextSn} - <> cause (NetworkEffect $ ReqSn version nextSn (txId <$> localTxs) decommitTx currentDepositTxId) + <> cause (NetworkEffect $ ReqSn version nextSn (txId <$> localTxs) nextDecommitTx depositToInclude) else outcome maybePostIncrementTx snapshot@Snapshot{utxoToCommit} signatures outcome = @@ -1080,6 +1105,15 @@ isLeader HeadParameters{parties} p sn = Just i -> ((fromIntegral sn - 1) `mod` length parties) == i _ -> False +-- | Get the next active deposit to include in a snapshot request. +-- Deposits are selected in arrival order (FIFO) based on creation time. +getNextActiveDeposit :: (Eq (UTxOType tx), Monoid (UTxOType tx), Ord (TxIdType tx)) => PendingDeposits tx -> Maybe (TxIdType tx) +getNextActiveDeposit deposits = + let isActive (_, Deposit{deposited, status}) = deposited /= mempty && status == Active + in case filter isActive (Map.toList deposits) of + [] -> Nothing + xs -> Just $ fst $ minimumBy (comparing (created . snd)) xs + -- ** Closing the Head -- | Client request to close the head. This leads to a close transaction on From ee9db03acc0db2d93bda3d1f3523430021c1e376 Mon Sep 17 00:00:00 2001 From: awcjack Date: Wed, 21 Jan 2026 06:22:09 +0000 Subject: [PATCH 08/11] trigger ci --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 4938dadd46f..4d33dc3fe7e 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,6 @@ Please follow our [Contributing Guidelines](./CONTRIBUTING.md) and [Code of Cond ## ๐Ÿ™ Credits - Logo created by Alexander Wende - ---

From 0638425f4691a516135ae4f807d4bd200a49d65c Mon Sep 17 00:00:00 2001 From: hinsonsidan Date: Wed, 21 Jan 2026 14:28:33 +0800 Subject: [PATCH 09/11] fix: stale oversight --- hydra-node/src/Hydra/HeadLogic.hs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/hydra-node/src/Hydra/HeadLogic.hs b/hydra-node/src/Hydra/HeadLogic.hs index 809035bf68f..9ee56feb023 100644 --- a/hydra-node/src/Hydra/HeadLogic.hs +++ b/hydra-node/src/Hydra/HeadLogic.hs @@ -461,6 +461,14 @@ onOpenNetworkReqSn env ledger pendingDeposits currentSlot st otherParty sv sn re , newCurrentDepositTxId = mDepositTxId } where + -- Allow version-1 only if ReqSn has no IC/ID content (safe stale request) + -- This handles the race condition where ReqSn is sent before L1 tx confirms + -- but processed after the version bump. + allowStaleVersion = + sv == version - 1 + && isNothing mDecommitTx + && isNothing mDepositTxId + requireReqSn continue | sv /= version && not allowStaleVersion = Error $ RequireFailed $ ReqSvNumberInvalid{requestedSv = sv, lastSeenSv = version} @@ -470,12 +478,6 @@ onOpenNetworkReqSn env ledger pendingDeposits currentSlot st otherParty sv sn re Error $ RequireFailed $ ReqSnNotLeader{requestedSn = sn, leader = otherParty} | otherwise = continue - where - -- Allow version-1 only if ReqSn has no IC/ID content (safe stale request) - allowStaleVersion = - sv == version - 1 - && isNothing mDecommitTx - && isNothing mDepositTxId waitNoSnapshotInFlight continue | confSn == seenSn = @@ -486,6 +488,8 @@ onOpenNetworkReqSn env ledger pendingDeposits currentSlot st otherParty sv sn re waitOnSnapshotVersion continue | version == sv = continue + | allowStaleVersion = + continue | otherwise = wait $ WaitOnSnapshotVersion sv From b89b8e648b721a0634e28a1d2eef7c8da428c3fa Mon Sep 17 00:00:00 2001 From: hinsonsidan Date: Wed, 21 Jan 2026 14:30:59 +0800 Subject: [PATCH 10/11] fix: compile error --- hydra-node/src/Hydra/HeadLogic.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hydra-node/src/Hydra/HeadLogic.hs b/hydra-node/src/Hydra/HeadLogic.hs index 9ee56feb023..402b30c1419 100644 --- a/hydra-node/src/Hydra/HeadLogic.hs +++ b/hydra-node/src/Hydra/HeadLogic.hs @@ -702,11 +702,11 @@ onOpenNetworkAckSn Environment{party} pendingDeposits openState otherParty snaps let nextSn = previous.number + 1 -- Clear if just processed (prevents stale reference after IC/ID) nextDepositTxId = - if isJust (utxoToCommit previous) + if isJust previous.utxoToCommit then Nothing else currentDepositTxId nextDecommitTx = - if isJust (utxoToDecommit previous) + if isJust previous.utxoToDecommit then Nothing else decommitTx -- Pick active deposit if available @@ -1116,7 +1116,7 @@ getNextActiveDeposit deposits = let isActive (_, Deposit{deposited, status}) = deposited /= mempty && status == Active in case filter isActive (Map.toList deposits) of [] -> Nothing - xs -> Just $ fst $ minimumBy (comparing (created . snd)) xs + xs -> Just $ fst $ minimumBy (comparing ((.created) . snd)) xs -- ** Closing the Head From 75e78aefbe9923a7eea287c2b4f2635a123d6f79 Mon Sep 17 00:00:00 2001 From: hinsonsidan Date: Wed, 21 Jan 2026 14:33:30 +0800 Subject: [PATCH 11/11] fix: ci --- hydra-node/src/Hydra/HeadLogic.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hydra-node/src/Hydra/HeadLogic.hs b/hydra-node/src/Hydra/HeadLogic.hs index 402b30c1419..b879d438501 100644 --- a/hydra-node/src/Hydra/HeadLogic.hs +++ b/hydra-node/src/Hydra/HeadLogic.hs @@ -698,15 +698,15 @@ onOpenNetworkAckSn Environment{party} pendingDeposits openState otherParty snaps RequireFailed $ InvalidMultisignature{multisig = show multisig, vkeys} - maybeRequestNextSnapshot previous outcome = do + maybeRequestNextSnapshot (previous :: Snapshot tx) outcome = do let nextSn = previous.number + 1 -- Clear if just processed (prevents stale reference after IC/ID) nextDepositTxId = - if isJust previous.utxoToCommit + if isJust (previous.utxoToCommit :: Maybe (UTxOType tx)) then Nothing else currentDepositTxId nextDecommitTx = - if isJust previous.utxoToDecommit + if isJust (previous.utxoToDecommit :: Maybe (UTxOType tx)) then Nothing else decommitTx -- Pick active deposit if available @@ -1116,7 +1116,7 @@ getNextActiveDeposit deposits = let isActive (_, Deposit{deposited, status}) = deposited /= mempty && status == Active in case filter isActive (Map.toList deposits) of [] -> Nothing - xs -> Just $ fst $ minimumBy (comparing ((.created) . snd)) xs + xs -> Just $ fst $ minimumBy (comparing (\(_, Deposit{created}) -> created)) xs -- ** Closing the Head