Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/actions/nix-cachix-setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
5 changes: 3 additions & 2 deletions hydra-node/src/Hydra/API/HTTPServer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -581,8 +581,9 @@ handleSubmitL2Tx putClientInput apiTransactionTimeout responseChannel body = do
go = do
event <- atomically $ readTChan dupChannel
case event of
Right (RejectedInput{clientInput = NewTx{}, reason}) -> do
pure $ SubmitTxRejectedResponse reason
Right (RejectedInput{clientInput = NewTx{transaction}, reason})
| txId transaction == txid ->
pure $ SubmitTxRejectedResponse reason
Left (TimedServerOutput{output}) -> case output of
TxValid{transactionId}
| transactionId == txid ->
Expand Down
49 changes: 49 additions & 0 deletions hydra-node/test/Hydra/API/HTTPServerSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,55 @@ apiServerSpec = do
$ do
post "/transaction" (mkReq testTx) `shouldRespondWith` 503

prop "ignores RejectedInput for different transaction" $ do
-- This test verifies the fix for the race condition where a RejectedInput
-- for one transaction was incorrectly matched by the handler waiting for
-- a different transaction.
responseChannel <- newTChanIO
let txA = SimpleTx 42 mempty mempty
txB = SimpleTx 99 mempty mempty
-- RejectedInput for txB (different from txA we're submitting)
rejectedB = RejectedInput{clientInput = NewTx txB, reason = "chain out of sync"}
-- SnapshotConfirmed includes txA
snapshot =
Snapshot
{ headId = testHeadId
, version = 1
, number = 7
, confirmed = [txA]
, utxo = mempty
, utxoToCommit = mempty
, utxoToDecommit = mempty
}
confirmedEvent =
TimedServerOutput
{ output = SnapshotConfirmed{snapshot = snapshot, signatures = mempty, headId = testHeadId}
, seq = 0
, time = now
}
withApplication
( httpApp @SimpleTx
nullTracer
dummyChainHandle
testEnvironment
dummyStatePath
defaultPParams
(pure inUnsyncedIdleState)
(pure CannotCommit)
(pure [])
-- First write RejectedInput for txB, then SnapshotConfirmed for txA
( const $ atomically $ do
writeTChan responseChannel (Right rejectedB)
writeTChan responseChannel (Left confirmedEvent)
)
10
responseChannel
)
$ do
-- Handler for txA should ignore the RejectedInput for txB
-- and correctly return 200 when txA is confirmed
post "/transaction" (mkReq txA) `shouldRespondWith` 200

describe "POST /decommit" $ do
it "returns 202 on timeout" $ do
responseChannel <- newTChanIO
Expand Down