Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cardano-testnet | configurable SPO and relays count, enable parallel execution of the test suite #6007

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cardano-testnet/cardano-testnet.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ library
, hedgehog-extras ^>= 0.6.4
, lens-aeson
, microlens
, mono-traversable
, mtl
, network
, network-mux
Expand Down
3 changes: 2 additions & 1 deletion cardano-testnet/src/Cardano/Testnet.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ module Cardano.Testnet (
-- * Configuration
Conf(..),
TmpAbsolutePath(..),
NodeConfigurationYaml(..),
NodeConfiguration,
NodeConfigurationYaml,
mkConf,
makeLogDir,
makeSocketDir,
Expand Down
26 changes: 14 additions & 12 deletions cardano-testnet/src/Parsers/Cardano.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ module Parsers.Cardano
( cmdCardano
) where

import Cardano.Api (EraInEon (..), bounded, AnyShelleyBasedEra (AnyShelleyBasedEra))
import Cardano.Api (AnyShelleyBasedEra (AnyShelleyBasedEra), EraInEon (..), File (..),
bounded)

import Cardano.CLI.Environment
import Cardano.CLI.EraBased.Options.Common hiding (pNetworkId)
Expand Down Expand Up @@ -64,23 +65,24 @@ pCardanoTestnetCliOptions envCli = CardanoTestnetOptions

pNumSpoNodes :: Parser [TestnetNodeOptions]
pNumSpoNodes =
OA.option
((`L.replicate` SpoTestnetNodeOptions Nothing []) <$> auto)
( OA.long "num-pool-nodes"
<> OA.help "Number of pool nodes. Note this uses a default node configuration for all nodes."
<> OA.metavar "COUNT"
<> OA.showDefault
<> OA.value (cardanoNodes def)
)
(`L.replicate` defaultSpoOptions) <$>
OA.option auto
( OA.long "num-pool-nodes"
<> OA.help "Number of pool nodes. Note this uses a default node configuration for all nodes."
<> OA.metavar "COUNT"
<> OA.showDefault
<> OA.value 1)
where
defaultSpoOptions = SpoNodeOptions Nothing []

_pSpo :: Parser TestnetNodeOptions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can delete this in a follow up PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI the removal is done in #6008

_pSpo =
SpoTestnetNodeOptions . Just
<$> parseNodeConfigFile
SpoNodeOptions -- TODO add parser for node roles
. Just <$> parseNodeConfigFile
<*> pure [] -- TODO: Consider adding support for extra args

parseNodeConfigFile :: Parser NodeConfigurationYaml
parseNodeConfigFile = NodeConfigurationYaml <$>
parseNodeConfigFile = File <$>
strOption
(mconcat
[ long "configuration-file"
Expand Down
32 changes: 9 additions & 23 deletions cardano-testnet/src/Testnet/Components/Configuration.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
Expand All @@ -13,11 +13,6 @@ module Testnet.Components.Configuration
, getByronGenesisHash
, getShelleyGenesisHash

, NumPools(..)
, numPools
, NumDReps
, numDReps

, anyEraToString
, eraToString
) where
Expand Down Expand Up @@ -61,7 +56,8 @@ import System.FilePath.Posix (takeDirectory, (</>))
import Testnet.Defaults
import Testnet.Filepath
import Testnet.Process.Run (execCli_)
import Testnet.Start.Types (CardanoTestnetOptions (..), anyEraToString, anyShelleyBasedEraToString, eraToString)
import Testnet.Start.Types (NumDReps (..), NumPools (..), anyEraToString,
anyShelleyBasedEraToString, eraToString)

import Hedgehog
import qualified Hedgehog as H
Expand Down Expand Up @@ -118,16 +114,6 @@ getShelleyGenesisHash path key = do
numSeededUTxOKeys :: Int
numSeededUTxOKeys = 3

newtype NumPools = NumPools Int

numPools :: CardanoTestnetOptions -> NumPools
numPools CardanoTestnetOptions { cardanoNodes } = NumPools $ length cardanoNodes

newtype NumDReps = NumDReps Int

numDReps :: CardanoTestnetOptions -> NumDReps
numDReps CardanoTestnetOptions { cardanoNumDReps } = NumDReps cardanoNumDReps

createSPOGenesisAndFiles
:: (MonadTest m, MonadCatch m, MonadIO m, HasCallStack)
=> NumPools -- ^ The number of pools to make
Expand All @@ -139,7 +125,7 @@ createSPOGenesisAndFiles
-> ConwayGenesis StandardCrypto -- ^ The conway genesis to use, for example 'Defaults.defaultConwayGenesis'.
-> TmpAbsolutePath
-> m FilePath -- ^ Shelley genesis directory
createSPOGenesisAndFiles (NumPools numPoolNodes) (NumDReps numDelReps) maxSupply sbe shelleyGenesis
createSPOGenesisAndFiles nPoolNodes nDelReps maxSupply sbe shelleyGenesis
alonzoGenesis conwayGenesis (TmpAbsolutePath tempAbsPath) = GHC.withFrozenCallStack $ do
let inputGenesisShelleyFp = tempAbsPath </> genesisInputFilepath ShelleyEra
inputGenesisAlonzoFp = tempAbsPath </> genesisInputFilepath AlonzoEra
Expand All @@ -158,7 +144,7 @@ createSPOGenesisAndFiles (NumPools numPoolNodes) (NumDReps numDelReps) maxSupply
let testnetMagic = sgNetworkMagic shelleyGenesis
-- At least there should be a delegator per DRep
-- otherwise some won't be representing anybody
numStakeDelegators = max 3 numDelReps :: Int
numStakeDelegators = max 3 (fromIntegral nDelReps) :: Int
startTime = sgSystemStart shelleyGenesis

-- TODO: Remove this rewrite.
Expand All @@ -171,8 +157,8 @@ createSPOGenesisAndFiles (NumPools numPoolNodes) (NumDReps numDelReps) maxSupply
-- TODO: create-testnet-data should have arguments for
-- Alonzo and Conway genesis that are optional and if not
-- supplised the users get a default
H.note_ $ "Number of pools: " <> show numPoolNodes
H.note_ $ "Number of stake delegators: " <> show numPoolNodes
H.note_ $ "Number of pools: " <> show nPoolNodes
H.note_ $ "Number of stake delegators: " <> show nPoolNodes
H.note_ $ "Number of seeded UTxO keys: " <> show numSeededUTxOKeys

execCli_
Expand All @@ -181,11 +167,11 @@ createSPOGenesisAndFiles (NumPools numPoolNodes) (NumDReps numDelReps) maxSupply
, "--spec-alonzo", inputGenesisAlonzoFp
, "--spec-conway", inputGenesisConwayFp
, "--testnet-magic", show testnetMagic
, "--pools", show numPoolNodes
, "--pools", show nPoolNodes
, "--total-supply", show maxSupply -- Half of this will be delegated, see https://github.com/IntersectMBO/cardano-cli/pull/874
, "--stake-delegators", show numStakeDelegators
, "--utxo-keys", show numSeededUTxOKeys
, "--drep-keys", show numDelReps
, "--drep-keys", show nDelReps
, "--start-time", DTC.formatIso8601 startTime
, "--out-dir", tempAbsPath
]
Expand Down
63 changes: 46 additions & 17 deletions cardano-testnet/src/Testnet/Defaults.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,24 @@ module Testnet.Defaults
, defaultDRepSkeyFp
, defaultDRepKeyPair
, defaultDelegatorStakeKeyPair
, defaultNodeName
, defaultNodeDataDir
, defaultSpoColdKeyPair
, defaultSPOColdVKeyFp
, defaultSPOColdSKeyFp
, defaultSpoColdVKeyFp
, defaultSpoColdSKeyFp
, defaultSpoKeys
, defaultSpoKeysDir
, defaultSpoName
, defaultShelleyGenesis
, defaultGenesisFilepath
, defaultYamlHardforkViaConfig
, defaultMainnetTopology
, defaultUtxoKeys
, plutusV3Script
) where

import Cardano.Api (CardanoEra (..), File (..), pshow, ShelleyBasedEra (..),
toCardanoEra, unsafeBoundedRational, AnyShelleyBasedEra (..))
import Cardano.Api (AnyShelleyBasedEra (..), CardanoEra (..), File (..),
ShelleyBasedEra (..), pshow, toCardanoEra, unsafeBoundedRational)
import qualified Cardano.Api.Shelley as Api

import Cardano.Ledger.Alonzo.Core (PParams (..))
Expand Down Expand Up @@ -256,7 +261,7 @@ defaultYamlHardforkViaConfig sbe =
, (proxyName (Proxy @TraceTxOutbound), False)
, (proxyName (Proxy @TraceTxSubmissionProtocol), False)
]

defaultYamlConfig :: Aeson.KeyMap Aeson.Value
defaultYamlConfig =
Aeson.fromList
Expand Down Expand Up @@ -468,37 +473,53 @@ defaultCommitteeKeyPair n =
}

-- | The relative path to SPO cold verification key in directories created by cardano-testnet
defaultSPOColdVKeyFp :: Int -> FilePath
defaultSPOColdVKeyFp n = "pools-keys" </> "pool" <> show n </> "cold.vkey"
defaultSpoColdVKeyFp :: Int -> FilePath
defaultSpoColdVKeyFp n = defaultSpoKeysDir n </> "cold.vkey"

-- | The relative path to SPO cold secret key in directories created by cardano-testnet
defaultSPOColdSKeyFp :: Int -> FilePath
defaultSPOColdSKeyFp n = "pools-keys" </> "pool" <> show n </> "cold.skey"
defaultSpoColdSKeyFp :: Int -> FilePath
defaultSpoColdSKeyFp n = defaultSpoKeysDir n </> "cold.skey"

-- | The name of a SPO, used in file system operations
defaultSpoName :: Int -> String
defaultSpoName n = "pool" <> show n

-- | The name of a node (which doesn't have to be a SPO)
defaultNodeName :: Int -> String
defaultNodeName n = "node" <> show n

-- | The relative path of the node data dir, where the database is stored
defaultNodeDataDir :: Int -> String
defaultNodeDataDir n = "node-data" </> defaultNodeName n

-- | The relative path where the SPO keys for the node are stored
defaultSpoKeysDir :: Int -> String
defaultSpoKeysDir n = "pools-keys" </> defaultSpoName n

-- | The relative path to SPO keys in directories created by cardano-testnet
defaultSpoColdKeyPair
:: Int
-> KeyPair SpoColdKey
defaultSpoColdKeyPair n =
KeyPair
{ verificationKey = File $ "pools-keys" </> "pool" <> show n </> "cold.vkey"
, signingKey = File $ "pools-keys" </> "pool" <> show n </> "cold.skey"
{ verificationKey = File $ defaultSpoKeysDir n </> "cold.vkey"
, signingKey = File $ defaultSpoKeysDir n </> "cold.skey"
}

-- | The relative path to SPO key pairs in directories created by cardano-testnet
defaultSpoKeys :: Int -> PoolNodeKeys
defaultSpoKeys :: Int -> SpoNodeKeys
defaultSpoKeys n =
PoolNodeKeys
SpoNodeKeys
{ poolNodeKeysCold = defaultSpoColdKeyPair n
, poolNodeKeysVrf =
KeyPair
{ verificationKey = File $ "pools-keys" </> "pool" ++ show n </> "vrf.vkey"
, signingKey = File $ "pools-keys" </> "pool" ++ show n </> "vrf.skey"
{ verificationKey = File $ defaultSpoKeysDir n </> "vrf.vkey"
, signingKey = File $ defaultSpoKeysDir n </> "vrf.skey"
}
, poolNodeKeysStaking =
KeyPair
{ verificationKey = File $ "pools-keys" </> "pool" ++ show n </> "staking-reward.vkey"
, signingKey = File $ "pools-keys" </> "pool" ++ show n </> "staking-reward.skey"
{ verificationKey = File $ defaultSpoKeysDir n </> "staking-reward.vkey"
, signingKey = File $ defaultSpoKeysDir n </> "staking-reward.skey"
}
}

Expand All @@ -510,6 +531,14 @@ defaultDelegatorStakeKeyPair n =
, signingKey = File $ "stake-delegators" </> ("delegator" <> show n) </> "staking.skey"
}

-- | The relative path to UTXO keys
defaultUtxoKeys :: Int -> KeyPair PaymentKey
defaultUtxoKeys n =
KeyPair
{ verificationKey = File $ "utxo-keys" </> "utxo" <> show n </> "utxo.vkey"
, signingKey = File $ "utxo-keys" </> "utxo" <> show n </> "utxo.skey"
}

-- | Default plutus script that always succeeds
plutusV3Script :: Text
plutusV3Script =
Expand Down
4 changes: 2 additions & 2 deletions cardano-testnet/src/Testnet/Process/Cli/SPO.hs
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ registerSingleSpo asbe identifier tap@(TmpAbsolutePath tempAbsPath') nodeConfigF
-- Returns a list of generated @File VoteFile In@ representing the paths to
-- the generated voting files.
-- TODO: unify with DRep.generateVoteFiles
generateVoteFiles :: (MonadTest m, MonadIO m, MonadCatch m)
generateVoteFiles :: (HasCallStack, MonadTest m, MonadIO m, MonadCatch m)
=> ConwayEraOnwards era -- ^ The conway era onwards witness for the era in which the
-- transaction will be constructed.
-> H.ExecConfig -- ^ Specifies the CLI execution configuration.
Expand All @@ -417,7 +417,7 @@ generateVoteFiles :: (MonadTest m, MonadIO m, MonadCatch m)
-- the output voting files.
-> String -- ^ Transaction ID string of the governance action.
-> Word16 -- ^ Index of the governance action.
-> [(PoolNodeKeys, [Char])] -- ^ List of tuples where each tuple contains a 'PoolNodeKeys'
-> [(SpoNodeKeys, [Char])] -- ^ List of tuples where each tuple contains a 'SpoNodeKeys'
-- representing the SPO keys and a 'String' representing the
-- vote type (i.e: "yes", "no", or "abstain").
-> m [File VoteFile In]
Expand Down
1 change: 0 additions & 1 deletion cardano-testnet/src/Testnet/Property/Assert.hs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import Data.Type.Equality
import Data.Word (Word8)
import GHC.Stack as GHC

import Testnet.Components.Configuration (NumPools(..))
import Testnet.Process.Run
import Testnet.Start.Types

Expand Down
6 changes: 3 additions & 3 deletions cardano-testnet/src/Testnet/Runtime.hs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import Testnet.Filepath
import qualified Testnet.Ping as Ping
import Testnet.Process.Run
import Testnet.Types (NodeRuntime (NodeRuntime), TestnetRuntime (configurationFile),
poolSprockets, showIpv4Address)
showIpv4Address, testnetSprockets)

import Hedgehog (MonadTest)
import qualified Hedgehog as H
Expand Down Expand Up @@ -190,7 +190,7 @@ startNode tp node ipv4 port testnetMagic nodeCmd = GHC.withFrozenCallStack $ do
NodeExecutableError . hsep $
["Socket", pretty socketAbsPath, "was not created after 120 seconds. There was no output on stderr. Exception:", prettyException ioex])
$ hoistEither eSprocketError

-- Ping node and fail on error
Ping.pingNode (fromIntegral testnetMagic) sprocket
>>= (firstExceptT (NodeExecutableError . ("Ping error:" <+>) . prettyError) . hoistEither)
Expand Down Expand Up @@ -286,7 +286,7 @@ startLedgerNewEpochStateLogging testnetRuntime tmpWorkspace = withFrozenCallStac
H.note_ $ "Epoch states logging to " <> logFile <> " is already started."
False -> do
H.evalIO $ appendFile logFile ""
socketPath <- H.noteM $ H.sprocketSystemName <$> H.headM (poolSprockets testnetRuntime)
socketPath <- H.noteM $ H.sprocketSystemName <$> H.headM (testnetSprockets testnetRuntime)

_ <- H.asyncRegister_ . runExceptT $
foldEpochState
Expand Down
Loading
Loading