@@ -42,6 +42,8 @@ module Ouroboros.Consensus.HardFork.History.Qry
42
42
, slotToSlotLength
43
43
, slotToWallclock
44
44
, wallclockToSlot
45
+ , perasRoundNoToSlot
46
+ , slotToPerasRoundNo
45
47
) where
46
48
47
49
import Codec.Serialise (Serialise (.. ))
@@ -126,6 +128,8 @@ import Quiet
126
128
127
129
These are equal by (INV-2a).
128
130
131
+ 5. Slot to Peras round translation.
132
+
129
133
This means that for values at that boundary, it does not matter if we use
130
134
this era or the next era for the translation. However, this is only true for
131
135
these 4 translations. If we are returning the era parameters directly, then
@@ -182,12 +186,14 @@ newtype TimeInSlot = TimeInSlot {getTimeInSlot :: NominalDiffTime} deriving Gene
182
186
newtype SlotInEra = SlotInEra { getSlotInEra :: Word64 } deriving Generic
183
187
newtype SlotInEpoch = SlotInEpoch { getSlotInEpoch :: Word64 } deriving Generic
184
188
newtype EpochInEra = EpochInEra { getEpochInEra :: Word64 } deriving Generic
189
+ newtype PerasRoundNoInEra = PerasRoundNoInEra { getPerasRoundNoInEra :: Word64 } deriving Generic
185
190
186
191
deriving via Quiet TimeInEra instance Show TimeInEra
187
192
deriving via Quiet TimeInSlot instance Show TimeInSlot
188
193
deriving via Quiet SlotInEra instance Show SlotInEra
189
194
deriving via Quiet SlotInEpoch instance Show SlotInEpoch
190
195
deriving via Quiet EpochInEra instance Show EpochInEra
196
+ deriving via Quiet PerasRoundNoInEra instance Show PerasRoundNoInEra
191
197
192
198
{- ------------------------------------------------------------------------------
193
199
Expressions
@@ -212,29 +218,34 @@ data Expr (f :: Type -> Type) :: Type -> Type where
212
218
EAbsToRelTime :: Expr f RelativeTime -> Expr f TimeInEra
213
219
EAbsToRelSlot :: Expr f SlotNo -> Expr f SlotInEra
214
220
EAbsToRelEpoch :: Expr f EpochNo -> Expr f EpochInEra
221
+ EAbsToRelPerasRoundNo :: Expr f PerasRoundNo -> Expr f PerasRoundNoInEra
215
222
-- Convert from era-relative to absolute
216
223
217
224
ERelToAbsTime :: Expr f TimeInEra -> Expr f RelativeTime
218
225
ERelToAbsSlot :: Expr f (SlotInEra , TimeInSlot ) -> Expr f SlotNo
219
226
ERelToAbsEpoch :: Expr f (EpochInEra , SlotInEpoch ) -> Expr f EpochNo
227
+ ERelToAbsPerasRoundNo :: Expr f PerasRoundNoInEra -> Expr f PerasRoundNo
220
228
-- Convert between relative values
221
229
222
230
ERelTimeToSlot :: Expr f TimeInEra -> Expr f (SlotInEra , TimeInSlot )
223
231
ERelSlotToTime :: Expr f SlotInEra -> Expr f TimeInEra
224
232
ERelSlotToEpoch :: Expr f SlotInEra -> Expr f (EpochInEra , SlotInEpoch )
225
233
ERelEpochToSlot :: Expr f EpochInEra -> Expr f SlotInEra
234
+ ERelPerasRoundNoToSlot :: Expr f PerasRoundNoInEra -> Expr f SlotInEra
235
+ ERelSlotToPerasRoundNo :: Expr f SlotInEra -> Expr f PerasRoundNoInEra
226
236
-- Get era parameters
227
237
228
238
-- The arguments are used for bound checks
229
239
ESlotLength :: Expr f SlotNo -> Expr f SlotLength
230
240
EEpochSize :: Expr f EpochNo -> Expr f EpochSize
231
241
EGenesisWindow :: Expr f SlotNo -> Expr f GenesisWindow
242
+ EPerasRoundLength :: Expr f SlotNo -> Expr f PerasRoundLength
232
243
233
244
{- ------------------------------------------------------------------------------
234
245
Interpreter
235
246
-------------------------------------------------------------------------------}
236
247
237
- evalExprInEra :: EraSummary -> ClosedExpr a -> Maybe a
248
+ evalExprInEra :: HasCallStack => forall a . EraSummary -> ClosedExpr a -> Maybe a
238
249
evalExprInEra EraSummary {.. } = \ (ClosedExpr e) -> go e
239
250
where
240
251
EraParams {.. } = eraParams
@@ -279,6 +290,11 @@ evalExprInEra EraSummary{..} = \(ClosedExpr e) -> go e
279
290
e <- go expr
280
291
guard (e >= boundEpoch eraStart)
281
292
return $ EpochInEra (countEpochs e (boundEpoch eraStart))
293
+ go (EAbsToRelPerasRoundNo expr) = do
294
+ absPerasRoundNo <- go expr
295
+ guard $ absPerasRoundNo >= boundPerasRound eraStart
296
+ -- TODO(geo2a): check we are in Peras-enabled era
297
+ pure $ PerasRoundNoInEra (countPerasRounds absPerasRoundNo (boundPerasRound eraStart))
282
298
283
299
-- Convert relative to absolute
284
300
--
@@ -304,6 +320,12 @@ evalExprInEra EraSummary{..} = \(ClosedExpr e) -> go e
304
320
absEpoch < boundEpoch end
305
321
|| absEpoch == boundEpoch end && getSlotInEpoch s == 0
306
322
return absEpoch
323
+ go (ERelToAbsPerasRoundNo expr) = do
324
+ relPerasRound <- go expr
325
+ let absPerasRound = addPerasRounds (getPerasRoundNoInEra relPerasRound) (boundPerasRound eraStart)
326
+ guardEnd $ \ end -> absPerasRound <= boundPerasRound end
327
+ -- TODO(geo2a): how to check that we are in Peras-enabled era?
328
+ pure absPerasRound
307
329
308
330
-- Convert between relative values
309
331
--
@@ -321,7 +343,15 @@ evalExprInEra EraSummary{..} = \(ClosedExpr e) -> go e
321
343
go (ERelEpochToSlot expr) = do
322
344
e <- go expr
323
345
return $ SlotInEra (getEpochInEra e * epochSize)
324
-
346
+ go (ERelPerasRoundNoToSlot expr) = do
347
+ r <- go expr
348
+ let slot = getPerasRoundNoInEra r * unPerasRoundLength eraPerasRoundLength
349
+ pure (SlotInEra slot)
350
+ go (ERelSlotToPerasRoundNo expr) = do
351
+ s <- go expr
352
+ let perasRoundNo = getSlotInEra s `div` unPerasRoundLength eraPerasRoundLength
353
+ guardEnd $ \ end -> perasRoundNo < unPerasRoundNo (boundPerasRound end)
354
+ pure (PerasRoundNoInEra perasRoundNo)
325
355
-- Get era parameters
326
356
--
327
357
-- Here the upper bound must definitely be exclusive, or we'd return the
@@ -342,6 +372,14 @@ evalExprInEra EraSummary{..} = \(ClosedExpr e) -> go e
342
372
guard $ s >= boundSlot eraStart
343
373
guardEnd $ \ end -> s < boundSlot end
344
374
return eraGenesisWin
375
+ go (EPerasRoundLength expr) = do
376
+ s <- go expr
377
+ guard $ s >= boundSlot eraStart
378
+ guardEnd $ \ end -> s < boundSlot end
379
+ -- TODO(geo2a): do we need to check that round length divides epoch length here?
380
+ ((_, _), es) <- go $ slotToEpochExpr s
381
+ guard $ (unEpochSize es) `mod` (unPerasRoundLength eraPerasRoundLength) == 0
382
+ return eraPerasRoundLength
345
383
346
384
{- ------------------------------------------------------------------------------
347
385
PastHorizonException
@@ -382,7 +420,9 @@ instance Exception PastHorizonException
382
420
runQuery ::
383
421
forall a xs .
384
422
HasCallStack =>
385
- Qry a -> Summary xs -> Either PastHorizonException a
423
+ Qry a ->
424
+ Summary xs ->
425
+ Either PastHorizonException a
386
426
runQuery qry (Summary summary) = go summary
387
427
where
388
428
go :: NonEmpty xs' EraSummary -> Either PastHorizonException a
@@ -528,6 +568,17 @@ epochToSize :: EpochNo -> Qry EpochSize
528
568
epochToSize absEpoch =
529
569
qryFromExpr (epochToSizeExpr absEpoch)
530
570
571
+ -- | Translate 'PerasRoundNo' to the 'SlotNo' of the first slot in that Peras round
572
+ --
573
+ -- Additionally returns the length of the round.
574
+ -- perasRoundNoToSlot :: PerasRoundNo -> Qry (SlotNo, PerasRoundLength)
575
+ perasRoundNoToSlot :: PerasRoundNo -> Qry SlotNo
576
+ perasRoundNoToSlot perasRoundNo = qryFromExpr (perasRoundNoToSlotExpr perasRoundNo)
577
+
578
+ -- | Translate 'SlotNo' to its corresponding 'PerasRoundNo'
579
+ slotToPerasRoundNo :: SlotNo -> Qry PerasRoundNo
580
+ slotToPerasRoundNo absSlot = qryFromExpr (slotToPerasRoundNoExpr absSlot)
581
+
531
582
{- ------------------------------------------------------------------------------
532
583
Supporting expressions for the queries above
533
584
-------------------------------------------------------------------------------}
@@ -581,6 +632,17 @@ slotToGenesisWindow :: SlotNo -> Expr f GenesisWindow
581
632
slotToGenesisWindow absSlot =
582
633
EGenesisWindow (ELit absSlot)
583
634
635
+ perasRoundNoToSlotExpr :: PerasRoundNo -> Expr f SlotNo
636
+ perasRoundNoToSlotExpr absPerasRoundNo =
637
+ let relPerasRoundExpr = EAbsToRelPerasRoundNo (ELit absPerasRoundNo)
638
+ startOfSlot = ELit (TimeInSlot 0 )
639
+ in ERelToAbsSlot (EPair (ERelPerasRoundNoToSlot relPerasRoundExpr) startOfSlot)
640
+
641
+ -- SlotNo -> SlotInEra -> PerasRoundNoInEra -> PerasRoundNo
642
+
643
+ slotToPerasRoundNoExpr :: SlotNo -> Expr f PerasRoundNo
644
+ slotToPerasRoundNoExpr absSlot = ERelToAbsPerasRoundNo (ERelSlotToPerasRoundNo (EAbsToRelSlot (ELit absSlot)))
645
+
584
646
{- ------------------------------------------------------------------------------
585
647
'Show' instances
586
648
-------------------------------------------------------------------------------}
@@ -629,13 +691,18 @@ instance Show (ClosedExpr a) where
629
691
EAbsToRelTime e -> showString " EAbsToRelTime " . go n 11 e
630
692
EAbsToRelSlot e -> showString " EAbsToRelSlot " . go n 11 e
631
693
EAbsToRelEpoch e -> showString " EAbsToRelEpoch " . go n 11 e
694
+ EAbsToRelPerasRoundNo e -> showString " EAbsToRelPerasRoundNo " . go n 11 e
632
695
ERelToAbsTime e -> showString " ERelToAbsTime " . go n 11 e
633
696
ERelToAbsSlot e -> showString " ERelToAbsSlot " . go n 11 e
634
697
ERelToAbsEpoch e -> showString " ERelToAbsEpoch " . go n 11 e
698
+ ERelToAbsPerasRoundNo e -> showString " ERelToAbsPerasRoundNo " . go n 11 e
635
699
ERelTimeToSlot e -> showString " ERelTimeToSlot " . go n 11 e
636
700
ERelSlotToTime e -> showString " ERelSlotToTime " . go n 11 e
637
701
ERelSlotToEpoch e -> showString " ERelSlotToEpoch " . go n 11 e
638
702
ERelEpochToSlot e -> showString " ERelEpochToSlot " . go n 11 e
703
+ ERelPerasRoundNoToSlot e -> showString " ERelPerasRoundNoToSlot " . go n 11 e
704
+ ERelSlotToPerasRoundNo e -> showString " ERelSlotToPerasRoundNo " . go n 11 e
639
705
ESlotLength e -> showString " ESlotLength " . go n 11 e
640
706
EEpochSize e -> showString " EEpochSize " . go n 11 e
641
707
EGenesisWindow e -> showString " EGenesisWindow " . go n 11 e
708
+ EPerasRoundLength e -> showString " EPerasRoundLength " . go n 11 e
0 commit comments