diff --git a/hydra-node/src/Hydra/HeadLogic.hs b/hydra-node/src/Hydra/HeadLogic.hs index a0e661a8a67..4d9ba0f8f7e 100644 --- a/hydra-node/src/Hydra/HeadLogic.hs +++ b/hydra-node/src/Hydra/HeadLogic.hs @@ -970,7 +970,16 @@ onCurrentChainRollback :: ChainSlot -> Outcome tx onCurrentChainRollback currentState slot = - NewState (rollback slot currentState) [ClientEffect RolledBack] + let atTheTimeState = rollback slot currentState + in case atTheTimeState of + Idle IdleState{chainState} -> + NewState (updateChainState chainState currentState) [] + Initial InitialState{chainState} -> + NewState (updateChainState chainState currentState) [] + Open OpenState{chainState} -> + NewState (updateChainState chainState currentState) [] + Closed ClosedState{chainState} -> + NewState (updateChainState chainState currentState) [] where -- TODO use slot instead of local rollbackSlot argument rollback rollbackSlot hs @@ -984,6 +993,14 @@ onCurrentChainRollback currentState slot = rollback rollbackSlot previousRecoverableState Closed ClosedState{previousRecoverableState} -> rollback rollbackSlot previousRecoverableState + updateChainState chainState = \case + Idle s@IdleState{} -> Idle s{chainState} + Initial s@InitialState{} -> + Initial s{chainState} + Open s@OpenState{} -> + Open s{chainState} + Closed s@ClosedState{} -> + Closed s{chainState} -- | The "pure core" of the Hydra node, which handles the 'Event' against a -- current 'HeadState'. Resulting new 'HeadState's are retained and 'Effect' diff --git a/hydra-node/test/Hydra/BehaviorSpec.hs b/hydra-node/test/Hydra/BehaviorSpec.hs index 22d08360936..77a42d56b1c 100644 --- a/hydra-node/test/Hydra/BehaviorSpec.hs +++ b/hydra-node/test/Hydra/BehaviorSpec.hs @@ -455,7 +455,7 @@ spec = parallel $ do roundtripAndGoldenSpecs (Proxy @(HydraNodeLog SimpleTx)) - describe "rolling back & forward" $ do + describe "rolling back & forward does not make the node crash" $ do it "does work for rollbacks past init" $ shouldRunInSim $ do withSimulatedChainAndNetwork $ \chain -> @@ -464,8 +464,9 @@ spec = parallel $ do waitUntil [n1] $ HeadIsInitializing testHeadId (fromList [alice]) -- We expect the Init to be rolled back and forward again rollbackAndForward chain 1 - waitUntil [n1] RolledBack - waitUntil [n1] $ HeadIsInitializing testHeadId (fromList [alice]) + -- We expect the node to still work and let us commit + send n1 (Commit (utxoRef 1)) + waitUntil [n1] $ Committed testHeadId alice (utxoRef 1) it "does work for rollbacks past open" $ shouldRunInSim $ do @@ -479,9 +480,9 @@ spec = parallel $ do -- We expect one Commit AND the CollectCom to be rolled back and -- forward again rollbackAndForward chain 2 - waitUntil [n1] RolledBack - waitUntil [n1] $ Committed testHeadId alice (utxoRef 1) - waitUntil [n1] $ HeadIsOpen{headId = testHeadId, utxo = utxoRefs [1]} + -- We expect the node to still work and let us post L2 transactions + send n1 (NewTx (aValidTx 42)) + waitUntil [n1] $ TxValid testHeadId (aValidTx 42) -- | Wait for some output at some node(s) to be produced /eventually/. See -- 'waitUntilMatch' for how long it waits. @@ -543,7 +544,8 @@ data TestHydraNode tx m = TestHydraNode data ConnectToChain tx m = ConnectToChain { chainComponent :: HydraNode tx m -> m (HydraNode tx m) , tickThread :: Async m () - , rollbackAndForward :: Natural -> m () + , -- TODO remove the following if we really don't use it anymore + rollbackAndForward :: Natural -> m () } -- | With-pattern wrapper around 'simulatedChainAndNetwork' which does 'cancel' diff --git a/hydra-node/test/Hydra/HeadLogicSpec.hs b/hydra-node/test/Hydra/HeadLogicSpec.hs index 7e0cb6c3f03..b852c27fb91 100644 --- a/hydra-node/test/Hydra/HeadLogicSpec.hs +++ b/hydra-node/test/Hydra/HeadLogicSpec.hs @@ -48,8 +48,6 @@ import Hydra.Party (Party (..)) import Hydra.Snapshot (ConfirmedSnapshot (..), Snapshot (..), getSnapshot) import Test.Aeson.GenericSpecs (roundtripAndGoldenSpecs) import Test.Hydra.Fixture (alice, aliceSk, bob, bobSk, carol, carolSk, cperiod) -import Test.QuickCheck (forAll) -import Test.QuickCheck.Monadic (monadicIO, run) spec :: Spec spec = do @@ -286,12 +284,6 @@ spec = do s2 = update bobEnv ledger s1 stepTimePastDeadline s2 `hasEffect` ClientEffect (ReadyToFanout testHeadId) - it "notify user on rollback" $ - forAll arbitrary $ \s -> monadicIO $ do - let rollback = OnChainEvent (Rollback $ ChainSlot 2) - let s' = update bobEnv ledger s rollback - void $ run $ s' `hasEffect` ClientEffect RolledBack - it "contests when detecting close with old snapshot" $ do let snapshot = Snapshot 2 mempty [] latestConfirmedSnapshot = ConfirmedSnapshot snapshot (aggregate []) diff --git a/hydra-node/test/Hydra/Model.hs b/hydra-node/test/Hydra/Model.hs index 81712a94ef7..1c3463f42fc 100644 --- a/hydra-node/test/Hydra/Model.hs +++ b/hydra-node/test/Hydra/Model.hs @@ -192,11 +192,7 @@ instance StateModel WorldState where , (1, genAbort) ] Open{} -> do - -- FIXME: Generation of arbitrary NewTx disabled as we don't control - -- rollbacks in the MockChain and the hydra-node purges L2 state when - -- rolling back "past open". - void genNewTx - pure $ error "NewTx disabled because of rollbacks past open" + genNewTx _ -> fmap Some genSeed where genCommit pending = do