@@ -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,78 @@ data EndorseBlocksSnapshot = EndorseBlocksSnapshot
663679 , certifiedEndorseBlocks :: (PipelineNo , PipelineNo ) -> [(PipelineNo , [(EndorseBlock , Certificate , UTCTime )])]
664680 }
665681
682+ -- | In which contemporary stage was an IB delivered
683+ --
684+ -- IBs cannot be deliver earlier than any of these options, due to the
685+ -- 'LeiosProtocol.Relay.shouldNotRequest' logic of the
686+ -- 'LeiosProtocol.Short.Node.relayIBState'.
687+ --
688+ -- IBs that are delivered later than any of these options are discarded,
689+ -- ignored.
690+ data IbDeliveryStage =
691+ IbDuringProposeOrDeliver1
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+ |
698+ IbDuringDeliver2
699+ -- ^ The node will include IBs that arrived during Deliver2 in an EB it makes.
700+ |
701+ IbDuringEndorse
702+ -- ^ The node will not vote for an EB that includes IBs that arrived later
703+ -- than Endorse.
704+ deriving (Bounded , Enum , Eq , Ord , Show )
705+
666706-- | Both constraints are inclusive.
667707data InputBlocksQuery = InputBlocksQuery
668- { generatedBetween :: (SlotNo , SlotNo )
669- , receivedBy :: SlotNo
708+ { generatedBetween :: (PipelineNo , PipelineNo )
709+ , receivedBy :: IbDeliveryStage
670710 -- ^ This is checked against time the body is downloaded, before validation.
671711 }
672712
673- inputBlocksToEndorse1 ::
713+ ibWasDeliveredLate :: LeiosConfig -> SlotConfig -> SlotNo -> UTCTime -> Bool
714+ ibWasDeliveredLate cfg slotCfg sl deliveryTime =
715+ case ibDeliveryStage cfg slotCfg sl deliveryTime of
716+ Nothing -> True
717+ Just {} -> False
718+
719+ ibDeliveryStage :: LeiosConfig -> SlotConfig -> SlotNo -> UTCTime -> Maybe IbDeliveryStage
720+ ibDeliveryStage
721+ cfg@ LeiosConfig {pipeline = _ :: SingPipeline p }
722+ slotCfg
723+ ibSlot
724+ deliveryTime
725+ | before loPropose = Nothing -- TODO future blocks?
726+ | before loDeliver2 = Just IbDuringProposeOrDeliver1
727+ | before loEndorse = Just IbDuringDeliver2
728+ | before (succ hiEndorse) = Just IbDuringEndorse
729+ | otherwise = Nothing -- TODO late blocks?
730+ where
731+ p = pipelineOf @ p cfg Propose ibSlot
732+
733+ before sl = deliveryTime < slotTime slotCfg sl
734+
735+ (loPropose, _) = stageRangeOf @ p cfg p Propose
736+ (loDeliver2, _) = stageRangeOf @ p cfg p Deliver2
737+ (loEndorse, hiEndorse) = stageRangeOf @ p cfg p Endorse
738+
739+ inputBlocksToEndorse ::
674740 LeiosConfig ->
675741 -- | current slot
676742 SlotNo ->
677743 InputBlocksSnapshot ->
678744 [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 $
745+ inputBlocksToEndorse cfg@ LeiosConfig {pipeline = _ :: SingPipeline p } current buffer =
683746 buffer. validInputBlocks
684747 InputBlocksQuery
685- { generatedBetween
686- , receivedBy
748+ { generatedBetween = (lo, hi)
749+ , receivedBy = IbDuringDeliver2
687750 }
688-
689- -- | Invokes 'inputBlocksToEndorse1' as many times as 'lateIbInclusion'
690- -- requires
691- inputBlocksToEndorse ::
692- LeiosConfig ->
693- -- | current slot
694- SlotNo ->
695- InputBlocksSnapshot ->
696- [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]
751+ where
752+ hi = pipelineOf @ p cfg Endorse current
753+ lo = if cfg. lateIbInclusion then pipelineMonus hi 2 else hi
708754
709755-- | Returns possible EBs to reference from current pipeline EB.
710756endorseBlocksToReference ::
@@ -760,21 +806,24 @@ shouldVoteOnEB ::
760806shouldVoteOnEB cfg@ LeiosConfig {voteSendStage} _ slot _buffers _
761807 -- checks whether a pipeline has been started before.
762808 | Nothing <- stageRange cfg voteSendStage slot Propose = const False
763- shouldVoteOnEB cfg@ LeiosConfig {voteSendStage} slotConfig slot buffers ebuffers = cond
809+ shouldVoteOnEB cfg@ LeiosConfig {voteSendStage = voteSendStage :: Stage p } slotConfig slot buffers ebuffers = cond
764810 where
765- generatedBetween = fromMaybe (error " impossible" ) $ stageRange cfg voteSendStage slot Propose
811+ generatedBetween = (lo, hi)
812+ where
813+ hi = pipelineOf @ p cfg voteSendStage slot
814+ lo = if cfg. lateIbInclusion then pipelineMonus hi 2 else hi
766815 receivedByEndorse =
767816 buffers. validInputBlocks
768817 InputBlocksQuery
769818 { generatedBetween
770- , receivedBy = fromMaybe ( error " impossible " ) $ stageEnd cfg voteSendStage slot Endorse
819+ , receivedBy = IbDuringEndorse
771820 }
772821 receivedByDeliver1 = buffers. validInputBlocks q
773822 where
774823 q =
775824 InputBlocksQuery
776825 { generatedBetween
777- , receivedBy = fromMaybe ( error " impossible " ) $ stageEnd cfg voteSendStage slot Deliver1
826+ , receivedBy = IbDuringProposeOrDeliver1
778827 }
779828 -- Order of references in EndorseBlock matters for ledger state, so we stick to lists.
780829 -- Note: maybe order on (slot, subSlot, vrf proof) should be used instead?
0 commit comments