@@ -467,21 +467,37 @@ isStage cfg stage slot = fromEnum slot >= cfg.sliceLength * fromEnum stage
467467newtype PipelineNo = PipelineNo Word64
468468 deriving (Bounded , Enum , Show , Eq , Ord )
469469
470+ pipelineMonus :: PipelineNo -> Word64 -> PipelineNo
471+ pipelineMonus (PipelineNo w) i = PipelineNo $ w - min w i
472+
470473stageRangeOf :: forall p . IsPipeline p => LeiosConfig -> PipelineNo -> Stage p -> (SlotNo , SlotNo )
471474stageRangeOf cfg pl stage =
472475 fromMaybe
473476 undefined
474477 (stageRange cfg minBound (toEnum (fromEnum pl * cfg. sliceLength)) stage)
475478
479+ -- | WARNING This fails if the slot is earlier than the beginning of the stage
480+ -- in the first iteration (ie @'PipelineNo' 0@)
476481pipelineOf :: forall p . IsPipeline p => LeiosConfig -> Stage p -> SlotNo -> PipelineNo
477482pipelineOf cfg stage sl =
478- toEnum $
479- fromMaybe undefined (fromEnum <$> stageStart cfg stage sl minBound )
480- `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 LeiosConfig {pipeline} -> case pipeline of
491+ SingSingleVote -> " SingleVote"
492+ SingSplitVote -> " SplitVote"
481493
482494forEachPipeline :: (forall p . Stage p ) -> (forall p . IsPipeline p => Stage p -> a ) -> [a ]
483495forEachPipeline s k = [k @ SingleVote s, k @ SplitVote s]
484496
497+ lastEndorse :: LeiosConfig -> PipelineNo -> SlotNo
498+ lastEndorse leios@ LeiosConfig {pipeline = _ :: SingPipeline p } pipelineNo =
499+ snd $ stageRangeOf @ p leios pipelineNo Endorse
500+
485501lastVoteSend :: LeiosConfig -> PipelineNo -> SlotNo
486502lastVoteSend leios@ LeiosConfig {pipeline} pipelineNo = case pipeline of
487503 SingSingleVote -> snd (stageRangeOf leios pipelineNo Vote )
@@ -663,48 +679,71 @@ data EndorseBlocksSnapshot = EndorseBlocksSnapshot
663679 , certifiedEndorseBlocks :: (PipelineNo , PipelineNo ) -> [(PipelineNo , [(EndorseBlock , Certificate , UTCTime )])]
664680 }
665681
682+ -- | In which contemporary stage was an IB delivered
683+ data IbDeliveryStage =
684+ IbDuringProposeOrDeliver1
685+ -- ^ The node will not vote for an EB that excludes IBs that arrived during
686+ -- Propose or Deliver1.
687+ --
688+ -- The node will include IBs that arrived during Propose or Deliver1 in an
689+ -- EB it makes.
690+ |
691+ IbDuringDeliver2
692+ -- ^ The node will include IBs that arrived during Deliver2 in an EB it makes.
693+ |
694+ IbDuringEndorse
695+ -- ^ The node will not vote for an EB that includes IBs that arrived later
696+ -- than Endorse.
697+ deriving (Bounded , Enum , Eq , Ord , Show )
698+
666699-- | Both constraints are inclusive.
667700data InputBlocksQuery = InputBlocksQuery
668- { generatedBetween :: (SlotNo , SlotNo )
669- , receivedBy :: SlotNo
701+ { generatedBetween :: (PipelineNo , PipelineNo )
702+ , receivedBy :: IbDeliveryStage
670703 -- ^ This is checked against time the body is downloaded, before validation.
671704 }
672705
673- inputBlocksToEndorse1 ::
674- LeiosConfig ->
675- -- | current slot
676- SlotNo ->
677- InputBlocksSnapshot ->
678- [InputBlockId ]
679- inputBlocksToEndorse1 cfg@ LeiosConfig {pipeline = _ :: SingPipeline p } current buffer = fromMaybe [] $ do
680- generatedBetween <- stageRange @ p cfg Endorse current Propose
681- receivedBy <- stageEnd @ p cfg Endorse current Deliver2
682- pure $
683- buffer. validInputBlocks
684- InputBlocksQuery
685- { generatedBetween
686- , receivedBy
687- }
706+ ibWasDeliveredLate :: LeiosConfig -> SlotConfig -> SlotNo -> UTCTime -> Bool
707+ ibWasDeliveredLate cfg slotCfg sl deliveryTime =
708+ case ibDeliveryStage cfg slotCfg sl deliveryTime of
709+ Nothing -> True
710+ Just {} -> False
711+
712+ ibDeliveryStage :: LeiosConfig -> SlotConfig -> SlotNo -> UTCTime -> Maybe IbDeliveryStage
713+ ibDeliveryStage
714+ cfg@ LeiosConfig {pipeline = _ :: SingPipeline p }
715+ slotCfg
716+ ibSlot
717+ deliveryTime
718+ | before loPropose = Nothing -- TODO future blocks?
719+ | before loDeliver2 = Just IbDuringProposeOrDeliver1
720+ | before loEndorse = Just IbDuringDeliver2
721+ | before (succ hiEndorse) = Just IbDuringEndorse
722+ | otherwise = Nothing -- TODO late blocks?
723+ where
724+ p = pipelineOf @ p cfg Propose ibSlot
725+
726+ before sl = deliveryTime < slotTime slotCfg sl
727+
728+ (loPropose, _) = stageRangeOf @ p cfg p Propose
729+ (loDeliver2, _) = stageRangeOf @ p cfg p Deliver2
730+ (loEndorse, hiEndorse) = stageRangeOf @ p cfg p Endorse
688731
689- -- | Invokes 'inputBlocksToEndorse1' as many times as 'lateIbInclusion'
690- -- requires
691732inputBlocksToEndorse ::
692733 LeiosConfig ->
693734 -- | current slot
694735 SlotNo ->
695736 InputBlocksSnapshot ->
696737 [InputBlockId ]
697- inputBlocksToEndorse cfg current buffer =
698- concatMap each iterations
699- where
700- each sl = inputBlocksToEndorse1 cfg sl buffer
701- capL = fromIntegral cfg. sliceLength
702- iterations =
703- if not cfg. lateIbInclusion
704- then [current]
705- else
706- -- discard underflows
707- dropWhile (> current) [current - 2 * capL, current - capL, current]
738+ inputBlocksToEndorse cfg@ LeiosConfig {pipeline = _ :: SingPipeline p } current buffer =
739+ let hi = pipelineOf @ p cfg Endorse current in
740+ let lo = if cfg. lateIbInclusion then pipelineMonus hi 2 else hi
741+ in
742+ buffer. validInputBlocks
743+ InputBlocksQuery
744+ { generatedBetween = (lo, hi)
745+ , receivedBy = IbDuringDeliver2
746+ }
708747
709748-- | Returns possible EBs to reference from current pipeline EB.
710749endorseBlocksToReference ::
@@ -760,21 +799,24 @@ shouldVoteOnEB ::
760799shouldVoteOnEB cfg@ LeiosConfig {voteSendStage} _ slot _buffers _
761800 -- checks whether a pipeline has been started before.
762801 | Nothing <- stageRange cfg voteSendStage slot Propose = const False
763- shouldVoteOnEB cfg@ LeiosConfig {voteSendStage} slotConfig slot buffers ebuffers = cond
802+ shouldVoteOnEB cfg@ LeiosConfig {voteSendStage = voteSendStage :: Stage p } slotConfig slot buffers ebuffers = cond
764803 where
765- generatedBetween = fromMaybe (error " impossible" ) $ stageRange cfg voteSendStage slot Propose
804+ generatedBetween = (lo, hi)
805+ where
806+ hi = pipelineOf @ p cfg voteSendStage slot
807+ lo = if cfg. lateIbInclusion then pipelineMonus hi 2 else hi
766808 receivedByEndorse =
767809 buffers. validInputBlocks
768810 InputBlocksQuery
769811 { generatedBetween
770- , receivedBy = fromMaybe ( error " impossible " ) $ stageEnd cfg voteSendStage slot Endorse
812+ , receivedBy = IbDuringEndorse
771813 }
772814 receivedByDeliver1 = buffers. validInputBlocks q
773815 where
774816 q =
775817 InputBlocksQuery
776818 { generatedBetween
777- , receivedBy = fromMaybe ( error " impossible " ) $ stageEnd cfg voteSendStage slot Deliver1
819+ , receivedBy = IbDuringProposeOrDeliver1
778820 }
779821 -- Order of references in EndorseBlock matters for ledger state, so we stick to lists.
780822 -- Note: maybe order on (slot, subSlot, vrf proof) should be used instead?
0 commit comments