@@ -467,21 +467,37 @@ isStage cfg stage slot = fromEnum slot >= cfg.sliceLength * fromEnum stage
467
467
newtype PipelineNo = PipelineNo Word64
468
468
deriving (Bounded , Enum , Show , Eq , Ord )
469
469
470
+ pipelineMonus :: PipelineNo -> Word64 -> PipelineNo
471
+ pipelineMonus (PipelineNo w) i = PipelineNo $ w - min w i
472
+
470
473
stageRangeOf :: forall p . IsPipeline p => LeiosConfig -> PipelineNo -> Stage p -> (SlotNo , SlotNo )
471
474
stageRangeOf cfg pl stage =
472
475
fromMaybe
473
476
undefined
474
477
(stageRange cfg minBound (toEnum (fromEnum pl * cfg. sliceLength)) stage)
475
478
479
+ -- | WARNING This fails if the slot is earlier than the beginning of the stage
480
+ -- in the first iteration (ie @'PipelineNo' 0@)
476
481
pipelineOf :: forall p . IsPipeline p => LeiosConfig -> Stage p -> SlotNo -> PipelineNo
477
482
pipelineOf 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"
481
493
482
494
forEachPipeline :: (forall p . Stage p ) -> (forall p . IsPipeline p => Stage p -> a ) -> [a ]
483
495
forEachPipeline s k = [k @ SingleVote s, k @ SplitVote s]
484
496
497
+ lastEndorse :: LeiosConfig -> PipelineNo -> SlotNo
498
+ lastEndorse leios@ LeiosConfig {pipeline = _ :: SingPipeline p } pipelineNo =
499
+ snd $ stageRangeOf @ p leios pipelineNo Endorse
500
+
485
501
lastVoteSend :: LeiosConfig -> PipelineNo -> SlotNo
486
502
lastVoteSend leios@ LeiosConfig {pipeline} pipelineNo = case pipeline of
487
503
SingSingleVote -> snd (stageRangeOf leios pipelineNo Vote )
@@ -663,48 +679,78 @@ data EndorseBlocksSnapshot = EndorseBlocksSnapshot
663
679
, certifiedEndorseBlocks :: (PipelineNo , PipelineNo ) -> [(PipelineNo , [(EndorseBlock , Certificate , UTCTime )])]
664
680
}
665
681
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
+
666
706
-- | Both constraints are inclusive.
667
707
data InputBlocksQuery = InputBlocksQuery
668
- { generatedBetween :: (SlotNo , SlotNo )
669
- , receivedBy :: SlotNo
708
+ { generatedBetween :: (PipelineNo , PipelineNo )
709
+ , receivedBy :: IbDeliveryStage
670
710
-- ^ This is checked against time the body is downloaded, before validation.
671
711
}
672
712
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 ::
674
740
LeiosConfig ->
675
741
-- | current slot
676
742
SlotNo ->
677
743
InputBlocksSnapshot ->
678
744
[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 =
683
746
buffer. validInputBlocks
684
747
InputBlocksQuery
685
- { generatedBetween
686
- , receivedBy
748
+ { generatedBetween = (lo, hi)
749
+ , receivedBy = IbDuringDeliver2
687
750
}
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
708
754
709
755
-- | Returns possible EBs to reference from current pipeline EB.
710
756
endorseBlocksToReference ::
@@ -760,21 +806,24 @@ shouldVoteOnEB ::
760
806
shouldVoteOnEB cfg@ LeiosConfig {voteSendStage} _ slot _buffers _
761
807
-- checks whether a pipeline has been started before.
762
808
| 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
764
810
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
766
815
receivedByEndorse =
767
816
buffers. validInputBlocks
768
817
InputBlocksQuery
769
818
{ generatedBetween
770
- , receivedBy = fromMaybe ( error " impossible " ) $ stageEnd cfg voteSendStage slot Endorse
819
+ , receivedBy = IbDuringEndorse
771
820
}
772
821
receivedByDeliver1 = buffers. validInputBlocks q
773
822
where
774
823
q =
775
824
InputBlocksQuery
776
825
{ generatedBetween
777
- , receivedBy = fromMaybe ( error " impossible " ) $ stageEnd cfg voteSendStage slot Deliver1
826
+ , receivedBy = IbDuringProposeOrDeliver1
778
827
}
779
828
-- Order of references in EndorseBlock matters for ledger state, so we stick to lists.
780
829
-- Note: maybe order on (slot, subSlot, vrf proof) should be used instead?
0 commit comments