{-# LANGUAGE DataKinds #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TypeApplications #-}
module Test.Consensus.Protocol.Praos2 (tests) where
import Cardano.Ledger.BaseTypes (Milliseconds32 (..), ProtVer (..))
import Cardano.Ledger.Coin (knownNonZeroCoin)
import Cardano.Ledger.State (PoolDistr (..), emptyLeiosCommittee)
import Cardano.Protocol.Crypto (StandardCrypto)
import Cardano.Slotting.EpochInfo (fixedEpochInfo)
import Cardano.Slotting.Slot (EpochSize (..), SlotNo (..), WithOrigin (..))
import Cardano.Slotting.Time (slotLengthFromSec)
import qualified Data.Map.Strict as Map
import Data.Proxy (Proxy (..))
import qualified Data.Strict.Either as Strict
import Data.Word (Word64)
import Ouroboros.Consensus.Leios.Protocol (LeiosAnnouncement, LeiosLedgerView (..))
import Ouroboros.Consensus.Protocol.Abstract (TranslateProto (..))
import Ouroboros.Consensus.Protocol.PolyPraos
( PolyPraosState (..)
, Ticked (..)
, WhyNotCertifiable (..)
, tickChainDepStatePolyPraos
)
import qualified Ouroboros.Consensus.Protocol.Praos.Views as Views
import Ouroboros.Consensus.Protocol.Praos2 (LeiosOnly (Praos2HasLeios), Praos2)
import Test.Consensus.Protocol.Serialisation.Generators ()
import Test.Tasty
import Test.Tasty.QuickCheck
tests :: TestTree
tests :: TestTree
tests =
TestName -> [TestTree] -> TestTree
testGroup
TestName
"Praos2"
[ TestName
-> (PolyPraosState (Praos2 StandardCrypto) -> Property) -> TestTree
forall a. Testable a => TestName -> a -> TestTree
testProperty
TestName
"crossing into another era with Leios makes an announcement uncertifiable"
PolyPraosState (Praos2 StandardCrypto) -> Property
prop_crossingEraMakesAnnouncementUncertifiable
, TestName
-> (PolyPraosState (Praos2 StandardCrypto) -> Property) -> TestTree
forall a. Testable a => TestName -> a -> TestTree
testProperty
TestName
"crossing into another epoch makes an announcement uncertifiable"
PolyPraosState (Praos2 StandardCrypto) -> Property
prop_crossingEpochMakesAnnouncementUncertifiable
, TestName
-> (PolyPraosState (Praos2 StandardCrypto) -> Property) -> TestTree
forall a. Testable a => TestName -> a -> TestTree
testProperty
TestName
"crossing an era and an epoch in either order leaves the era's reason"
PolyPraosState (Praos2 StandardCrypto) -> Property
prop_crossingEraAndEpochInEitherOrder
, TestName
-> (WhyNotCertifiable
-> WhyNotCertifiable -> WhyNotCertifiable -> Property)
-> TestTree
forall a. Testable a => TestName -> a -> TestTree
testProperty TestName
"WhyNotCertifiable's <> is associative" WhyNotCertifiable
-> WhyNotCertifiable -> WhyNotCertifiable -> Property
prop_whyNotCertifiableAssociative
, TestName
-> (WhyNotCertifiable -> WhyNotCertifiable -> Property) -> TestTree
forall a. Testable a => TestName -> a -> TestTree
testProperty TestName
"WhyNotCertifiable's <> is commutative" WhyNotCertifiable -> WhyNotCertifiable -> Property
prop_whyNotCertifiableCommutative
]
prop_crossingEraMakesAnnouncementUncertifiable ::
PolyPraosState (Praos2 StandardCrypto) -> Property
prop_crossingEraMakesAnnouncementUncertifiable :: PolyPraosState (Praos2 StandardCrypto) -> Property
prop_crossingEraMakesAnnouncementUncertifiable PolyPraosState (Praos2 StandardCrypto)
st =
PolyPraosState (Praos2 StandardCrypto)
-> PolyPraosState (Praos2 StandardCrypto)
translateEra PolyPraosState (Praos2 StandardCrypto)
st PolyPraosState (Praos2 StandardCrypto)
-> PolyPraosState (Praos2 StandardCrypto) -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== PolyPraosState (Praos2 StandardCrypto)
st{praosStateLeiosAnnouncement = Praos2HasLeios expected}
where
Praos2HasLeios Either WhyNotCertifiable LeiosAnnouncement
before = PolyPraosState (Praos2 StandardCrypto)
-> LeiosOnly
(Praos2 StandardCrypto)
()
(Either WhyNotCertifiable LeiosAnnouncement)
forall proto.
PolyPraosState proto
-> WhenLeios proto (Either WhyNotCertifiable LeiosAnnouncement)
praosStateLeiosAnnouncement PolyPraosState (Praos2 StandardCrypto)
st
expected :: Either WhyNotCertifiable LeiosAnnouncement
expected = Either WhyNotCertifiable LeiosAnnouncement
-> Either WhyNotCertifiable LeiosAnnouncement
afterEraBoundary Either WhyNotCertifiable LeiosAnnouncement
before
prop_crossingEpochMakesAnnouncementUncertifiable ::
PolyPraosState (Praos2 StandardCrypto) -> Property
prop_crossingEpochMakesAnnouncementUncertifiable :: PolyPraosState (Praos2 StandardCrypto) -> Property
prop_crossingEpochMakesAnnouncementUncertifiable PolyPraosState (Praos2 StandardCrypto)
st =
Gen Word64 -> (Word64 -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll ((Word64, Word64) -> Gen Word64
forall a. Random a => (a, a) -> Gen a
choose (Word64
1, Word64
2 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
epochSize)) ((Word64 -> Property) -> Property)
-> (Word64 -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Word64
delta ->
let slot :: SlotNo
slot = Word64 -> SlotNo
SlotNo (Word64 -> SlotNo) -> Word64 -> SlotNo
forall a b. (a -> b) -> a -> b
$ Word64
lastSlot Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
delta
crosses :: Bool
crosses = Word64 -> Word64
epochOf (SlotNo -> Word64
unSlotNo SlotNo
slot) Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64 -> Word64
epochOf Word64
lastSlot
expected :: Either WhyNotCertifiable LeiosAnnouncement
expected
| Bool
crosses = Either WhyNotCertifiable LeiosAnnouncement
-> Either WhyNotCertifiable LeiosAnnouncement
afterEpochBoundary Either WhyNotCertifiable LeiosAnnouncement
before
| Bool
otherwise = Either WhyNotCertifiable LeiosAnnouncement
before
in Bool -> TestName -> Property -> Property
forall prop. Testable prop => Bool -> TestName -> prop -> Property
classify Bool
crosses TestName
"crosses an epoch boundary" (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
PolyPraosState (Praos2 StandardCrypto)
-> LeiosOnly
(Praos2 StandardCrypto)
()
(Either WhyNotCertifiable LeiosAnnouncement)
forall proto.
PolyPraosState proto
-> WhenLeios proto (Either WhyNotCertifiable LeiosAnnouncement)
praosStateLeiosAnnouncement (SlotNo
-> PolyPraosState (Praos2 StandardCrypto)
-> PolyPraosState (Praos2 StandardCrypto)
tickTo SlotNo
slot PolyPraosState (Praos2 StandardCrypto)
st) LeiosOnly
(Praos2 StandardCrypto)
()
(Either WhyNotCertifiable LeiosAnnouncement)
-> LeiosOnly
(Praos2 StandardCrypto)
()
(Either WhyNotCertifiable LeiosAnnouncement)
-> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== Either WhyNotCertifiable LeiosAnnouncement
-> LeiosOnly
(Praos2 StandardCrypto)
()
(Either WhyNotCertifiable LeiosAnnouncement)
forall c a b. b -> LeiosOnly (Praos2 c) a b
Praos2HasLeios Either WhyNotCertifiable LeiosAnnouncement
expected
where
Praos2HasLeios Either WhyNotCertifiable LeiosAnnouncement
before = PolyPraosState (Praos2 StandardCrypto)
-> LeiosOnly
(Praos2 StandardCrypto)
()
(Either WhyNotCertifiable LeiosAnnouncement)
forall proto.
PolyPraosState proto
-> WhenLeios proto (Either WhyNotCertifiable LeiosAnnouncement)
praosStateLeiosAnnouncement PolyPraosState (Praos2 StandardCrypto)
st
lastSlot :: Word64
lastSlot = case PolyPraosState (Praos2 StandardCrypto) -> WithOrigin SlotNo
forall proto. PolyPraosState proto -> WithOrigin SlotNo
praosStateLastSlot PolyPraosState (Praos2 StandardCrypto)
st of
WithOrigin SlotNo
Origin -> Word64
0
At (SlotNo Word64
s) -> Word64
s
prop_crossingEraAndEpochInEitherOrder ::
PolyPraosState (Praos2 StandardCrypto) -> Property
prop_crossingEraAndEpochInEitherOrder :: PolyPraosState (Praos2 StandardCrypto) -> Property
prop_crossingEraAndEpochInEitherOrder PolyPraosState (Praos2 StandardCrypto)
st =
PolyPraosState (Praos2 StandardCrypto)
-> LeiosOnly
(Praos2 StandardCrypto)
()
(Either WhyNotCertifiable LeiosAnnouncement)
forall proto.
PolyPraosState proto
-> WhenLeios proto (Either WhyNotCertifiable LeiosAnnouncement)
praosStateLeiosAnnouncement (SlotNo
-> PolyPraosState (Praos2 StandardCrypto)
-> PolyPraosState (Praos2 StandardCrypto)
tickTo SlotNo
nextEpoch (PolyPraosState (Praos2 StandardCrypto)
-> PolyPraosState (Praos2 StandardCrypto)
translateEra PolyPraosState (Praos2 StandardCrypto)
st))
LeiosOnly
(Praos2 StandardCrypto)
()
(Either WhyNotCertifiable LeiosAnnouncement)
-> LeiosOnly
(Praos2 StandardCrypto)
()
(Either WhyNotCertifiable LeiosAnnouncement)
-> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== Either WhyNotCertifiable LeiosAnnouncement
-> LeiosOnly
(Praos2 StandardCrypto)
()
(Either WhyNotCertifiable LeiosAnnouncement)
forall c a b. b -> LeiosOnly (Praos2 c) a b
Praos2HasLeios Either WhyNotCertifiable LeiosAnnouncement
expected
Property -> Property -> Property
forall prop1 prop2.
(Testable prop1, Testable prop2) =>
prop1 -> prop2 -> Property
.&&. PolyPraosState (Praos2 StandardCrypto)
-> LeiosOnly
(Praos2 StandardCrypto)
()
(Either WhyNotCertifiable LeiosAnnouncement)
forall proto.
PolyPraosState proto
-> WhenLeios proto (Either WhyNotCertifiable LeiosAnnouncement)
praosStateLeiosAnnouncement (PolyPraosState (Praos2 StandardCrypto)
-> PolyPraosState (Praos2 StandardCrypto)
translateEra (SlotNo
-> PolyPraosState (Praos2 StandardCrypto)
-> PolyPraosState (Praos2 StandardCrypto)
tickTo SlotNo
nextEpoch PolyPraosState (Praos2 StandardCrypto)
st))
LeiosOnly
(Praos2 StandardCrypto)
()
(Either WhyNotCertifiable LeiosAnnouncement)
-> LeiosOnly
(Praos2 StandardCrypto)
()
(Either WhyNotCertifiable LeiosAnnouncement)
-> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== Either WhyNotCertifiable LeiosAnnouncement
-> LeiosOnly
(Praos2 StandardCrypto)
()
(Either WhyNotCertifiable LeiosAnnouncement)
forall c a b. b -> LeiosOnly (Praos2 c) a b
Praos2HasLeios Either WhyNotCertifiable LeiosAnnouncement
expected
where
Praos2HasLeios Either WhyNotCertifiable LeiosAnnouncement
before = PolyPraosState (Praos2 StandardCrypto)
-> LeiosOnly
(Praos2 StandardCrypto)
()
(Either WhyNotCertifiable LeiosAnnouncement)
forall proto.
PolyPraosState proto
-> WhenLeios proto (Either WhyNotCertifiable LeiosAnnouncement)
praosStateLeiosAnnouncement PolyPraosState (Praos2 StandardCrypto)
st
expected :: Either WhyNotCertifiable LeiosAnnouncement
expected = Either WhyNotCertifiable LeiosAnnouncement
-> Either WhyNotCertifiable LeiosAnnouncement
afterEraBoundary Either WhyNotCertifiable LeiosAnnouncement
before
nextEpoch :: SlotNo
nextEpoch = Word64 -> SlotNo
SlotNo (Word64 -> SlotNo) -> Word64 -> SlotNo
forall a b. (a -> b) -> a -> b
$ (Word64 -> Word64
epochOf Word64
lastSlot Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
1) Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
epochSize
lastSlot :: Word64
lastSlot = case PolyPraosState (Praos2 StandardCrypto) -> WithOrigin SlotNo
forall proto. PolyPraosState proto -> WithOrigin SlotNo
praosStateLastSlot PolyPraosState (Praos2 StandardCrypto)
st of
WithOrigin SlotNo
Origin -> Word64
0
At (SlotNo Word64
s) -> Word64
s
prop_whyNotCertifiableAssociative ::
WhyNotCertifiable -> WhyNotCertifiable -> WhyNotCertifiable -> Property
prop_whyNotCertifiableAssociative :: WhyNotCertifiable
-> WhyNotCertifiable -> WhyNotCertifiable -> Property
prop_whyNotCertifiableAssociative WhyNotCertifiable
a WhyNotCertifiable
b WhyNotCertifiable
c = (WhyNotCertifiable
a WhyNotCertifiable -> WhyNotCertifiable -> WhyNotCertifiable
forall a. Semigroup a => a -> a -> a
<> WhyNotCertifiable
b) WhyNotCertifiable -> WhyNotCertifiable -> WhyNotCertifiable
forall a. Semigroup a => a -> a -> a
<> WhyNotCertifiable
c WhyNotCertifiable -> WhyNotCertifiable -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== WhyNotCertifiable
a WhyNotCertifiable -> WhyNotCertifiable -> WhyNotCertifiable
forall a. Semigroup a => a -> a -> a
<> (WhyNotCertifiable
b WhyNotCertifiable -> WhyNotCertifiable -> WhyNotCertifiable
forall a. Semigroup a => a -> a -> a
<> WhyNotCertifiable
c)
prop_whyNotCertifiableCommutative :: WhyNotCertifiable -> WhyNotCertifiable -> Property
prop_whyNotCertifiableCommutative :: WhyNotCertifiable -> WhyNotCertifiable -> Property
prop_whyNotCertifiableCommutative WhyNotCertifiable
a WhyNotCertifiable
b = WhyNotCertifiable
a WhyNotCertifiable -> WhyNotCertifiable -> WhyNotCertifiable
forall a. Semigroup a => a -> a -> a
<> WhyNotCertifiable
b WhyNotCertifiable -> WhyNotCertifiable -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== WhyNotCertifiable
b WhyNotCertifiable -> WhyNotCertifiable -> WhyNotCertifiable
forall a. Semigroup a => a -> a -> a
<> WhyNotCertifiable
a
afterEraBoundary ::
Strict.Either WhyNotCertifiable LeiosAnnouncement ->
Strict.Either WhyNotCertifiable LeiosAnnouncement
afterEraBoundary :: Either WhyNotCertifiable LeiosAnnouncement
-> Either WhyNotCertifiable LeiosAnnouncement
afterEraBoundary = \case
Strict.Left WhyNotCertifiable
NothingAnnounced -> WhyNotCertifiable -> Either WhyNotCertifiable LeiosAnnouncement
forall a b. a -> Either a b
Strict.Left WhyNotCertifiable
NothingAnnounced
Strict.Left WhyNotCertifiable
AnnouncedInPreviousEra -> WhyNotCertifiable -> Either WhyNotCertifiable LeiosAnnouncement
forall a b. a -> Either a b
Strict.Left WhyNotCertifiable
AnnouncedInPreviousEra
Strict.Left WhyNotCertifiable
AnnouncedInPreviousEpoch -> WhyNotCertifiable -> Either WhyNotCertifiable LeiosAnnouncement
forall a b. a -> Either a b
Strict.Left WhyNotCertifiable
AnnouncedInPreviousEra
Strict.Right LeiosAnnouncement
_ann -> WhyNotCertifiable -> Either WhyNotCertifiable LeiosAnnouncement
forall a b. a -> Either a b
Strict.Left WhyNotCertifiable
AnnouncedInPreviousEra
afterEpochBoundary ::
Strict.Either WhyNotCertifiable LeiosAnnouncement ->
Strict.Either WhyNotCertifiable LeiosAnnouncement
afterEpochBoundary :: Either WhyNotCertifiable LeiosAnnouncement
-> Either WhyNotCertifiable LeiosAnnouncement
afterEpochBoundary = \case
Strict.Left WhyNotCertifiable
NothingAnnounced -> WhyNotCertifiable -> Either WhyNotCertifiable LeiosAnnouncement
forall a b. a -> Either a b
Strict.Left WhyNotCertifiable
NothingAnnounced
Strict.Left WhyNotCertifiable
AnnouncedInPreviousEra -> WhyNotCertifiable -> Either WhyNotCertifiable LeiosAnnouncement
forall a b. a -> Either a b
Strict.Left WhyNotCertifiable
AnnouncedInPreviousEra
Strict.Left WhyNotCertifiable
AnnouncedInPreviousEpoch -> WhyNotCertifiable -> Either WhyNotCertifiable LeiosAnnouncement
forall a b. a -> Either a b
Strict.Left WhyNotCertifiable
AnnouncedInPreviousEpoch
Strict.Right LeiosAnnouncement
_ann -> WhyNotCertifiable -> Either WhyNotCertifiable LeiosAnnouncement
forall a b. a -> Either a b
Strict.Left WhyNotCertifiable
AnnouncedInPreviousEpoch
translateEra :: PolyPraosState (Praos2 StandardCrypto) -> PolyPraosState (Praos2 StandardCrypto)
translateEra :: PolyPraosState (Praos2 StandardCrypto)
-> PolyPraosState (Praos2 StandardCrypto)
translateEra =
Proxy (Praos2 StandardCrypto, Praos2 StandardCrypto, ())
-> ChainDepState (Praos2 StandardCrypto)
-> ChainDepState (Praos2 StandardCrypto)
forall protoFrom protoTo eraTo.
TranslateProto protoFrom protoTo eraTo =>
Proxy (protoFrom, protoTo, eraTo)
-> ChainDepState protoFrom -> ChainDepState protoTo
translateChainDepState (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @(Praos2 StandardCrypto, Praos2 StandardCrypto, ()))
tickTo :: SlotNo -> PolyPraosState (Praos2 StandardCrypto) -> PolyPraosState (Praos2 StandardCrypto)
tickTo :: SlotNo
-> PolyPraosState (Praos2 StandardCrypto)
-> PolyPraosState (Praos2 StandardCrypto)
tickTo SlotNo
slot =
Ticked (PolyPraosState (Praos2 StandardCrypto))
-> PolyPraosState (Praos2 StandardCrypto)
forall proto. Ticked (PolyPraosState proto) -> PolyPraosState proto
tickedPraosStateChainDepState
(Ticked (PolyPraosState (Praos2 StandardCrypto))
-> PolyPraosState (Praos2 StandardCrypto))
-> (PolyPraosState (Praos2 StandardCrypto)
-> Ticked (PolyPraosState (Praos2 StandardCrypto)))
-> PolyPraosState (Praos2 StandardCrypto)
-> PolyPraosState (Praos2 StandardCrypto)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EpochInfo (Except PastHorizonException)
-> PolyPraosLedgerView (Praos2 StandardCrypto)
-> SlotNo
-> PolyPraosState (Praos2 StandardCrypto)
-> Ticked (PolyPraosState (Praos2 StandardCrypto))
forall proto.
Functor (WhenLeios proto) =>
EpochInfo (Except PastHorizonException)
-> PolyPraosLedgerView proto
-> SlotNo
-> PolyPraosState proto
-> Ticked (PolyPraosState proto)
tickChainDepStatePolyPraos
(EpochSize -> SlotLength -> EpochInfo (Except PastHorizonException)
forall (m :: * -> *).
Monad m =>
EpochSize -> SlotLength -> EpochInfo m
fixedEpochInfo (Word64 -> EpochSize
EpochSize Word64
epochSize) (Integer -> SlotLength
slotLengthFromSec Integer
1))
PolyPraosLedgerView (Praos2 StandardCrypto)
ledgerView
SlotNo
slot
epochSize :: Word64
epochSize :: Word64
epochSize = Word64
5
epochOf :: Word64 -> Word64
epochOf :: Word64 -> Word64
epochOf Word64
s = Word64
s Word64 -> Word64 -> Word64
forall a. Integral a => a -> a -> a
`div` Word64
epochSize
ledgerView :: Views.PolyPraosLedgerView (Praos2 StandardCrypto)
ledgerView :: PolyPraosLedgerView (Praos2 StandardCrypto)
ledgerView =
Views.PraosLedgerView
{ plvPoolDistr :: PoolDistr
Views.plvPoolDistr = Map (KeyHash StakePool) IndividualPoolStake
-> NonZero Coin -> PoolDistr
PoolDistr Map (KeyHash StakePool) IndividualPoolStake
forall k a. Map k a
Map.empty (forall (n :: Natural). (KnownNat n, 1 <= n) => NonZero Coin
knownNonZeroCoin @1)
, plvMaxHeaderSize :: Word16
Views.plvMaxHeaderSize = Word16
0
, plvMaxBodySize :: Word32
Views.plvMaxBodySize = Word32
0
, plvProtocolVersion :: ProtVer
Views.plvProtocolVersion = Version -> Word32 -> ProtVer
ProtVer Version
forall a. Bounded a => a
minBound Word32
0
, plvLeios :: WhenLeios (Praos2 StandardCrypto) LeiosLedgerView
Views.plvLeios =
LeiosLedgerView
-> WhenLeios (Praos2 StandardCrypto) LeiosLedgerView
forall c a b. b -> LeiosOnly (Praos2 c) a b
Praos2HasLeios
MkLeiosLedgerView
{ llvCommittee :: LeiosCommittee
llvCommittee = LeiosCommittee
emptyLeiosCommittee
, llvQuorumStakeThreshold :: UnitInterval
llvQuorumStakeThreshold = UnitInterval
forall a. Bounded a => a
maxBound
, llvAnnouncementPeriod :: Milliseconds32
llvAnnouncementPeriod = Word32 -> Milliseconds32
Milliseconds32 Word32
1000
, llvVotePeriod :: Milliseconds32
llvVotePeriod = Word32 -> Milliseconds32
Milliseconds32 Word32
4000
, llvDiffusionPeriod :: Milliseconds32
llvDiffusionPeriod = Word32 -> Milliseconds32
Milliseconds32 Word32
1000
, llvMaxEbBodySize :: Word32
llvMaxEbBodySize = Word32
0
, llvMaxEbTxsSize :: Word32
llvMaxEbTxsSize = Word32
0
}
}