Skip to content

Commit f1d6ed3

Browse files
committed
New topology file format
Fixes #4559.
1 parent c9457d4 commit f1d6ed3

File tree

4 files changed

+94
-25
lines changed

4 files changed

+94
-25
lines changed

cardano-node/src/Cardano/Node/Configuration/TopologyP2P.hs

+73-23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
{-# LANGUAGE FlexibleContexts #-}
2+
{-# LANGUAGE FlexibleInstances #-}
13
{-# LANGUAGE NamedFieldPuns #-}
24
{-# LANGUAGE OverloadedStrings #-}
5+
{-# LANGUAGE PackageImports #-}
36

47
module Cardano.Node.Configuration.TopologyP2P
58
( TopologyError(..)
@@ -30,11 +33,14 @@ import qualified Data.ByteString as BS
3033
import qualified Data.ByteString.Lazy.Char8 as LBS
3134
import qualified Data.Text as Text
3235

36+
import "contra-tracer" Control.Tracer (Tracer, traceWith)
37+
3338
import Cardano.Node.Configuration.POM (NodeConfiguration (..))
3439
import Cardano.Slotting.Slot (SlotNo (..))
3540

3641
import Cardano.Node.Configuration.NodeAddress
3742
import Cardano.Node.Types
43+
import Cardano.Node.Startup (StartupTrace (..))
3844
import Cardano.Node.Configuration.Topology (TopologyError (..))
3945

4046
import Ouroboros.Network.NodeToNode (PeerAdvertise (..))
@@ -132,48 +138,42 @@ data LocalRootPeersGroup = LocalRootPeersGroup
132138
, valency :: Int
133139
} deriving (Eq, Show)
134140

141+
-- | Does not use the 'FromJSON' instance of 'RootConfig', so that
142+
-- 'accessPoints', 'advertise' and 'valency' fields are attached to the same
143+
-- object.
135144
instance FromJSON LocalRootPeersGroup where
136145
parseJSON = withObject "LocalRootPeersGroup" $ \o ->
137146
LocalRootPeersGroup
138-
<$> o .: "localRoots"
147+
<$> parseJSON (Object o)
139148
<*> o .: "valency"
140149

141150
instance ToJSON LocalRootPeersGroup where
142151
toJSON lrpg =
143152
object
144-
[ "localRoots" .= localRoots lrpg
145-
, "valency" .= valency lrpg
153+
[ "accessPoints" .= rootAccessPoints (localRoots lrpg)
154+
, "advertise" .= rootAdvertise (localRoots lrpg)
155+
, "valency" .= valency lrpg
146156
]
147157

148158
newtype LocalRootPeersGroups = LocalRootPeersGroups
149159
{ groups :: [LocalRootPeersGroup]
150160
} deriving (Eq, Show)
151161

152162
instance FromJSON LocalRootPeersGroups where
153-
parseJSON = withObject "LocalRootPeersGroups" $ \o ->
154-
LocalRootPeersGroups
155-
<$> o .: "groups"
163+
parseJSON = fmap LocalRootPeersGroups . parseJSONList
156164

157165
instance ToJSON LocalRootPeersGroups where
158-
toJSON lrpg =
159-
object
160-
[ "groups" .= groups lrpg
161-
]
166+
toJSON = toJSON . groups
162167

163168
newtype PublicRootPeers = PublicRootPeers
164169
{ publicRoots :: RootConfig
165170
} deriving (Eq, Show)
166171

167172
instance FromJSON PublicRootPeers where
168-
parseJSON = withObject "PublicRootPeers" $ \o ->
169-
PublicRootPeers
170-
<$> o .: "publicRoots"
173+
parseJSON = fmap PublicRootPeers . parseJSON
171174

172175
instance ToJSON PublicRootPeers where
173-
toJSON prp =
174-
object
175-
[ "publicRoots" .= publicRoots prp
176-
]
176+
toJSON = toJSON . publicRoots
177177

178178
data NetworkTopology = RealNodeTopology !LocalRootPeersGroups ![PublicRootPeers] !UseLedger
179179
deriving (Eq, Show)
@@ -192,17 +192,66 @@ instance ToJSON NetworkTopology where
192192
, "useLedgerAfterSlot" .= ul
193193
]
194194

195+
--
196+
-- Legacy p2p topology file format
197+
--
198+
199+
-- | A newtype wrapper which provides legacy 'FromJSON' instances.
200+
--
201+
newtype Legacy a = Legacy { getLegacy :: a }
202+
203+
instance FromJSON (Legacy a) => FromJSON (Legacy [a]) where
204+
parseJSON = fmap (Legacy . map getLegacy) . parseJSONList
205+
206+
instance FromJSON (Legacy LocalRootPeersGroup) where
207+
parseJSON = withObject "LocalRootPeersGroup" $ \o ->
208+
fmap Legacy $ LocalRootPeersGroup
209+
<$> o .: "localRoots"
210+
<*> o .: "valency"
211+
212+
instance FromJSON (Legacy LocalRootPeersGroups) where
213+
parseJSON = withObject "LocalRootPeersGroups" $ \o ->
214+
Legacy . LocalRootPeersGroups . getLegacy
215+
<$> o .: "groups"
216+
217+
instance FromJSON (Legacy PublicRootPeers) where
218+
parseJSON = withObject "PublicRootPeers" $ \o ->
219+
Legacy . PublicRootPeers
220+
<$> o .: "publicRoots"
221+
222+
instance FromJSON (Legacy NetworkTopology) where
223+
parseJSON = fmap Legacy
224+
. withObject "NetworkTopology" (\o ->
225+
RealNodeTopology <$> fmap getLegacy (o .: "LocalRoots")
226+
<*> fmap getLegacy (o .: "PublicRoots")
227+
<*> (o .:? "useLedgerAfterSlot" .!= UseLedger DontUseLedger))
228+
195229
-- | Read the `NetworkTopology` configuration from the specified file.
196230
--
197-
readTopologyFile :: NodeConfiguration -> IO (Either Text NetworkTopology)
198-
readTopologyFile nc = do
231+
readTopologyFile :: Tracer IO (StartupTrace blk)
232+
-> NodeConfiguration -> IO (Either Text NetworkTopology)
233+
readTopologyFile tr nc = do
199234
eBs <- Exception.try $ BS.readFile (unTopology $ ncTopologyFile nc)
200235

201236
case eBs of
202237
Left e -> return . Left $ handler e
203-
Right bs -> return . first handlerJSON . eitherDecode $ LBS.fromStrict bs
238+
Right bs ->
239+
let bs' = LBS.fromStrict bs in
240+
first handlerJSON (eitherDecode bs')
241+
`combine`
242+
first handlerJSON (eitherDecode bs')
204243

205244
where
245+
combine :: Either Text NetworkTopology
246+
-> Either Text (Legacy NetworkTopology)
247+
-> IO (Either Text NetworkTopology)
248+
combine a b = case (a, b) of
249+
(Right {}, _) -> return a
250+
(_, Right {}) -> traceWith tr NetworkConfigLegacy
251+
>> return (getLegacy <$> b)
252+
(Left _, Left _) -> -- ignore parsing error of legacy format
253+
return a
254+
206255
handler :: IOException -> Text
207256
handler e = Text.pack $ "Cardano.Node.Configuration.Topology.readTopologyFile: "
208257
++ displayException e
@@ -214,9 +263,10 @@ readTopologyFile nc = do
214263
\make sure that you correctly setup EnableP2P \
215264
\configuration flag. " <> Text.pack err
216265

217-
readTopologyFileOrError :: NodeConfiguration -> IO NetworkTopology
218-
readTopologyFileOrError nc =
219-
readTopologyFile nc
266+
readTopologyFileOrError :: Tracer IO (StartupTrace blk)
267+
-> NodeConfiguration -> IO NetworkTopology
268+
readTopologyFileOrError tr nc =
269+
readTopologyFile tr nc
220270
>>= either (\err -> panic $ "Cardano.Node.Configuration.TopologyP2P.readTopologyFile: "
221271
<> err)
222272
pure

cardano-node/src/Cardano/Node/Run.hs

+3-2
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ handleSimpleNode runP p2pMode tracers nc onKernel = do
407407
EnabledP2PMode -> do
408408
traceWith (startupTracer tracers)
409409
(StartupP2PInfo (ncDiffusionMode nc))
410-
nt <- TopologyP2P.readTopologyFileOrError nc
410+
nt <- TopologyP2P.readTopologyFileOrError (startupTracer tracers) nc
411411
let (localRoots, publicRoots) = producerAddresses nt
412412
traceWith (startupTracer tracers)
413413
$ NetworkConfig localRoots
@@ -515,14 +515,15 @@ handleSimpleNode runP p2pMode tracers nc onKernel = do
515515
developmentNtcVersions)
516516

517517
#ifdef UNIX
518+
-- only used when P2P is enabled
518519
updateTopologyConfiguration :: StrictTVar IO [(Int, Map RelayAccessPoint PeerAdvertise)]
519520
-> StrictTVar IO [RelayAccessPoint]
520521
-> StrictTVar IO UseLedgerAfter
521522
-> Signals.Handler
522523
updateTopologyConfiguration localRootsVar publicRootsVar useLedgerVar =
523524
Signals.Catch $ do
524525
traceWith (startupTracer tracers) NetworkConfigUpdate
525-
result <- try $ readTopologyFileOrError nc
526+
result <- try $ TopologyP2P.readTopologyFileOrError (startupTracer tracers) nc
526527
case result of
527528
Left (FatalError err) ->
528529
traceWith (startupTracer tracers)

cardano-node/src/Cardano/Node/Startup.hs

+4
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ data StartupTrace blk =
8989
--
9090
| NetworkConfigUpdateError Text
9191

92+
-- | Legacy topology file format is used.
93+
--
94+
| NetworkConfigLegacy
95+
9296
-- | Log peer-to-peer network configuration, either on startup or when its
9397
-- updated.
9498
--

cardano-node/src/Cardano/Node/Tracing/Tracers/Startup.hs

+14
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ namesStartupInfo = \case
133133
NetworkConfigUpdateUnsupported -> ["NetworkConfigUpdateUnsupported"]
134134
NetworkConfigUpdateError {} -> ["NetworkConfigUpdateError"]
135135
NetworkConfig {} -> ["NetworkConfig"]
136+
NetworkConfigLegacy {} -> ["NetworkConfigLegacy"]
136137
P2PWarning {} -> ["P2PWarning"]
137138
P2PWarningDevelopementNetworkProtocols {} -> ["P2PWarningDevelopementNetworkProtocols"]
138139
WarningDevelopmentNetworkProtocols {} -> ["WarningDevelopmentNetworkProtocols"]
@@ -212,6 +213,10 @@ instance ( Show (BlockNodeToNodeVersion blk)
212213
, "publicRoots" .= toJSON publicRoots
213214
, "useLedgerAfter" .= UseLedger useLedgerAfter
214215
]
216+
forMachine _dtal NetworkConfigLegacy =
217+
mconcat [ "kind" .= String "NetworkConfigLegacy"
218+
, "message" .= String p2pNetworkConfigLegacyMessage
219+
]
215220
forMachine _dtal P2PWarning =
216221
mconcat [ "kind" .= String "P2PWarning"
217222
, "message" .= String p2pWarningMessage ]
@@ -319,6 +324,7 @@ ppStartupInfoTrace (NetworkConfig localRoots publicRoots useLedgerAfter) =
319324
++ show (unSlotNo slotNo)
320325
DontUseLedger -> "Don't use ledger to get root peers."
321326
]
327+
ppStartupInfoTrace NetworkConfigLegacy = p2pNetworkConfigLegacyMessage
322328

323329
ppStartupInfoTrace P2PWarning = p2pWarningMessage
324330

@@ -365,6 +371,14 @@ p2pWarningDevelopmentNetworkProtocolsMessage :: Text
365371
p2pWarningDevelopmentNetworkProtocolsMessage =
366372
"peer-to-peer requires TestEnableDevelopmentNetworkProtocols to be set to True"
367373

374+
p2pNetworkConfigLegacyMessage :: Text
375+
p2pNetworkConfigLegacyMessage =
376+
pack
377+
$ intercalate "\n"
378+
[ "You are using legacy p2p topology file format."
379+
, "See https://github.com/input-output-hk/cardano-node/issues/4559"
380+
, "Note that the legacy p2p format will be removed in `1.37` release."
381+
]
368382

369383
docStartupInfo :: Documented (StartupTrace blk)
370384
docStartupInfo = Documented [

0 commit comments

Comments
 (0)