{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Ouroboros.Network.Protocol.ChainSync.PipelineDecision
( PipelineDecision (..)
, MkPipelineDecision (..)
, runPipelineDecision
, constantPipelineDecision
, pipelineDecisionMax
, pipelineDecisionMin
, pipelineDecisionLowHighMark
) where
import Control.Exception (assert)
import Data.Word
import Network.TypedProtocol.Pipelined
import Ouroboros.Network.Block (BlockNo)
import Ouroboros.Network.Point (WithOrigin (..))
data PipelineDecision n where
Request :: PipelineDecision Z
Pipeline :: PipelineDecision n
CollectOrPipeline :: PipelineDecision (S n)
Collect :: PipelineDecision (S n)
data MkPipelineDecision where
MkPipelineDecision
:: (forall n. Nat n
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision n, MkPipelineDecision))
-> MkPipelineDecision
runPipelineDecision
:: MkPipelineDecision
-> Nat n -> WithOrigin BlockNo -> WithOrigin BlockNo
-> (PipelineDecision n, MkPipelineDecision)
runPipelineDecision :: MkPipelineDecision
-> Nat n
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision n, MkPipelineDecision)
runPipelineDecision (MkPipelineDecision forall (n :: N).
Nat n
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision n, MkPipelineDecision)
f) Nat n
n WithOrigin BlockNo
clientTipBlockNo WithOrigin BlockNo
serverTipBlockNo =
Nat n
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision n, MkPipelineDecision)
forall (n :: N).
Nat n
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision n, MkPipelineDecision)
f Nat n
n WithOrigin BlockNo
clientTipBlockNo WithOrigin BlockNo
serverTipBlockNo
constantPipelineDecision
:: (forall n. Nat n -> WithOrigin BlockNo -> WithOrigin BlockNo -> PipelineDecision n)
-> MkPipelineDecision
constantPipelineDecision :: (forall (n :: N).
Nat n
-> WithOrigin BlockNo -> WithOrigin BlockNo -> PipelineDecision n)
-> MkPipelineDecision
constantPipelineDecision forall (n :: N).
Nat n
-> WithOrigin BlockNo -> WithOrigin BlockNo -> PipelineDecision n
f = (forall (n :: N).
Nat n
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision n, MkPipelineDecision))
-> MkPipelineDecision
MkPipelineDecision
((forall (n :: N).
Nat n
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision n, MkPipelineDecision))
-> MkPipelineDecision)
-> (forall (n :: N).
Nat n
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision n, MkPipelineDecision))
-> MkPipelineDecision
forall a b. (a -> b) -> a -> b
$ \Nat n
n WithOrigin BlockNo
clientTipBlockNo WithOrigin BlockNo
serverTipBlockNo ->
(Nat n
-> WithOrigin BlockNo -> WithOrigin BlockNo -> PipelineDecision n
forall (n :: N).
Nat n
-> WithOrigin BlockNo -> WithOrigin BlockNo -> PipelineDecision n
f Nat n
n WithOrigin BlockNo
clientTipBlockNo WithOrigin BlockNo
serverTipBlockNo, (forall (n :: N).
Nat n
-> WithOrigin BlockNo -> WithOrigin BlockNo -> PipelineDecision n)
-> MkPipelineDecision
constantPipelineDecision forall (n :: N).
Nat n
-> WithOrigin BlockNo -> WithOrigin BlockNo -> PipelineDecision n
f)
pipelineDecisionMax :: Word32 -> Nat n -> WithOrigin BlockNo -> WithOrigin BlockNo
-> PipelineDecision n
pipelineDecisionMax :: Word32
-> Nat n
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> PipelineDecision n
pipelineDecisionMax Word32
omax Nat n
n WithOrigin BlockNo
cliTipBlockNo WithOrigin BlockNo
srvTipBlockNo =
case Nat n
n of
Nat n
Zero
| WithOrigin BlockNo
cliTipBlockNo WithOrigin BlockNo -> WithOrigin BlockNo -> Bool
forall a. Eq a => a -> a -> Bool
== WithOrigin BlockNo
srvTipBlockNo
-> PipelineDecision n
PipelineDecision 'Z
Request
| Bool
otherwise
-> PipelineDecision n
forall (n :: N). PipelineDecision n
Pipeline
Succ{}
| WithOrigin BlockNo
cliTipBlockNo WithOrigin BlockNo -> BlockNo -> WithOrigin BlockNo
`bnoPlus` BlockNo
n' WithOrigin BlockNo -> WithOrigin BlockNo -> Bool
forall a. Ord a => a -> a -> Bool
>= WithOrigin BlockNo
srvTipBlockNo Bool -> Bool -> Bool
|| BlockNo
n' BlockNo -> BlockNo -> Bool
forall a. Ord a => a -> a -> Bool
>= BlockNo
omax'
-> PipelineDecision n
forall (n :: N). PipelineDecision ('S n)
Collect
| Bool
otherwise
-> PipelineDecision n
forall (n :: N). PipelineDecision n
Pipeline
where
n' :: BlockNo
n' :: BlockNo
n' = Int -> BlockNo
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Nat n -> Int
forall (n :: N). Nat n -> Int
natToInt Nat n
n)
omax' :: BlockNo
omax' :: BlockNo
omax' = Word32 -> BlockNo
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
omax
pipelineDecisionMin :: Word32 -> Nat n -> WithOrigin BlockNo -> WithOrigin BlockNo
-> PipelineDecision n
pipelineDecisionMin :: Word32
-> Nat n
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> PipelineDecision n
pipelineDecisionMin Word32
omax Nat n
n WithOrigin BlockNo
cliTipBlockNo WithOrigin BlockNo
srvTipBlockNo =
case Nat n
n of
Nat n
Zero
| WithOrigin BlockNo
cliTipBlockNo WithOrigin BlockNo -> WithOrigin BlockNo -> Bool
forall a. Eq a => a -> a -> Bool
== WithOrigin BlockNo
srvTipBlockNo
-> PipelineDecision n
PipelineDecision 'Z
Request
| Bool
otherwise
-> PipelineDecision n
forall (n :: N). PipelineDecision n
Pipeline
Succ{}
| WithOrigin BlockNo
cliTipBlockNo WithOrigin BlockNo -> BlockNo -> WithOrigin BlockNo
`bnoPlus` BlockNo
n' WithOrigin BlockNo -> WithOrigin BlockNo -> Bool
forall a. Ord a => a -> a -> Bool
>= WithOrigin BlockNo
srvTipBlockNo Bool -> Bool -> Bool
|| BlockNo
n' BlockNo -> BlockNo -> Bool
forall a. Ord a => a -> a -> Bool
>= BlockNo
omax'
-> PipelineDecision n
forall (n :: N). PipelineDecision ('S n)
Collect
| Bool
otherwise
-> PipelineDecision n
forall (n :: N). PipelineDecision ('S n)
CollectOrPipeline
where
n' :: BlockNo
n' :: BlockNo
n' = Int -> BlockNo
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Nat n -> Int
forall (n :: N). Nat n -> Int
natToInt Nat n
n)
omax' :: BlockNo
omax' :: BlockNo
omax' = Word32 -> BlockNo
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
omax
pipelineDecisionLowHighMark :: Word32 -> Word32-> MkPipelineDecision
pipelineDecisionLowHighMark :: Word32 -> Word32 -> MkPipelineDecision
pipelineDecisionLowHighMark Word32
lowMark Word32
highMark =
Bool -> MkPipelineDecision -> MkPipelineDecision
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Word32
lowMark Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word32
highMark) MkPipelineDecision
goLow
where
goZero :: Nat Z -> WithOrigin BlockNo -> WithOrigin BlockNo
-> (PipelineDecision Z, MkPipelineDecision)
goZero :: Nat 'Z
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision 'Z, MkPipelineDecision)
goZero Nat 'Z
Zero WithOrigin BlockNo
clientTipBlockNo WithOrigin BlockNo
serverTipBlockNo
| WithOrigin BlockNo
clientTipBlockNo WithOrigin BlockNo -> WithOrigin BlockNo -> Bool
forall a. Eq a => a -> a -> Bool
== WithOrigin BlockNo
serverTipBlockNo
= (PipelineDecision 'Z
Request, MkPipelineDecision
goLow)
| Bool
otherwise
= (PipelineDecision 'Z
forall (n :: N). PipelineDecision n
Pipeline, MkPipelineDecision
goLow)
goLow, goHigh :: MkPipelineDecision
goLow :: MkPipelineDecision
goLow = (forall (n :: N).
Nat n
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision n, MkPipelineDecision))
-> MkPipelineDecision
MkPipelineDecision ((forall (n :: N).
Nat n
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision n, MkPipelineDecision))
-> MkPipelineDecision)
-> (forall (n :: N).
Nat n
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision n, MkPipelineDecision))
-> MkPipelineDecision
forall a b. (a -> b) -> a -> b
$
\Nat n
n WithOrigin BlockNo
clientTipBlockNo WithOrigin BlockNo
serverTipBlockNo ->
case Nat n
n of
Nat n
Zero -> Nat 'Z
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision 'Z, MkPipelineDecision)
goZero Nat n
Nat 'Z
n WithOrigin BlockNo
clientTipBlockNo WithOrigin BlockNo
serverTipBlockNo
Succ{} | WithOrigin BlockNo
clientTipBlockNo WithOrigin BlockNo -> BlockNo -> WithOrigin BlockNo
`bnoPlus` BlockNo
n' WithOrigin BlockNo -> WithOrigin BlockNo -> Bool
forall a. Ord a => a -> a -> Bool
>= WithOrigin BlockNo
serverTipBlockNo
-> (PipelineDecision n
forall (n :: N). PipelineDecision ('S n)
Collect, MkPipelineDecision
goLow)
| BlockNo
n' BlockNo -> BlockNo -> Bool
forall a. Ord a => a -> a -> Bool
>= BlockNo
highMark'
-> (PipelineDecision n
forall (n :: N). PipelineDecision ('S n)
Collect, MkPipelineDecision
goHigh)
| Bool
otherwise
-> (PipelineDecision n
forall (n :: N). PipelineDecision ('S n)
CollectOrPipeline, MkPipelineDecision
goLow)
where
n' :: BlockNo
n' :: BlockNo
n' = Int -> BlockNo
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Nat n -> Int
forall (n :: N). Nat n -> Int
natToInt Nat n
n)
goHigh :: MkPipelineDecision
goHigh = (forall (n :: N).
Nat n
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision n, MkPipelineDecision))
-> MkPipelineDecision
MkPipelineDecision ((forall (n :: N).
Nat n
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision n, MkPipelineDecision))
-> MkPipelineDecision)
-> (forall (n :: N).
Nat n
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision n, MkPipelineDecision))
-> MkPipelineDecision
forall a b. (a -> b) -> a -> b
$
\Nat n
n WithOrigin BlockNo
clientTipBlockNo WithOrigin BlockNo
serverTipBlockNo ->
case Nat n
n of
Nat n
Zero -> Nat 'Z
-> WithOrigin BlockNo
-> WithOrigin BlockNo
-> (PipelineDecision 'Z, MkPipelineDecision)
goZero Nat n
Nat 'Z
n WithOrigin BlockNo
clientTipBlockNo WithOrigin BlockNo
serverTipBlockNo
Succ{} ->
if BlockNo
n' BlockNo -> BlockNo -> Bool
forall a. Ord a => a -> a -> Bool
> BlockNo
lowMark'
then (PipelineDecision n
forall (n :: N). PipelineDecision ('S n)
Collect, MkPipelineDecision
goHigh)
else (PipelineDecision n
forall (n :: N). PipelineDecision ('S n)
CollectOrPipeline, MkPipelineDecision
goLow)
where
n' :: BlockNo
n' :: BlockNo
n' = Int -> BlockNo
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Nat n -> Int
forall (n :: N). Nat n -> Int
natToInt Nat n
n)
lowMark' :: BlockNo
lowMark' :: BlockNo
lowMark' = Word32 -> BlockNo
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
lowMark
highMark' :: BlockNo
highMark' :: BlockNo
highMark' = Word32 -> BlockNo
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
highMark
bnoPlus :: WithOrigin BlockNo -> BlockNo -> WithOrigin BlockNo
bnoPlus :: WithOrigin BlockNo -> BlockNo -> WithOrigin BlockNo
bnoPlus (At BlockNo
x) BlockNo
y = BlockNo -> WithOrigin BlockNo
forall t. t -> WithOrigin t
At (BlockNo
x BlockNo -> BlockNo -> BlockNo
forall a. Num a => a -> a -> a
+ BlockNo
y)
bnoPlus WithOrigin BlockNo
Origin BlockNo
y = BlockNo -> WithOrigin BlockNo
forall t. t -> WithOrigin t
At (BlockNo
1 BlockNo -> BlockNo -> BlockNo
forall a. Num a => a -> a -> a
+ BlockNo
y)