{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Ouroboros.Consensus.Peras.Voting.Rules
( isPerasVotingAllowed
, PerasVotingRule (..)
, PerasVotingRulesDecision (..)
, perasVR1A
, perasVR1B
, perasVR2A
, perasVR2B
, perasVR1
, perasVR2
, perasVotingRules
)
where
import Ouroboros.Consensus.Block (WithOrigin (..))
import Ouroboros.Consensus.Block.Abstract
( SlotNo (..)
)
import Ouroboros.Consensus.Block.SupportsPeras
( HasPerasCertRound (..)
, PerasRoundNo (..)
, getPerasCertRound
, onPerasRoundNo
)
import Ouroboros.Consensus.Peras.Params
( PerasCertArrivalThreshold (..)
, PerasCooldownRounds (..)
, PerasIgnoranceRounds (..)
, PerasParams (..)
)
import Ouroboros.Consensus.Peras.Voting.View
( LatestCertOnChainView (..)
, LatestCertSeenView (..)
, PerasVotingView (..)
)
import Ouroboros.Consensus.Util.Pred
( Evidence (..)
, Explainable (..)
, ExplanationMode (..)
, Pred (..)
, evalPred
)
data PerasVotingRulesDecision
= Vote (Evidence True PerasVotingRule)
| NoVote (Evidence False PerasVotingRule)
deriving Int -> PerasVotingRulesDecision -> ShowS
[PerasVotingRulesDecision] -> ShowS
PerasVotingRulesDecision -> String
(Int -> PerasVotingRulesDecision -> ShowS)
-> (PerasVotingRulesDecision -> String)
-> ([PerasVotingRulesDecision] -> ShowS)
-> Show PerasVotingRulesDecision
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PerasVotingRulesDecision -> ShowS
showsPrec :: Int -> PerasVotingRulesDecision -> ShowS
$cshow :: PerasVotingRulesDecision -> String
show :: PerasVotingRulesDecision -> String
$cshowList :: [PerasVotingRulesDecision] -> ShowS
showList :: [PerasVotingRulesDecision] -> ShowS
Show
instance Explainable PerasVotingRulesDecision where
explain :: ExplanationMode -> PerasVotingRulesDecision -> String
explain ExplanationMode
mode = \case
Vote (ETrue Pred PerasVotingRule
e) -> String
"Vote(" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> ExplanationMode -> Pred PerasVotingRule -> String
forall a. Explainable a => ExplanationMode -> a -> String
explain ExplanationMode
mode Pred PerasVotingRule
e String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
")"
NoVote (EFalse Pred PerasVotingRule
e) -> String
"NoVote(" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> ExplanationMode -> Pred PerasVotingRule -> String
forall a. Explainable a => ExplanationMode -> a -> String
explain ExplanationMode
mode Pred PerasVotingRule
e String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
")"
isPerasVotingAllowed ::
HasPerasCertRound cert =>
PerasVotingView cert ->
PerasVotingRulesDecision
isPerasVotingAllowed :: forall cert.
HasPerasCertRound cert =>
PerasVotingView cert -> PerasVotingRulesDecision
isPerasVotingAllowed PerasVotingView cert
pvv =
Pred PerasVotingRule
-> (forall (res :: Bool).
Evidence res PerasVotingRule -> PerasVotingRulesDecision)
-> PerasVotingRulesDecision
forall tag r.
Pred tag -> (forall (res :: Bool). Evidence res tag -> r) -> r
evalPred (PerasVotingView cert -> Pred PerasVotingRule
forall cert.
HasPerasCertRound cert =>
PerasVotingView cert -> Pred PerasVotingRule
perasVotingRules PerasVotingView cert
pvv) ((forall (res :: Bool).
Evidence res PerasVotingRule -> PerasVotingRulesDecision)
-> PerasVotingRulesDecision)
-> (forall (res :: Bool).
Evidence res PerasVotingRule -> PerasVotingRulesDecision)
-> PerasVotingRulesDecision
forall a b. (a -> b) -> a -> b
$ \Evidence res PerasVotingRule
e ->
case Evidence res PerasVotingRule
e of
ETrue{} -> Evidence 'True PerasVotingRule -> PerasVotingRulesDecision
Vote Evidence res PerasVotingRule
Evidence 'True PerasVotingRule
e
EFalse{} -> Evidence 'False PerasVotingRule -> PerasVotingRulesDecision
NoVote Evidence res PerasVotingRule
Evidence 'False PerasVotingRule
e
data PerasVotingRule
=
VR1A
|
VR1B
|
VR2A
|
VR2B PerasRoundNo
deriving (Int -> PerasVotingRule -> ShowS
[PerasVotingRule] -> ShowS
PerasVotingRule -> String
(Int -> PerasVotingRule -> ShowS)
-> (PerasVotingRule -> String)
-> ([PerasVotingRule] -> ShowS)
-> Show PerasVotingRule
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PerasVotingRule -> ShowS
showsPrec :: Int -> PerasVotingRule -> ShowS
$cshow :: PerasVotingRule -> String
show :: PerasVotingRule -> String
$cshowList :: [PerasVotingRule] -> ShowS
showList :: [PerasVotingRule] -> ShowS
Show, PerasVotingRule -> PerasVotingRule -> Bool
(PerasVotingRule -> PerasVotingRule -> Bool)
-> (PerasVotingRule -> PerasVotingRule -> Bool)
-> Eq PerasVotingRule
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PerasVotingRule -> PerasVotingRule -> Bool
== :: PerasVotingRule -> PerasVotingRule -> Bool
$c/= :: PerasVotingRule -> PerasVotingRule -> Bool
/= :: PerasVotingRule -> PerasVotingRule -> Bool
Eq)
instance Explainable PerasVotingRule where
explain :: ExplanationMode -> PerasVotingRule -> String
explain ExplanationMode
Shallow = \case
PerasVotingRule
VR1A -> String
"VR-1A"
PerasVotingRule
VR1B -> String
"VR-1B"
PerasVotingRule
VR2A -> String
"VR-2A"
VR2B PerasRoundNo
_ -> String
"VR-2B"
explain ExplanationMode
Deep = \case
PerasVotingRule
VR1A ->
String
"voter has seen the certificate for the previous round in time"
PerasVotingRule
VR1B ->
String
"the block being voted upon extends the most recently certified block"
PerasVotingRule
VR2A ->
String
"the last certificate seen is sufficiently old"
VR2B PerasRoundNo
_ ->
String
"the last certificate on chain is exactly one or more cooldown periods old"
perasVR1A ::
HasPerasCertRound cert =>
PerasVotingView cert ->
Pred PerasVotingRule
perasVR1A :: forall cert.
HasPerasCertRound cert =>
PerasVotingView cert -> Pred PerasVotingRule
perasVR1A
PerasVotingView
{ PerasParams
perasParams :: PerasParams
perasParams :: forall cert. PerasVotingView cert -> PerasParams
perasParams
, PerasRoundNo
currRoundNo :: PerasRoundNo
currRoundNo :: forall cert. PerasVotingView cert -> PerasRoundNo
currRoundNo
, WithOrigin (LatestCertSeenView cert)
latestCertSeen :: WithOrigin (LatestCertSeenView cert)
latestCertSeen :: forall cert.
PerasVotingView cert -> WithOrigin (LatestCertSeenView cert)
latestCertSeen
} =
PerasVotingRule
VR1A PerasVotingRule -> Pred PerasVotingRule -> Pred PerasVotingRule
forall tag. tag -> Pred tag -> Pred tag
:= Pred PerasVotingRule
vr1a1 Pred PerasVotingRule
-> Pred PerasVotingRule -> Pred PerasVotingRule
forall tag. Pred tag -> Pred tag -> Pred tag
:/\: Pred PerasVotingRule
vr1a2
where
vr1a1 :: Pred PerasVotingRule
vr1a1 =
case WithOrigin (LatestCertSeenView cert)
latestCertSeen of
NotOrigin LatestCertSeenView cert
cert ->
PerasRoundNo
currRoundNo PerasRoundNo -> PerasRoundNo -> Pred PerasVotingRule
forall a tag. (Typeable a, Eq a, Show a) => a -> a -> Pred tag
:==: cert -> PerasRoundNo
forall cert. HasPerasCertRound cert => cert -> PerasRoundNo
getPerasCertRound (LatestCertSeenView cert -> cert
forall cert. LatestCertSeenView cert -> cert
lcsCert LatestCertSeenView cert
cert) PerasRoundNo -> PerasRoundNo -> PerasRoundNo
forall a. Num a => a -> a -> a
+ PerasRoundNo
1
WithOrigin (LatestCertSeenView cert)
Origin ->
PerasRoundNo
currRoundNo PerasRoundNo -> PerasRoundNo -> Pred PerasVotingRule
forall a tag. (Typeable a, Eq a, Show a) => a -> a -> Pred tag
:==: Word64 -> PerasRoundNo
PerasRoundNo Word64
0
vr1a2 :: Pred PerasVotingRule
vr1a2 =
case WithOrigin (LatestCertSeenView cert)
latestCertSeen of
NotOrigin LatestCertSeenView cert
cert ->
LatestCertSeenView cert -> SlotNo
forall cert. LatestCertSeenView cert -> SlotNo
lcsArrivalSlot LatestCertSeenView cert
cert SlotNo -> SlotNo -> Pred PerasVotingRule
forall a tag. (Typeable a, Ord a, Show a) => a -> a -> Pred tag
:<=: LatestCertSeenView cert -> SlotNo
forall cert. LatestCertSeenView cert -> SlotNo
lcsRoundStartSlot LatestCertSeenView cert
cert SlotNo -> SlotNo -> SlotNo
forall a. Num a => a -> a -> a
+ SlotNo
_X
WithOrigin (LatestCertSeenView cert)
Origin ->
Bool -> Pred PerasVotingRule
forall tag. Bool -> Pred tag
Bool Bool
True
_X :: SlotNo
_X =
Word64 -> SlotNo
SlotNo (Word64 -> SlotNo) -> Word64 -> SlotNo
forall a b. (a -> b) -> a -> b
$
PerasCertArrivalThreshold -> Word64
unPerasCertArrivalThreshold (PerasCertArrivalThreshold -> Word64)
-> PerasCertArrivalThreshold -> Word64
forall a b. (a -> b) -> a -> b
$
PerasParams -> PerasCertArrivalThreshold
perasCertArrivalThreshold PerasParams
perasParams
perasVR1B ::
PerasVotingView cert ->
Pred PerasVotingRule
perasVR1B :: forall cert. PerasVotingView cert -> Pred PerasVotingRule
perasVR1B
PerasVotingView
{ WithOrigin (LatestCertSeenView cert)
latestCertSeen :: forall cert.
PerasVotingView cert -> WithOrigin (LatestCertSeenView cert)
latestCertSeen :: WithOrigin (LatestCertSeenView cert)
latestCertSeen
} =
PerasVotingRule
VR1B PerasVotingRule -> Pred PerasVotingRule -> Pred PerasVotingRule
forall tag. tag -> Pred tag -> Pred tag
:= Pred PerasVotingRule
vr1b
where
vr1b :: Pred PerasVotingRule
vr1b =
case WithOrigin (LatestCertSeenView cert)
latestCertSeen of
NotOrigin LatestCertSeenView cert
cert ->
Bool -> Pred PerasVotingRule
forall tag. Bool -> Pred tag
Bool (LatestCertSeenView cert -> Bool
forall cert. LatestCertSeenView cert -> Bool
lcsCandidateBlockExtendsCert LatestCertSeenView cert
cert)
WithOrigin (LatestCertSeenView cert)
Origin ->
Bool -> Pred PerasVotingRule
forall tag. Bool -> Pred tag
Bool Bool
True
perasVR2A ::
HasPerasCertRound cert =>
PerasVotingView cert ->
Pred PerasVotingRule
perasVR2A :: forall cert.
HasPerasCertRound cert =>
PerasVotingView cert -> Pred PerasVotingRule
perasVR2A
PerasVotingView
{ PerasParams
perasParams :: forall cert. PerasVotingView cert -> PerasParams
perasParams :: PerasParams
perasParams
, PerasRoundNo
currRoundNo :: forall cert. PerasVotingView cert -> PerasRoundNo
currRoundNo :: PerasRoundNo
currRoundNo
, WithOrigin (LatestCertSeenView cert)
latestCertSeen :: forall cert.
PerasVotingView cert -> WithOrigin (LatestCertSeenView cert)
latestCertSeen :: WithOrigin (LatestCertSeenView cert)
latestCertSeen
} =
PerasVotingRule
VR2A PerasVotingRule -> Pred PerasVotingRule -> Pred PerasVotingRule
forall tag. tag -> Pred tag -> Pred tag
:= Pred PerasVotingRule
vr2a
where
vr2a :: Pred PerasVotingRule
vr2a =
case WithOrigin (LatestCertSeenView cert)
latestCertSeen of
NotOrigin LatestCertSeenView cert
cert ->
cert -> PerasRoundNo
forall cert. HasPerasCertRound cert => cert -> PerasRoundNo
getPerasCertRound (LatestCertSeenView cert -> cert
forall cert. LatestCertSeenView cert -> cert
lcsCert LatestCertSeenView cert
cert) PerasRoundNo -> PerasRoundNo -> PerasRoundNo
forall a. Num a => a -> a -> a
+ PerasRoundNo
_R PerasRoundNo -> PerasRoundNo -> Pred PerasVotingRule
forall a tag. (Typeable a, Ord a, Show a) => a -> a -> Pred tag
:<=: PerasRoundNo
currRoundNo
WithOrigin (LatestCertSeenView cert)
Origin ->
PerasRoundNo
_R PerasRoundNo -> PerasRoundNo -> Pred PerasVotingRule
forall a tag. (Typeable a, Ord a, Show a) => a -> a -> Pred tag
:<=: PerasRoundNo
currRoundNo
_R :: PerasRoundNo
_R =
Word64 -> PerasRoundNo
PerasRoundNo (Word64 -> PerasRoundNo) -> Word64 -> PerasRoundNo
forall a b. (a -> b) -> a -> b
$
PerasIgnoranceRounds -> Word64
unPerasIgnoranceRounds (PerasIgnoranceRounds -> Word64) -> PerasIgnoranceRounds -> Word64
forall a b. (a -> b) -> a -> b
$
PerasParams -> PerasIgnoranceRounds
perasIgnoranceRounds (PerasParams -> PerasIgnoranceRounds)
-> PerasParams -> PerasIgnoranceRounds
forall a b. (a -> b) -> a -> b
$
PerasParams
perasParams
perasVR2B ::
HasPerasCertRound cert =>
PerasVotingView cert ->
Pred PerasVotingRule
perasVR2B :: forall cert.
HasPerasCertRound cert =>
PerasVotingView cert -> Pred PerasVotingRule
perasVR2B
PerasVotingView
{ PerasParams
perasParams :: forall cert. PerasVotingView cert -> PerasParams
perasParams :: PerasParams
perasParams
, PerasRoundNo
currRoundNo :: forall cert. PerasVotingView cert -> PerasRoundNo
currRoundNo :: PerasRoundNo
currRoundNo
, WithOrigin (LatestCertOnChainView cert)
latestCertOnChain :: WithOrigin (LatestCertOnChainView cert)
latestCertOnChain :: forall cert.
PerasVotingView cert -> WithOrigin (LatestCertOnChainView cert)
latestCertOnChain
} =
PerasRoundNo -> PerasVotingRule
VR2B PerasRoundNo
c PerasVotingRule -> Pred PerasVotingRule -> Pred PerasVotingRule
forall tag. tag -> Pred tag -> Pred tag
:= Pred PerasVotingRule
vr2b
where
vr2b :: Pred PerasVotingRule
vr2b =
case WithOrigin (LatestCertOnChainView cert)
latestCertOnChain of
NotOrigin LatestCertOnChainView cert
cert ->
(PerasRoundNo
currRoundNo PerasRoundNo -> PerasRoundNo -> Pred PerasVotingRule
forall a tag. (Typeable a, Ord a, Show a) => a -> a -> Pred tag
:>: cert -> PerasRoundNo
forall cert. HasPerasCertRound cert => cert -> PerasRoundNo
getPerasCertRound (LatestCertOnChainView cert -> cert
forall cert. LatestCertOnChainView cert -> cert
lcocCert LatestCertOnChainView cert
cert))
Pred PerasVotingRule
-> Pred PerasVotingRule -> Pred PerasVotingRule
forall tag. Pred tag -> Pred tag -> Pred tag
:/\: ( (PerasRoundNo
currRoundNo PerasRoundNo -> PerasRoundNo -> PerasRoundNo
`rmod` PerasRoundNo
_K)
PerasRoundNo -> PerasRoundNo -> Pred PerasVotingRule
forall a tag. (Typeable a, Eq a, Show a) => a -> a -> Pred tag
:==: (cert -> PerasRoundNo
forall cert. HasPerasCertRound cert => cert -> PerasRoundNo
getPerasCertRound (LatestCertOnChainView cert -> cert
forall cert. LatestCertOnChainView cert -> cert
lcocCert LatestCertOnChainView cert
cert) PerasRoundNo -> PerasRoundNo -> PerasRoundNo
`rmod` PerasRoundNo
_K)
)
WithOrigin (LatestCertOnChainView cert)
Origin ->
PerasRoundNo
currRoundNo PerasRoundNo -> PerasRoundNo -> PerasRoundNo
`rmod` PerasRoundNo
_K PerasRoundNo -> PerasRoundNo -> Pred PerasVotingRule
forall a tag. (Typeable a, Eq a, Show a) => a -> a -> Pred tag
:==: PerasRoundNo
_K PerasRoundNo -> PerasRoundNo -> PerasRoundNo
forall a. Num a => a -> a -> a
- PerasRoundNo
1
rmod :: PerasRoundNo -> PerasRoundNo -> PerasRoundNo
rmod = (Word64 -> Word64 -> Word64)
-> PerasRoundNo -> PerasRoundNo -> PerasRoundNo
onPerasRoundNo Word64 -> Word64 -> Word64
forall a. Integral a => a -> a -> a
mod
rquot :: PerasRoundNo -> PerasRoundNo -> PerasRoundNo
rquot = (Word64 -> Word64 -> Word64)
-> PerasRoundNo -> PerasRoundNo -> PerasRoundNo
onPerasRoundNo Word64 -> Word64 -> Word64
forall a. Integral a => a -> a -> a
quot
c :: PerasRoundNo
c = PerasRoundNo
currRoundNo PerasRoundNo -> PerasRoundNo -> PerasRoundNo
`rquot` PerasRoundNo
_K
_K :: PerasRoundNo
_K =
Word64 -> PerasRoundNo
PerasRoundNo (Word64 -> PerasRoundNo) -> Word64 -> PerasRoundNo
forall a b. (a -> b) -> a -> b
$
PerasCooldownRounds -> Word64
unPerasCooldownRounds (PerasCooldownRounds -> Word64) -> PerasCooldownRounds -> Word64
forall a b. (a -> b) -> a -> b
$
PerasParams -> PerasCooldownRounds
perasCooldownRounds (PerasParams -> PerasCooldownRounds)
-> PerasParams -> PerasCooldownRounds
forall a b. (a -> b) -> a -> b
$
PerasParams
perasParams
perasVR1 ::
HasPerasCertRound cert =>
PerasVotingView cert ->
Pred PerasVotingRule
perasVR1 :: forall cert.
HasPerasCertRound cert =>
PerasVotingView cert -> Pred PerasVotingRule
perasVR1 PerasVotingView cert
pvv =
PerasVotingView cert -> Pred PerasVotingRule
forall cert.
HasPerasCertRound cert =>
PerasVotingView cert -> Pred PerasVotingRule
perasVR1A PerasVotingView cert
pvv Pred PerasVotingRule
-> Pred PerasVotingRule -> Pred PerasVotingRule
forall tag. Pred tag -> Pred tag -> Pred tag
:/\: PerasVotingView cert -> Pred PerasVotingRule
forall cert. PerasVotingView cert -> Pred PerasVotingRule
perasVR1B PerasVotingView cert
pvv
perasVR2 ::
HasPerasCertRound cert =>
PerasVotingView cert ->
Pred PerasVotingRule
perasVR2 :: forall cert.
HasPerasCertRound cert =>
PerasVotingView cert -> Pred PerasVotingRule
perasVR2 PerasVotingView cert
pvv =
PerasVotingView cert -> Pred PerasVotingRule
forall cert.
HasPerasCertRound cert =>
PerasVotingView cert -> Pred PerasVotingRule
perasVR2A PerasVotingView cert
pvv Pred PerasVotingRule
-> Pred PerasVotingRule -> Pred PerasVotingRule
forall tag. Pred tag -> Pred tag -> Pred tag
:/\: PerasVotingView cert -> Pred PerasVotingRule
forall cert.
HasPerasCertRound cert =>
PerasVotingView cert -> Pred PerasVotingRule
perasVR2B PerasVotingView cert
pvv
perasVotingRules ::
HasPerasCertRound cert =>
PerasVotingView cert ->
Pred PerasVotingRule
perasVotingRules :: forall cert.
HasPerasCertRound cert =>
PerasVotingView cert -> Pred PerasVotingRule
perasVotingRules PerasVotingView cert
pvv =
PerasVotingView cert -> Pred PerasVotingRule
forall cert.
HasPerasCertRound cert =>
PerasVotingView cert -> Pred PerasVotingRule
perasVR1 PerasVotingView cert
pvv Pred PerasVotingRule
-> Pred PerasVotingRule -> Pred PerasVotingRule
forall tag. Pred tag -> Pred tag -> Pred tag
:\/: PerasVotingView cert -> Pred PerasVotingRule
forall cert.
HasPerasCertRound cert =>
PerasVotingView cert -> Pred PerasVotingRule
perasVR2 PerasVotingView cert
pvv