Skip to content

Commit 6beea61

Browse files
authored
Merge pull request #6007 from IntersectMBO/mgalazyn/feature/enable-configurable-testnet-topology
cardano-testnet | configurable SPO and relays count, enable parallel execution of the test suite
2 parents 7a68d1d + c4d12d1 commit 6beea61

39 files changed

+683
-544
lines changed

cardano-testnet/cardano-testnet.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ library
6565
, hedgehog-extras ^>= 0.6.4
6666
, lens-aeson
6767
, microlens
68+
, mono-traversable
6869
, mtl
6970
, network
7071
, network-mux

cardano-testnet/src/Cardano/Testnet.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ module Cardano.Testnet (
1818
-- * Configuration
1919
Conf(..),
2020
TmpAbsolutePath(..),
21-
NodeConfigurationYaml(..),
21+
NodeConfiguration,
22+
NodeConfigurationYaml,
2223
mkConf,
2324
makeLogDir,
2425
makeSocketDir,

cardano-testnet/src/Parsers/Cardano.hs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ module Parsers.Cardano
22
( cmdCardano
33
) where
44

5-
import Cardano.Api (EraInEon (..), bounded, AnyShelleyBasedEra (AnyShelleyBasedEra))
5+
import Cardano.Api (AnyShelleyBasedEra (AnyShelleyBasedEra), EraInEon (..), File (..),
6+
bounded)
67

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

6566
pNumSpoNodes :: Parser [TestnetNodeOptions]
6667
pNumSpoNodes =
67-
OA.option
68-
((`L.replicate` SpoTestnetNodeOptions Nothing []) <$> auto)
69-
( OA.long "num-pool-nodes"
70-
<> OA.help "Number of pool nodes. Note this uses a default node configuration for all nodes."
71-
<> OA.metavar "COUNT"
72-
<> OA.showDefault
73-
<> OA.value (cardanoNodes def)
74-
)
68+
(`L.replicate` defaultSpoOptions) <$>
69+
OA.option auto
70+
( OA.long "num-pool-nodes"
71+
<> OA.help "Number of pool nodes. Note this uses a default node configuration for all nodes."
72+
<> OA.metavar "COUNT"
73+
<> OA.showDefault
74+
<> OA.value 1)
75+
where
76+
defaultSpoOptions = SpoNodeOptions Nothing []
7577

7678
_pSpo :: Parser TestnetNodeOptions
7779
_pSpo =
78-
SpoTestnetNodeOptions . Just
79-
<$> parseNodeConfigFile
80+
SpoNodeOptions -- TODO add parser for node roles
81+
. Just <$> parseNodeConfigFile
8082
<*> pure [] -- TODO: Consider adding support for extra args
8183

8284
parseNodeConfigFile :: Parser NodeConfigurationYaml
83-
parseNodeConfigFile = NodeConfigurationYaml <$>
85+
parseNodeConfigFile = File <$>
8486
strOption
8587
(mconcat
8688
[ long "configuration-file"

cardano-testnet/src/Testnet/Components/Configuration.hs

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
{-# LANGUAGE DerivingVia #-}
12
{-# LANGUAGE GADTs #-}
2-
{-# LANGUAGE NamedFieldPuns #-}
33
{-# LANGUAGE OverloadedStrings #-}
44
{-# LANGUAGE ScopedTypeVariables #-}
55
{-# LANGUAGE TypeApplications #-}
@@ -13,11 +13,6 @@ module Testnet.Components.Configuration
1313
, getByronGenesisHash
1414
, getShelleyGenesisHash
1515

16-
, NumPools(..)
17-
, numPools
18-
, NumDReps
19-
, numDReps
20-
2116
, anyEraToString
2217
, eraToString
2318
) where
@@ -61,7 +56,8 @@ import System.FilePath.Posix (takeDirectory, (</>))
6156
import Testnet.Defaults
6257
import Testnet.Filepath
6358
import Testnet.Process.Run (execCli_)
64-
import Testnet.Start.Types (CardanoTestnetOptions (..), anyEraToString, anyShelleyBasedEraToString, eraToString)
59+
import Testnet.Start.Types (NumDReps (..), NumPools (..), anyEraToString,
60+
anyShelleyBasedEraToString, eraToString)
6561

6662
import Hedgehog
6763
import qualified Hedgehog as H
@@ -118,16 +114,6 @@ getShelleyGenesisHash path key = do
118114
numSeededUTxOKeys :: Int
119115
numSeededUTxOKeys = 3
120116

121-
newtype NumPools = NumPools Int
122-
123-
numPools :: CardanoTestnetOptions -> NumPools
124-
numPools CardanoTestnetOptions { cardanoNodes } = NumPools $ length cardanoNodes
125-
126-
newtype NumDReps = NumDReps Int
127-
128-
numDReps :: CardanoTestnetOptions -> NumDReps
129-
numDReps CardanoTestnetOptions { cardanoNumDReps } = NumDReps cardanoNumDReps
130-
131117
createSPOGenesisAndFiles
132118
:: (MonadTest m, MonadCatch m, MonadIO m, HasCallStack)
133119
=> NumPools -- ^ The number of pools to make
@@ -139,7 +125,7 @@ createSPOGenesisAndFiles
139125
-> ConwayGenesis StandardCrypto -- ^ The conway genesis to use, for example 'Defaults.defaultConwayGenesis'.
140126
-> TmpAbsolutePath
141127
-> m FilePath -- ^ Shelley genesis directory
142-
createSPOGenesisAndFiles (NumPools numPoolNodes) (NumDReps numDelReps) maxSupply sbe shelleyGenesis
128+
createSPOGenesisAndFiles nPoolNodes nDelReps maxSupply sbe shelleyGenesis
143129
alonzoGenesis conwayGenesis (TmpAbsolutePath tempAbsPath) = GHC.withFrozenCallStack $ do
144130
let inputGenesisShelleyFp = tempAbsPath </> genesisInputFilepath ShelleyEra
145131
inputGenesisAlonzoFp = tempAbsPath </> genesisInputFilepath AlonzoEra
@@ -158,7 +144,7 @@ createSPOGenesisAndFiles (NumPools numPoolNodes) (NumDReps numDelReps) maxSupply
158144
let testnetMagic = sgNetworkMagic shelleyGenesis
159145
-- At least there should be a delegator per DRep
160146
-- otherwise some won't be representing anybody
161-
numStakeDelegators = max 3 numDelReps :: Int
147+
numStakeDelegators = max 3 (fromIntegral nDelReps) :: Int
162148
startTime = sgSystemStart shelleyGenesis
163149

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

178164
execCli_
@@ -181,11 +167,11 @@ createSPOGenesisAndFiles (NumPools numPoolNodes) (NumDReps numDelReps) maxSupply
181167
, "--spec-alonzo", inputGenesisAlonzoFp
182168
, "--spec-conway", inputGenesisConwayFp
183169
, "--testnet-magic", show testnetMagic
184-
, "--pools", show numPoolNodes
170+
, "--pools", show nPoolNodes
185171
, "--total-supply", show maxSupply -- Half of this will be delegated, see https://github.com/IntersectMBO/cardano-cli/pull/874
186172
, "--stake-delegators", show numStakeDelegators
187173
, "--utxo-keys", show numSeededUTxOKeys
188-
, "--drep-keys", show numDelReps
174+
, "--drep-keys", show nDelReps
189175
, "--start-time", DTC.formatIso8601 startTime
190176
, "--out-dir", tempAbsPath
191177
]

cardano-testnet/src/Testnet/Defaults.hs

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,24 @@ module Testnet.Defaults
2121
, defaultDRepSkeyFp
2222
, defaultDRepKeyPair
2323
, defaultDelegatorStakeKeyPair
24+
, defaultNodeName
25+
, defaultNodeDataDir
2426
, defaultSpoColdKeyPair
25-
, defaultSPOColdVKeyFp
26-
, defaultSPOColdSKeyFp
27+
, defaultSpoColdVKeyFp
28+
, defaultSpoColdSKeyFp
2729
, defaultSpoKeys
30+
, defaultSpoKeysDir
31+
, defaultSpoName
2832
, defaultShelleyGenesis
2933
, defaultGenesisFilepath
3034
, defaultYamlHardforkViaConfig
3135
, defaultMainnetTopology
36+
, defaultUtxoKeys
3237
, plutusV3Script
3338
) where
3439

35-
import Cardano.Api (CardanoEra (..), File (..), pshow, ShelleyBasedEra (..),
36-
toCardanoEra, unsafeBoundedRational, AnyShelleyBasedEra (..))
40+
import Cardano.Api (AnyShelleyBasedEra (..), CardanoEra (..), File (..),
41+
ShelleyBasedEra (..), pshow, toCardanoEra, unsafeBoundedRational)
3742
import qualified Cardano.Api.Shelley as Api
3843

3944
import Cardano.Ledger.Alonzo.Core (PParams (..))
@@ -256,7 +261,7 @@ defaultYamlHardforkViaConfig sbe =
256261
, (proxyName (Proxy @TraceTxOutbound), False)
257262
, (proxyName (Proxy @TraceTxSubmissionProtocol), False)
258263
]
259-
264+
260265
defaultYamlConfig :: Aeson.KeyMap Aeson.Value
261266
defaultYamlConfig =
262267
Aeson.fromList
@@ -468,37 +473,53 @@ defaultCommitteeKeyPair n =
468473
}
469474

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

474479
-- | The relative path to SPO cold secret key in directories created by cardano-testnet
475-
defaultSPOColdSKeyFp :: Int -> FilePath
476-
defaultSPOColdSKeyFp n = "pools-keys" </> "pool" <> show n </> "cold.skey"
480+
defaultSpoColdSKeyFp :: Int -> FilePath
481+
defaultSpoColdSKeyFp n = defaultSpoKeysDir n </> "cold.skey"
482+
483+
-- | The name of a SPO, used in file system operations
484+
defaultSpoName :: Int -> String
485+
defaultSpoName n = "pool" <> show n
486+
487+
-- | The name of a node (which doesn't have to be a SPO)
488+
defaultNodeName :: Int -> String
489+
defaultNodeName n = "node" <> show n
490+
491+
-- | The relative path of the node data dir, where the database is stored
492+
defaultNodeDataDir :: Int -> String
493+
defaultNodeDataDir n = "node-data" </> defaultNodeName n
494+
495+
-- | The relative path where the SPO keys for the node are stored
496+
defaultSpoKeysDir :: Int -> String
497+
defaultSpoKeysDir n = "pools-keys" </> defaultSpoName n
477498

478499
-- | The relative path to SPO keys in directories created by cardano-testnet
479500
defaultSpoColdKeyPair
480501
:: Int
481502
-> KeyPair SpoColdKey
482503
defaultSpoColdKeyPair n =
483504
KeyPair
484-
{ verificationKey = File $ "pools-keys" </> "pool" <> show n </> "cold.vkey"
485-
, signingKey = File $ "pools-keys" </> "pool" <> show n </> "cold.skey"
505+
{ verificationKey = File $ defaultSpoKeysDir n </> "cold.vkey"
506+
, signingKey = File $ defaultSpoKeysDir n </> "cold.skey"
486507
}
487508

488509
-- | The relative path to SPO key pairs in directories created by cardano-testnet
489-
defaultSpoKeys :: Int -> PoolNodeKeys
510+
defaultSpoKeys :: Int -> SpoNodeKeys
490511
defaultSpoKeys n =
491-
PoolNodeKeys
512+
SpoNodeKeys
492513
{ poolNodeKeysCold = defaultSpoColdKeyPair n
493514
, poolNodeKeysVrf =
494515
KeyPair
495-
{ verificationKey = File $ "pools-keys" </> "pool" ++ show n </> "vrf.vkey"
496-
, signingKey = File $ "pools-keys" </> "pool" ++ show n </> "vrf.skey"
516+
{ verificationKey = File $ defaultSpoKeysDir n </> "vrf.vkey"
517+
, signingKey = File $ defaultSpoKeysDir n </> "vrf.skey"
497518
}
498519
, poolNodeKeysStaking =
499520
KeyPair
500-
{ verificationKey = File $ "pools-keys" </> "pool" ++ show n </> "staking-reward.vkey"
501-
, signingKey = File $ "pools-keys" </> "pool" ++ show n </> "staking-reward.skey"
521+
{ verificationKey = File $ defaultSpoKeysDir n </> "staking-reward.vkey"
522+
, signingKey = File $ defaultSpoKeysDir n </> "staking-reward.skey"
502523
}
503524
}
504525

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

534+
-- | The relative path to UTXO keys
535+
defaultUtxoKeys :: Int -> KeyPair PaymentKey
536+
defaultUtxoKeys n =
537+
KeyPair
538+
{ verificationKey = File $ "utxo-keys" </> "utxo" <> show n </> "utxo.vkey"
539+
, signingKey = File $ "utxo-keys" </> "utxo" <> show n </> "utxo.skey"
540+
}
541+
513542
-- | Default plutus script that always succeeds
514543
plutusV3Script :: Text
515544
plutusV3Script =

cardano-testnet/src/Testnet/Process/Cli/SPO.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ registerSingleSpo asbe identifier tap@(TmpAbsolutePath tempAbsPath') nodeConfigF
407407
-- Returns a list of generated @File VoteFile In@ representing the paths to
408408
-- the generated voting files.
409409
-- TODO: unify with DRep.generateVoteFiles
410-
generateVoteFiles :: (MonadTest m, MonadIO m, MonadCatch m)
410+
generateVoteFiles :: (HasCallStack, MonadTest m, MonadIO m, MonadCatch m)
411411
=> ConwayEraOnwards era -- ^ The conway era onwards witness for the era in which the
412412
-- transaction will be constructed.
413413
-> H.ExecConfig -- ^ Specifies the CLI execution configuration.
@@ -417,7 +417,7 @@ generateVoteFiles :: (MonadTest m, MonadIO m, MonadCatch m)
417417
-- the output voting files.
418418
-> String -- ^ Transaction ID string of the governance action.
419419
-> Word16 -- ^ Index of the governance action.
420-
-> [(PoolNodeKeys, [Char])] -- ^ List of tuples where each tuple contains a 'PoolNodeKeys'
420+
-> [(SpoNodeKeys, [Char])] -- ^ List of tuples where each tuple contains a 'SpoNodeKeys'
421421
-- representing the SPO keys and a 'String' representing the
422422
-- vote type (i.e: "yes", "no", or "abstain").
423423
-> m [File VoteFile In]

cardano-testnet/src/Testnet/Property/Assert.hs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ import Data.Type.Equality
4040
import Data.Word (Word8)
4141
import GHC.Stack as GHC
4242

43-
import Testnet.Components.Configuration (NumPools(..))
4443
import Testnet.Process.Run
4544
import Testnet.Start.Types
4645

cardano-testnet/src/Testnet/Runtime.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ import Testnet.Filepath
4949
import qualified Testnet.Ping as Ping
5050
import Testnet.Process.Run
5151
import Testnet.Types (NodeRuntime (NodeRuntime), TestnetRuntime (configurationFile),
52-
poolSprockets, showIpv4Address)
52+
showIpv4Address, testnetSprockets)
5353

5454
import Hedgehog (MonadTest)
5555
import qualified Hedgehog as H
@@ -190,7 +190,7 @@ startNode tp node ipv4 port testnetMagic nodeCmd = GHC.withFrozenCallStack $ do
190190
NodeExecutableError . hsep $
191191
["Socket", pretty socketAbsPath, "was not created after 120 seconds. There was no output on stderr. Exception:", prettyException ioex])
192192
$ hoistEither eSprocketError
193-
193+
194194
-- Ping node and fail on error
195195
Ping.pingNode (fromIntegral testnetMagic) sprocket
196196
>>= (firstExceptT (NodeExecutableError . ("Ping error:" <+>) . prettyError) . hoistEither)
@@ -286,7 +286,7 @@ startLedgerNewEpochStateLogging testnetRuntime tmpWorkspace = withFrozenCallStac
286286
H.note_ $ "Epoch states logging to " <> logFile <> " is already started."
287287
False -> do
288288
H.evalIO $ appendFile logFile ""
289-
socketPath <- H.noteM $ H.sprocketSystemName <$> H.headM (poolSprockets testnetRuntime)
289+
socketPath <- H.noteM $ H.sprocketSystemName <$> H.headM (testnetSprockets testnetRuntime)
290290

291291
_ <- H.asyncRegister_ . runExceptT $
292292
foldEpochState

0 commit comments

Comments
 (0)