module Cardano.Ledger.Shelley.StabilityWindow
  ( computeStabilityWindow,
    computeRandomnessStabilisationWindow,
  )
where

import Cardano.Ledger.BaseTypes
import Data.Word (Word64)

-- | Calculate the stability window (e.g. the number of slots needed for a block
-- to become stable) from the security param and the active slot coefficient.
--
-- The value 3k/f is determined to be a suitabe value as per
-- https://docs.google.com/document/d/1B8BNMx8jVWRjYiUBOaI3jfZ7dQNvNTSDODvT5iOuYCU/edit#heading=h.qh2zcajmu6hm
computeStabilityWindow ::
  Word64 ->
  ActiveSlotCoeff ->
  Word64
computeStabilityWindow :: Word64 -> ActiveSlotCoeff -> Word64
computeStabilityWindow Word64
k ActiveSlotCoeff
asc =
  Rational -> Word64
forall a b. (RealFrac a, Integral b) => a -> b
ceiling (Rational -> Word64) -> Rational -> Word64
forall a b. (a -> b) -> a -> b
$ (Rational
3 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Word64 -> Rational
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
k) Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ Rational
f
  where
    f :: Rational
f = PositiveUnitInterval -> Rational
forall r. BoundedRational r => r -> Rational
unboundRational (PositiveUnitInterval -> Rational)
-> (ActiveSlotCoeff -> PositiveUnitInterval)
-> ActiveSlotCoeff
-> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ActiveSlotCoeff -> PositiveUnitInterval
activeSlotVal (ActiveSlotCoeff -> Rational) -> ActiveSlotCoeff -> Rational
forall a b. (a -> b) -> a -> b
$ ActiveSlotCoeff
asc

-- | Calculate the randomness stabilisation window from the security param and
-- the active slot coefficient.
--
-- The value 4k/f is determined to be a suitabe value as per
-- https://docs.google.com/document/d/1B8BNMx8jVWRjYiUBOaI3jfZ7dQNvNTSDODvT5iOuYCU/edit#heading=h.qh2zcajmu6hm
computeRandomnessStabilisationWindow ::
  Word64 ->
  ActiveSlotCoeff ->
  Word64
computeRandomnessStabilisationWindow :: Word64 -> ActiveSlotCoeff -> Word64
computeRandomnessStabilisationWindow Word64
k ActiveSlotCoeff
asc =
  Rational -> Word64
forall a b. (RealFrac a, Integral b) => a -> b
ceiling (Rational -> Word64) -> Rational -> Word64
forall a b. (a -> b) -> a -> b
$ (Rational
4 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Word64 -> Rational
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
k) Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ Rational
f
  where
    f :: Rational
f = PositiveUnitInterval -> Rational
forall r. BoundedRational r => r -> Rational
unboundRational (PositiveUnitInterval -> Rational)
-> (ActiveSlotCoeff -> PositiveUnitInterval)
-> ActiveSlotCoeff
-> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ActiveSlotCoeff -> PositiveUnitInterval
activeSlotVal (ActiveSlotCoeff -> Rational) -> ActiveSlotCoeff -> Rational
forall a b. (a -> b) -> a -> b
$ ActiveSlotCoeff
asc