Skip to content

Commit 8e9df01

Browse files
committed
refactor synced status to compute diff based on query tip
1 parent b6f706a commit 8e9df01

File tree

13 files changed

+89
-71
lines changed

13 files changed

+89
-71
lines changed

hydra-node/golden/ServerOutput/ChainOutOfSync.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
{
22
"samples": [
33
{
4-
"nodeStateSlot": 0,
54
"syncedStatus": {
65
"diff": 0,
76
"point": {
8-
"blockHash": "0001000000010100010100000000010101010001010000010000010101000001",
7+
"blockHash": "0101000000000000000000000000010001000100010000010100010101010000",
98
"slot": 0,
109
"tag": "ChainPoint"
1110
},
12-
"status": true
11+
"status": true,
12+
"tip": {
13+
"blockHash": "0101000001000101010001000101000001010101010101000101010101010001",
14+
"slot": 1,
15+
"tag": "ChainPoint"
16+
}
1317
},
1418
"tag": "ChainOutOfSync"
1519
}

hydra-node/json-schemas/api.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,7 +1806,6 @@ components:
18061806
- tag
18071807
- seq
18081808
- syncedStatus
1809-
- nodeStateSlot
18101809
- timestamp
18111810
properties:
18121811
tag:
@@ -1816,8 +1815,6 @@ components:
18161815
$ref: "api.yaml#/components/schemas/SequenceNumber"
18171816
syncedStatus:
18181817
$ref: "api.yaml#/components/schemas/SyncedStatus"
1819-
nodeStateSlot:
1820-
$ref: "api.yaml#/components/schemas/ChainSlot"
18211818
timestamp:
18221819
$ref: "api.yaml#/components/schemas/UTCTime"
18231820

@@ -3583,6 +3580,7 @@ components:
35833580
- status
35843581
- diff
35853582
- point
3583+
- tip
35863584
properties:
35873585
status:
35883586
type: boolean
@@ -3593,3 +3591,5 @@ components:
35933591
- type: "null"
35943592
point:
35953593
$ref: "api.yaml#/components/schemas/ChainPoint"
3594+
tip:
3595+
$ref: "api.yaml#/components/schemas/ChainPoint"

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Data.Aeson.Lens (atKey, key)
1111
import Data.ByteString.Lazy qualified as LBS
1212
import Hydra.API.ClientInput (ClientInput)
1313
import Hydra.Chain (PostChainTx, PostTxError)
14-
import Hydra.Chain.ChainState (ChainSlot, ChainStateType, IsChainState)
14+
import Hydra.Chain.ChainState (ChainStateType, IsChainState)
1515
import Hydra.Chain.SyncedStatus (SyncedStatus)
1616
import Hydra.HeadLogic.State (ClosedState (..), HeadState (..), InitialState (..), OpenState (..), SeenSnapshot (..))
1717
import Hydra.HeadLogic.State qualified as HeadState
@@ -216,7 +216,7 @@ data ServerOutput tx
216216
-- Any signing round has been discarded, and the snapshot leader has changed accordingly.
217217
SnapshotSideLoaded {headId :: HeadId, snapshotNumber :: SnapshotNumber}
218218
| EventLogRotated {checkpoint :: NodeState tx}
219-
| ChainOutOfSync {syncedStatus :: SyncedStatus, nodeStateSlot :: ChainSlot}
219+
| ChainOutOfSync {syncedStatus :: SyncedStatus}
220220
deriving stock (Generic)
221221

222222
deriving stock instance IsChainState tx => Eq (ServerOutput tx)

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

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ import Hydra.API.ServerOutputFilter (
4242
import Hydra.Chain.ChainState (
4343
IsChainState,
4444
)
45-
import Hydra.Chain.Direct.State (chainSlotFromPoint)
4645
import Hydra.Chain.SyncedStatus (SyncedStatus (..))
4746
import Hydra.HeadLogic (ClosedState (ClosedState, readyToFanoutSent), HeadState, InitialState (..), OpenState (..), StateChanged)
4847
import Hydra.HeadLogic.State qualified as HeadState
@@ -85,13 +84,10 @@ wsApp env party tracer history callback nodeStateP networkInfoP responseChannel
8584
queryParams <- uriQuery <$> mkURIBs path
8685
con <- acceptRequest pending
8786
_ <- forkLabelled "ws-check-sync-status" $ forever $ do
88-
NodeState{currentSlot} <- atomically getLatestNodeState
89-
synced@SyncedStatus{status, point} <- chainSyncedStatus
90-
if status && currentSlot <= chainSlotFromPoint point
91-
then pure ()
92-
else do
93-
tso <- timed 0 (ChainOutOfSync synced currentSlot)
94-
atomically $ writeTChan responseChannel (Left tso)
87+
synced@SyncedStatus{status} <- chainSyncedStatus
88+
unless status $ do
89+
tso <- timed 0 (ChainOutOfSync synced)
90+
atomically $ writeTChan responseChannel (Left tso)
9591
-- check every second
9692
-- TODO! configure threadDelay
9793
threadDelay 1
@@ -186,9 +182,8 @@ wsApp env party tracer history callback nodeStateP networkInfoP responseChannel
186182
msg <- receiveData con
187183
case Aeson.eitherDecode msg of
188184
Right input -> do
189-
NodeState{currentSlot} <- atomically getLatestNodeState
190-
SyncedStatus{status, point} <- chainSyncedStatus
191-
if status && currentSlot <= chainSlotFromPoint point
185+
SyncedStatus{status} <- chainSyncedStatus
186+
if status
192187
then do
193188
traceWith tracer (APIInputReceived $ toJSON input)
194189
callback input

hydra-node/src/Hydra/Chain/Blockfrost.hs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,16 @@ withBlockfrostChain backend tracer config ctx wallet chainStateHistory callback
126126
let persistedPoint = recordedAt (currentState chainStateHistory)
127127
queue <- newLabelledTQueueIO "blockfrost-chain-queue"
128128
-- Select a chain point from which to start synchronizing
129-
chainPoint <- maybe (queryTip backend) pure $ do
129+
let getCurrentTip = queryTip backend
130+
chainPoint <- maybe getCurrentTip pure $ do
130131
(max <$> startChainFrom <*> persistedPoint)
131132
<|> persistedPoint
132133
<|> startChainFrom
133134

134135
let getTimeHandle = queryTimeHandle backend
135136
localChainState <- newLocalChainState chainStateHistory
136-
syncedStatus <- newLabelledTVarIO "blockfrost-chain-sync-status" unSynced
137+
tip <- getCurrentTip
138+
syncedStatus <- newLabelledTVarIO "blockfrost-chain-sync-status" (unSynced tip)
137139
let chainHandle =
138140
mkChain
139141
tracer
@@ -143,7 +145,7 @@ withBlockfrostChain backend tracer config ctx wallet chainStateHistory callback
143145
localChainState
144146
(submitTx queue)
145147
syncedStatus
146-
let handler = chainSyncHandler tracer callback getTimeHandle ctx localChainState contestationPeriod syncedStatus
148+
let handler = chainSyncHandler tracer callback getTimeHandle ctx localChainState syncedStatus getCurrentTip
147149

148150
res <-
149151
raceLabelled
@@ -158,7 +160,7 @@ withBlockfrostChain backend tracer config ctx wallet chainStateHistory callback
158160
Right a -> pure a
159161
where
160162
BlockfrostBackend{options = BlockfrostOptions{projectPath}} = backend
161-
CardanoChainConfig{startChainFrom, contestationPeriod} = config
163+
CardanoChainConfig{startChainFrom} = config
162164

163165
submitTx :: TQueue IO (Tx, TMVar IO (Maybe (PostTxError Tx))) -> Tx -> IO ()
164166
submitTx queue tx = do

hydra-node/src/Hydra/Chain/Direct.hs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,14 +143,16 @@ withDirectChain backend tracer config ctx wallet chainStateHistory callback acti
143143
let persistedPoint = recordedAt (currentState chainStateHistory)
144144
queue <- newLabelledTQueueIO "direct-chain-queue"
145145
-- Select a chain point from which to start synchronizing
146-
chainPoint <- maybe (queryTip backend) pure $ do
146+
let getCurrentTip = queryTip backend
147+
chainPoint <- maybe getCurrentTip pure $ do
147148
(max <$> startChainFrom <*> persistedPoint)
148149
<|> persistedPoint
149150
<|> startChainFrom
150151

151152
let getTimeHandle = queryTimeHandle backend
152153
localChainState <- newLocalChainState chainStateHistory
153-
syncedStatus <- newLabelledTVarIO "direct-chain-sync-status" unSynced
154+
tip <- getCurrentTip
155+
syncedStatus <- newLabelledTVarIO "direct-chain-sync-status" (unSynced tip)
154156
let chainHandle =
155157
mkChain
156158
tracer
@@ -160,7 +162,7 @@ withDirectChain backend tracer config ctx wallet chainStateHistory callback acti
160162
localChainState
161163
(submitTx queue)
162164
syncedStatus
163-
let handler = chainSyncHandler tracer callback getTimeHandle ctx localChainState contestationPeriod syncedStatus
165+
let handler = chainSyncHandler tracer callback getTimeHandle ctx localChainState syncedStatus getCurrentTip
164166
res <-
165167
raceLabelled
166168
( "direct-chain-connection"
@@ -175,7 +177,7 @@ withDirectChain backend tracer config ctx wallet chainStateHistory callback acti
175177
Right a -> pure a
176178
where
177179
DirectBackend{options = DirectOptions{networkId, nodeSocket}} = backend
178-
CardanoChainConfig{startChainFrom, contestationPeriod} = config
180+
CardanoChainConfig{startChainFrom} = config
179181

180182
connectInfo networkId' nodeSocket' =
181183
LocalNodeConnectInfo

hydra-node/src/Hydra/Chain/Direct/Handlers.hs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ import Hydra.Tx (
8383
UTxOType,
8484
headSeedToTxIn,
8585
)
86-
import Hydra.Tx.ContestationPeriod (ContestationPeriod, toNominalDiffTime)
86+
import Hydra.Tx.ContestationPeriod (toNominalDiffTime)
8787
import Hydra.Tx.Deposit (DepositObservation (..), depositTx, splitTokens)
8888
import Hydra.Tx.Observe (
8989
AbortObservation (..),
@@ -315,7 +315,7 @@ data TimeConversionException = TimeConversionException
315315
-- converted to a 'UTCTime' with the given 'TimeHandle'.
316316
chainSyncHandler ::
317317
forall m.
318-
(MonadSTM m, MonadThrow m, MonadTime m) =>
318+
(MonadSTM m, MonadThrow m) =>
319319
-- | Tracer for logging
320320
Tracer m CardanoChainLog ->
321321
ChainCallback Tx m ->
@@ -324,11 +324,11 @@ chainSyncHandler ::
324324
-- | Contextual information about our chain connection.
325325
ChainContext ->
326326
LocalChainState m Tx ->
327-
ContestationPeriod ->
328327
TVar m SyncedStatus ->
328+
m ChainPoint ->
329329
-- | A chain-sync handler to use in a local-chain-sync client.
330330
ChainSyncHandler m
331-
chainSyncHandler tracer callback getTimeHandle ctx localChainState contestationPeriod syncedStatus = do
331+
chainSyncHandler tracer callback getTimeHandle ctx localChainState syncedStatus getCurrentTip = do
332332
ChainSyncHandler
333333
{ onRollBackward
334334
, onRollForward
@@ -362,7 +362,8 @@ chainSyncHandler tracer callback getTimeHandle ctx localChainState contestationP
362362
Right utcTime -> do
363363
let chainSlot = ChainSlot . fromIntegral $ unSlotNo slotNo
364364
callback (Tick{chainTime = utcTime, chainSlot})
365-
updateSyncStatus syncedStatus contestationPeriod utcTime point
365+
tip <- getCurrentTip
366+
updateSyncStatus syncedStatus tip point
366367

367368
forM_ receivedTxs $
368369
maybeObserveSomeTx timeHandle point >=> \case

hydra-node/src/Hydra/Chain/Offline.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Cardano.Slotting.Time (SystemStart (SystemStart), mkSlotLength)
99
import Control.Monad.Class.MonadAsync (link)
1010
import Data.Aeson qualified as Aeson
1111
import Data.Aeson.Types qualified as Aeson
12-
import Hydra.Cardano.Api (GenesisParameters (..), ShelleyEra, ShelleyGenesis (..), Tx)
12+
import Hydra.Cardano.Api (ChainPoint (ChainPointAtGenesis), GenesisParameters (..), ShelleyEra, ShelleyGenesis (..), Tx)
1313
import Hydra.Chain (
1414
Chain (..),
1515
ChainComponent,
@@ -86,7 +86,7 @@ withOfflineChain config party otherParties chainStateHistory callback action = d
8686
chainHandle =
8787
Chain
8888
{ mkChainState = initialChainState
89-
, chainSyncedStatus = pure unSynced
89+
, chainSyncedStatus = pure (unSynced ChainPointAtGenesis)
9090
, submitTx = const $ pure ()
9191
, draftCommitTx = \_ _ -> pure $ Left FailedToDraftTxNotInitializing
9292
, draftDepositTx = \_ _ _ _ _ _ -> pure $ Left FailedToConstructDepositTx{failureReason = "not implemented"}

hydra-node/src/Hydra/Chain/SyncedStatus.hs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ module Hydra.Chain.SyncedStatus where
33
import Hydra.Prelude
44

55
import Control.Concurrent.Class.MonadSTM (writeTVar)
6-
import Hydra.Cardano.Api (ChainPoint (..))
7-
import Hydra.Tx.ContestationPeriod (ContestationPeriod, toNominalDiffTime)
6+
import Hydra.Cardano.Api (ChainPoint (..), SlotNo (SlotNo), chainPointToSlotNo)
7+
import Hydra.Chain.ChainState (ChainSlot (ChainSlot))
88

99
data SyncedStatus
1010
= SyncedStatus
1111
{ status :: Bool
12-
, diff :: Maybe NominalDiffTime
12+
, diff :: Maybe ChainSlot
1313
, point :: ChainPoint
14+
, tip :: ChainPoint
1415
}
1516
deriving stock (Eq, Show, Generic)
1617
deriving anyclass (ToJSON, FromJSON)
@@ -19,20 +20,24 @@ instance Arbitrary SyncedStatus where
1920
arbitrary = genericArbitrary
2021
shrink = genericShrink
2122

22-
unSynced :: SyncedStatus
23-
unSynced = SyncedStatus{status = False, diff = Nothing, point = ChainPointAtGenesis}
23+
unSynced :: ChainPoint -> SyncedStatus
24+
unSynced tip = SyncedStatus{status = False, diff = Nothing, point = ChainPointAtGenesis, tip}
2425

2526
updateSyncStatus ::
26-
(MonadSTM m, MonadTime m) =>
27+
MonadSTM m =>
2728
TVar m SyncedStatus ->
28-
ContestationPeriod ->
29-
UTCTime ->
29+
ChainPoint ->
3030
ChainPoint ->
3131
m ()
32-
updateSyncStatus syncedStatus contestationPeriod slotUTCTime point = do
33-
-- TODO! replace by: slotToUTCTime tipSlot
34-
now <- getCurrentTime
35-
let diff = now `diffUTCTime` slotUTCTime
36-
synced = diff < toNominalDiffTime contestationPeriod
32+
updateSyncStatus syncedStatus tip point = do
33+
let diff = chainSlotFromPoint tip - chainSlotFromPoint point
34+
synced = tip == point
3735
atomically $
38-
writeTVar syncedStatus SyncedStatus{status = synced, diff = Just diff, point}
36+
writeTVar syncedStatus SyncedStatus{status = synced, diff = Just diff, point, tip}
37+
where
38+
-- TODO! DRY
39+
chainSlotFromPoint :: ChainPoint -> ChainSlot
40+
chainSlotFromPoint p =
41+
case chainPointToSlotNo p of
42+
Nothing -> ChainSlot 0
43+
Just (SlotNo s) -> ChainSlot $ fromIntegral s

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ dummyChainHandle :: Chain tx IO
380380
dummyChainHandle =
381381
Chain
382382
{ mkChainState = error "unexpected call to mkChainState"
383-
, chainSyncedStatus = pure SyncedStatus{status = True, diff = Nothing, point = ChainPointAtGenesis}
383+
, chainSyncedStatus = pure SyncedStatus{status = True, diff = Nothing, point = ChainPointAtGenesis, tip = ChainPointAtGenesis}
384384
, postTx = \_ -> error "unexpected call to postTx"
385385
, draftCommitTx = \_ -> error "unexpected call to draftCommitTx"
386386
, draftDepositTx = \_ -> error "unexpected call to draftDepositTx"

0 commit comments

Comments
 (0)