@@ -37,7 +37,6 @@ module Test.Consensus.PointSchedule (
3737 , ensureScheduleDuration
3838 , genesisNodeState
3939 , longRangeAttack
40- , mkPointSchedule
4140 , peerSchedulesBlocks
4241 , peerStates
4342 , peersStates
@@ -55,7 +54,6 @@ import Control.Monad.Class.MonadTime.SI (Time (Time), addTime,
5554import Control.Monad.ST (ST )
5655import Data.Functor (($>) )
5756import Data.List (mapAccumL , partition , scanl' )
58- import qualified Data.Map.Strict as Map
5957import Data.Maybe (catMaybes , fromMaybe , mapMaybe )
6058import Data.Time (DiffTime )
6159import Data.Word (Word64 )
@@ -77,8 +75,8 @@ import Test.Consensus.BlockTree (BlockTree (..), BlockTreeBranch (..),
7775import Test.Consensus.PeerSimulator.StateView (StateView )
7876import Test.Consensus.PointSchedule.NodeState (NodeState (.. ),
7977 genesisNodeState )
80- import Test.Consensus.PointSchedule.Peers (Peer (.. ), Peers ( .. ) ,
81- peers' , peersList )
78+ import Test.Consensus.PointSchedule.Peers (Peer (.. ), PeerId ,
79+ Peers ( .. ), getPeerIds , peers' , peersList )
8280import Test.Consensus.PointSchedule.SinglePeer
8381 (IsTrunk (IsBranch , IsTrunk ), PeerScheduleParams (.. ),
8482 SchedulePoint (.. ), defaultPeerScheduleParams , mergeOn ,
@@ -97,21 +95,24 @@ prettyPointSchedule ::
9795 (CondenseList (NodeState blk )) =>
9896 PointSchedule blk ->
9997 [String ]
100- prettyPointSchedule peers =
101- [ " honest peers: " ++ show (Map. size (honestPeers $ psSchedule peers))
102- , " adversaries: " ++ show (Map. size (adversarialPeers $ psSchedule peers))
103- , " minimal duration: " ++ show (psMinEndTime peers)
104- ] ++
105- zipWith3
106- (\ number time peerState ->
107- number ++ " : " ++ peerState ++ " @ " ++ time
108- )
109- (condenseListWithPadding PadLeft $ fst <$> numberedPeersStates)
110- (showDT . fst . snd <$> numberedPeersStates)
111- (condenseList $ (snd . snd ) <$> numberedPeersStates)
98+ prettyPointSchedule ps@ PointSchedule {psStartOrder, psMinEndTime} =
99+ []
100+ ++ [ " psSchedule ="
101+ ]
102+ ++ ( zipWith3
103+ ( \ number time peerState ->
104+ " " ++ number ++ " : " ++ peerState ++ " @ " ++ time
105+ )
106+ (condenseListWithPadding PadLeft $ fst <$> numberedPeersStates)
107+ (showDT . fst . snd <$> numberedPeersStates)
108+ (condenseList $ (snd . snd ) <$> numberedPeersStates)
109+ )
110+ ++ [ " psStartOrder = " ++ show psStartOrder,
111+ " psMinEndTime = " ++ show psMinEndTime
112+ ]
112113 where
113114 numberedPeersStates :: [(Int , (Time , Peer (NodeState blk )))]
114- numberedPeersStates = zip [0 .. ] (peersStates peers )
115+ numberedPeersStates = zip [0 .. ] (peersStates ps )
115116
116117 showDT :: Time -> String
117118 showDT (Time dt) = printf " %.6f" (realToFrac dt :: Double )
@@ -177,15 +178,17 @@ peerScheduleBlocks = mapMaybe (withOriginToMaybe . schedulePointToBlock . snd)
177178data PointSchedule blk = PointSchedule {
178179 -- | The actual point schedule
179180 psSchedule :: Peers (PeerSchedule blk ),
181+ -- | The order in which the peers start and connect to the node under test.
182+ -- The peers that are absent from 'psSchedule' are ignored; the peers from
183+ -- 'psSchedule' that are absent of 'psStartOrder' are started in the end in
184+ -- the order of 'PeerId'.
185+ psStartOrder :: [PeerId ],
180186 -- | Minimum duration for the simulation of this point schedule.
181187 -- If no point in the schedule is larger than 'psMinEndTime',
182188 -- the simulation will still run until this time is reached.
183189 psMinEndTime :: Time
184190 }
185191
186- mkPointSchedule :: Peers (PeerSchedule blk ) -> PointSchedule blk
187- mkPointSchedule sch = PointSchedule sch $ Time 0
188-
189192-- | List of all blocks appearing in the schedules.
190193peerSchedulesBlocks :: Peers (PeerSchedule blk ) -> [blk ]
191194peerSchedulesBlocks = concatMap (peerScheduleBlocks . value) . peersList
@@ -208,7 +211,11 @@ longRangeAttack ::
208211longRangeAttack BlockTree {btTrunk, btBranches = [branch]} g = do
209212 honest <- peerScheduleFromTipPoints g honParams [(IsTrunk , [AF. length btTrunk - 1 ])] btTrunk []
210213 adv <- peerScheduleFromTipPoints g advParams [(IsBranch , [AF. length (btbFull branch) - 1 ])] btTrunk [btbFull branch]
211- pure $ mkPointSchedule $ peers' [honest] [adv]
214+ pure $ PointSchedule {
215+ psSchedule = peers' [honest] [adv],
216+ psStartOrder = [] ,
217+ psMinEndTime = Time 0
218+ }
212219 where
213220 honParams = defaultPeerScheduleParams {pspHeaderDelayInterval = (0.3 , 0.4 )}
214221 advParams = defaultPeerScheduleParams {pspTipDelayInterval = (0 , 0.1 )}
@@ -240,6 +247,7 @@ uniformPoints PointsGeneratorParams {pgpExtraHonestPeers, pgpDowntime} = case pg
240247-- Include rollbacks in a percentage of adversaries, in which case that peer uses two branchs.
241248--
242249uniformPointsWithExtraHonestPeers ::
250+ forall g m blk .
243251 (StatefulGen g m , AF. HasHeader blk ) =>
244252 Int ->
245253 BlockTree blk ->
@@ -254,7 +262,9 @@ uniformPointsWithExtraHonestPeers
254262 honests <- replicateM (extraHonestPeers + 1 ) $
255263 mkSchedule [(IsTrunk , [honestTip0 .. AF. length btTrunk - 1 ])] []
256264 advs <- takeBranches btBranches
257- pure $ mkPointSchedule $ peers' honests advs
265+ let psSchedule = peers' honests advs
266+ psStartOrder <- shuffle (getPeerIds psSchedule)
267+ pure $ PointSchedule {psSchedule, psStartOrder, psMinEndTime = Time 0 }
258268 where
259269 takeBranches = \ case
260270 [] -> pure []
@@ -305,6 +315,15 @@ uniformPointsWithExtraHonestPeers
305315
306316 rollbackProb = 0.2
307317
318+ -- Inefficient implementation, but sufficient for small lists.
319+ shuffle :: [a ] -> m [a ]
320+ shuffle [] = pure []
321+ shuffle xs = do
322+ i <- Random. uniformRM (0 , length xs - 1 ) g
323+ let x = xs !! i
324+ xs' = take i xs ++ drop (i+ 1 ) xs
325+ (x : ) <$> shuffle xs'
326+
308327minusClamp :: (Ord a , Num a ) => a -> a -> a
309328minusClamp a b | a <= b = 0
310329 | otherwise = a - b
@@ -361,6 +380,7 @@ syncTips honests advs =
361380--
362381-- Includes rollbacks in some schedules.
363382uniformPointsWithExtraHonestPeersAndDowntime ::
383+ forall g m blk .
364384 (StatefulGen g m , AF. HasHeader blk ) =>
365385 Int ->
366386 SecurityParam ->
@@ -383,7 +403,9 @@ uniformPointsWithExtraHonestPeersAndDowntime
383403 mkSchedule [(IsTrunk , [honestTip0, minusClamp (AF. length btTrunk) 1 ])] []
384404 advs <- takeBranches pauseSlot btBranches
385405 let (honests', advs') = syncTips honests advs
386- pure $ mkPointSchedule $ peers' honests' advs'
406+ psSchedule = peers' honests' advs'
407+ psStartOrder <- shuffle $ getPeerIds psSchedule
408+ pure $ PointSchedule {psSchedule, psStartOrder, psMinEndTime = Time 0 }
387409 where
388410 takeBranches pause = \ case
389411 [] -> pure []
@@ -438,6 +460,15 @@ uniformPointsWithExtraHonestPeersAndDowntime
438460
439461 rollbackProb = 0.2
440462
463+ -- Inefficient implementation, but sufficient for small lists.
464+ shuffle :: [a ] -> m [a ]
465+ shuffle [] = pure []
466+ shuffle xs = do
467+ i <- Random. uniformRM (0 , length xs - 1 ) g
468+ let x = xs !! i
469+ xs' = take i xs ++ drop (i+ 1 ) xs
470+ (x : ) <$> shuffle xs'
471+
441472newtype ForecastRange = ForecastRange { unForecastRange :: Word64 }
442473 deriving (Show )
443474
@@ -545,9 +576,10 @@ stToGen gen = do
545576 pure (runSTGen_ seed gen)
546577
547578ensureScheduleDuration :: GenesisTest blk a -> PointSchedule blk -> PointSchedule blk
548- ensureScheduleDuration gt PointSchedule {psSchedule, psMinEndTime} =
579+ ensureScheduleDuration gt PointSchedule {psSchedule, psStartOrder, psMinEndTime} =
549580 PointSchedule
550581 { psSchedule
582+ , psStartOrder
551583 , psMinEndTime = max psMinEndTime (Time endingDelay)
552584 }
553585 where
0 commit comments