@@ -35,11 +35,11 @@ import qualified Cardano.Api.Byron as Byron
3535
3636import Cardano.CLI.Type.Common (SigningKeyFile )
3737import Cardano.Node.Configuration.NodeAddress (NodeAddress' (.. ),
38- NodeHostIPv4Address (.. ))
39- import qualified Cardano.Node.Configuration.TopologyP2P as P2P
38+ NodeHostIPv4Address (.. ), PortNumber )
4039import Cardano.Prelude (NonEmpty ((:|) ), canonicalEncodePretty )
4140import Cardano.TxGenerator.Setup.NixService (NixServiceOptions (.. ), NodeDescription (.. ))
4241import Ouroboros.Network.PeerSelection.RelayAccessPoint (RelayAccessPoint (.. ))
42+ import Cardano.Network.Diffusion.Topology (CardanoNetworkTopology )
4343
4444import Prelude hiding (lines )
4545
@@ -107,6 +107,7 @@ createTestnetEnv :: ()
107107 => HasCallStack
108108 => MonadIO m
109109 => MonadThrow m
110+ => MonadFail m
110111 => CardanoTestnetOptions
111112 -> GenesisOptions
112113 -> CreateEnvOptions
@@ -142,14 +143,24 @@ createTestnetEnv
142143
143144 liftIOAnnotated . LBS. writeFile configurationFile $ A. encodePretty $ Object config
144145
145- -- Create network topology, with abstract IDs in lieu of addresses
146+ portNumbers <- forM (NEL. zip (1 :| [2 .. ]) cardanoNodes)
147+ (\ (i, _nodeOption) -> (i,) <$> H. randomPort testnetDefaultIpv4Address)
148+
149+ let portNumbersMap = Map. fromList (NEL. toList portNumbers)
150+
151+ -- Create network topology and write port files
146152 let nodeIds = fst <$> NEL. zip (1 :| [2 .. ]) cardanoNodes
147153 forM_ nodeIds $ \ i -> do
148154 let nodeDataDir = tmpAbsPath </> Defaults. defaultNodeDataDir i
149155 liftIOAnnotated $ IO. createDirectoryIfMissing True nodeDataDir
150156
151- let producers = NodeId <$> NEL. filter (/= i) nodeIds
152- topology = Defaults. defaultP2PTopology producers
157+ -- Write port file
158+ case Map. lookup i portNumbersMap of
159+ Just port -> liftIOAnnotated $ writeFile (nodeDataDir </> " port" ) (show port)
160+ Nothing -> error $ " Port not found for node " <> show i
161+
162+ producers <- mapM (idToRemoteAddressP2P portNumbersMap) $ NodeId <$> NEL. filter (/= i) nodeIds
163+ let topology = Defaults. defaultP2PTopology producers
153164 liftIOAnnotated . LBS. writeFile (nodeDataDir </> " topology.json" ) $ A. encodePretty topology
154165
155166-- | Starts a number of nodes, as configured by the value of the 'cardanoNodes'
@@ -268,38 +279,23 @@ cardanoTestnet
268279 , paymentKeyInfoAddr = Text. pack paymentAddr
269280 }
270281
271- portNumbersWithNodeOptions <- forM cardanoNodes
272- (\ nodeOption -> (nodeOption,) <$> H. randomPort testnetDefaultIpv4Address)
273-
274- let portNumbers = NEL. zip (1 :| [2 .. ]) $ snd <$> portNumbersWithNodeOptions
275- portNumbersMap = Map. fromList (NEL. toList portNumbers)
276-
277- idToRemoteAddressP2P :: ()
278- => MonadIO m
279- => HasCallStack
280- => NodeId -> m RelayAccessPoint
281- idToRemoteAddressP2P (NodeId i) = case Map. lookup i portNumbersMap of
282- Just port -> pure $ RelayAccessAddress
283- (showIpv4Address testnetDefaultIpv4Address)
284- port
285- Nothing -> do
286- throwString $ " Found node id that was unaccounted for: " ++ show i
287-
288- forM_ portNumbers $ \ (i, portNumber) -> do
282+ -- Read port numbers from disk (written by createTestnetEnv)
283+ portNumbers <- forM (NEL. zip (1 :| [2 .. ]) cardanoNodes) $ \ (i, _nodeOption) -> do
289284 let nodeDataDir = tmpAbsPath </> Defaults. defaultNodeDataDir i
290- liftIOAnnotated $ IO. createDirectoryIfMissing True nodeDataDir
291- liftIOAnnotated $ writeFile (nodeDataDir </> " port" ) (show portNumber)
292- let topologyPath = tmpAbsPath </> Defaults. defaultNodeDataDir i </> " topology.json"
285+ portPath = nodeDataDir </> " port"
286+ portStr <- liftIOAnnotated $ readFile portPath
287+ let port = read portStr :: PortNumber
288+ let topologyPath = nodeDataDir </> " topology.json"
293289 tBytes <- liftIOAnnotated $ LBS. readFile topologyPath
294290 case eitherDecode tBytes of
295- Right (abstractTopology :: P2P. NetworkTopology NodeId ) -> do
296- topology <- mapM idToRemoteAddressP2P abstractTopology
297- liftIOAnnotated $ LBS. writeFile topologyPath $ encode topology
291+ Right (abstractTopology :: CardanoNetworkTopology ) -> do
292+ liftIOAnnotated $ LBS. writeFile topologyPath $ encode abstractTopology
298293 Left e -> do
299294 -- There can be multiple reasons for why both decodings have failed.
300295 -- Here we assume, very optimistically, that the user has already
301296 -- instantiated it with a concrete topology file.
302297 liftIOAnnotated . putStrLn $ " Could not decode topology file: " <> topologyPath <> " . This may be okay. Reason for decoding failure is:\n " ++ e
298+ pure (i, port)
303299
304300 -- If necessary, update the time stamps in Byron and Shelley Genesis files.
305301 -- This is a QoL feature so that users who edit their configuration files don't
@@ -321,7 +317,12 @@ cardanoTestnet
321317 let shelleyGenesis' = shelleyGenesis{sgSystemStart = startTime}
322318 liftIOAnnotated . LBS. writeFile shelleyGenesisFile $ A. encodePretty shelleyGenesis'
323319
324- eTestnetNodes <- forConcurrently (NEL. zip (1 :| [2 .. ]) portNumbersWithNodeOptions) $ \ (i, (nodeOptions, port)) -> do
320+ let portNumbersMap = Map. fromList (NEL. toList portNumbers)
321+
322+ eTestnetNodes <- forConcurrently (NEL. zip (1 :| [2 .. ]) cardanoNodes) $ \ (i, nodeOptions) -> do
323+ port <- case Map. lookup i portNumbersMap of
324+ Just p -> pure p
325+ Nothing -> throwString $ " Port not found for node " <> show i
325326 let nodeName = Defaults. defaultNodeName i
326327 nodeDataDir = tmpAbsPath </> Defaults. defaultNodeDataDir i
327328 nodePoolKeysDir = tmpAbsPath </> Defaults. defaultSpoKeysDir i
@@ -490,6 +491,17 @@ cardanoTestnet
490491 throwString $ nodeName <> " was unable to produce any blocks for " <> show timeoutSeconds <> " s"
491492
492493
494+ idToRemoteAddressP2P :: ()
495+ => MonadIO m
496+ => HasCallStack
497+ => Map. Map Int PortNumber -> NodeId -> m RelayAccessPoint
498+ idToRemoteAddressP2P portNumbersMap (NodeId i) = case Map. lookup i portNumbersMap of
499+ Just port -> pure $ RelayAccessAddress
500+ (showIpv4Address testnetDefaultIpv4Address)
501+ port
502+ Nothing -> do
503+ throwString $ " Found node id that was unaccounted for: " ++ show i
504+
493505-- | A convenience wrapper around `createTestnetEnv` and `cardanoTestnet`
494506createAndRunTestnet :: ()
495507 => HasCallStack
0 commit comments