@@ -111,6 +111,10 @@ data LeiosConfig = forall p. IsPipeline p => LeiosConfig
111111 , variant :: LeiosVariant
112112 , headerDiffusionTime :: NominalDiffTime
113113 -- ^ Δ_{hdr}.
114+ , lateIbInclusion :: 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+ , lateIbInclusion = 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+ , lateIbInclusion = cfg. lateIbInclusion
288294 , pipelinesToReferenceFromEB = cfg. pipelinesToReferenceFromEB
289295 , activeVotingStageLength = cfg. activeVotingStageLength
290296 , votingFrequencyPerStage = cfg. votingFrequencyPerStage
@@ -461,21 +467,38 @@ isStage cfg stage slot = fromEnum slot >= cfg.sliceLength * fromEnum stage
461467newtype PipelineNo = PipelineNo Word64
462468 deriving (Bounded , Enum , Show , Eq , Ord )
463469
470+ pipelineMonus :: PipelineNo -> Word64 -> PipelineNo
471+ pipelineMonus (PipelineNo w) i = PipelineNo $ w - min w i
472+
464473stageRangeOf :: forall p . IsPipeline p => LeiosConfig -> PipelineNo -> Stage p -> (SlotNo , SlotNo )
465474stageRangeOf cfg pl stage =
466475 fromMaybe
467476 undefined
468477 (stageRange cfg minBound (toEnum (fromEnum pl * cfg. sliceLength)) stage)
469478
479+ -- | WARNING This fails if the slot is earlier than the beginning of the stage
480+ -- in the first iteration (ie @'PipelineNo' 0@)
470481pipelineOf :: forall p . IsPipeline p => LeiosConfig -> Stage p -> SlotNo -> PipelineNo
471482pipelineOf cfg stage sl =
472- toEnum $
473- fromMaybe undefined (fromEnum <$> stageStart cfg stage sl minBound )
474- `div` cfg. sliceLength
483+ maybe err cnv $ stageStart cfg stage sl minBound
484+ where
485+ cnv = toEnum . (`div` cfg. sliceLength) . fromEnum
486+
487+ err = error $ show (cfg. sliceLength, x, stage, sl)
488+
489+ x :: String
490+ x = case cfg of
491+ LeiosConfig {pipeline} -> case pipeline of
492+ SingSingleVote -> " SingleVote"
493+ SingSplitVote -> " SplitVote"
475494
476495forEachPipeline :: (forall p . Stage p ) -> (forall p . IsPipeline p => Stage p -> a ) -> [a ]
477496forEachPipeline s k = [k @ SingleVote s, k @ SplitVote s]
478497
498+ lastEndorse :: LeiosConfig -> PipelineNo -> SlotNo
499+ lastEndorse leios@ LeiosConfig {pipeline = _ :: SingPipeline p } pipelineNo =
500+ snd $ stageRangeOf @ p leios pipelineNo Endorse
501+
479502lastVoteSend :: LeiosConfig -> PipelineNo -> SlotNo
480503lastVoteSend leios@ LeiosConfig {pipeline} pipelineNo = case pipeline of
481504 SingSingleVote -> snd (stageRangeOf leios pipelineNo Vote )
@@ -657,28 +680,76 @@ data EndorseBlocksSnapshot = EndorseBlocksSnapshot
657680 , certifiedEndorseBlocks :: (PipelineNo , PipelineNo ) -> [(PipelineNo , [(EndorseBlock , Certificate , UTCTime )])]
658681 }
659682
683+ -- | In which contemporary stage was an IB delivered
684+ --
685+ -- IBs cannot be deliver earlier than any of these options, due to the
686+ -- 'LeiosProtocol.Relay.shouldNotRequest' logic of the
687+ -- 'LeiosProtocol.Short.Node.relayIBState'.
688+ --
689+ -- IBs that are delivered later than any of these options are discarded,
690+ -- ignored.
691+ data IbDeliveryStage
692+ = -- | The node will not vote for an EB that excludes IBs that arrived during
693+ -- Propose or Deliver1.
694+ --
695+ -- The node will include IBs that arrived during Propose or Deliver1 in an
696+ -- EB it makes.
697+ IbDuringProposeOrDeliver1
698+ | -- | The node will include IBs that arrived during Deliver2 in an EB it makes.
699+ IbDuringDeliver2
700+ | -- | The node will not vote for an EB that includes IBs that arrived later
701+ -- than Endorse.
702+ IbDuringEndorse
703+ deriving (Bounded , Enum , Eq , Ord , Show )
704+
660705-- | Both constraints are inclusive.
661706data InputBlocksQuery = InputBlocksQuery
662- { generatedBetween :: (SlotNo , SlotNo )
663- , receivedBy :: SlotNo
707+ { generatedBetween :: (PipelineNo , PipelineNo )
708+ , receivedBy :: IbDeliveryStage
664709 -- ^ This is checked against time the body is downloaded, before validation.
665710 }
666711
712+ ibWasDeliveredLate :: LeiosConfig -> SlotConfig -> SlotNo -> UTCTime -> Bool
713+ ibWasDeliveredLate cfg slotCfg sl deliveryTime =
714+ case ibDeliveryStage cfg slotCfg sl deliveryTime of
715+ Nothing -> True
716+ Just {} -> False
717+
718+ ibDeliveryStage :: LeiosConfig -> SlotConfig -> SlotNo -> UTCTime -> Maybe IbDeliveryStage
719+ ibDeliveryStage
720+ cfg@ LeiosConfig {pipeline = _ :: SingPipeline p }
721+ slotCfg
722+ ibSlot
723+ deliveryTime
724+ | before loPropose = Nothing -- TODO future blocks?
725+ | before loDeliver2 = Just IbDuringProposeOrDeliver1
726+ | before loEndorse = Just IbDuringDeliver2
727+ | before (succ hiEndorse) = Just IbDuringEndorse
728+ | otherwise = Nothing -- TODO late blocks?
729+ where
730+ p = pipelineOf @ p cfg Propose ibSlot
731+
732+ before sl = deliveryTime < slotTime slotCfg sl
733+
734+ (loPropose, _) = stageRangeOf @ p cfg p Propose
735+ (loDeliver2, _) = stageRangeOf @ p cfg p Deliver2
736+ (loEndorse, hiEndorse) = stageRangeOf @ p cfg p Endorse
737+
667738inputBlocksToEndorse ::
668739 LeiosConfig ->
669740 -- | current slot
670741 SlotNo ->
671742 InputBlocksSnapshot ->
672743 [InputBlockId ]
673- inputBlocksToEndorse cfg@ LeiosConfig {pipeline = _ :: SingPipeline p } current buffer = fromMaybe [] $ do
674- generatedBetween <- stageRange @ p cfg Endorse current Propose
675- receivedBy <- stageEnd @ p cfg Endorse current Deliver2
676- pure $
677- buffer . validInputBlocks
678- InputBlocksQuery
679- { generatedBetween
680- , receivedBy
681- }
744+ inputBlocksToEndorse cfg@ LeiosConfig {pipeline = _ :: SingPipeline p } current buffer =
745+ buffer . validInputBlocks
746+ InputBlocksQuery
747+ { generatedBetween = (lo, hi)
748+ , receivedBy = IbDuringDeliver2
749+ }
750+ where
751+ hi = pipelineOf @ p cfg Endorse current
752+ lo = if cfg . lateIbInclusion then pipelineMonus hi 2 else hi
682753
683754-- | Returns possible EBs to reference from current pipeline EB.
684755endorseBlocksToReference ::
@@ -734,21 +805,24 @@ shouldVoteOnEB ::
734805shouldVoteOnEB cfg@ LeiosConfig {voteSendStage} _ slot _buffers _
735806 -- checks whether a pipeline has been started before.
736807 | Nothing <- stageRange cfg voteSendStage slot Propose = const False
737- shouldVoteOnEB cfg@ LeiosConfig {voteSendStage} slotConfig slot buffers ebuffers = cond
808+ shouldVoteOnEB cfg@ LeiosConfig {voteSendStage = voteSendStage :: Stage p } slotConfig slot buffers ebuffers = cond
738809 where
739- generatedBetween = fromMaybe (error " impossible" ) $ stageRange cfg voteSendStage slot Propose
810+ generatedBetween = (lo, hi)
811+ where
812+ hi = pipelineOf @ p cfg voteSendStage slot
813+ lo = if cfg. lateIbInclusion then pipelineMonus hi 2 else hi
740814 receivedByEndorse =
741815 buffers. validInputBlocks
742816 InputBlocksQuery
743817 { generatedBetween
744- , receivedBy = fromMaybe ( error " impossible " ) $ stageEnd cfg voteSendStage slot Endorse
818+ , receivedBy = IbDuringEndorse
745819 }
746820 receivedByDeliver1 = buffers. validInputBlocks q
747821 where
748822 q =
749823 InputBlocksQuery
750824 { generatedBetween
751- , receivedBy = fromMaybe ( error " impossible " ) $ stageEnd cfg voteSendStage slot Deliver1
825+ , receivedBy = IbDuringProposeOrDeliver1
752826 }
753827 -- Order of references in EndorseBlock matters for ledger state, so we stick to lists.
754828 -- Note: maybe order on (slot, subSlot, vrf proof) should be used instead?
0 commit comments