{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ViewPatterns #-}
module Test.ThreadNet.Cardano (tests) where
import qualified Cardano.Chain.Block as CC
import qualified Cardano.Chain.Common as CC.Common
import qualified Cardano.Chain.Genesis as CC.Genesis
import Cardano.Chain.ProtocolConstants (kEpochSlots)
import Cardano.Chain.Slotting (unEpochSlots)
import qualified Cardano.Chain.Update as CC.Update
import qualified Cardano.Chain.Update.Validation.Interface as CC
import qualified Cardano.Ledger.Api.Era as L
import Cardano.Ledger.BaseTypes (nonZero, unNonZero)
import qualified Cardano.Ledger.BaseTypes as SL
import qualified Cardano.Ledger.Shelley.API as SL
import qualified Cardano.Ledger.Shelley.Core as SL
import qualified Cardano.Protocol.TPraos.OCert as SL
import Cardano.Slotting.Slot (EpochSize (..), SlotNo (..))
import Control.Exception (assert)
import Control.Monad (replicateM)
import qualified Data.Map.Strict as Map
import Data.Maybe (maybeToList)
import Data.Proxy (Proxy (..))
import Data.Set (Set)
import qualified Data.Set as Set
import Data.SOP.Functors
import Data.Word (Word64)
import Lens.Micro
import Ouroboros.Consensus.Block.Forging (BlockForging)
import Ouroboros.Consensus.BlockchainTime
import Ouroboros.Consensus.Byron.Ledger (LedgerState (..))
import Ouroboros.Consensus.Byron.Ledger.Block (ByronBlock)
import Ouroboros.Consensus.Byron.Ledger.Conversions
import Ouroboros.Consensus.Byron.Node
import Ouroboros.Consensus.Cardano.Block
import Ouroboros.Consensus.Cardano.Condense ()
import Ouroboros.Consensus.Config.SecurityParam
import Ouroboros.Consensus.HardFork.Combinator
import Ouroboros.Consensus.HardFork.Combinator.Serialisation.Common
(isHardForkNodeToNodeEnabled)
import Ouroboros.Consensus.HardFork.Combinator.State (Current (..))
import Ouroboros.Consensus.Ledger.Extended (ExtLedgerState (..))
import Ouroboros.Consensus.Ledger.SupportsMempool (extractTxs)
import Ouroboros.Consensus.Node.NetworkProtocolVersion
import Ouroboros.Consensus.Node.ProtocolInfo
import Ouroboros.Consensus.NodeId
import Ouroboros.Consensus.Protocol.PBFT
import Ouroboros.Consensus.Shelley.HFEras ()
import Ouroboros.Consensus.Shelley.Ledger.SupportsProtocol ()
import Ouroboros.Consensus.Shelley.Node
import Ouroboros.Consensus.Util.IOLike (IOLike)
import Test.Consensus.Cardano.ProtocolInfo
(hardForkOnDefaultProtocolVersions, mkTestProtocolInfo)
import Test.QuickCheck
import Test.Tasty
import Test.Tasty.QuickCheck
import Test.ThreadNet.General
import qualified Test.ThreadNet.Infra.Byron as Byron
import qualified Test.ThreadNet.Infra.Shelley as Shelley
import Test.ThreadNet.Infra.TwoEras
import Test.ThreadNet.Network (NodeOutput (..),
TestNodeInitialization (..))
import Test.ThreadNet.TxGen.Cardano (CardanoTxGenExtra (..))
import Test.ThreadNet.Util.Expectations (NumBlocks (..))
import Test.ThreadNet.Util.NodeJoinPlan (trivialNodeJoinPlan)
import Test.ThreadNet.Util.NodeRestarts (noRestarts)
import Test.ThreadNet.Util.NodeToNodeVersion (genVersionFiltered)
import Test.ThreadNet.Util.Seed (runGen)
import qualified Test.Util.BoolProps as BoolProps
import Test.Util.HardFork.Future
import Test.Util.Orphans.Arbitrary ()
import Test.Util.Slots (NumSlots (..))
import Test.Util.TestEnv
type Crypto = StandardCrypto
data TestSetup = TestSetup
{ TestSetup -> DecentralizationParam
setupD :: Shelley.DecentralizationParam
, TestSetup -> Bool
setupHardFork :: Bool
, TestSetup -> Nonce
setupInitialNonce :: SL.Nonce
, TestSetup -> SecurityParam
setupK :: SecurityParam
, TestSetup -> Partition
setupPartition :: Partition
, TestSetup -> SlotLength
setupSlotLengthByron :: SlotLength
, TestSetup -> SlotLength
setupSlotLengthShelley :: SlotLength
, TestSetup -> TestConfig
setupTestConfig :: TestConfig
, TestSetup
-> (NodeToNodeVersion,
BlockNodeToNodeVersion (CardanoBlock Crypto))
setupVersion :: (NodeToNodeVersion, BlockNodeToNodeVersion (CardanoBlock Crypto))
}
deriving (Int -> TestSetup -> ShowS
[TestSetup] -> ShowS
TestSetup -> String
(Int -> TestSetup -> ShowS)
-> (TestSetup -> String)
-> ([TestSetup] -> ShowS)
-> Show TestSetup
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TestSetup -> ShowS
showsPrec :: Int -> TestSetup -> ShowS
$cshow :: TestSetup -> String
show :: TestSetup -> String
$cshowList :: [TestSetup] -> ShowS
showList :: [TestSetup] -> ShowS
Show)
instance Arbitrary TestSetup where
arbitrary :: Gen TestSetup
arbitrary = do
setupD <- Gen DecentralizationParam
forall a. Arbitrary a => Gen a
arbitrary
Gen DecentralizationParam
-> (DecentralizationParam -> Bool) -> Gen DecentralizationParam
forall a. Gen a -> (a -> Bool) -> Gen a
`suchThat` ((Rational -> Rational -> Bool
forall a. Eq a => a -> a -> Bool
/= Rational
0) (Rational -> Bool)
-> (DecentralizationParam -> Rational)
-> DecentralizationParam
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DecentralizationParam -> Rational
Shelley.decentralizationParamToRational)
setupK <- SecurityParam <$> choose (8, 10) `suchThatMap` nonZero
setupInitialNonce <- genNonce
setupSlotLengthByron <- arbitrary
setupSlotLengthShelley <- arbitrary
setupTestConfig <- genTestConfig
setupK
( EpochSize $ byronEpochSize setupK
, EpochSize $ shelleyEpochSize setupK
)
let TestConfig{numCoreNodes, numSlots} = setupTestConfig
setupHardFork <- frequency [(49, pure True), (1, pure False)]
setupPartition <- genPartition numCoreNodes numSlots setupK
setupVersion <- genVersionFiltered
isHardForkNodeToNodeEnabled
(Proxy @(CardanoBlock Crypto))
pure TestSetup
{ setupD
, setupHardFork
, setupInitialNonce
, setupK
, setupPartition
, setupSlotLengthByron
, setupSlotLengthShelley
, setupTestConfig
, setupVersion
}
tests :: TestTree
tests :: TestTree
tests = String -> [TestTree] -> TestTree
testGroup String
"Cardano ThreadNet" [
let name :: String
name = String
"simple convergence" in
(TestEnv -> TestTree) -> TestTree
askTestEnv ((TestEnv -> TestTree) -> TestTree)
-> (TestEnv -> TestTree) -> TestTree
forall a b. (a -> b) -> a -> b
$ TestTree -> TestEnv -> TestTree
adjustTestMode (TestTree -> TestEnv -> TestTree)
-> TestTree -> TestEnv -> TestTree
forall a b. (a -> b) -> a -> b
$
String -> (TestSetup -> Property) -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
name TestSetup -> Property
prop_simple_cardano_convergence
]
where
adjustTestMode :: TestTree -> TestEnv -> TestTree
adjustTestMode :: TestTree -> TestEnv -> TestTree
adjustTestMode TestTree
tree = \case
TestEnv
Nightly -> TestTree
tree
TestEnv
_ -> (Int -> Int) -> TestTree -> TestTree
adjustQuickCheckTests (\Int
n -> (Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
n) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
5) TestTree
tree
prop_simple_cardano_convergence :: TestSetup -> Property
prop_simple_cardano_convergence :: TestSetup -> Property
prop_simple_cardano_convergence TestSetup
{ DecentralizationParam
setupD :: TestSetup -> DecentralizationParam
setupD :: DecentralizationParam
setupD
, Bool
setupHardFork :: TestSetup -> Bool
setupHardFork :: Bool
setupHardFork
, Nonce
setupInitialNonce :: TestSetup -> Nonce
setupInitialNonce :: Nonce
setupInitialNonce
, SecurityParam
setupK :: TestSetup -> SecurityParam
setupK :: SecurityParam
setupK
, Partition
setupPartition :: TestSetup -> Partition
setupPartition :: Partition
setupPartition
, SlotLength
setupSlotLengthByron :: TestSetup -> SlotLength
setupSlotLengthByron :: SlotLength
setupSlotLengthByron
, SlotLength
setupSlotLengthShelley :: TestSetup -> SlotLength
setupSlotLengthShelley :: SlotLength
setupSlotLengthShelley
, TestConfig
setupTestConfig :: TestSetup -> TestConfig
setupTestConfig :: TestConfig
setupTestConfig
, (NodeToNodeVersion, BlockNodeToNodeVersion (CardanoBlock Crypto))
setupVersion :: TestSetup
-> (NodeToNodeVersion,
BlockNodeToNodeVersion (CardanoBlock Crypto))
setupVersion :: (NodeToNodeVersion, BlockNodeToNodeVersion (CardanoBlock Crypto))
setupVersion
} =
PropGeneralArgs (CardanoBlock Crypto)
-> TestOutput (CardanoBlock Crypto) -> Property
forall blk.
(Condense blk, Condense (HeaderHash blk), Eq blk, RunNode blk) =>
PropGeneralArgs blk -> TestOutput blk -> Property
prop_general_semisync PropGeneralArgs (CardanoBlock Crypto)
pga TestOutput (CardanoBlock Crypto)
testOutput Property -> Property -> Property
forall prop1 prop2.
(Testable prop1, Testable prop2) =>
prop1 -> prop2 -> Property
.&&.
TestOutput (CardanoBlock Crypto) -> Property
forall blk. HasHeader blk => TestOutput blk -> Property
prop_inSync TestOutput (CardanoBlock Crypto)
testOutput Property -> Property -> Property
forall prop1 prop2.
(Testable prop1, Testable prop2) =>
prop1 -> prop2 -> Property
.&&.
ReachesEra2 -> Property
prop_ReachesEra2 ReachesEra2
reachesEra2 Property -> Property -> Property
forall prop1 prop2.
(Testable prop1, Testable prop2) =>
prop1 -> prop2 -> Property
.&&.
Property
prop_noCPViolation Property -> Property -> Property
forall prop1 prop2.
(Testable prop1, Testable prop2) =>
prop1 -> prop2 -> Property
.&&.
( String -> [String] -> Property -> Property
forall prop.
Testable prop =>
String -> [String] -> prop -> Property
tabulate String
"ReachesEra2 label" [ReachesEra2 -> String
label_ReachesEra2 ReachesEra2
reachesEra2] (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
String -> [String] -> Property -> Property
forall prop.
Testable prop =>
String -> [String] -> prop -> Property
tabulate String
"Observed forge during a non-overlay Shelley slot"
[TestOutput (CardanoBlock Crypto) -> Set SlotNo -> String
forall era (eras :: [*]).
TestOutput (HardForkBlock (era : eras)) -> Set SlotNo -> String
label_hadActiveNonOverlaySlots TestOutput (CardanoBlock Crypto)
testOutput Set SlotNo
overlaySlots] (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
SecurityParam -> Partition -> Property -> Property
tabulatePartitionDuration SecurityParam
setupK Partition
setupPartition (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
SecurityParam -> NumBlocks -> String -> Property -> Property
tabulateFinalIntersectionDepth
SecurityParam
setupK
(Word64 -> NumBlocks
NumBlocks Word64
finalIntersectionDepth)
String
finalBlockEra (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
NumSlots -> Partition -> Bool -> Property -> Property
tabulatePartitionPosition
(Word64 -> NumSlots
NumSlots Word64
numByronSlots)
Partition
setupPartition
(ReachesEra2 -> Bool
ledgerReachesEra2 ReachesEra2
reachesEra2) (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
True
)
where
TestConfig
{ Seed
initSeed :: Seed
initSeed :: TestConfig -> Seed
initSeed
, NumCoreNodes
numCoreNodes :: TestConfig -> NumCoreNodes
numCoreNodes :: NumCoreNodes
numCoreNodes
, NumSlots
numSlots :: TestConfig -> NumSlots
numSlots :: NumSlots
numSlots
} = TestConfig
setupTestConfig
pga :: PropGeneralArgs (CardanoBlock Crypto)
pga = PropGeneralArgs
{ pgaBlockProperty :: CardanoBlock Crypto -> Property
pgaBlockProperty = Property -> CardanoBlock Crypto -> Property
forall a b. a -> b -> a
const (Property -> CardanoBlock Crypto -> Property)
-> Property -> CardanoBlock Crypto -> Property
forall a b. (a -> b) -> a -> b
$ Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
True
, pgaCountTxs :: CardanoBlock Crypto -> Word64
pgaCountTxs = Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word64)
-> (CardanoBlock Crypto -> Int) -> CardanoBlock Crypto -> Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [GenTx (CardanoBlock Crypto)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([GenTx (CardanoBlock Crypto)] -> Int)
-> (CardanoBlock Crypto -> [GenTx (CardanoBlock Crypto)])
-> CardanoBlock Crypto
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CardanoBlock Crypto -> [GenTx (CardanoBlock Crypto)]
forall blk. HasTxs blk => blk -> [GenTx blk]
extractTxs
, pgaExpectedCannotForge :: SlotNo -> NodeId -> WrapCannotForge (CardanoBlock Crypto) -> Bool
pgaExpectedCannotForge = SlotNo -> NodeId -> WrapCannotForge (CardanoBlock Crypto) -> Bool
forall blk. SlotNo -> NodeId -> WrapCannotForge blk -> Bool
noExpectedCannotForges
, pgaFirstBlockNo :: BlockNo
pgaFirstBlockNo = BlockNo
1
, pgaFixedMaxForkLength :: Maybe NumBlocks
pgaFixedMaxForkLength = NumBlocks -> Maybe NumBlocks
forall a. a -> Maybe a
Just NumBlocks
maxForkLength
, pgaFixedSchedule :: Maybe LeaderSchedule
pgaFixedSchedule =
Maybe LeaderSchedule
forall a. Maybe a
Nothing
, pgaSecurityParam :: SecurityParam
pgaSecurityParam = SecurityParam
setupK
, pgaTestConfig :: TestConfig
pgaTestConfig = TestConfig
setupTestConfig
, pgaTestConfigB :: TestConfigB (CardanoBlock Crypto)
pgaTestConfigB = TestConfigB (CardanoBlock Crypto)
testConfigB
}
testConfigB :: TestConfigB (CardanoBlock Crypto)
testConfigB = TestConfigB
{ forgeEbbEnv :: Maybe (ForgeEbbEnv (CardanoBlock Crypto))
forgeEbbEnv = Maybe (ForgeEbbEnv (CardanoBlock Crypto))
forall a. Maybe a
Nothing
, future :: Future
future =
if Bool
setupHardFork
then
SlotLength -> EpochSize -> EraSize -> Future -> Future
EraCons SlotLength
setupSlotLengthByron EpochSize
epochSizeByron EraSize
eraSizeByron (Future -> Future) -> Future -> Future
forall a b. (a -> b) -> a -> b
$
SlotLength -> EpochSize -> Future
EraFinal SlotLength
setupSlotLengthShelley EpochSize
epochSizeShelley
else
SlotLength -> EpochSize -> Future
EraFinal SlotLength
setupSlotLengthByron EpochSize
epochSizeByron
, messageDelay :: CalcMessageDelay (CardanoBlock Crypto)
messageDelay = Partition -> CalcMessageDelay (CardanoBlock Crypto)
forall blk. Partition -> CalcMessageDelay blk
mkMessageDelay Partition
setupPartition
, nodeJoinPlan :: NodeJoinPlan
nodeJoinPlan = NumCoreNodes -> NodeJoinPlan
trivialNodeJoinPlan NumCoreNodes
numCoreNodes
, nodeRestarts :: NodeRestarts
nodeRestarts = NodeRestarts
noRestarts
, txGenExtra :: TxGenExtra (CardanoBlock Crypto)
txGenExtra = CardanoTxGenExtra
{ ctgeByronGenesisKeys :: GeneratedSecrets
ctgeByronGenesisKeys = GeneratedSecrets
generatedSecrets
, ctgeNetworkMagic :: NetworkMagic
ctgeNetworkMagic =
AProtocolMagic () -> NetworkMagic
forall a. AProtocolMagic a -> NetworkMagic
CC.Common.makeNetworkMagic (AProtocolMagic () -> NetworkMagic)
-> AProtocolMagic () -> NetworkMagic
forall a b. (a -> b) -> a -> b
$
Config -> AProtocolMagic ()
CC.Genesis.configProtocolMagic Config
genesisByron
, ctgeShelleyCoreNodes :: [CoreNode Crypto]
ctgeShelleyCoreNodes = [CoreNode Crypto]
coreNodes
}
, version :: (NodeToNodeVersion, BlockNodeToNodeVersion (CardanoBlock Crypto))
version = (NodeToNodeVersion, BlockNodeToNodeVersion (CardanoBlock Crypto))
setupVersion
}
testOutput :: TestOutput (CardanoBlock Crypto)
testOutput :: TestOutput (CardanoBlock Crypto)
testOutput =
TestConfig
-> TestConfigB (CardanoBlock Crypto)
-> (forall (m :: * -> *).
IOLike m =>
TestConfigMB m (CardanoBlock Crypto))
-> TestOutput (CardanoBlock Crypto)
forall blk.
(RunNode blk, TxGen blk, TracingConstraints blk, HasCallStack) =>
TestConfig
-> TestConfigB blk
-> (forall (m :: * -> *). IOLike m => TestConfigMB m blk)
-> TestOutput blk
runTestNetwork TestConfig
setupTestConfig TestConfigB (CardanoBlock Crypto)
testConfigB TestConfigMB
{ nodeInfo :: CoreNodeId -> TestNodeInitialization m (CardanoBlock Crypto)
nodeInfo = \coreNodeId :: CoreNodeId
coreNodeId@(CoreNodeId Word64
nid) ->
PBftParams
-> CoreNodeId
-> Config
-> GeneratedSecrets
-> ProtocolVersion
-> ShelleyGenesis
-> Nonce
-> CoreNode Crypto
-> TestNodeInitialization m (CardanoBlock Crypto)
forall c (m :: * -> *).
(IOLike m, c ~ Crypto) =>
PBftParams
-> CoreNodeId
-> Config
-> GeneratedSecrets
-> ProtocolVersion
-> ShelleyGenesis
-> Nonce
-> CoreNode c
-> TestNodeInitialization m (CardanoBlock c)
mkProtocolCardanoAndHardForkTxs
PBftParams
pbftParams
CoreNodeId
coreNodeId
Config
genesisByron
GeneratedSecrets
generatedSecrets
ProtocolVersion
propPV
ShelleyGenesis
genesisShelley
Nonce
setupInitialNonce
([CoreNode Crypto]
coreNodes [CoreNode Crypto] -> Int -> CoreNode Crypto
forall a. HasCallStack => [a] -> Int -> a
!! Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
nid)
, mkRekeyM :: Maybe (m (RekeyM m (CardanoBlock Crypto)))
mkRekeyM = Maybe (m (RekeyM m (CardanoBlock Crypto)))
forall a. Maybe a
Nothing
}
maxForkLength :: NumBlocks
maxForkLength :: NumBlocks
maxForkLength = Word64 -> NumBlocks
NumBlocks (Word64 -> NumBlocks) -> Word64 -> NumBlocks
forall a b. (a -> b) -> a -> b
$
if ReachesEra2 -> Bool
rsEra2Blocks ReachesEra2
reachesEra2
then
NonZero Word64 -> Word64
forall a. NonZero a -> a
unNonZero (NonZero Word64 -> Word64) -> NonZero Word64 -> Word64
forall a b. (a -> b) -> a -> b
$ SecurityParam -> NonZero Word64
maxRollbacks SecurityParam
setupK
else
Word64 -> Word64 -> Word64
forall a. Integral a => a -> a -> a
div Word64
partitionDuration Word64
2 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64 -> Word64 -> Word64
forall a. Integral a => a -> a -> a
mod Word64
partitionDuration Word64
2
partitionDuration :: Word64
partitionDuration :: Word64
partitionDuration = Word64
dur
where
Partition SlotNo
_ (NumSlots Word64
dur) = Partition
setupPartition
pbftParams :: PBftParams
pbftParams :: PBftParams
pbftParams = SecurityParam -> NumCoreNodes -> PBftParams
Byron.byronPBftParams SecurityParam
setupK NumCoreNodes
numCoreNodes
epochSizeByron :: EpochSize
epochSizeByron :: EpochSize
epochSizeByron =
EpochSlots -> EpochSize
fromByronEpochSlots (EpochSlots -> EpochSize) -> EpochSlots -> EpochSize
forall a b. (a -> b) -> a -> b
$ Config -> EpochSlots
CC.Genesis.configEpochSlots Config
genesisByron
eraSizeByron :: EraSize
eraSizeByron :: EraSize
eraSizeByron = Word64 -> EraSize
EraSize Word64
forall a. Num a => a
numFirstEraEpochs
genesisByron :: CC.Genesis.Config
generatedSecrets :: CC.Genesis.GeneratedSecrets
(Config
genesisByron, GeneratedSecrets
generatedSecrets) =
SlotLength -> PBftParams -> (Config, GeneratedSecrets)
Byron.generateGenesisConfig SlotLength
setupSlotLengthByron PBftParams
pbftParams
initialKESPeriod :: SL.KESPeriod
initialKESPeriod :: KESPeriod
initialKESPeriod = Word -> KESPeriod
SL.KESPeriod Word
0
coreNodes :: [Shelley.CoreNode Crypto]
coreNodes :: [CoreNode Crypto]
coreNodes = Seed -> Gen [CoreNode Crypto] -> [CoreNode Crypto]
forall a. Seed -> Gen a -> a
runGen Seed
initSeed (Gen [CoreNode Crypto] -> [CoreNode Crypto])
-> Gen [CoreNode Crypto] -> [CoreNode Crypto]
forall a b. (a -> b) -> a -> b
$
Int -> Gen (CoreNode Crypto) -> Gen [CoreNode Crypto]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM (Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
n) (Gen (CoreNode Crypto) -> Gen [CoreNode Crypto])
-> Gen (CoreNode Crypto) -> Gen [CoreNode Crypto]
forall a b. (a -> b) -> a -> b
$
KESPeriod -> Gen (CoreNode Crypto)
forall c. Crypto c => KESPeriod -> Gen (CoreNode c)
Shelley.genCoreNode KESPeriod
initialKESPeriod
where
NumCoreNodes Word64
n = NumCoreNodes
numCoreNodes
maxLovelaceSupply :: Word64
maxLovelaceSupply :: Word64
maxLovelaceSupply = Word64
45000000000000000
genesisShelley :: ShelleyGenesis
genesisShelley :: ShelleyGenesis
genesisShelley =
ProtVer
-> SecurityParam
-> Rational
-> DecentralizationParam
-> Word64
-> SlotLength
-> KesConfig
-> [CoreNode Crypto]
-> ShelleyGenesis
forall c.
PraosCrypto c =>
ProtVer
-> SecurityParam
-> Rational
-> DecentralizationParam
-> Word64
-> SlotLength
-> KesConfig
-> [CoreNode c]
-> ShelleyGenesis
Shelley.mkGenesisConfig
(Version -> Natural -> ProtVer
SL.ProtVer Version
shelleyMajorVersion Natural
0)
SecurityParam
setupK
Rational
activeSlotCoeff
DecentralizationParam
setupD
Word64
maxLovelaceSupply
SlotLength
setupSlotLengthShelley
(Proxy Crypto -> NumSlots -> KesConfig
forall (proxy :: * -> *) c.
Crypto c =>
proxy c -> NumSlots -> KesConfig
Shelley.mkKesConfig (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @Crypto) NumSlots
numSlots)
[CoreNode Crypto]
coreNodes
epochSizeShelley :: EpochSize
epochSizeShelley :: EpochSize
epochSizeShelley = ShelleyGenesis -> EpochSize
sgEpochLength ShelleyGenesis
genesisShelley
propPV :: CC.Update.ProtocolVersion
propPV :: ProtocolVersion
propPV =
if Bool
setupHardFork
then
Word16 -> Word16 -> Word8 -> ProtocolVersion
CC.Update.ProtocolVersion (Version -> Word16
forall i. Integral i => Version -> i
SL.getVersion Version
shelleyMajorVersion) Word16
0 Word8
0
else
Word16 -> Word16 -> Word8 -> ProtocolVersion
CC.Update.ProtocolVersion
Word16
forall a. Integral a => a
byronMajorVersion (Word16
forall a. Num a => a
byronInitialMinorVersion Word16 -> Word16 -> Word16
forall a. Num a => a -> a -> a
+ Word16
1) Word8
0
reachesEra2 :: ReachesEra2
reachesEra2 :: ReachesEra2
reachesEra2 = ReachesEra2
{ rsEra1Slots :: Prereq
rsEra1Slots =
Bool -> Prereq
BoolProps.enabledIf (Bool -> Prereq) -> Bool -> Prereq
forall a b. (a -> b) -> a -> b
$ Word64
t Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
numByronSlots
, rsPV :: Prereq
rsPV = Bool -> Prereq
BoolProps.enabledIf Bool
setupHardFork
, rsEra2Blocks :: Bool
rsEra2Blocks =
[Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or ([Bool] -> Bool) -> [Bool] -> Bool
forall a b. (a -> b) -> a -> b
$
[ Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ CardanoBlock Crypto -> Bool
forall era (eras :: [*]). HardForkBlock (era : eras) -> Bool
isFirstEraBlock CardanoBlock Crypto
blk
| (NodeId
_nid, NodeOutput (CardanoBlock Crypto)
no) <- Map NodeId (NodeOutput (CardanoBlock Crypto))
-> [(NodeId, NodeOutput (CardanoBlock Crypto))]
forall k a. Map k a -> [(k, a)]
Map.toList Map NodeId (NodeOutput (CardanoBlock Crypto))
testOutputNodes
, let NodeOutput{Map SlotNo (CardanoBlock Crypto)
nodeOutputForges :: Map SlotNo (CardanoBlock Crypto)
nodeOutputForges :: forall blk. NodeOutput blk -> Map SlotNo blk
nodeOutputForges} = NodeOutput (CardanoBlock Crypto)
no
, (CardanoBlock Crypto
blk, Map SlotNo (CardanoBlock Crypto)
_m) <- Maybe (CardanoBlock Crypto, Map SlotNo (CardanoBlock Crypto))
-> [(CardanoBlock Crypto, Map SlotNo (CardanoBlock Crypto))]
forall a. Maybe a -> [a]
maybeToList (Maybe (CardanoBlock Crypto, Map SlotNo (CardanoBlock Crypto))
-> [(CardanoBlock Crypto, Map SlotNo (CardanoBlock Crypto))])
-> Maybe (CardanoBlock Crypto, Map SlotNo (CardanoBlock Crypto))
-> [(CardanoBlock Crypto, Map SlotNo (CardanoBlock Crypto))]
forall a b. (a -> b) -> a -> b
$ Map SlotNo (CardanoBlock Crypto)
-> Maybe (CardanoBlock Crypto, Map SlotNo (CardanoBlock Crypto))
forall k a. Map k a -> Maybe (a, Map k a)
Map.maxView Map SlotNo (CardanoBlock Crypto)
nodeOutputForges
]
, rsEra2Slots :: Requirement
rsEra2Slots =
Bool -> Requirement -> Requirement
forall a. HasCallStack => Bool -> a -> a
assert (Word64
w Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word64
k) (Requirement -> Requirement) -> Requirement -> Requirement
forall a b. (a -> b) -> a -> b
$
Bool -> Requirement
BoolProps.requiredIf (Bool -> Requirement) -> Bool -> Requirement
forall a b. (a -> b) -> a -> b
$
Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Set SlotNo -> Bool
forall a. Set a -> Bool
Set.null (Set SlotNo -> Bool) -> Set SlotNo -> Bool
forall a b. (a -> b) -> a -> b
$ Set SlotNo
overlaySlots
}
where
NumSlots Word64
t = NumSlots
numSlots
TestOutput{Map NodeId (NodeOutput (CardanoBlock Crypto))
testOutputNodes :: Map NodeId (NodeOutput (CardanoBlock Crypto))
testOutputNodes :: forall blk. TestOutput blk -> Map NodeId (NodeOutput blk)
testOutputNodes} = TestOutput (CardanoBlock Crypto)
testOutput
k :: Word64
k :: Word64
k = NonZero Word64 -> Word64
forall a. NonZero a -> a
unNonZero (NonZero Word64 -> Word64) -> NonZero Word64 -> Word64
forall a b. (a -> b) -> a -> b
$ SecurityParam -> NonZero Word64
maxRollbacks SecurityParam
setupK
coeff :: SL.ActiveSlotCoeff
coeff :: ActiveSlotCoeff
coeff = ShelleyGenesis -> ActiveSlotCoeff
SL.sgActiveSlotCoeff ShelleyGenesis
genesisShelley
w :: Word64
w :: Word64
w = Word64 -> ActiveSlotCoeff -> Word64
SL.computeStabilityWindow Word64
k ActiveSlotCoeff
coeff
overlaySlots :: Set SlotNo
overlaySlots :: Set SlotNo
overlaySlots =
NumSlots -> NumSlots -> UnitInterval -> EpochSize -> Set SlotNo
secondEraOverlaySlots
NumSlots
numSlots
(Word64 -> NumSlots
NumSlots Word64
numByronSlots)
(ShelleyGenesis -> PParams ShelleyEra
sgProtocolParams ShelleyGenesis
genesisShelley PParams ShelleyEra
-> Getting UnitInterval (PParams ShelleyEra) UnitInterval
-> UnitInterval
forall s a. s -> Getting a s a -> a
^. Getting UnitInterval (PParams ShelleyEra) UnitInterval
forall era.
(EraPParams era, ProtVerAtMost era 6) =>
Lens' (PParams era) UnitInterval
Lens' (PParams ShelleyEra) UnitInterval
SL.ppDL)
EpochSize
epochSizeShelley
numByronSlots :: Word64
numByronSlots :: Word64
numByronSlots = Word64
forall a. Num a => a
numFirstEraEpochs Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* EpochSize -> Word64
unEpochSize EpochSize
epochSizeByron
finalBlockEra :: String
finalBlockEra :: String
finalBlockEra =
if ReachesEra2 -> Bool
rsEra2Blocks ReachesEra2
reachesEra2 then String
"Shelley" else String
"Byron"
finalIntersectionDepth :: Word64
finalIntersectionDepth :: Word64
finalIntersectionDepth = Word64
depth
where
NumBlocks Word64
depth = PropGeneralArgs (CardanoBlock Crypto)
-> TestOutput (CardanoBlock Crypto) -> NumBlocks
forall blk.
HasHeader blk =>
PropGeneralArgs blk -> TestOutput blk -> NumBlocks
calcFinalIntersectionDepth PropGeneralArgs (CardanoBlock Crypto)
pga TestOutput (CardanoBlock Crypto)
testOutput
prop_noCPViolation :: Property
prop_noCPViolation :: Property
prop_noCPViolation =
String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
( String
"finalChains: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<>
Map NodeId (Chain (CardanoBlock Crypto)) -> String
forall a. Show a => a -> String
show (NodeOutput (CardanoBlock Crypto) -> Chain (CardanoBlock Crypto)
forall blk. NodeOutput blk -> Chain blk
nodeOutputFinalChain (NodeOutput (CardanoBlock Crypto) -> Chain (CardanoBlock Crypto))
-> Map NodeId (NodeOutput (CardanoBlock Crypto))
-> Map NodeId (Chain (CardanoBlock Crypto))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TestOutput (CardanoBlock Crypto)
-> Map NodeId (NodeOutput (CardanoBlock Crypto))
forall blk. TestOutput blk -> Map NodeId (NodeOutput blk)
testOutputNodes TestOutput (CardanoBlock Crypto)
testOutput)
) (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample String
"CP violation in final chains!" (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
Bool -> Property
forall prop. Testable prop => prop -> Property
property (Bool -> Property) -> Bool -> Property
forall a b. (a -> b) -> a -> b
$ NonZero Word64 -> Word64
forall a. NonZero a -> a
unNonZero (SecurityParam -> NonZero Word64
maxRollbacks SecurityParam
setupK) Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word64
finalIntersectionDepth
mkProtocolCardanoAndHardForkTxs ::
forall c m. (IOLike m, c ~ StandardCrypto)
=> PBftParams
-> CoreNodeId
-> CC.Genesis.Config
-> CC.Genesis.GeneratedSecrets
-> CC.Update.ProtocolVersion
-> ShelleyGenesis
-> SL.Nonce
-> Shelley.CoreNode c
-> TestNodeInitialization m (CardanoBlock c)
mkProtocolCardanoAndHardForkTxs :: forall c (m :: * -> *).
(IOLike m, c ~ Crypto) =>
PBftParams
-> CoreNodeId
-> Config
-> GeneratedSecrets
-> ProtocolVersion
-> ShelleyGenesis
-> Nonce
-> CoreNode c
-> TestNodeInitialization m (CardanoBlock c)
mkProtocolCardanoAndHardForkTxs
PBftParams
pbftParams CoreNodeId
coreNodeId Config
genesisByron GeneratedSecrets
generatedSecretsByron ProtocolVersion
propPV
ShelleyGenesis
genesisShelley Nonce
initialNonce CoreNode c
coreNodeShelley
=
TestNodeInitialization
{ tniCrucialTxs :: [GenTx (CardanoBlock c)]
tniCrucialTxs = [GenTx (CardanoBlock c)]
crucialTxs
, tniProtocolInfo :: ProtocolInfo (CardanoBlock c)
tniProtocolInfo = ProtocolInfo (CardanoBlock c)
protocolInfo
, tniBlockForging :: m [BlockForging m (CardanoBlock c)]
tniBlockForging = m [BlockForging m (CardanoBlock c)]
blockForging
}
where
crucialTxs :: [GenTx (CardanoBlock c)]
crucialTxs :: [GenTx (CardanoBlock c)]
crucialTxs =
GenTx ByronBlock -> GenTx (CardanoBlock c)
forall c. GenTx ByronBlock -> CardanoGenTx c
GenTxByron (GenTx ByronBlock -> GenTx (CardanoBlock c))
-> [GenTx ByronBlock] -> [GenTx (CardanoBlock c)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TestNodeInitialization m ByronBlock -> [GenTx ByronBlock]
forall (m :: * -> *) blk.
TestNodeInitialization m blk -> [GenTx blk]
tniCrucialTxs TestNodeInitialization m ByronBlock
tniByron
where
tniByron :: TestNodeInitialization m ByronBlock
tniByron :: TestNodeInitialization m ByronBlock
tniByron =
PBftParams
-> CoreNodeId
-> Config
-> GeneratedSecrets
-> ProtocolVersion
-> TestNodeInitialization m ByronBlock
forall (m :: * -> *).
(Monad m, HasCallStack) =>
PBftParams
-> CoreNodeId
-> Config
-> GeneratedSecrets
-> ProtocolVersion
-> TestNodeInitialization m ByronBlock
Byron.mkProtocolByronAndHardForkTxs
PBftParams
pbftParams
CoreNodeId
coreNodeId
Config
genesisByron
GeneratedSecrets
generatedSecretsByron
ProtocolVersion
propPV
protocolInfo :: ProtocolInfo (CardanoBlock c)
blockForging :: m [BlockForging m (CardanoBlock c)]
(ProtocolInfo (CardanoBlock c) -> ProtocolInfo (CardanoBlock c)
forall c.
ProtocolInfo (CardanoBlock c) -> ProtocolInfo (CardanoBlock c)
setByronProtVer -> ProtocolInfo (CardanoBlock c)
protocolInfo, m [BlockForging m (CardanoBlock c)]
blockForging) =
(CoreNodeId, CoreNode c)
-> ShelleyGenesis
-> ProtocolVersion
-> Nonce
-> Config
-> GeneratedSecrets
-> Maybe PBftSignatureThreshold
-> ProtVer
-> CardanoHardForkTriggers
-> (ProtocolInfo (CardanoBlock c),
m [BlockForging m (CardanoBlock c)])
forall (m :: * -> *) c.
(CardanoHardForkConstraints c, IOLike m) =>
(CoreNodeId, CoreNode c)
-> ShelleyGenesis
-> ProtocolVersion
-> Nonce
-> Config
-> GeneratedSecrets
-> Maybe PBftSignatureThreshold
-> ProtVer
-> CardanoHardForkTriggers
-> (ProtocolInfo (CardanoBlock c),
m [BlockForging m (CardanoBlock c)])
mkTestProtocolInfo
(CoreNodeId
coreNodeId, CoreNode c
coreNodeShelley)
ShelleyGenesis
genesisShelley
ProtocolVersion
propPV
Nonce
initialNonce
Config
genesisByron
GeneratedSecrets
generatedSecretsByron
(PBftSignatureThreshold -> Maybe PBftSignatureThreshold
forall a. a -> Maybe a
Just (PBftSignatureThreshold -> Maybe PBftSignatureThreshold)
-> PBftSignatureThreshold -> Maybe PBftSignatureThreshold
forall a b. (a -> b) -> a -> b
$ Double -> PBftSignatureThreshold
PBftSignatureThreshold Double
1)
(Version -> Natural -> ProtVer
SL.ProtVer Version
shelleyMajorVersion Natural
0)
CardanoHardForkTriggers
hardForkOnDefaultProtocolVersions
byronMajorVersion :: Integral a => a
byronMajorVersion :: forall a. Integral a => a
byronMajorVersion = Version -> a
forall i. Integral i => Version -> i
SL.getVersion Version
shelleyMajorVersion a -> a -> a
forall a. Num a => a -> a -> a
- a
1
byronInitialMinorVersion :: Num a => a
byronInitialMinorVersion :: forall a. Num a => a
byronInitialMinorVersion = a
0
shelleyMajorVersion :: SL.Version
shelleyMajorVersion :: Version
shelleyMajorVersion = forall era. Era era => Version
L.eraProtVerLow @ShelleyEra
byronEpochSize :: SecurityParam -> Word64
byronEpochSize :: SecurityParam -> Word64
byronEpochSize (SecurityParam NonZero Word64
k) =
EpochSlots -> Word64
unEpochSlots (EpochSlots -> Word64) -> EpochSlots -> Word64
forall a b. (a -> b) -> a -> b
$ BlockCount -> EpochSlots
kEpochSlots (BlockCount -> EpochSlots) -> BlockCount -> EpochSlots
forall a b. (a -> b) -> a -> b
$ Word64 -> BlockCount
CC.Common.BlockCount (Word64 -> BlockCount) -> Word64 -> BlockCount
forall a b. (a -> b) -> a -> b
$ NonZero Word64 -> Word64
forall a. NonZero a -> a
unNonZero NonZero Word64
k
setByronProtVer :: ProtocolInfo (CardanoBlock c) -> ProtocolInfo (CardanoBlock c)
setByronProtVer :: forall c.
ProtocolInfo (CardanoBlock c) -> ProtocolInfo (CardanoBlock c)
setByronProtVer =
(ExtLedgerState (CardanoBlock c) ValuesMK
-> ExtLedgerState (CardanoBlock c) ValuesMK)
-> ProtocolInfo (CardanoBlock c) -> ProtocolInfo (CardanoBlock c)
forall {b}.
(ExtLedgerState b ValuesMK -> ExtLedgerState b ValuesMK)
-> ProtocolInfo b -> ProtocolInfo b
modifyInitLedger ((ExtLedgerState (CardanoBlock c) ValuesMK
-> ExtLedgerState (CardanoBlock c) ValuesMK)
-> ProtocolInfo (CardanoBlock c) -> ProtocolInfo (CardanoBlock c))
-> (ExtLedgerState (CardanoBlock c) ValuesMK
-> ExtLedgerState (CardanoBlock c) ValuesMK)
-> ProtocolInfo (CardanoBlock c)
-> ProtocolInfo (CardanoBlock c)
forall a b. (a -> b) -> a -> b
$ (LedgerState (CardanoBlock c) ValuesMK
-> LedgerState (CardanoBlock c) ValuesMK)
-> ExtLedgerState (CardanoBlock c) ValuesMK
-> ExtLedgerState (CardanoBlock c) ValuesMK
forall {blk} {mk :: MapKind} {mk :: MapKind}.
(LedgerState blk mk -> LedgerState blk mk)
-> ExtLedgerState blk mk -> ExtLedgerState blk mk
modifyExtLedger ((LedgerState (CardanoBlock c) ValuesMK
-> LedgerState (CardanoBlock c) ValuesMK)
-> ExtLedgerState (CardanoBlock c) ValuesMK
-> ExtLedgerState (CardanoBlock c) ValuesMK)
-> (LedgerState (CardanoBlock c) ValuesMK
-> LedgerState (CardanoBlock c) ValuesMK)
-> ExtLedgerState (CardanoBlock c) ValuesMK
-> ExtLedgerState (CardanoBlock c) ValuesMK
forall a b. (a -> b) -> a -> b
$ (LedgerState ByronBlock ValuesMK
-> LedgerState ByronBlock ValuesMK)
-> LedgerState (CardanoBlock c) ValuesMK
-> LedgerState (CardanoBlock c) ValuesMK
forall x (mk :: MapKind) (xs :: [*]).
(LedgerState x mk -> LedgerState x mk)
-> LedgerState (HardForkBlock (x : xs)) mk
-> LedgerState (HardForkBlock (x : xs)) mk
modifyHFLedgerState ((LedgerState ByronBlock ValuesMK
-> LedgerState ByronBlock ValuesMK)
-> LedgerState (CardanoBlock c) ValuesMK
-> LedgerState (CardanoBlock c) ValuesMK)
-> (LedgerState ByronBlock ValuesMK
-> LedgerState ByronBlock ValuesMK)
-> LedgerState (CardanoBlock c) ValuesMK
-> LedgerState (CardanoBlock c) ValuesMK
forall a b. (a -> b) -> a -> b
$ \LedgerState ByronBlock ValuesMK
st ->
let cvs :: ChainValidationState
cvs = LedgerState ByronBlock ValuesMK -> ChainValidationState
forall (mk :: MapKind).
LedgerState ByronBlock mk -> ChainValidationState
byronLedgerState LedgerState ByronBlock ValuesMK
st
us :: State
us = (ChainValidationState -> State
CC.cvsUpdateState ChainValidationState
cvs) {
CC.adoptedProtocolVersion =
CC.Update.ProtocolVersion byronMajorVersion byronInitialMinorVersion 0
}
in LedgerState ByronBlock ValuesMK
st { byronLedgerState = cvs { CC.cvsUpdateState = us } }
where
modifyInitLedger :: (ExtLedgerState b ValuesMK -> ExtLedgerState b ValuesMK)
-> ProtocolInfo b -> ProtocolInfo b
modifyInitLedger ExtLedgerState b ValuesMK -> ExtLedgerState b ValuesMK
f ProtocolInfo b
pinfo = ProtocolInfo b
pinfo { pInfoInitLedger = f (pInfoInitLedger pinfo) }
modifyExtLedger :: (LedgerState blk mk -> LedgerState blk mk)
-> ExtLedgerState blk mk -> ExtLedgerState blk mk
modifyExtLedger LedgerState blk mk -> LedgerState blk mk
f ExtLedgerState blk mk
elgr = ExtLedgerState blk mk
elgr { ledgerState = f (ledgerState elgr ) }
modifyHFLedgerState ::
(LedgerState x mk -> LedgerState x mk)
-> LedgerState (HardForkBlock (x : xs)) mk
-> LedgerState (HardForkBlock (x : xs)) mk
modifyHFLedgerState :: forall x (mk :: MapKind) (xs :: [*]).
(LedgerState x mk -> LedgerState x mk)
-> LedgerState (HardForkBlock (x : xs)) mk
-> LedgerState (HardForkBlock (x : xs)) mk
modifyHFLedgerState LedgerState x mk -> LedgerState x mk
f (HardForkLedgerState (HardForkState (TZ Current (Flip LedgerState mk) x
st))) =
HardForkState (Flip LedgerState mk) (x : xs)
-> LedgerState (HardForkBlock (x : xs)) mk
forall (xs :: [*]) (mk :: MapKind).
HardForkState (Flip LedgerState mk) xs
-> LedgerState (HardForkBlock xs) mk
HardForkLedgerState (Telescope (K Past) (Current (Flip LedgerState mk)) (x : xs)
-> HardForkState (Flip LedgerState mk) (x : xs)
forall (f :: * -> *) (xs :: [*]).
Telescope (K Past) (Current f) xs -> HardForkState f xs
HardForkState (Current (Flip LedgerState mk) x
-> Telescope (K Past) (Current (Flip LedgerState mk)) (x : xs)
forall {k} (f :: k -> *) (x :: k) (g :: k -> *) (xs1 :: [k]).
f x -> Telescope g f (x : xs1)
TZ Current (Flip LedgerState mk) x
st {currentState = Flip $ f (unFlip $ currentState st)}))
modifyHFLedgerState LedgerState x mk -> LedgerState x mk
_ LedgerState (HardForkBlock (x : xs)) mk
st = LedgerState (HardForkBlock (x : xs)) mk
st