Skip to content

Commit 1a31407

Browse files
committed
move current slot to node-level
> this allows handling client recover in all head states
1 parent 4dd889b commit 1a31407

File tree

13 files changed

+4896
-3847
lines changed

13 files changed

+4896
-3847
lines changed

hydra-cluster/test/Test/EndToEndSpec.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ spec = around (showLogsOnFailure "EndToEndSpec") $ do
307307
withBackend (contramap FromCardanoNode tracer) tmpDir $ \blockTime backend -> do
308308
publishHydraScriptsAs backend Faucet
309309
>>= rejectCommit tracer tmpDir blockTime backend
310-
it "can recover deposit" $ \tracer -> do
310+
fit "can recover deposit" $ \tracer -> do
311311
withClusterTempDir $ \tmpDir -> do
312312
withBackend (contramap FromCardanoNode tracer) tmpDir $ \_ backend -> do
313313
publishHydraScriptsAs backend Faucet

hydra-node/golden/ReasonablySized (HeadState (Tx ConwayEra)).json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2540,7 +2540,6 @@
25402540
},
25412541
"version": 6
25422542
},
2543-
"currentSlot": 3,
25442543
"headId": "07020001010706020408080606050806",
25452544
"headSeed": "02040200030102080101040806050005",
25462545
"parameters": {
@@ -3468,7 +3467,6 @@
34683467
},
34693468
"version": 4
34703469
},
3471-
"currentSlot": 1,
34723470
"headId": "08010805060703000503060200020400",
34733471
"headSeed": "06070108050501010706050403040108",
34743472
"parameters": {

hydra-node/golden/ReasonablySized (NodeState (Tx ConwayEra)).json

Lines changed: 4843 additions & 3798 deletions
Large diffs are not rendered by default.

hydra-node/json-schemas/api.yaml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3317,7 +3317,6 @@ components:
33173317
- coordinatedHeadState
33183318
- chainState
33193319
- headId
3320-
- currentSlot
33213320
- headSeed
33223321
properties:
33233322
parameters:
@@ -3328,8 +3327,6 @@ components:
33283327
$ref: "api.yaml#/components/schemas/ChainState"
33293328
headId:
33303329
$ref: "api.yaml#/components/schemas/HeadId"
3331-
currentSlot:
3332-
$ref: "api.yaml#/components/schemas/ChainSlot"
33333330
headSeed:
33343331
$ref: "api.yaml#/components/schemas/HeadSeed"
33353332

hydra-node/src/Hydra/API/Server.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import Hydra.API.ServerOutputFilter (
3030
import Hydra.API.WSServer (wsApp)
3131
import Hydra.Cardano.Api (LedgerEra)
3232
import Hydra.Chain (Chain (..))
33-
import Hydra.Chain.ChainState (IsChainState)
33+
import Hydra.Chain.ChainState (IsChainState, chainStateSlot)
3434
import Hydra.Chain.Direct.State ()
3535
import Hydra.Events (EventSink (..), EventSource (..))
3636
import Hydra.HeadLogic (
@@ -106,6 +106,7 @@ withAPIServer config env party eventSource tracer chain pparams serverOutputFilt
106106
( NodeState
107107
{ headState = Idle $ IdleState mkChainState
108108
, pendingDeposits = mempty
109+
, currentSlot = chainStateSlot mkChainState
109110
}
110111
)
111112
aggregateNodeState

hydra-node/src/Hydra/HeadLogic.hs

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -301,12 +301,13 @@ onOpenNetworkReqTx ::
301301
IsTx tx =>
302302
Environment ->
303303
Ledger tx ->
304+
ChainSlot ->
304305
OpenState tx ->
305306
TTL ->
306307
-- | The transaction to be submitted to the head.
307308
tx ->
308309
Outcome tx
309-
onOpenNetworkReqTx env ledger st ttl tx =
310+
onOpenNetworkReqTx env ledger currentSlot st ttl tx =
310311
-- Keep track of transactions by-id
311312
(newState TransactionReceived{tx} <>) $
312313
-- Spec: wait L̂ ◦ tx ≠ ⊥
@@ -363,7 +364,7 @@ onOpenNetworkReqTx env ledger st ttl tx =
363364

364365
Snapshot{number = confirmedSn} = getSnapshot confirmedSnapshot
365366

366-
OpenState{coordinatedHeadState, headId, currentSlot, parameters} = st
367+
OpenState{coordinatedHeadState, headId, parameters} = st
367368

368369
snapshotInFlight = case seenSnapshot of
369370
NoSeenSnapshot -> False
@@ -392,6 +393,7 @@ onOpenNetworkReqSn ::
392393
Environment ->
393394
Ledger tx ->
394395
PendingDeposits tx ->
396+
ChainSlot ->
395397
OpenState tx ->
396398
-- | Party which sent the ReqSn.
397399
Party ->
@@ -406,7 +408,7 @@ onOpenNetworkReqSn ::
406408
-- | Optional commit of additional funds into the head.
407409
Maybe (TxIdType tx) ->
408410
Outcome tx
409-
onOpenNetworkReqSn env ledger pendingDeposits st otherParty sv sn requestedTxIds mDecommitTx mDepositTxId =
411+
onOpenNetworkReqSn env ledger pendingDeposits currentSlot st otherParty sv sn requestedTxIds mDecommitTx mDepositTxId =
410412
-- Spec: require v = v̂ ∧ s = ŝ + 1 ∧ leader(s) = j
411413
requireReqSn $
412414
-- Spec: wait ŝ = ̅S.s
@@ -582,7 +584,7 @@ onOpenNetworkReqSn env ledger pendingDeposits st otherParty sv sn requestedTxIds
582584

583585
CoordinatedHeadState{confirmedSnapshot, seenSnapshot, allTxs, localTxs, version} = coordinatedHeadState
584586

585-
OpenState{parameters, coordinatedHeadState, currentSlot, headId} = st
587+
OpenState{parameters, coordinatedHeadState, headId} = st
586588

587589
Environment{signingKey} = env
588590

@@ -750,18 +752,17 @@ onOpenNetworkAckSn Environment{party} pendingDeposits openState otherParty snaps
750752
-- | Client request to recover deposited UTxO.
751753
--
752754
-- __Transition__: 'OpenState' → 'OpenState'
753-
onOpenClientRecover ::
755+
onClientRecover ::
754756
IsTx tx =>
755-
HeadId ->
756757
ChainSlot ->
757758
PendingDeposits tx ->
758759
TxIdType tx ->
759760
Outcome tx
760-
onOpenClientRecover headId currentSlot pendingDeposits recoverTxId =
761+
onClientRecover currentSlot pendingDeposits recoverTxId =
761762
case Map.lookup recoverTxId pendingDeposits of
762763
Nothing ->
763764
Error $ RequireFailed NoMatchingDeposit
764-
Just Deposit{deposited} ->
765+
Just Deposit{headId, deposited} ->
765766
causes
766767
[ OnChainEffect
767768
{ postChainTx =
@@ -842,10 +843,11 @@ onOpenNetworkReqDec ::
842843
Environment ->
843844
Ledger tx ->
844845
TTL ->
846+
ChainSlot ->
845847
OpenState tx ->
846848
tx ->
847849
Outcome tx
848-
onOpenNetworkReqDec env ledger ttl openState decommitTx =
850+
onOpenNetworkReqDec env ledger ttl currentSlot openState decommitTx =
849851
-- Spec: wait 𝑈𝛼 = ∅ ^ txω =⊥ ∧ L̂ ◦ tx ≠ ⊥
850852
waitOnApplicableDecommit $ \newLocalUTxO -> do
851853
-- Spec: L̂ ← L̂ ◦ tx \ outputs(tx)
@@ -921,7 +923,6 @@ onOpenNetworkReqDec env ledger ttl openState decommitTx =
921923
{ headId
922924
, parameters
923925
, coordinatedHeadState
924-
, currentSlot
925926
} = openState
926927

927928
-- | Process the chain (and time) advancing in an open head.
@@ -978,6 +979,8 @@ onOpenChainTick env pendingDeposits st chainTime =
978979

979980
plusTime = flip addUTCTime
980981

982+
-- REVIEW! check what if there are more than 1 new active deposit
983+
-- What is the sorting criteria to pick next?
981984
withNextActive :: forall tx. (Eq (UTxOType tx), Monoid (UTxOType tx)) => Map (TxIdType tx) (Deposit tx) -> (TxIdType tx -> Outcome tx) -> Outcome tx
982985
withNextActive deposits cont = do
983986
-- NOTE: Do not consider empty deposits.
@@ -1326,7 +1329,7 @@ update ::
13261329
-- | Input to be processed.
13271330
Input tx ->
13281331
Outcome tx
1329-
update env ledger NodeState{headState = st, pendingDeposits} ev = case (st, ev) of
1332+
update env ledger NodeState{headState = st, pendingDeposits, currentSlot} ev = case (st, ev) of
13301333
(_, NetworkInput _ (ConnectivityEvent conn)) ->
13311334
onConnectionEvent env.configuredPeers conn
13321335
(Idle _, ClientInput Init) ->
@@ -1350,9 +1353,9 @@ update env ledger NodeState{headState = st, pendingDeposits} ev = case (st, ev)
13501353
(Open{}, ClientInput (NewTx tx)) ->
13511354
onOpenClientNewTx tx
13521355
(Open openState, NetworkInput ttl (ReceivedMessage{msg = ReqTx tx})) ->
1353-
onOpenNetworkReqTx env ledger openState ttl tx
1356+
onOpenNetworkReqTx env ledger currentSlot openState ttl tx
13541357
(Open openState, NetworkInput _ (ReceivedMessage{sender, msg = ReqSn sv sn txIds decommitTx depositTxId})) ->
1355-
onOpenNetworkReqSn env ledger pendingDeposits openState sender sv sn txIds decommitTx depositTxId
1358+
onOpenNetworkReqSn env ledger pendingDeposits currentSlot openState sender sv sn txIds decommitTx depositTxId
13561359
(Open openState, NetworkInput _ (ReceivedMessage{sender, msg = AckSn snapshotSignature sn})) ->
13571360
onOpenNetworkAckSn env pendingDeposits openState sender snapshotSignature sn
13581361
( Open openState@OpenState{headId = ourHeadId}
@@ -1371,12 +1374,10 @@ update env ledger NodeState{headState = st, pendingDeposits} ev = case (st, ev)
13711374
-- another party likely opened the head before us and it's okay to ignore.
13721375
(Open{}, ChainInput PostTxError{postChainTx = CollectComTx{}}) ->
13731376
noop
1374-
(Open OpenState{headId, currentSlot}, ClientInput Recover{recoverTxId}) -> do
1375-
onOpenClientRecover headId currentSlot pendingDeposits recoverTxId
1376-
(Open OpenState{headId, coordinatedHeadState, currentSlot}, ClientInput Decommit{decommitTx}) -> do
1377+
(Open OpenState{headId, coordinatedHeadState}, ClientInput Decommit{decommitTx}) -> do
13771378
onOpenClientDecommit headId ledger currentSlot coordinatedHeadState decommitTx
13781379
(Open openState, NetworkInput ttl (ReceivedMessage{msg = ReqDec{transaction}})) ->
1379-
onOpenNetworkReqDec env ledger ttl openState transaction
1380+
onOpenNetworkReqDec env ledger ttl currentSlot openState transaction
13801381
(Open OpenState{headId = ourHeadId}, ChainInput Observation{observedTx = OnDepositTx{headId, depositTxId, deposited, created, deadline}, newChainState})
13811382
| ourHeadId == headId ->
13821383
newState DepositRecorded{chainState = newChainState, headId, depositTxId, deposited, created, deadline}
@@ -1421,6 +1422,9 @@ update env ledger NodeState{headState = st, pendingDeposits} ev = case (st, ev)
14211422
onClosedChainFanoutTx closedState newChainState fanoutUTxO
14221423
| otherwise ->
14231424
Error NotOurHead{ourHeadId, otherHeadId = headId}
1425+
-- Node-level
1426+
(_, ClientInput Recover{recoverTxId}) -> do
1427+
onClientRecover currentSlot pendingDeposits recoverTxId
14241428
-- General
14251429
(_, ChainInput Rollback{rolledBackChainState}) ->
14261430
newState ChainRolledBack{chainState = rolledBackChainState}
@@ -1441,8 +1445,8 @@ aggregateNodeState nodeState@NodeState{headState} sc =
14411445
let headState' = aggregate headState sc
14421446
ns@NodeState{headState = st, pendingDeposits} = nodeState{headState = headState'}
14431447
in case sc of
1444-
HeadOpened{} ->
1445-
ns{pendingDeposits = mempty}
1448+
HeadOpened{chainState} ->
1449+
ns{pendingDeposits = mempty, currentSlot = chainStateSlot chainState}
14461450
DepositRecorded{headId, depositTxId, deposited, created, deadline} ->
14471451
ns{pendingDeposits = Map.insert depositTxId Deposit{headId, deposited, created, deadline, status = Inactive} pendingDeposits}
14481452
DepositActivated{depositTxId, deposit} ->
@@ -1479,6 +1483,8 @@ aggregateNodeState nodeState@NodeState{headState} sc =
14791483
ns
14801484
{ pendingDeposits = Map.delete depositTxId pendingDeposits
14811485
}
1486+
TickObserved{chainSlot} ->
1487+
ns{currentSlot = chainSlot}
14821488
_ -> ns
14831489

14841490
-- * HeadState aggregate
@@ -1543,7 +1549,6 @@ aggregate st = \case
15431549
, chainState
15441550
, headId
15451551
, headSeed
1546-
, currentSlot = chainStateSlot chainState
15471552
}
15481553
_otherState -> st
15491554
TransactionReceived{tx} ->
@@ -1758,10 +1763,7 @@ aggregate st = \case
17581763
_otherState -> st
17591764
ChainRolledBack{chainState} ->
17601765
setChainState chainState st
1761-
TickObserved{chainSlot} ->
1762-
case st of
1763-
Open ost@OpenState{} -> Open ost{currentSlot = chainSlot}
1764-
_otherState -> st
1766+
TickObserved{} -> st
17651767
IgnoredHeadInitializing{} -> st
17661768
TxInvalid{transaction} -> case st of
17671769
Open ost@OpenState{coordinatedHeadState = coordState@CoordinatedHeadState{allTxs = allTransactions}} ->

hydra-node/src/Hydra/HeadLogic/State.hs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ data NodeState tx = NodeState
3434
-- ^ Pending deposits as observed on chain.
3535
-- TODO: could even move the chain state here (also see todo below)
3636
-- , chainState :: ChaiStateType tx
37-
-- TODO: could even move the currentSlot here (not head specific!)
38-
-- , currentSlot :: ChainSlot
37+
, currentSlot :: ChainSlot
3938
}
4039
deriving stock (Generic)
4140

@@ -154,7 +153,6 @@ data OpenState tx = OpenState
154153
, coordinatedHeadState :: CoordinatedHeadState tx
155154
, chainState :: ChainStateType tx
156155
, headId :: HeadId
157-
, currentSlot :: ChainSlot
158156
, headSeed :: HeadSeed
159157
}
160158
deriving stock (Generic)
@@ -172,7 +170,6 @@ instance (ArbitraryIsTx tx, Arbitrary (ChainStateType tx)) => Arbitrary (OpenSta
172170
<*> arbitrary
173171
<*> arbitrary
174172
<*> arbitrary
175-
<*> arbitrary
176173

177174
-- | Off-chain state of the Coordinated Head protocol.
178175
data CoordinatedHeadState tx = CoordinatedHeadState

hydra-node/src/Hydra/Node.hs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import Hydra.Chain (
2929
PostTxError,
3030
initHistory,
3131
)
32-
import Hydra.Chain.ChainState (ChainStateType, IsChainState)
32+
import Hydra.Chain.ChainState (ChainStateType, IsChainState, chainStateSlot)
3333
import Hydra.Events (EventId, EventSink (..), EventSource (..), getEventId, putEventsToSinks)
3434
import Hydra.Events.Rotation (EventStore (..))
3535
import Hydra.HeadLogic (
@@ -220,6 +220,7 @@ hydrate tracer env ledger initialChainState EventStore{eventSource, eventSink} e
220220
NodeState
221221
{ headState = Idle IdleState{chainState = initialChainState}
222222
, pendingDeposits = mempty
223+
, currentSlot = chainStateSlot initialChainState
223224
}
224225

225226
recoverNodeStateC =
@@ -409,6 +410,8 @@ processEffects node tracer inputId effects = do
409410

410411
-- ** Manage state
411412

413+
-- TODO! pendingDeposits :: Map (TxIdType tx) (Deposit tx)
414+
412415
-- | Handle to access and modify the state in the Hydra Node.
413416
data NodeStateHandler tx m = NodeStateHandler
414417
{ modifyNodeState :: forall a. (NodeState tx -> (a, NodeState tx)) -> STM m a

hydra-node/src/Hydra/Node/Run.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import Hydra.Chain (ChainComponent, ChainStateHistory, maximumNumberOfParties)
2222
import Hydra.Chain.Backend (ChainBackend (queryGenesisParameters))
2323
import Hydra.Chain.Blockfrost (BlockfrostBackend (..))
2424
import Hydra.Chain.Cardano (withCardanoChain)
25-
import Hydra.Chain.ChainState (IsChainState (..))
25+
import Hydra.Chain.ChainState (IsChainState (..), chainStateSlot)
2626
import Hydra.Chain.Direct (DirectBackend (..))
2727
import Hydra.Chain.Direct.State (initialChainState)
2828
import Hydra.Chain.Offline (loadGenesisFile, withOfflineChain)
@@ -154,6 +154,7 @@ run opts = do
154154
NodeState
155155
{ headState = Idle IdleState{chainState = initialChainState}
156156
, pendingDeposits = mempty
157+
, currentSlot = chainStateSlot initialChainState
157158
}
158159
let aggregator :: IsChainState tx => NodeState tx -> StateEvent tx -> NodeState tx
159160
aggregator s StateEvent{stateChanged} = aggregateNodeState s stateChanged

hydra-node/test/Hydra/API/HTTPServerSpec.hs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import Hydra.Cardano.Api (
3131
serialiseToTextEnvelope,
3232
)
3333
import Hydra.Chain (Chain (draftCommitTx), PostTxError (..), draftDepositTx)
34+
import Hydra.Chain.ChainState (ChainSlot (ChainSlot))
3435
import Hydra.Chain.Direct.Handlers (checkAmount, rejectLowDeposits)
3536
import Hydra.HeadLogic.State (ClosedState (..), HeadState (..), NodeState (..), SeenSnapshot (..))
3637
import Hydra.HeadLogicSpec (inIdleState)
@@ -362,7 +363,7 @@ apiServerSpec = do
362363
dummyChainHandle
363364
testEnvironment
364365
defaultPParams
365-
(pure NodeState{headState = Closed closedState, pendingDeposits = mempty})
366+
(pure NodeState{headState = Closed closedState, pendingDeposits = mempty, currentSlot = ChainSlot 0})
366367
cantCommit
367368
getPendingDeposits
368369
putClientInput
@@ -522,7 +523,7 @@ apiServerSpec = do
522523
dummyChainHandle
523524
testEnvironment
524525
defaultPParams
525-
(pure NodeState{headState = Closed closedState', pendingDeposits = mempty})
526+
(pure NodeState{headState = Closed closedState', pendingDeposits = mempty, currentSlot = ChainSlot 0})
526527
cantCommit
527528
getPendingDeposits
528529
putClientInput
@@ -556,7 +557,7 @@ apiServerSpec = do
556557
workingChainHandle
557558
testEnvironment
558559
defaultPParams
559-
(pure NodeState{headState = initialHeadState, pendingDeposits = mempty})
560+
(pure NodeState{headState = initialHeadState, pendingDeposits = mempty, currentSlot = ChainSlot 0})
560561
getHeadId
561562
getPendingDeposits
562563
putClientInput
@@ -611,7 +612,7 @@ apiServerSpec = do
611612
(failingChainHandle postTxError)
612613
testEnvironment
613614
defaultPParams
614-
(pure NodeState{headState = openHeadState, pendingDeposits = mempty})
615+
(pure NodeState{headState = openHeadState, pendingDeposits = mempty, currentSlot = ChainSlot 0})
615616
getHeadId
616617
getPendingDeposits
617618
putClientInput

0 commit comments

Comments
 (0)