Skip to content

Commit bc16cf4

Browse files
committed
Model PerasCertDiffusion idling in GSM state machine tests
1 parent 751b517 commit bc16cf4

File tree

1 file changed

+123
-34
lines changed
  • ouroboros-consensus-diffusion/test/consensus-test/Test/Consensus

1 file changed

+123
-34
lines changed

ouroboros-consensus-diffusion/test/consensus-test/Test/Consensus/GSM.hs

Lines changed: 123 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ prop_yield_regression =
106106
yieldRegressionActions :: QD.Actions Model
107107
yieldRegressionActions =
108108
(wrapPositiveAction $ NewCandidate Amara (B 1))
109-
<> (wrapPositiveAction $ StartIdling Amara)
109+
<> (wrapPositiveAction $ ChainSyncStartIdling Amara)
110110
<> (wrapPositiveAction $ TimePasses 61)
111111
<> (wrapPositiveAction $ ExtendSelection (S (-4)))
112112
<> (wrapPositiveAction $ ReadMarker)
@@ -137,8 +137,8 @@ setupGsm isHaaSatisfied vars = do
137137
(id, tracer)
138138
GSM.GsmView
139139
{ GSM.antiThunderingHerd = Nothing
140-
, GSM.getCandidateOverSelection = pure $ \s (PeerState c _) ->
141-
candidateOverSelection s c
140+
, GSM.getCandidateOverSelection = pure $ \s peer ->
141+
candidateOverSelection s (psCandidate peer)
142142
, GSM.peerIsIdle = isIdling
143143
, GSM.durationUntilTooOld = Just durationUntilTooOld
144144
, GSM.equivalent = (==) -- unsound, but harmless in this test
@@ -246,7 +246,8 @@ data StaticParams = StaticParams
246246
data Model = Model
247247
{ mCandidates :: Map.Map UpstreamPeer Candidate
248248
, mClock :: SI.Time
249-
, mIdlers :: Set.Set UpstreamPeer
249+
, mChainSyncIdlers :: Set.Set UpstreamPeer
250+
, mPerasCertDiffusionIdlers :: Set.Set UpstreamPeer
250251
, mNotables :: Set.Set Notable
251252
, mPrev :: WhetherPrevTimePasses
252253
, mSelection :: Selection
@@ -261,18 +262,20 @@ initModel =
261262
Model
262263
{ mCandidates = Map.empty
263264
, mClock = SI.Time 0
264-
, mIdlers = idlers
265+
, mChainSyncIdlers = chainSyncIdlers
266+
, mPerasCertDiffusionIdlers = perasCertDiffusionIdlers
265267
, mNotables = Set.empty
266268
, mPrev = WhetherPrevTimePasses True
267269
, mSelection = initialSelection pInitialJudgement
268270
, mState = case pInitialJudgement of
269271
TooOld
270-
| pIsHaaSatisfied idlers -> ModelSyncing
272+
| pIsHaaSatisfied chainSyncIdlers -> ModelSyncing
271273
| otherwise -> ModelPreSyncing
272274
YoungEnough -> ModelCaughtUp (SI.Time (-10000))
273275
}
274276
where
275-
idlers = Set.empty
277+
perasCertDiffusionIdlers = Set.empty
278+
chainSyncIdlers = Set.empty
276279

277280
StaticParams{pIsHaaSatisfied, pInitialJudgement} = Reflection.given
278281

@@ -296,10 +299,16 @@ instance Reflection.Given StaticParams => QD.StateModel Model where
296299
NewCandidate :: UpstreamPeer -> B -> QD.Action Model ()
297300
-- \^ INVARIANT new peer
298301
--
299-
-- Mocks the necessary ChainSync client behavior.z
302+
-- Mocks the necessary ChainSync client behavior.
303+
NewPerasCert :: UpstreamPeer -> QD.Action Model ()
304+
-- \^ INVARIANT existing peer
305+
--
306+
-- Mocks the necessary PerasCertDiffusion client behavior.
300307
ReadGsmState :: QD.Action Model GSM.GsmState
301308
ReadMarker :: QD.Action Model MarkerState
302-
StartIdling :: UpstreamPeer -> QD.Action Model ()
309+
ChainSyncStartIdling :: UpstreamPeer -> QD.Action Model ()
310+
-- \^ INVARIANT existing peer, not idling
311+
PerasCertDiffusionStartIdling :: UpstreamPeer -> QD.Action Model ()
303312
-- \^ INVARIANT existing peer, not idling
304313
TimePasses :: Int -> QD.Action Model ()
305314

@@ -437,23 +446,51 @@ instance (IOLike m, Reflection.Given StaticParams) => QD.RunModel Model (RunMona
437446
ModifyCandidate peer bdel -> do
438447
atomically $ do
439448
v <- (Map.! peer) <$> readTVar varStates
440-
Candidate b <- psCandidate <$> readTVar v
441-
writeTVar v $! PeerState (Candidate (b + bdel)) (Idling False)
442-
449+
modifyTVar v $! \ps ->
450+
let Candidate b = psCandidate ps
451+
in ps
452+
{ psCandidate = Candidate (b + bdel)
453+
, psChainSyncIdling = Idling False
454+
}
443455
pure ()
444456
NewCandidate peer bdel -> do
445457
atomically $ do
446458
Selection b _s <- readTVar varSelection
447-
v <- newTVar $! PeerState (Candidate (b + bdel)) (Idling False)
459+
v <-
460+
newTVar $!
461+
PeerState
462+
{ psCandidate = Candidate (b + bdel)
463+
, psChainSyncIdling = Idling False
464+
, psPerasCertDiffusionIdling = Idling True
465+
-- NOTE: this new peer will idle until it gets a 'NewPerasCert'
466+
}
448467
modifyTVar varStates $ Map.insert peer v
449468
pure ()
469+
NewPerasCert peer -> do
470+
atomically $ do
471+
v <- (Map.! peer) <$> readTVar varStates
472+
modifyTVar v $ \ps ->
473+
ps
474+
{ psPerasCertDiffusionIdling = Idling False
475+
}
476+
pure ()
450477
ReadGsmState -> do
451478
atomically $ readTVar varGsmState
452479
ReadMarker -> do
453480
atomically $ readTVar varMarker
454-
StartIdling peer -> atomically $ do
481+
ChainSyncStartIdling peer -> atomically $ do
455482
v <- (Map.! peer) <$> readTVar varStates
456-
modifyTVar v $ \(PeerState c _) -> PeerState c (Idling True)
483+
modifyTVar v $ \ps ->
484+
ps
485+
{ psChainSyncIdling = Idling True
486+
}
487+
pure ()
488+
PerasCertDiffusionStartIdling peer -> atomically $ do
489+
v <- (Map.! peer) <$> readTVar varStates
490+
modifyTVar v $ \ps ->
491+
ps
492+
{ psPerasCertDiffusionIdling = Idling True
493+
}
457494
pure ()
458495
TimePasses dur -> do
459496
SI.threadDelay (0.1 * fromIntegral dur)
@@ -596,20 +633,26 @@ precondition model = \case
596633
peer `Map.member` cands
597634
NewCandidate peer _bdel ->
598635
peer `Map.notMember` cands
636+
NewPerasCert peer ->
637+
peer `Map.member` cands
599638
ReadGsmState ->
600639
True
601640
ReadMarker ->
602641
True
603-
StartIdling peer ->
642+
ChainSyncStartIdling peer ->
643+
peer `Map.member` cands
644+
&& peer `Set.notMember` chainSyncIdlers
645+
PerasCertDiffusionStartIdling peer ->
604646
peer `Map.member` cands
605-
&& peer `Set.notMember` idlers
647+
&& peer `Set.notMember` perasCertDiffusionIdlers
606648
TimePasses dur ->
607649
0 < dur
608650
&& boringDur model dur
609651
where
610652
Model
611653
{ mCandidates = cands
612-
, mIdlers = idlers
654+
, mChainSyncIdlers = chainSyncIdlers
655+
, mPerasCertDiffusionIdlers = perasCertDiffusionIdlers
613656
} = model
614657

615658
generator ::
@@ -635,15 +678,29 @@ generator model =
635678
)
636679
| notNull new
637680
]
681+
<> [ (,) 20 $ do
682+
QD.Some . NewPerasCert <$> QC.elements old
683+
| notNull old
684+
]
638685
<> [(,) 20 $ pure . QD.Some $ ReadGsmState]
639686
<> [(,) 20 $ pure . QD.Some $ ReadMarker]
640-
<> [(,) 50 $ QD.Some . StartIdling <$> QC.elements oldNotIdling | notNull oldNotIdling]
687+
<> [ (,) 50 $
688+
QD.Some . ChainSyncStartIdling <$> do
689+
QC.elements oldNotChainSyncIdling
690+
| notNull oldNotChainSyncIdling
691+
]
692+
<> [ (,) 50 $
693+
QD.Some . PerasCertDiffusionStartIdling <$> do
694+
QC.elements oldNotPerasCertDiffusionIdling
695+
| notNull oldNotPerasCertDiffusionIdling
696+
]
641697
<> [(,) 100 $ QD.Some . TimePasses <$> genTimePassesDur | prev == WhetherPrevTimePasses False]
642698
where
643699
Model
644700
{ mCandidates = cands
645701
, mClock = clk
646-
, mIdlers = idlers
702+
, mChainSyncIdlers = chainSyncIdlers
703+
, mPerasCertDiffusionIdlers = perasCertDiffusionIdlers
647704
, mPrev = prev
648705
, mSelection = sel
649706
} = model
@@ -659,7 +716,8 @@ generator model =
659716
Nothing -> []
660717
Just peer -> [minBound .. peer] \\ old
661718

662-
oldNotIdling = old \\ Set.toList idlers
719+
oldNotChainSyncIdling = old \\ Set.toList chainSyncIdlers
720+
oldNotPerasCertDiffusionIdling = old \\ Set.toList perasCertDiffusionIdlers
663721

664722
genTimePassesDur =
665723
QC.frequency $
@@ -700,11 +758,15 @@ shrinker _model = \case
700758
[QD.Some $ ModifyCandidate peer bdel' | bdel' <- shrinkB bdel, bdel' /= 0]
701759
NewCandidate peer bdel ->
702760
[QD.Some $ NewCandidate peer bdel' | bdel' <- shrinkB bdel, bdel' /= 0]
761+
NewPerasCert{} ->
762+
[]
703763
ReadGsmState ->
704764
[]
705765
ReadMarker ->
706766
[]
707-
StartIdling{} ->
767+
ChainSyncStartIdling{} ->
768+
[]
769+
PerasCertDiffusionStartIdling{} ->
708770
[]
709771
TimePasses dur ->
710772
[QD.Some $ TimePasses dur' | dur' <- QC.shrink dur, 0 < dur']
@@ -722,23 +784,40 @@ transition model cmd =
722784
Disconnect peer ->
723785
model'
724786
{ mCandidates = Map.delete peer cands
725-
, mIdlers = Set.delete peer idlers
787+
, mChainSyncIdlers = Set.delete peer chainSyncIdlers
788+
, mPerasCertDiffusionIdlers = Set.delete peer perasCertDiffusionIdlers
726789
}
727790
ExtendSelection sdel ->
728-
model'{mSelection = Selection (b + 1) (s + sdel)}
791+
model'
792+
{ mSelection = Selection (b + 1) (s + sdel)
793+
}
729794
ModifyCandidate peer bdel ->
730795
model'
731796
{ mCandidates = Map.insertWith plusC peer (Candidate bdel) cands
732-
, mIdlers = Set.delete peer idlers
797+
, mChainSyncIdlers = Set.delete peer chainSyncIdlers
733798
}
734799
NewCandidate peer bdel ->
735-
model'{mCandidates = Map.insert peer (Candidate (b + bdel)) cands}
800+
model'
801+
{ mCandidates = Map.insert peer (Candidate (b + bdel)) cands
802+
, mPerasCertDiffusionIdlers = Set.insert peer perasCertDiffusionIdlers
803+
-- NOTE: this new peer will idle until it gets a 'NewPerasCert'
804+
}
805+
NewPerasCert peer ->
806+
model'
807+
{ mPerasCertDiffusionIdlers = Set.delete peer perasCertDiffusionIdlers
808+
}
736809
ReadGsmState ->
737810
model'
738811
ReadMarker ->
739812
model'
740-
StartIdling peer ->
741-
model'{mIdlers = Set.insert peer idlers}
813+
ChainSyncStartIdling peer ->
814+
model'
815+
{ mChainSyncIdlers = Set.insert peer chainSyncIdlers
816+
}
817+
PerasCertDiffusionStartIdling peer ->
818+
model'
819+
{ mPerasCertDiffusionIdlers = Set.insert peer perasCertDiffusionIdlers
820+
}
742821
TimePasses dur ->
743822
addNotableWhen BigDurN (dur > 300) $
744823
model
@@ -749,7 +828,8 @@ transition model cmd =
749828
Model
750829
{ mCandidates = cands
751830
, mClock = clk
752-
, mIdlers = idlers
831+
, mChainSyncIdlers = chainSyncIdlers
832+
, mPerasCertDiffusionIdlers = perasCertDiffusionIdlers
753833
, mSelection = Selection b s
754834
} = model
755835

@@ -806,7 +886,8 @@ fixupModelState cmd model =
806886
Model
807887
{ mCandidates = cands
808888
, mClock = clk
809-
, mIdlers = idlers
889+
, mChainSyncIdlers = chainSyncIdlers
890+
, mPerasCertDiffusionIdlers = perasCertDiffusionIdlers
810891
, mSelection = sel
811892
, mState = st
812893
} = model
@@ -820,7 +901,9 @@ fixupModelState cmd model =
820901

821902
some = 0 < Map.size cands
822903

823-
allIdling = idlers == Map.keysSet cands
904+
allIdling =
905+
chainSyncIdlers == Map.keysSet cands
906+
&& perasCertDiffusionIdlers == Map.keysSet cands
824907

825908
ok cand =
826909
GSM.WhetherCandidateIsBetter False == candidateOverSelection sel cand
@@ -936,14 +1019,20 @@ instance TD.ToExpr Notable where toExpr = TD.defaultExprViaShow
9361019

9371020
---
9381021

939-
newtype Idling = Idling Bool
1022+
newtype Idling = Idling {unIdling :: Bool}
9401023
deriving (Eq, Ord, Show)
9411024

942-
data PeerState = PeerState {psCandidate :: !Candidate, psIdling :: !Idling}
1025+
data PeerState = PeerState
1026+
{ psCandidate :: !Candidate
1027+
, psChainSyncIdling :: !Idling
1028+
, psPerasCertDiffusionIdling :: !Idling
1029+
}
9431030
deriving (Eq, Ord, Show)
9441031

9451032
isIdling :: PeerState -> Bool
946-
isIdling (PeerState{psIdling = Idling i}) = i
1033+
isIdling (PeerState{psChainSyncIdling, psPerasCertDiffusionIdling}) =
1034+
unIdling psChainSyncIdling
1035+
&& unIdling psPerasCertDiffusionIdling
9471036

9481037
-- | Ensure the GSM thread's transactions quiesce
9491038
--

0 commit comments

Comments
 (0)