Skip to content

Commit 284dd45

Browse files
iohk-bors[bot]coot
andauthored
Merge #4209 #4563
4209: Document how to disable ledger peers r=coot a=coot 4563: New p2p topology file format r=coot a=coot Fixes #4559. Co-authored-by: Marcin Szamotulski <[email protected]>
3 parents f4dc7c4 + 5f0dd34 + d5e5835 commit 284dd45

File tree

10 files changed

+209
-48
lines changed

10 files changed

+209
-48
lines changed

cardano-node/ChangeLog.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
11
# Changelog for cardano-node
22

3+
## vNext
4+
5+
### node changes
6+
7+
None
8+
9+
### consensus changes
10+
11+
None
12+
13+
### network changes
14+
15+
- New P2P topology file format, see [issue #4563][#4563] or the [config
16+
files][understanding-config-files] documentation. The old p2p topology
17+
format will be supported for next two major releases of the node (the last
18+
major version which will support it is `1.37`).
19+
20+
[#4563]: https://github.com/input-output-hk/cardano-node/issues/4563
21+
[understanding-config-files]: https://github.com/input-output-hk/cardano-node/blob/master/doc/getting-started/understanding-config-files.md
22+
23+
### ledger changes
24+
25+
None
26+
327
## 1.35.3 -- August 2022
428

529
### node changes

cardano-node/cardano-node.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ test-suite cardano-node-test
215215
type: exitcode-stdio-1.0
216216

217217
build-depends: aeson >= 1.5.6.0
218+
, bytestring
218219
, cardano-api
219220
, cardano-node
220221
, cardano-prelude
@@ -226,6 +227,7 @@ test-suite cardano-node-test
226227
, ouroboros-consensus
227228
, ouroboros-network
228229
, time
230+
, vector
229231

230232
other-modules: Test.Cardano.Node.FilePermissions
231233
Test.Cardano.Node.Gen

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

Lines changed: 77 additions & 27 deletions
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,77 +138,120 @@ 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 = toJSONList . 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)
180180

181181
instance FromJSON NetworkTopology where
182182
parseJSON = withObject "NetworkTopology" $ \o ->
183-
RealNodeTopology <$> (o .: "LocalRoots" )
184-
<*> (o .: "PublicRoots" )
183+
RealNodeTopology <$> (o .: "localRoots" )
184+
<*> (o .: "publicRoots" )
185185
<*> (o .:? "useLedgerAfterSlot" .!= UseLedger DontUseLedger)
186186

187187
instance ToJSON NetworkTopology where
188188
toJSON top =
189189
case top of
190-
RealNodeTopology lrpg prp ul -> object [ "LocalRoots" .= lrpg
191-
, "PublicRoots" .= prp
190+
RealNodeTopology lrpg prp ul -> object [ "localRoots" .= lrpg
191+
, "publicRoots" .= prp
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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ handleSimpleNode runP p2pMode tracers nc onKernel = do
405405
EnabledP2PMode -> do
406406
traceWith (startupTracer tracers)
407407
(StartupP2PInfo (ncDiffusionMode nc))
408-
nt <- TopologyP2P.readTopologyFileOrError nc
408+
nt <- TopologyP2P.readTopologyFileOrError (startupTracer tracers) nc
409409
let (localRoots, publicRoots) = producerAddresses nt
410410
traceWith (startupTracer tracers)
411411
$ NetworkConfig localRoots
@@ -513,14 +513,15 @@ handleSimpleNode runP p2pMode tracers nc onKernel = do
513513
developmentNtcVersions)
514514

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

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

Lines changed: 4 additions & 0 deletions
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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ namesStartupInfo = \case
132132
NetworkConfigUpdateUnsupported -> ["NetworkConfigUpdateUnsupported"]
133133
NetworkConfigUpdateError {} -> ["NetworkConfigUpdateError"]
134134
NetworkConfig {} -> ["NetworkConfig"]
135+
NetworkConfigLegacy {} -> ["NetworkConfigLegacy"]
135136
P2PWarning {} -> ["P2PWarning"]
136137
P2PWarningDevelopementNetworkProtocols {} -> ["P2PWarningDevelopementNetworkProtocols"]
137138
WarningDevelopmentNetworkProtocols {} -> ["WarningDevelopmentNetworkProtocols"]
@@ -211,6 +212,10 @@ instance ( Show (BlockNodeToNodeVersion blk)
211212
, "publicRoots" .= toJSON publicRoots
212213
, "useLedgerAfter" .= UseLedger useLedgerAfter
213214
]
215+
forMachine _dtal NetworkConfigLegacy =
216+
mconcat [ "kind" .= String "NetworkConfigLegacy"
217+
, "message" .= String p2pNetworkConfigLegacyMessage
218+
]
214219
forMachine _dtal P2PWarning =
215220
mconcat [ "kind" .= String "P2PWarning"
216221
, "message" .= String p2pWarningMessage ]
@@ -318,6 +323,7 @@ ppStartupInfoTrace (NetworkConfig localRoots publicRoots useLedgerAfter) =
318323
++ show (unSlotNo slotNo)
319324
DontUseLedger -> "Don't use ledger to get root peers."
320325
]
326+
ppStartupInfoTrace NetworkConfigLegacy = p2pNetworkConfigLegacyMessage
321327

322328
ppStartupInfoTrace P2PWarning = p2pWarningMessage
323329

@@ -364,6 +370,14 @@ p2pWarningDevelopmentNetworkProtocolsMessage :: Text
364370
p2pWarningDevelopmentNetworkProtocolsMessage =
365371
"peer-to-peer requires TestEnableDevelopmentNetworkProtocols to be set to True"
366372

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

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

cardano-node/test/Test/Cardano/Node/Gen.hs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
module Test.Cardano.Node.Gen
99
( genNetworkTopology
10+
, genNetworkTopologyEncoding
1011
, genNodeHostIPv4Address
1112
, genNodeHostIPv6Address
1213
, genNodeHostIPAddress
@@ -16,6 +17,11 @@ module Test.Cardano.Node.Gen
1617
, genNodeSetup
1718
) where
1819

20+
import qualified Data.Aeson as Aeson
21+
import qualified Data.Aeson.KeyMap as Aeson.KeyMap
22+
import qualified Data.Vector as Vector
23+
import qualified Data.ByteString.Lazy as LBS
24+
1925
import Cardano.Prelude
2026

2127
import Cardano.Node.Configuration.TopologyP2P (NetworkTopology (..), PublicRootPeers (..),
@@ -46,6 +52,53 @@ genNetworkTopology =
4652
<*> genUseLedger
4753
]
4854

55+
-- | Generate valid encodings of p2p topology files
56+
--
57+
genNetworkTopologyEncoding :: Gen LBS.ByteString
58+
genNetworkTopologyEncoding = Aeson.encode <$> genNetworkTopologyValue
59+
60+
-- | Generate a Aeson.Object which encodes a p2p topology.
61+
--
62+
genNetworkTopologyValue :: Gen Aeson.Object
63+
genNetworkTopologyValue =
64+
(\a b c -> Aeson.KeyMap.fromList
65+
[ ("localRoots", Aeson.Array . Vector.fromList $ a)
66+
, ("publicRoots", Aeson.Array . Vector.fromList $ b)
67+
, ("useLedgerAfter", Aeson.Number . fromIntegral $ c)
68+
]
69+
) <$> Gen.list (Range.constantFrom 0 0 10) genLocalRootsValue
70+
<*> Gen.list (Range.constantFrom 0 0 10) genPublicRootsValue
71+
<*> Gen.int (Range.constantFrom 0 0 100)
72+
where
73+
genLocalRootsValue :: Gen Aeson.Value
74+
genLocalRootsValue =
75+
(\a b c -> Aeson.Object $ Aeson.KeyMap.fromList
76+
[ ("accessPoints", Aeson.Array . Vector.fromList $ a)
77+
, ("advertise", Aeson.Bool b)
78+
, ("valency", Aeson.Number (fromIntegral c))
79+
]
80+
) <$> Gen.list (Range.constantFrom 0 0 10) genAccessPointValue
81+
<*> Gen.bool
82+
<*> Gen.int (Range.constantFrom 0 0 100)
83+
84+
genPublicRootsValue :: Gen Aeson.Value
85+
genPublicRootsValue =
86+
(\a b -> Aeson.Object $ Aeson.KeyMap.fromList
87+
[ ("accessPoints", Aeson.Array . Vector.fromList $ a)
88+
, ("advertise", Aeson.Bool b)
89+
]
90+
) <$> Gen.list (Range.constantFrom 0 0 10) genAccessPointValue
91+
<*> Gen.bool
92+
93+
genAccessPointValue :: Gen Aeson.Value
94+
genAccessPointValue =
95+
(\a -> Aeson.Object $ Aeson.KeyMap.fromList
96+
[ ("address", Aeson.String (show $ naHostAddress a))
97+
, ("port", Aeson.Number (fromIntegral $ naPort a))
98+
]
99+
) <$> genNodeIPAddress
100+
101+
49102
genNodeAddress' :: Gen addr -> Gen (NodeAddress' addr)
50103
genNodeAddress' genAddr =
51104
NodeAddress

0 commit comments

Comments
 (0)