Skip to content

Commit 0c43985

Browse files
committed
Ensure there is at least one block per epoch in LoP tests
1 parent 93e74d6 commit 0c43985

1 file changed

Lines changed: 26 additions & 4 deletions

File tree

  • ouroboros-consensus-diffusion/test/consensus-test/Test/Consensus/Genesis/Tests

ouroboros-consensus-diffusion/test/consensus-test/Test/Consensus/Genesis/Tests/LoP.hs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ module Test.Consensus.Genesis.Tests.LoP
1212
, testSuite
1313
) where
1414

15+
import Cardano.Ledger.BaseTypes.NonZero (unNonZero)
1516
import Data.Functor (($>))
1617
import Data.Ratio ((%))
17-
import Ouroboros.Consensus.Block.Abstract (Header)
18+
import Ouroboros.Consensus.Block.Abstract (Header, HeaderFields (..), unSlotNo)
19+
import Ouroboros.Consensus.Config.SecurityParam (SecurityParam (..))
1820
import qualified Ouroboros.Consensus.MiniProtocol.ChainSync.Client as CSClient
1921
import Ouroboros.Consensus.Util.IOLike
2022
( DiffTime
@@ -26,7 +28,7 @@ import Ouroboros.Consensus.Util.LeakyBucket
2628
)
2729
import Ouroboros.Network.AnchoredFragment
2830
( AnchoredFragment
29-
, HasHeader
31+
, HasHeader (..)
3032
)
3133
import qualified Ouroboros.Network.AnchoredFragment as AF
3234
import Test.Consensus.BlockTree (BlockTree (..), BlockTreeBranch (..))
@@ -49,6 +51,7 @@ import Test.Consensus.PointSchedule.SinglePeer
4951
, scheduleHeaderPoint
5052
, scheduleTipPoint
5153
)
54+
import Test.QuickCheck.Gen (suchThat)
5255
import Test.Util.Orphans.IOLike ()
5356
import Test.Util.PartialAccessors
5457

@@ -216,7 +219,7 @@ testServe description mustTimeout =
216219
adjustTestCount
217220
adjustMaxSize
218221
( do
219-
gt@GenesisTest{gtBlockTree} <- genChains (pure 0)
222+
gt@GenesisTest{gtBlockTree} <- genChains (pure 0) `suchThat` hasAtLeastOneBlockPerEpoch
220223
let lbpRate = borderlineRate (AF.length (btTrunk gtBlockTree))
221224
ps = makeSchedule (btTrunk gtBlockTree)
222225
gt' = gt{gtLoPBucketParams = LoPBucketParams{lbpCapacity, lbpRate}}
@@ -279,7 +282,7 @@ testDelayAttack description lopEnabled =
279282
adjustTestCount
280283
adjustMaxSize
281284
( do
282-
gt@GenesisTest{gtBlockTree} <- genChains (pure 1)
285+
gt@GenesisTest{gtBlockTree} <- genChains (pure 1) `suchThat` hasAtLeastOneBlockPerEpoch
283286
let gt' = gt{gtLoPBucketParams = LoPBucketParams{lbpCapacity = 10, lbpRate = 1}}
284287
ps = delaySchedule gtBlockTree
285288
pure $ gt' $> ps
@@ -354,3 +357,22 @@ testDelayAttack description lopEnabled =
354357
-- Wait for LoP bucket to empty
355358
psMinEndTime = Time 11
356359
in PointSchedule{psSchedule, psStartOrder = [], psMinEndTime}
360+
361+
-- \| Ensure that the block tree has at least one block per epoch on all branches.
362+
-- Otherwise, issues would arise when trying to update the ledger from era n to era n+2.
363+
hasAtLeastOneBlockPerEpoch :: HasHeader blk => GenesisTest blk schedule -> Bool
364+
hasAtLeastOneBlockPerEpoch GenesisTest{gtBlockTree, gtSecurityParam} =
365+
all fragmentHasEnoughBlocks (btTrunk gtBlockTree : (btbFull <$> btBranches gtBlockTree))
366+
where
367+
k = unNonZero $ maxRollbacks gtSecurityParam
368+
-- \| This value comes from `defaultErasParams`, which is way out of scope from here.
369+
-- We should find a way to avoid repetition of this value, or at least centralize it.
370+
epochSize = 10 * k
371+
slotList frag = slotNo <$> AF.toOldestFirst frag
372+
slotNo = unSlotNo . headerFieldSlot . getHeaderFields
373+
374+
fragmentHasEnoughBlocks frag =
375+
all
376+
(\(prev, next) -> next - prev <= epochSize)
377+
-- \| Add 0 at the beginning to simulate Origin
378+
(zip (0 : slotList frag) (slotList frag))

0 commit comments

Comments
 (0)