@@ -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,71 @@ 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
+ 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
+
666
699
-- | Both constraints are inclusive.
667
700
data InputBlocksQuery = InputBlocksQuery
668
- { generatedBetween :: (SlotNo , SlotNo )
669
- , receivedBy :: SlotNo
701
+ { generatedBetween :: (PipelineNo , PipelineNo )
702
+ , receivedBy :: IbDeliveryStage
670
703
-- ^ This is checked against time the body is downloaded, before validation.
671
704
}
672
705
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
688
731
689
- -- | Invokes 'inputBlocksToEndorse1' as many times as 'lateIbInclusion'
690
- -- requires
691
732
inputBlocksToEndorse ::
692
733
LeiosConfig ->
693
734
-- | current slot
694
735
SlotNo ->
695
736
InputBlocksSnapshot ->
696
737
[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
+ }
708
747
709
748
-- | Returns possible EBs to reference from current pipeline EB.
710
749
endorseBlocksToReference ::
@@ -760,21 +799,24 @@ shouldVoteOnEB ::
760
799
shouldVoteOnEB cfg@ LeiosConfig {voteSendStage} _ slot _buffers _
761
800
-- checks whether a pipeline has been started before.
762
801
| 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
764
803
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
766
808
receivedByEndorse =
767
809
buffers. validInputBlocks
768
810
InputBlocksQuery
769
811
{ generatedBetween
770
- , receivedBy = fromMaybe ( error " impossible " ) $ stageEnd cfg voteSendStage slot Endorse
812
+ , receivedBy = IbDuringEndorse
771
813
}
772
814
receivedByDeliver1 = buffers. validInputBlocks q
773
815
where
774
816
q =
775
817
InputBlocksQuery
776
818
{ generatedBetween
777
- , receivedBy = fromMaybe ( error " impossible " ) $ stageEnd cfg voteSendStage slot Deliver1
819
+ , receivedBy = IbDuringProposeOrDeliver1
778
820
}
779
821
-- Order of references in EndorseBlock matters for ledger state, so we stick to lists.
780
822
-- Note: maybe order on (slot, subSlot, vrf proof) should be used instead?
0 commit comments