Skip to content

Commit b5993e0

Browse files
authored
Add leios-late-ib-inclusion to the Haskell simulator (#413)
* Support leios-late-ib-inclusion * Update SimulatorModel.md
1 parent 199680a commit b5993e0

File tree

13 files changed

+306
-100
lines changed

13 files changed

+306
-100
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.

data/simulation/variants/config.full.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ leios-variant: full
44
# "Random" is meant to ensure that different producers include different TXs.
55
leios-mempool-sampling-strategy: random
66

7-
# Allow EBs to include IBs from previous slots
7+
# Allow EBs to include IBs from previous pipelines
88
leios-late-ib-inclusion: true
99

1010
# Chain quality controls how far back EB recursion can reach.

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 = True
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

leios-trace-verifier/hs-src/test/Spec/Scenario.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import qualified Data.Map.Strict as M
1919
import qualified Data.Set as S
2020

2121
config :: Config
22-
config = Config{relayStrategy = RequestFromFirst, tcpCongestionControl = True, multiplexMiniProtocols = True, treatBlocksAsFull = False, cleanupPolicies = CleanupPolicies (S.fromList [CleanupExpiredVote]), simulateTransactions = True, leiosStageLengthSlots = 2, leiosStageActiveVotingSlots = 1, leiosVoteSendRecvStages = False, leiosVariant = Short, leiosHeaderDiffusionTimeMs = 1000.0, praosChainQuality = 20.0, txGenerationDistribution = Exp{lambda = 0.85, scale = pure 1000.0}, txSizeBytesDistribution = LogNormal{mu = 6.833, sigma = 1.127}, txValidationCpuTimeMs = 1.5, txMaxSizeBytes = 16384, rbGenerationProbability = 5.0e-2, rbGenerationCpuTimeMs = 1.0, rbHeadValidationCpuTimeMs = 1.0, rbHeadSizeBytes = 1024, rbBodyMaxSizeBytes = 90112, rbBodyLegacyPraosPayloadValidationCpuTimeMsConstant = 50.0, rbBodyLegacyPraosPayloadValidationCpuTimeMsPerByte = 5.0e-4, rbBodyLegacyPraosPayloadAvgSizeBytes = 0, ibGenerationProbability = 5.0, ibGenerationCpuTimeMs = 130.0, ibHeadSizeBytes = 304, ibHeadValidationCpuTimeMs = 1.0, ibBodyValidationCpuTimeMsConstant = 50.0, ibBodyValidationCpuTimeMsPerByte = 5.0e-4, ibBodyMaxSizeBytes = 327680, ibBodyAvgSizeBytes = 98304, ibDiffusionStrategy = FreshestFirst, ibDiffusionMaxWindowSize = 100, ibDiffusionMaxHeadersToRequest = 100, ibDiffusionMaxBodiesToRequest = 1, ibShards = 50, ebGenerationProbability = 1.5, ebGenerationCpuTimeMs = 75.0, ebValidationCpuTimeMs = 1.0, ebSizeBytesConstant = 240, ebSizeBytesPerIb = 32, ebDiffusionStrategy = PeerOrder, ebDiffusionMaxWindowSize = 100, ebDiffusionMaxHeadersToRequest = 100, ebDiffusionMaxBodiesToRequest = 1, ebMaxAgeSlots = 100, ebMaxAgeForRelaySlots = 40, voteGenerationProbability = 500.0, voteGenerationCpuTimeMsConstant = 0.164, voteGenerationCpuTimeMsPerIb = 0.0, voteValidationCpuTimeMs = 0.816, voteThreshold = 300, voteBundleSizeBytesConstant = 0, voteBundleSizeBytesPerEb = 105, voteDiffusionStrategy = PeerOrder, voteDiffusionMaxWindowSize = 100, voteDiffusionMaxHeadersToRequest = 100, voteDiffusionMaxBodiesToRequest = 1, certGenerationCpuTimeMsConstant = 90.0, certGenerationCpuTimeMsPerNode = 0.0, certValidationCpuTimeMsConstant = 130.0, certValidationCpuTimeMsPerNode = 0.0, certSizeBytesConstant = 7168, certSizeBytesPerNode = 0}
22+
config = Config{relayStrategy = RequestFromFirst, tcpCongestionControl = True, multiplexMiniProtocols = True, treatBlocksAsFull = False, cleanupPolicies = CleanupPolicies (S.fromList [CleanupExpiredVote]), simulateTransactions = True, leiosStageLengthSlots = 2, leiosStageActiveVotingSlots = 1, leiosVoteSendRecvStages = False, leiosVariant = Short, leiosLateIbInclusion = False, leiosHeaderDiffusionTimeMs = 1000.0, praosChainQuality = 20.0, txGenerationDistribution = Exp{lambda = 0.85, scale = pure 1000.0}, txSizeBytesDistribution = LogNormal{mu = 6.833, sigma = 1.127}, txValidationCpuTimeMs = 1.5, txMaxSizeBytes = 16384, rbGenerationProbability = 5.0e-2, rbGenerationCpuTimeMs = 1.0, rbHeadValidationCpuTimeMs = 1.0, rbHeadSizeBytes = 1024, rbBodyMaxSizeBytes = 90112, rbBodyLegacyPraosPayloadValidationCpuTimeMsConstant = 50.0, rbBodyLegacyPraosPayloadValidationCpuTimeMsPerByte = 5.0e-4, rbBodyLegacyPraosPayloadAvgSizeBytes = 0, ibGenerationProbability = 5.0, ibGenerationCpuTimeMs = 130.0, ibHeadSizeBytes = 304, ibHeadValidationCpuTimeMs = 1.0, ibBodyValidationCpuTimeMsConstant = 50.0, ibBodyValidationCpuTimeMsPerByte = 5.0e-4, ibBodyMaxSizeBytes = 327680, ibBodyAvgSizeBytes = 98304, ibDiffusionStrategy = FreshestFirst, ibDiffusionMaxWindowSize = 100, ibDiffusionMaxHeadersToRequest = 100, ibDiffusionMaxBodiesToRequest = 1, ibShards = 50, ebGenerationProbability = 1.5, ebGenerationCpuTimeMs = 75.0, ebValidationCpuTimeMs = 1.0, ebSizeBytesConstant = 240, ebSizeBytesPerIb = 32, ebDiffusionStrategy = PeerOrder, ebDiffusionMaxWindowSize = 100, ebDiffusionMaxHeadersToRequest = 100, ebDiffusionMaxBodiesToRequest = 1, ebMaxAgeSlots = 100, ebMaxAgeForRelaySlots = 40, voteGenerationProbability = 500.0, voteGenerationCpuTimeMsConstant = 0.164, voteGenerationCpuTimeMsPerIb = 0.0, voteValidationCpuTimeMs = 0.816, voteThreshold = 300, voteBundleSizeBytesConstant = 0, voteBundleSizeBytesPerEb = 105, voteDiffusionStrategy = PeerOrder, voteDiffusionMaxWindowSize = 100, voteDiffusionMaxHeadersToRequest = 100, voteDiffusionMaxBodiesToRequest = 1, certGenerationCpuTimeMsConstant = 90.0, certGenerationCpuTimeMsPerNode = 0.0, certValidationCpuTimeMsConstant = 130.0, certValidationCpuTimeMsPerNode = 0.0, certSizeBytesConstant = 7168, certSizeBytesPerNode = 0}
2323

2424
topology :: Topology 'COORD2D
2525
topology = Topology{nodes = M.fromList [(NodeName "node-0", Node{nodeInfo = NodeInfo{stake = 500, cpuCoreCount = CpuCoreCount mzero, location = LocCoord2D{coord2D = Point{_1 = 0.12000040231003672, _2 = 0.1631004621065356}}, adversarial = mzero}, producers = M.fromList [(NodeName "node-1", LinkInfo{latencyMs = 141.01364015418432, bandwidthBytesPerSecond = BandwidthBps $ pure 1024000}), (NodeName "node-2", LinkInfo{latencyMs = 254.6249782835189, bandwidthBytesPerSecond = BandwidthBps $ pure 1024000})]}), (NodeName "node-1", Node{nodeInfo = NodeInfo{stake = 200, cpuCoreCount = CpuCoreCount mzero, location = LocCoord2D{coord2D = Point{_1 = 0.34276660615051174, _2 = 0.2636899791034371}}, adversarial = mzero}, producers = M.fromList [(NodeName "node-2", LinkInfo{latencyMs = 175.32530255486685, bandwidthBytesPerSecond = BandwidthBps $ pure 1024000}), (NodeName "node-3", LinkInfo{latencyMs = 379.1167948193313, bandwidthBytesPerSecond = BandwidthBps $ pure 1024000})]}), (NodeName "node-2", Node{nodeInfo = NodeInfo{stake = 100, cpuCoreCount = CpuCoreCount mzero, location = LocCoord2D{coord2D = Point{_1 = 0.5150493264153491, _2 = 0.27873594531347595}}, adversarial = mzero}, producers = M.fromList [(NodeName "node-3", LinkInfo{latencyMs = 248.31457793649423, bandwidthBytesPerSecond = BandwidthBps $ pure 1024000})]}), (NodeName "node-3", Node{nodeInfo = NodeInfo{stake = 0, cpuCoreCount = CpuCoreCount mzero, location = LocCoord2D{coord2D = Point{_1 = 0.3503537969220088, _2 = 0.13879558055660354}}, adversarial = mzero}, producers = M.fromList [(NodeName "node-0", LinkInfo{latencyMs = 140.19739576271448, bandwidthBytesPerSecond = BandwidthBps $ pure 1024000})]})]}

simulation/docs/SimulatorModel.md

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ Each EB (see `LeiosProtocol.Common.EndorseBlock`) consists of the following fiel
9696

9797
More details for some fields.
9898

99-
- An EB from iteration `i` includes the IDs of all IBs that were already adopted, are also from iteration `i`, and arrived before the end of `i`'s Deliver2 stage.
99+
- If `leios-late-ib-inclusion` is disabled, an EB from iteration `i` includes the IDs of all IBs that were already adopted, are also from iteration `i`, and arrived before the end of `i`'s Deliver2 stage.
100+
- If `leios-late-ib-inclusion` is enabled, an EB from iteration `i` includes the IDs of all IBs that were already adopted, are from an iteration `j` in the closed interval `[max 0 (i-2), i]`, and arrived before the end of `j`'s contemporary Deliver2 stage.
100101
- If the Leios variant is set to `short`, this EB includes no EB IDs.
101102
- If the Leios variant is set to `full`, an EB from iteration `i` includes the ID of the best eligible EB from each iteration with any eligible EBs.
102103
- An eligible EB has already been adopted, has already been certified, and is from an iteration in the closed interval `[i - min i (2 + pipelinesToReferenceFromEB), i-3]`.
@@ -129,8 +130,10 @@ More details for some fields.
129130
- A VB from iteration `i` includes the IDs of all EBs that satisfy the following.
130131
- The EB must have already been adopted.
131132
- The EB must also be from iteration `i`.
132-
- The EB must only include IBs that have already been adopted, are from iteration `i`, and arrived before the end of `i`'s Endorse stage.
133-
- The EB must include all IBs that have already been adopted, are from iteration `i`, and arrived before the end of `i`'s Deliver1 stage.
133+
- If `leios-late-ib-inclusion` is disabled, the EB must only include IBs that have already been adopted, are from iteration `i`, and arrived before the end of `i`'s Endorse stage.
134+
- If `leios-late-ib-inclusion` is disabled, the EB must include all IBs that have already been adopted, are from iteration `i`, and arrived before the end of `i`'s Deliver1 stage.
135+
- If `leios-late-ib-inclusion` is enabled, the EB must only include IBs that have already been adopted, are from an iteration `j` in the closed interval `[max 0 (i-2), i]`, and arrived before the end of `j`'s Endorse stage.
136+
- If `leios-late-ib-inclusion` is enabled, the EB must include all IBs that have already been adopted, are from an iteration `j` in the closed interval `[max 0 (i-2), i]`, and arrived before the end of `j`'s Deliver1 stage.
134137
- If the Leios variant is set to `full`, then let X be the EB's included EBs in iteration order; let Y be the EBs this node would have considered eligible if it were to retroactively create an EB for iteration `i` right now with the only extra restriction being ignore EBs that arrived within Δ_hdr of the end of iteration `i`; then `and (zipWith elem X Y)` must be `True`.
135138
(TODO the `zipWith` is suspicious; whether it would misbehave in various scenarios depends on many implementation details.)
136139
- The byte size is computed as `voteBundleSizeBytesConstant + voteBundleSizeBytesPerEb * #EBs` (which implies the weighted-vote perspective).
@@ -192,7 +195,7 @@ TODO discuss the other Relay parameters, backpressure, pipelining, etc?
192195
When an IB header arrives, its validation task is enqueued on the model CPU---for VBs and EBs it's just an ID, not a header, so there's no validation.
193196
Once that finishes, the Relay logic will decide whether it needs to fetch the body.
194197

195-
- An IB body is not fetched if it's older than the slot to which the buffer as has already been pruned or if it's already in the buffer.
198+
- An IB body is not fetched if it exists earlier than it should, it's being offered later than it should be, or if it's already in the buffer.
196199
- An EB is not fetched if it's older than the slot to which the buffer has already been pruned, it's too old to be included by an RB (see `maxEndorseBlockAgeSlots`), or if it's already in the buffer.
197200
- A VB is not fetched if it's older than the slot to which the buffer has already been pruned or if it's already in the buffer.
198201

@@ -233,7 +236,9 @@ Because those threads use STM to read both the state of pending tasks as well as
233236

234237
The existence of those threads enable very simple logic for the adoption tasks.
235238

236-
- The node adopts a validated IB by starting to diffuse it, adding its `UTCTime` arrival to `ibDeliveryTimesVar`, and removing the IB from the todo lists in `ibsNeededForEBVar`.
239+
- The node adopts a validated IB by starting to diffuse it, removing the IB from the todo lists in `ibsNeededForEBVar`, and recording its ID and which stage it arrived during.
240+
See `iBsForEBsAndVotesVar`.
241+
If it arrived during the IB's iteration's Propose stage (aka "early") or after the IB's iteration's Endorse stage (aka "tardy"), then the IB is discarded.
237242
- The node adopts a validated EB by starting to diffuse it, adding it to `relayEBState`, and adding a corresponding todo list of the not-already-available IBs to `ibsNeededForEBVar`.
238243
- The node adopts a validated VB by starting to diffuse it and adding it to `votesForEBVar`.
239244
- The node adopts a validated RB by starting to diffuse it and including it whenever calculating its selection; see `preferredChain`.
@@ -245,17 +250,18 @@ The Relay component invokes the given callback when some object arrives, and tha
245250
## Pruning threads
246251

247252
- *IBs 1*.
248-
At the end of the Vote(Send) stage for iteration `i`, the node stops diffusing all IBs from `i`.
249-
(TODO this should happen at the end of the Endorse stage, but this buffer is being abused as the adoption buffer as well.)
250-
It also forgets any of those IBs it had adopted, with the exception of their arrival time, which is used when generating VBs.
253+
At the end of the Endorse stage for iteration `i`, the node stops diffusing all IBs from `i`.
251254
See `relayIBState`.
255+
- *IBs 2*.
256+
If `leios-late-ib-inclusion` is disabled, then at the end of the Vote(Send) stage for iteration `i`, the node forgets the arrival times of all IBs from `i`.
257+
If `leios-late-ib-inclusion` is enabled, the node instead does that two stages later.
258+
See `iBsForEBsAndVotesVar`.
252259
- *EBs 1*.
253260
At the end of the Vote(Recv) stage for iteration `i`, the node stops diffusing and completely forgets all EBs from `i` that are not already certified.
254261
See `relayEBState`, `votesForEBVar`, and `ibsNeededForEBVar`.
255-
- *VBs* and *IBs 2*.
262+
- *VBs*.
256263
At the end of the Vote(Recv) stage for iteration `i`, the node stops diffusing and completely forgets all VBs from `i`, except that certified EBs from `i` remember the ID and multiplicity of the VBs that first met quorum.
257-
It also forgets the arrival time of IBs from `i`.
258-
See `relayVoteState` and `ibDeliveryTimesVar`.
264+
See `relayVoteState`.
259265
- *EBs 2*.
260266
If the Leios variant is set to `short`, then `maxEndorseBlockAgeSlots` after the end of the Endorse stage for iteration `i`, the node stops diffusing and forgets all EBs from `i` that were certified but are not included by an RB on the selected chain.
261267
(TODO these blocks should have stopped diffusing a long time ago, assuming `maxEndorseBlockAgeSlots >> sliceLength`)
@@ -281,7 +287,7 @@ TODO include `taskQueue`
281287

282288
TODO `relayIBState` abuse
283289

284-
TODO `ibDeliveryTimesVar`
290+
TODO `iBsForEBsAndVotesVar`
285291

286292
## Adopted EBs state
287293

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/Relay.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ data SubmitPolicy = SubmitInOrder | SubmitAll
498498

499499
data RelayConsumerConfig id header body m = RelayConsumerConfig
500500
{ relay :: !RelayConfig
501-
, shouldIgnore :: m (header -> Bool)
501+
, shouldNotRequest :: m (header -> Bool)
502502
-- ^ headers to ignore, e.g. already received or coming too late.
503503
, validateHeaders :: [header] -> m ()
504504
, headerId :: !(header -> id)
@@ -761,7 +761,7 @@ relayConsumerPipelined config sst =
761761
if (min (Map.size lst0.available) (fromIntegral config.maxBodiesToRequest)) == 0
762762
then return (Left lst0)
763763
else return . Right . TS.Effect $ do
764-
isIgnored <- config.shouldIgnore
764+
isIgnored <- config.shouldNotRequest
765765
atomically $ do
766766
-- New headers are filtered before becoming available, but we have
767767
-- to filter `lst.available` again in the same STM tx that sets them as
@@ -987,7 +987,7 @@ relayConsumerPipelined config sst =
987987
m (RelayConsumerLocalState id header body n)
988988
acknowledgeIds lst idsSeq _ | Seq.null idsSeq = pure lst
989989
acknowledgeIds lst idsSeq idsMap = do
990-
isIgnored <- config.shouldIgnore
990+
isIgnored <- config.shouldNotRequest
991991
inFlight <- readTVarIO sst.inFlightVar
992992

993993
let lst1 =

0 commit comments

Comments
 (0)