From 0d63445afe3ffea9aa5823ecb8011e4616fa4b17 Mon Sep 17 00:00:00 2001 From: Jordan Millar Date: Mon, 16 Jan 2023 20:23:42 -0400 Subject: [PATCH] Compiles and passes tests --- cardano-testnet/src/Parsers/Cardano.hs | 39 +++++++----- cardano-testnet/src/Testnet.hs | 37 ++++++++--- cardano-testnet/src/Testnet/Babbage.hs | 6 +- cardano-testnet/src/Testnet/Cardano.hs | 61 +++++++++++++------ .../test/Test/Cli/KesPeriodInfo.hs | 4 +- .../test/Test/ShutdownOnSlotSynced.hs | 17 +++--- 6 files changed, 106 insertions(+), 58 deletions(-) diff --git a/cardano-testnet/src/Parsers/Cardano.hs b/cardano-testnet/src/Parsers/Cardano.hs index 5dc5a4b92f2..3e1514ebd85 100644 --- a/cardano-testnet/src/Parsers/Cardano.hs +++ b/cardano-testnet/src/Parsers/Cardano.hs @@ -7,15 +7,16 @@ module Parsers.Cardano ) where import Prelude + import qualified Data.List as L import Options.Applicative import qualified Options.Applicative as OA import Text.Read -import Testnet.Util.Runtime (readNodeLoggingFormat) import Testnet import Testnet.Cardano import Testnet.Run (runTestnet) +import Testnet.Util.Runtime (readNodeLoggingFormat) data CardanoOptions = CardanoOptions @@ -25,21 +26,7 @@ data CardanoOptions = CardanoOptions optsTestnet :: Parser CardanoTestnetOptions optsTestnet = CardanoTestnetOptions - <$> OA.option - ((`L.replicate` cardanoDefaultTestnetNodeOptions) <$> auto) - ( OA.long "num-bft-nodes" - <> OA.help "Number of BFT nodes" - <> OA.metavar "COUNT" - <> OA.showDefault - <> OA.value (cardanoBftNodeOptions defaultTestnetOptions) - ) - <*> OA.option auto - ( OA.long "num-pool-nodes" - <> OA.help "Number of pool nodes" - <> OA.metavar "COUNT" - <> OA.showDefault - <> OA.value (cardanoNumPoolNodes defaultTestnetOptions) - ) + <$> pNumBftAndSpoNodes <*> OA.option (OA.eitherReader readEither) ( OA.long "era" <> OA.help ("Era to upgrade to. " <> show @[Era] [minBound .. maxBound]) @@ -83,6 +70,26 @@ optsTestnet = CardanoTestnetOptions <> OA.value (cardanoNodeLoggingFormat defaultTestnetOptions) ) +pNumBftAndSpoNodes :: Parser [TestnetNodeOptions] +pNumBftAndSpoNodes = + (++) + <$> OA.option + ((`L.replicate` BftTestnetNodeOptions []) <$> auto) + ( OA.long "num-bft-nodes" + <> OA.help "Number of BFT nodes" + <> OA.metavar "COUNT" + <> OA.showDefault + <> OA.value (cardanoNodes defaultTestnetOptions) + ) + <*> OA.option + ((`L.replicate` SpoTestnetNodeOptions) <$> auto) + ( OA.long "num-pool-nodes" + <> OA.help "Number of pool nodes" + <> OA.metavar "COUNT" + <> OA.showDefault + <> OA.value (cardanoNodes defaultTestnetOptions) + ) + optsCardano :: Parser CardanoOptions optsCardano = CardanoOptions <$> optional diff --git a/cardano-testnet/src/Testnet.hs b/cardano-testnet/src/Testnet.hs index 9273958502d..1b36bf6c878 100644 --- a/cardano-testnet/src/Testnet.hs +++ b/cardano-testnet/src/Testnet.hs @@ -6,15 +6,18 @@ module Testnet , Testnet.testnet ) where -import Data.Eq (Eq) -import Text.Show (Show) +import Control.Monad +import Prelude -import qualified Hedgehog.Extras.Test.Base as H + +import Hedgehog +import Hedgehog.Extras.Test.Base (Integration, noteShow_) import Testnet.Babbage as Babbage import Testnet.Cardano as Cardano import Testnet.Conf -import Testnet.Shelley as Shelley +import Testnet.Shelley as Shelley (ShelleyTestnetOptions, defaultTestnetOptions, + shelleyTestnet) data TestnetOptions = ShelleyOnlyTestnetOptions ShelleyTestnetOptions @@ -22,11 +25,27 @@ data TestnetOptions | CardanoOnlyTestnetOptions CardanoTestnetOptions deriving (Eq, Show) -testnet :: TestnetOptions -> Conf -> H.Integration TestnetRuntime -testnet options = case options of - ShelleyOnlyTestnetOptions o -> shelleyTestnet o - BabbageOnlyTestnetOptions o -> babbageTestnet o - CardanoOnlyTestnetOptions o -> cardanoTestnet o +-- | There are certain conditions that need to be met in order to run +-- a valid node cluster. +testnetMinimumConfigurationRequirements :: CardanoTestnetOptions -> Integration () +testnetMinimumConfigurationRequirements cTestnetOpts = do + when (length (cardanoNodes cTestnetOpts) < 2) $ do + noteShow_ ("Need at least two nodes to run a cluster" :: String) + noteShow_ cTestnetOpts + assert False + + when (cardanoNumPoolNodes (cardanoNodes cTestnetOpts) < 1) $ do + noteShow_ ("Need at least one SPO to run a cluster" :: String) + noteShow_ cTestnetOpts + assert False + +testnet :: TestnetOptions -> Conf -> Integration TestnetRuntime +testnet options conf = case options of + ShelleyOnlyTestnetOptions o -> shelleyTestnet o conf + BabbageOnlyTestnetOptions o -> babbageTestnet o conf + CardanoOnlyTestnetOptions o -> do + testnetMinimumConfigurationRequirements o + cardanoTestnet o conf babbageDefaultTestnetOptions :: BabbageTestnetOptions babbageDefaultTestnetOptions = Babbage.defaultTestnetOptions diff --git a/cardano-testnet/src/Testnet/Babbage.hs b/cardano-testnet/src/Testnet/Babbage.hs index 17243cdcca5..8988058718a 100644 --- a/cardano-testnet/src/Testnet/Babbage.hs +++ b/cardano-testnet/src/Testnet/Babbage.hs @@ -31,12 +31,12 @@ import qualified Hedgehog.Extras.Test.Base as H import qualified Hedgehog.Extras.Test.File as H import qualified System.Info as OS +import qualified Testnet.Conf as H import qualified Testnet.Util.Assert as H import Testnet.Util.Process (execCli_) import Testnet.Util.Runtime (Delegator (..), NodeLoggingFormat (..), PaymentKeyPair (..), - PoolNode (PoolNode), PoolNodeKeys (..), StakingKeyPair (..), - TestnetRuntime (..), startNode) -import qualified Testnet.Conf as H + PoolNode (PoolNode), PoolNodeKeys (..), StakingKeyPair (..), TestnetRuntime (..), + startNode) {- HLINT ignore "Redundant flip" -} diff --git a/cardano-testnet/src/Testnet/Cardano.hs b/cardano-testnet/src/Testnet/Cardano.hs index 43ee240ed45..f581f4581ce 100644 --- a/cardano-testnet/src/Testnet/Cardano.hs +++ b/cardano-testnet/src/Testnet/Cardano.hs @@ -6,6 +6,10 @@ module Testnet.Cardano ( ForkPoint(..) , CardanoTestnetOptions(..) + , cardanoPoolNodes + , cardanoBftNodes + , cardanoNumPoolNodes + , extraBftNodeCliArgs , defaultTestnetOptions , TestnetNodeOptions(..) , cardanoDefaultTestnetNodeOptions @@ -17,6 +21,8 @@ module Testnet.Cardano , cardanoTestnet ) where +import Prelude + import qualified Cardano.Crypto.Hash.Blake2b import qualified Cardano.Crypto.Hash.Class import Control.Monad @@ -33,7 +39,6 @@ import Hedgehog.Extras.Stock.IO.Network.Sprocket (Sprocket (..)) import Hedgehog.Extras.Stock.Time (formatIso8601, showUTCTimeSeconds) import Ouroboros.Network.PeerSelection.LedgerPeers (UseLedgerAfter (..)) import Ouroboros.Network.PeerSelection.RelayAccessPoint (RelayAccessPoint (..)) -import Prelude import System.FilePath.Posix (()) import Cardano.Chain.Genesis (GenesisHash (unGenesisHash), readGenesisData) @@ -77,8 +82,7 @@ data Era = Byron | Shelley | Allegra | Mary | Alonzo deriving (Eq, Enum, Bounded data CardanoTestnetOptions = CardanoTestnetOptions { -- | List of node options. Each option will result in a single node being -- created. - cardanoBftNodeOptions :: [TestnetNodeOptions] - , cardanoNumPoolNodes :: Int + cardanoNodes :: [TestnetNodeOptions] , cardanoEra :: Era , cardanoEpochLength :: Int , cardanoSlotLength :: Double @@ -89,8 +93,7 @@ data CardanoTestnetOptions = CardanoTestnetOptions defaultTestnetOptions :: CardanoTestnetOptions defaultTestnetOptions = CardanoTestnetOptions - { cardanoBftNodeOptions = L.replicate 2 cardanoDefaultTestnetNodeOptions - , cardanoNumPoolNodes = 1 + { cardanoNodes = cardanoDefaultTestnetNodeOptions , cardanoEra = Alonzo , cardanoEpochLength = 1500 , cardanoSlotLength = 0.2 @@ -99,16 +102,36 @@ defaultTestnetOptions = CardanoTestnetOptions , cardanoNodeLoggingFormat = NodeLoggingFormatAsText } -newtype TestnetNodeOptions = TestnetNodeOptions - { -- | These arguments will be appended to the default set of CLI options when +-- | Specify a BFT node (Pre-Babbage era only) or an SPO (Shelley era onwards only) +data TestnetNodeOptions + = BftTestnetNodeOptions [String] + -- ^ These arguments will be appended to the default set of CLI options when -- starting the node. - extraNodeCliArgs :: [String] - } deriving (Eq, Show) + | SpoTestnetNodeOptions + deriving (Eq, Show) -cardanoDefaultTestnetNodeOptions :: TestnetNodeOptions -cardanoDefaultTestnetNodeOptions = TestnetNodeOptions - { extraNodeCliArgs = [] - } +extraBftNodeCliArgs :: TestnetNodeOptions -> [String] +extraBftNodeCliArgs (BftTestnetNodeOptions args) = args +extraBftNodeCliArgs SpoTestnetNodeOptions = [] + +cardanoPoolNodes :: [TestnetNodeOptions] -> [TestnetNodeOptions] +cardanoPoolNodes = filter (== SpoTestnetNodeOptions) + +cardanoBftNodes :: [TestnetNodeOptions] -> [TestnetNodeOptions] +cardanoBftNodes = filter (/= SpoTestnetNodeOptions) + +cardanoNumPoolNodes :: [TestnetNodeOptions] -> Int +cardanoNumPoolNodes = length . cardanoPoolNodes + +cardanoNumBftNodes :: [TestnetNodeOptions] -> Int +cardanoNumBftNodes = length . cardanoBftNodes + +cardanoDefaultTestnetNodeOptions :: [TestnetNodeOptions] +cardanoDefaultTestnetNodeOptions = + [ BftTestnetNodeOptions [] + , BftTestnetNodeOptions [] + , SpoTestnetNodeOptions + ] ifaceAddress :: String ifaceAddress = "127.0.0.1" @@ -161,9 +184,9 @@ cardanoTestnet testnetOptions H.Conf {..} = do currentTime <- H.noteShowIO DTC.getCurrentTime startTime <- H.noteShow $ DTC.addUTCTime startTimeOffsetSeconds currentTime configurationFile <- H.noteShow $ tempAbsPath "configuration.yaml" - let numBftNodes = L.length (cardanoBftNodeOptions testnetOptions) + let numBftNodes = cardanoNumBftNodes $ cardanoNodes testnetOptions bftNodesN = [1 .. numBftNodes] - poolNodesN = [1 .. cardanoNumPoolNodes testnetOptions] + poolNodesN = [1 .. cardanoNumPoolNodes $ cardanoNodes testnetOptions] bftNodeNames = ("node-bft" <>) . show @Int <$> bftNodesN poolNodeNames = ("node-pool" <>) . show @Int <$> poolNodesN allNodeNames = bftNodeNames <> poolNodeNames @@ -247,7 +270,7 @@ cardanoTestnet testnetOptions H.Conf {..} = do forM_ allNodeNames $ \node -> do let port = fromJust $ M.lookup node nodeToPort H.lbsWriteFile (tempAbsPath node "topology.json") $ - mkTopologyConfig (numBftNodes + cardanoNumPoolNodes testnetOptions) + mkTopologyConfig (numBftNodes + cardanoNumPoolNodes (cardanoNodes testnetOptions)) allPorts port (cardanoEnableP2P testnetOptions) H.writeFile (tempAbsPath node "port") (show port) @@ -432,7 +455,7 @@ cardanoTestnet testnetOptions H.Conf {..} = do , "--genesis-dir", tempAbsPath "shelley" , "--gen-genesis-keys", show @Int numBftNodes , "--start-time", formatIso8601 startTime - , "--gen-utxo-keys", show @Int (cardanoNumPoolNodes testnetOptions) + , "--gen-utxo-keys", show (cardanoNumBftNodes $ cardanoNodes testnetOptions) ] -- Generated genesis keys and genesis files @@ -725,7 +748,7 @@ cardanoTestnet testnetOptions H.Conf {..} = do -------------------------------- -- Launch cluster of three nodes - let bftNodeNameAndOpts = L.zip bftNodeNames (cardanoBftNodeOptions testnetOptions) + let bftNodeNameAndOpts = L.zip bftNodeNames (cardanoBftNodes $ cardanoNodes testnetOptions) bftNodes <- forM bftNodeNameAndOpts $ \(node, nodeOpts) -> do startNode tempBaseAbsPath tempAbsPath logDir socketDir node ([ "run" @@ -737,7 +760,7 @@ cardanoTestnet testnetOptions H.Conf {..} = do , "--shelley-operational-certificate", tempAbsPath node "shelley/node.cert" , "--delegation-certificate", tempAbsPath node "byron/delegate.cert" , "--signing-key", tempAbsPath node "byron/delegate.key" - ] <> extraNodeCliArgs nodeOpts) + ] <> extraBftNodeCliArgs nodeOpts) H.threadDelay 100000 diff --git a/cardano-testnet/test/Test/Cli/KesPeriodInfo.hs b/cardano-testnet/test/Test/Cli/KesPeriodInfo.hs index b9398f3f449..ccdd67fc3b6 100644 --- a/cardano-testnet/test/Test/Cli/KesPeriodInfo.hs +++ b/cardano-testnet/test/Test/Cli/KesPeriodInfo.hs @@ -34,8 +34,8 @@ import qualified Hedgehog.Extras.Test.Process as H import qualified System.Directory as IO import qualified System.Info as SYS -import Test.Misc import Cardano.Testnet +import Test.Misc import Testnet.Util.Process import Testnet.Util.Runtime @@ -51,7 +51,7 @@ hprop_kes_period_info = integration . H.runFinallies . H.workspace "chairman" $ tempAbsBasePath' Nothing let fastTestnetOptions = CardanoOnlyTestnetOptions $ cardanoDefaultTestnetOptions - { cardanoBftNodeOptions = replicate 1 cardanoDefaultTestnetNodeOptions + { cardanoNodes = cardanoDefaultTestnetNodeOptions , cardanoEpochLength = 500 , cardanoSlotLength = 0.02 , cardanoActiveSlotsCoeff = 0.1 diff --git a/cardano-testnet/test/Test/ShutdownOnSlotSynced.hs b/cardano-testnet/test/Test/ShutdownOnSlotSynced.hs index 59532a6e1b9..bffa6c0cfef 100644 --- a/cardano-testnet/test/Test/ShutdownOnSlotSynced.hs +++ b/cardano-testnet/test/Test/ShutdownOnSlotSynced.hs @@ -7,15 +7,16 @@ module Test.ShutdownOnSlotSynced ) where import Prelude + import Control.Monad import Data.Either (isRight) import Data.List (find, isInfixOf) import Data.Maybe import GHC.IO.Exception (ExitCode (ExitSuccess)) import GHC.Stack (callStack) -import System.FilePath (()) import qualified System.Directory as IO -import Text.Read (readMaybe) +import System.FilePath (()) +import Text.Read (readMaybe) import Hedgehog (Property, assert, (===)) import qualified Hedgehog.Extras.Test.Base as H @@ -23,7 +24,7 @@ import qualified Hedgehog.Extras.Test.File as H import qualified Hedgehog.Extras.Test.Process as H import Cardano.Testnet -import Testnet.Util.Runtime (TestnetRuntime(..)) +import Testnet.Util.Runtime (TestnetRuntime (..)) hprop_shutdownOnSlotSynced :: Property hprop_shutdownOnSlotSynced = integration . H.runFinallies . H.workspace "chairman" $ \tempAbsBasePath' -> do @@ -37,12 +38,10 @@ hprop_shutdownOnSlotSynced = integration . H.runFinallies . H.workspace "chairma let fastTestnetOptions = CardanoOnlyTestnetOptions $ cardanoDefaultTestnetOptions { cardanoEpochLength = 300 , cardanoSlotLength = slotLen - , cardanoBftNodeOptions = - [ TestnetNodeOptions - { extraNodeCliArgs = ["--shutdown-on-slot-synced", show maxSlot] - } - , cardanoDefaultTestnetNodeOptions - , cardanoDefaultTestnetNodeOptions + , cardanoNodes = + [ BftTestnetNodeOptions ["--shutdown-on-slot-synced", show maxSlot] + , BftTestnetNodeOptions [] + , SpoTestnetNodeOptions ] } TestnetRuntime { bftNodes = node:_ } <- testnet fastTestnetOptions conf