Skip to content

Commit eaff568

Browse files
committed
Support leios-late-ib-inclusion
1 parent b20de35 commit eaff568

File tree

7 files changed

+117
-7
lines changed

7 files changed

+117
-7
lines changed

data/simulation/config.d.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ export interface Config {
3939
* Only supported by Haskell simulation. */
4040
"leios-vote-send-recv-stages": boolean;
4141
/**
42-
* Extends Leios so that EB producers include IBs directly from previous pipelines
43-
* where no certified EB was observed.
44-
*
45-
* Only supported by Rust simulation. */
42+
* Extends Leios so that EB producers include IBs directly from previous pipelines.
43+
* Due to casuality, the EB must always include them, even if those IBs end up being
44+
* certified in their own pipeline.
45+
*/
4646
"leios-late-ib-inclusion": boolean;
4747
/**
4848
* The expected time it takes a header to fully diffuse across the network.

leios-trace-hs/src/LeiosConfig.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ data Config = Config
9999
, leiosStageActiveVotingSlots :: Word
100100
, leiosVoteSendRecvStages :: Bool
101101
, leiosVariant :: LeiosVariant
102+
, leiosLateIbInclusion :: Bool
102103
, leiosHeaderDiffusionTimeMs :: DurationMs
103104
, praosChainQuality :: Double
104105
, txGenerationDistribution :: Distribution
@@ -171,6 +172,7 @@ instance Default Config where
171172
, leiosStageActiveVotingSlots = 1
172173
, leiosVoteSendRecvStages = False
173174
, leiosVariant = Short
175+
, leiosLateIbInclusion = False
174176
, leiosHeaderDiffusionTimeMs = 1000
175177
, praosChainQuality = 40
176178
, txGenerationDistribution = Exp{lambda = 0.85, scale = Just 1000}
@@ -243,6 +245,7 @@ configToKVsWith getter cfg =
243245
, get @"treatBlocksAsFull" getter cfg
244246
, get @"cleanupPolicies" getter cfg
245247
, get @"leiosVariant" getter cfg
248+
, get @"leiosLateIbInclusion" getter cfg
246249
, get @"leiosHeaderDiffusionTimeMs" getter cfg
247250
, get @"praosChainQuality" getter cfg
248251
, get @"simulateTransactions" getter cfg
@@ -329,6 +332,7 @@ instance FromJSON Config where
329332
treatBlocksAsFull <- parseFieldOrDefault @Config @"treatBlocksAsFull" obj
330333
cleanupPolicies <- parseFieldOrDefault @Config @"cleanupPolicies" obj
331334
leiosVariant <- parseFieldOrDefault @Config @"leiosVariant" obj
335+
leiosLateIbInclusion <- parseFieldOrDefault @Config @"leiosLateIbInclusion" obj
332336
leiosHeaderDiffusionTimeMs <- parseFieldOrDefault @Config @"leiosHeaderDiffusionTimeMs" obj
333337
praosChainQuality <- parseFieldOrDefault @Config @"praosChainQuality" obj
334338
simulateTransactions <- parseFieldOrDefault @Config @"simulateTransactions" obj

simulation/ouroboros-leios-sim.cabal

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ test-suite ols-test
218218
, bytestring
219219
other-modules:
220220
Paths_ouroboros_leios_sim
221-
Test.Topology
222221
Test.Config
222+
Test.ShortToFull
223+
Test.Topology
223224
default-language: Haskell2010

simulation/src/LeiosProtocol/Short.hs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ data LeiosConfig = forall p. IsPipeline p => LeiosConfig
111111
, variant :: LeiosVariant
112112
, headerDiffusionTime :: NominalDiffTime
113113
-- ^ Δ_{hdr}.
114+
, leiosLateIbInclusion :: Bool
115+
-- ^ Whether an EB also includes IBs from the two previous iterations.
116+
--
117+
-- TODO Merely one previous iteration if 'pipeline' is 'SingleVote'?
114118
, pipelinesToReferenceFromEB :: Int
115119
-- ^ how many older pipelines to reference from an EB when `variant = Full`.
116120
, votingFrequencyPerStage :: Double
@@ -147,6 +151,7 @@ convertConfig disk =
147151
, cleanupPolicies = disk.cleanupPolicies
148152
, variant = disk.leiosVariant
149153
, headerDiffusionTime = realToFrac $ durationMsToDiffTime disk.leiosHeaderDiffusionTimeMs
154+
, leiosLateIbInclusion = disk.leiosLateIbInclusion
150155
, pipelinesToReferenceFromEB =
151156
if disk.leiosVariant == Full
152157
then
@@ -285,6 +290,7 @@ delaysAndSizesAsFull cfg@LeiosConfig{pipeline, voteSendStage} =
285290
, cleanupPolicies = cfg.cleanupPolicies
286291
, variant = cfg.variant
287292
, headerDiffusionTime = cfg.headerDiffusionTime
293+
, leiosLateIbInclusion = cfg.leiosLateIbInclusion
288294
, pipelinesToReferenceFromEB = cfg.pipelinesToReferenceFromEB
289295
, activeVotingStageLength = cfg.activeVotingStageLength
290296
, votingFrequencyPerStage = cfg.votingFrequencyPerStage
@@ -664,13 +670,13 @@ data InputBlocksQuery = InputBlocksQuery
664670
-- ^ This is checked against time the body is downloaded, before validation.
665671
}
666672

667-
inputBlocksToEndorse ::
673+
inputBlocksToEndorse1 ::
668674
LeiosConfig ->
669675
-- | current slot
670676
SlotNo ->
671677
InputBlocksSnapshot ->
672678
[InputBlockId]
673-
inputBlocksToEndorse cfg@LeiosConfig{pipeline = _ :: SingPipeline p} current buffer = fromMaybe [] $ do
679+
inputBlocksToEndorse1 cfg@LeiosConfig{pipeline = _ :: SingPipeline p} current buffer = fromMaybe [] $ do
674680
generatedBetween <- stageRange @p cfg Endorse current Propose
675681
receivedBy <- stageEnd @p cfg Endorse current Deliver2
676682
pure $
@@ -680,6 +686,23 @@ inputBlocksToEndorse cfg@LeiosConfig{pipeline = _ :: SingPipeline p} current buf
680686
, receivedBy
681687
}
682688

689+
-- | Invokes 'inputBlocksToEndorse1' as many times as 'leiosLateIbInclusion' requires
690+
inputBlocksToEndorse ::
691+
LeiosConfig ->
692+
-- | current slot
693+
SlotNo ->
694+
InputBlocksSnapshot ->
695+
[InputBlockId]
696+
inputBlocksToEndorse cfg current buffer =
697+
concatMap each iterations
698+
where
699+
each sl = inputBlocksToEndorse1 cfg sl buffer
700+
capL = fromIntegral cfg.sliceLength
701+
iterations =
702+
if not cfg.leiosLateIbInclusion then [current] else
703+
-- discard underflows
704+
dropWhile (> current) [ current - 2 * capL, current - capL, current ]
705+
683706
-- | Returns possible EBs to reference from current pipeline EB.
684707
endorseBlocksToReference ::
685708
LeiosConfig ->

simulation/src/LeiosProtocol/Short/Sim.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,7 @@ traceRelayLink1 connectionOptions =
426426
, cleanupPolicies = def
427427
, variant = Short
428428
, headerDiffusionTime = 1
429+
, leiosLateIbInclusion = False
429430
, pipelinesToReferenceFromEB = 0
430431
, activeVotingStageLength = 1
431432
, pipeline = SingSingleVote

simulation/test/Main.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module Main where
22

33
import qualified Test.Config
4+
import qualified Test.ShortToFull
45
import Test.Tasty (defaultMain, testGroup)
56
import qualified Test.Topology
67

@@ -9,4 +10,5 @@ main =
910
defaultMain . testGroup "ouroboros-leios-sim" $
1011
[ Test.Topology.tests
1112
, Test.Config.tests
13+
, Test.ShortToFull.tests
1214
]
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
{-# LANGUAGE OverloadedRecordDot #-}
2+
{-# LANGUAGE RecordWildCards #-}
3+
4+
module Test.ShortToFull where
5+
6+
import Data.Default (def)
7+
import LeiosProtocol.Common (InputBlockId (..), NodeId (..), SlotNo)
8+
import LeiosProtocol.Config (Config)
9+
import qualified LeiosProtocol.Short as Short
10+
import Test.QuickCheck as Q
11+
import Test.Tasty (TestTree, testGroup)
12+
import Test.Tasty.QuickCheck (testProperty)
13+
14+
tests :: TestTree
15+
tests =
16+
testGroup
17+
"ShortToFull"
18+
[ testProperty "test_leiosLateIbInclusion" test_leiosLateIbInclusion
19+
]
20+
21+
data Test_leiosLateIbInclusion = Test_leiosLateIbInclusion
22+
{ ibTable :: [(Int, SlotNo, SlotNo)] -- the Int is @zip [0..]@, /before shrinking/
23+
, current :: SlotNo
24+
}
25+
deriving (Show)
26+
27+
instance Q.Arbitrary Test_leiosLateIbInclusion where
28+
arbitrary = do
29+
let cfg = Short.convertConfig def
30+
let arbSlot = Q.choose (0, 10 * cfg.sliceLength)
31+
let toSlot :: Int -> SlotNo
32+
toSlot = toEnum
33+
current <- toSlot <$> arbSlot
34+
ibTable <- do
35+
n <- Q.choose (0, 10)
36+
flip mapM [0 .. n - 1] $ \i -> do
37+
gen <- Q.choose (0, fromEnum current)
38+
delay <- Q.choose (0, 3 * cfg.sliceLength)
39+
pure (i, toSlot gen, toSlot (gen + delay))
40+
pure Test_leiosLateIbInclusion {..}
41+
42+
shrink testSetup =
43+
[ testSetup { ibTable = ibTable' }
44+
| ibTable' <- shrinkList (const []) testSetup.ibTable
45+
]
46+
47+
test_leiosLateIbInclusion :: Test_leiosLateIbInclusion -> Property
48+
test_leiosLateIbInclusion testSetup =
49+
Q.counterexample (show (cfg.sliceLength, iterations))
50+
$ Q.counterexample ("on " <> show (map (.num) on))
51+
$ Q.counterexample
52+
(unlines $ ("off":) $ map (show . map (.num) . off) $ iterations)
53+
$ on Q.=== concatMap off iterations
54+
where
55+
Test_leiosLateIbInclusion {..} = testSetup
56+
cfg = Short.convertConfig def
57+
ibSnapshot = Short.InputBlocksSnapshot {
58+
validInputBlocks = \q ->
59+
[ InputBlockId { node = NodeId 0, num = i }
60+
| (i, gen, recv) <- ibTable
61+
, gen `Short.inRange` q.generatedBetween
62+
, recv <= q.receivedBy
63+
]
64+
}
65+
on =
66+
Short.inputBlocksToEndorse
67+
cfg { Short.leiosLateIbInclusion = True }
68+
current
69+
ibSnapshot
70+
off sl =
71+
Short.inputBlocksToEndorse
72+
cfg { Short.leiosLateIbInclusion = False }
73+
sl
74+
ibSnapshot
75+
iterations =
76+
let capL = fromIntegral cfg.sliceLength
77+
in
78+
-- detect underflow
79+
dropWhile (> current) [ current - 2 * capL, current - capL, current ]

0 commit comments

Comments
 (0)