{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NamedFieldPuns #-}
module Ouroboros.Consensus.Forecast (
Forecast (..)
, OutsideForecastRange (..)
, constantForecastInRange
, constantForecastOf
, mapForecast
, trivialForecast
, crossEraForecastBound
) where
import Control.Exception (Exception)
import Control.Monad (guard)
import Control.Monad.Except (Except, throwError)
import Data.Word (Word64)
import Ouroboros.Consensus.Block
import Ouroboros.Consensus.HardFork.History.Util (addSlots)
import Ouroboros.Consensus.Ledger.Basics (GetTip, getTipSlot)
data Forecast a = Forecast {
forall a. Forecast a -> WithOrigin SlotNo
forecastAt :: WithOrigin SlotNo
, forall a. Forecast a -> SlotNo -> Except OutsideForecastRange a
forecastFor :: SlotNo -> Except OutsideForecastRange a
}
mapForecast :: (a -> b) -> Forecast a -> Forecast b
mapForecast :: forall a b. (a -> b) -> Forecast a -> Forecast b
mapForecast a -> b
f (Forecast WithOrigin SlotNo
at SlotNo -> Except OutsideForecastRange a
for) = Forecast{
forecastAt :: WithOrigin SlotNo
forecastAt = WithOrigin SlotNo
at
, forecastFor :: SlotNo -> Except OutsideForecastRange b
forecastFor = (a -> b)
-> Except OutsideForecastRange a -> Except OutsideForecastRange b
forall a b.
(a -> b)
-> ExceptT OutsideForecastRange Identity a
-> ExceptT OutsideForecastRange Identity b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f (Except OutsideForecastRange a -> Except OutsideForecastRange b)
-> (SlotNo -> Except OutsideForecastRange a)
-> SlotNo
-> Except OutsideForecastRange b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SlotNo -> Except OutsideForecastRange a
for
}
trivialForecast :: GetTip b => b -> Forecast ()
trivialForecast :: forall b. GetTip b => b -> Forecast ()
trivialForecast b
x = () -> WithOrigin SlotNo -> Forecast ()
forall a. a -> WithOrigin SlotNo -> Forecast a
constantForecastOf () (b -> WithOrigin SlotNo
forall l. GetTip l => l -> WithOrigin SlotNo
getTipSlot b
x)
constantForecastOf :: a -> WithOrigin SlotNo -> Forecast a
constantForecastOf :: forall a. a -> WithOrigin SlotNo -> Forecast a
constantForecastOf = Maybe SlotNo -> a -> WithOrigin SlotNo -> Forecast a
forall a. Maybe SlotNo -> a -> WithOrigin SlotNo -> Forecast a
constantForecastInRange Maybe SlotNo
forall a. Maybe a
Nothing
constantForecastInRange :: Maybe SlotNo -> a -> WithOrigin SlotNo -> Forecast a
constantForecastInRange :: forall a. Maybe SlotNo -> a -> WithOrigin SlotNo -> Forecast a
constantForecastInRange Maybe SlotNo
range' a
a WithOrigin SlotNo
at = Forecast {
forecastAt :: WithOrigin SlotNo
forecastAt = WithOrigin SlotNo
at
, forecastFor :: SlotNo -> Except OutsideForecastRange a
forecastFor = Maybe SlotNo -> SlotNo -> Except OutsideForecastRange a
forall {m :: * -> *}.
MonadError OutsideForecastRange m =>
Maybe SlotNo -> SlotNo -> m a
forecastForWithRange Maybe SlotNo
range'
}
where
forecastForWithRange :: Maybe SlotNo -> SlotNo -> m a
forecastForWithRange Maybe SlotNo
Nothing = \SlotNo
for ->
if SlotNo -> WithOrigin SlotNo
forall t. t -> WithOrigin t
NotOrigin SlotNo
for WithOrigin SlotNo -> WithOrigin SlotNo -> Bool
forall a. Ord a => a -> a -> Bool
>= WithOrigin SlotNo
at
then a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
else [Char] -> m a
forall a. HasCallStack => [Char] -> a
error [Char]
"constantForecastOf: precondition violated"
forecastForWithRange (Just SlotNo
range) = \SlotNo
for ->
let outsideForecastMaxFor :: SlotNo
outsideForecastMaxFor = WithOrigin SlotNo -> SlotNo
forall t. (Bounded t, Enum t) => WithOrigin t -> t
succWithOrigin WithOrigin SlotNo
at SlotNo -> SlotNo -> SlotNo
forall a. Num a => a -> a -> a
+ SlotNo
range
in if SlotNo
for SlotNo -> SlotNo -> Bool
forall a. Ord a => a -> a -> Bool
>= SlotNo
outsideForecastMaxFor
then OutsideForecastRange -> m a
forall a. OutsideForecastRange -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (OutsideForecastRange -> m a) -> OutsideForecastRange -> m a
forall a b. (a -> b) -> a -> b
$ OutsideForecastRange {
outsideForecastAt :: WithOrigin SlotNo
outsideForecastAt = WithOrigin SlotNo
at
, SlotNo
outsideForecastMaxFor :: SlotNo
outsideForecastMaxFor :: SlotNo
outsideForecastMaxFor
, outsideForecastFor :: SlotNo
outsideForecastFor = SlotNo
for
}
else Maybe SlotNo -> SlotNo -> m a
forecastForWithRange Maybe SlotNo
forall a. Maybe a
Nothing SlotNo
for
data OutsideForecastRange =
OutsideForecastRange {
OutsideForecastRange -> WithOrigin SlotNo
outsideForecastAt :: !(WithOrigin SlotNo)
, OutsideForecastRange -> SlotNo
outsideForecastMaxFor :: !SlotNo
, OutsideForecastRange -> SlotNo
outsideForecastFor :: !SlotNo
}
deriving (Int -> OutsideForecastRange -> ShowS
[OutsideForecastRange] -> ShowS
OutsideForecastRange -> [Char]
(Int -> OutsideForecastRange -> ShowS)
-> (OutsideForecastRange -> [Char])
-> ([OutsideForecastRange] -> ShowS)
-> Show OutsideForecastRange
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> OutsideForecastRange -> ShowS
showsPrec :: Int -> OutsideForecastRange -> ShowS
$cshow :: OutsideForecastRange -> [Char]
show :: OutsideForecastRange -> [Char]
$cshowList :: [OutsideForecastRange] -> ShowS
showList :: [OutsideForecastRange] -> ShowS
Show, OutsideForecastRange -> OutsideForecastRange -> Bool
(OutsideForecastRange -> OutsideForecastRange -> Bool)
-> (OutsideForecastRange -> OutsideForecastRange -> Bool)
-> Eq OutsideForecastRange
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: OutsideForecastRange -> OutsideForecastRange -> Bool
== :: OutsideForecastRange -> OutsideForecastRange -> Bool
$c/= :: OutsideForecastRange -> OutsideForecastRange -> Bool
/= :: OutsideForecastRange -> OutsideForecastRange -> Bool
Eq)
instance Exception OutsideForecastRange
crossEraForecastBound ::
WithOrigin SlotNo
-> SlotNo
-> Word64
-> Word64
-> SlotNo
crossEraForecastBound :: WithOrigin SlotNo -> SlotNo -> Word64 -> Word64 -> SlotNo
crossEraForecastBound WithOrigin SlotNo
currentTip SlotNo
transitionSlot Word64
currentLookahead Word64
nextLookahead =
SlotNo -> (SlotNo -> SlotNo) -> Maybe SlotNo -> SlotNo
forall b a. b -> (a -> b) -> Maybe a -> b
maybe SlotNo
boundFromNextEra (SlotNo -> SlotNo -> SlotNo
forall a. Ord a => a -> a -> a
min SlotNo
boundFromNextEra) Maybe SlotNo
boundFromCurrentEra
where
tipSucc :: SlotNo
tipSucc :: SlotNo
tipSucc = WithOrigin SlotNo -> SlotNo
forall t. (Bounded t, Enum t) => WithOrigin t -> t
succWithOrigin WithOrigin SlotNo
currentTip
boundFromCurrentEra :: Maybe SlotNo
boundFromCurrentEra :: Maybe SlotNo
boundFromCurrentEra = do
Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (SlotNo
tipSucc SlotNo -> SlotNo -> Bool
forall a. Ord a => a -> a -> Bool
< SlotNo
transitionSlot)
SlotNo -> Maybe SlotNo
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return (SlotNo -> Maybe SlotNo) -> SlotNo -> Maybe SlotNo
forall a b. (a -> b) -> a -> b
$ Word64 -> SlotNo -> SlotNo
addSlots Word64
currentLookahead SlotNo
tipSucc
boundFromNextEra :: SlotNo
boundFromNextEra :: SlotNo
boundFromNextEra = Word64 -> SlotNo -> SlotNo
addSlots Word64
nextLookahead SlotNo
transitionSlot