Skip to content

Commit 1608ebb

Browse files
authored
Merge pull request #1475 from IntersectMBO/config-dedup
Replace manual node config checking with a call to `readNodeConfig`
2 parents 74dd2ce + f464a86 commit 1608ebb

14 files changed

Lines changed: 564 additions & 161 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
project: cardano-cli
2+
pr: 1475
3+
kind:
4+
- breaking
5+
description: |
6+
`debug check-node-configuration` now reads the configuration with cardano-config. It accepts both the old flat format and the new cardano-config format.
7+
Genesis hashes are now required. Before, a configuration without them was accepted, and only the hashes it gave were checked.
8+
Every genesis file is now decoded, not only hashed.
9+
With `ExperimentalHardForksEnabled`, the configuration must also name a `DijkstraGenesisFile` and its `DijkstraGenesisHash`, and that file is checked too.
10+
The initial data in the Shelley and Conway genesis files, such as `initialFunds`, is now checked too: it is rejected on mainnet, when it is given both at the top level and under `extraConfig`, or when a file it names is missing.
11+
The success message now goes to stderr instead of stdout.
12+
`DebugNodeConfigWrongGenesisHashCmdError` is replaced by `DebugNodeConfigReadCmdError`, which carries the configuration file path and cardano-api's `NodeConfigError`.

‎.gitattributes‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ cardano-cli/test/cardano-cli-test/files/input/example_anchor_data2.txt -text
55
cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.alonzo.spec.json -text
66
cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.byron.spec.json -text
77
cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.conway.spec.json -text
8+
cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.dijkstra.spec.json -text
89
cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.shelley.spec.json -text

‎cabal.project‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ repository cardano-haskell-packages
1414
-- you need to run if you change them
1515
index-state:
1616
, hackage.haskell.org 2026-09-02T14:05:07Z
17-
, cardano-haskell-packages 2026-10-13T14:57:01Z
17+
, cardano-haskell-packages 2026-10-21T13:12:35Z
1818

1919
packages:
2020
cardano-cli

‎cardano-cli/cardano-cli.cabal‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,9 @@ library
250250
binary,
251251
bytestring,
252252
canonical-json,
253-
cardano-api ^>=11.9,
253+
cardano-api ^>=11.10,
254254
cardano-binary,
255+
cardano-config ^>=2.2.2,
255256
cardano-crypto,
256257
cardano-crypto-class ^>=2.6,
257258
cardano-crypto-wrapper ^>=1.8,

‎cardano-cli/src/Cardano/CLI/EraIndependent/Debug/CheckNodeConfiguration/Run.hs‎

Lines changed: 10 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,68 +5,23 @@
55
module Cardano.CLI.EraIndependent.Debug.CheckNodeConfiguration.Run (runCheckNodeConfig) where
66

77
import Cardano.Api
8-
import Cardano.Api.Byron qualified as Byron
98

109
import Cardano.CLI.Compatible.Exception
1110
import Cardano.CLI.EraIndependent.Debug.CheckNodeConfiguration.Command
12-
import Cardano.CLI.Read qualified as Read
1311
import Cardano.CLI.Type.Error.DebugCmdError
14-
import Cardano.Crypto.Hash qualified as Crypto
1512

16-
import Control.Monad
17-
import Data.Foldable (for_)
18-
import Data.Text qualified as Text
19-
import Data.Yaml qualified as Yaml
20-
import System.FilePath
13+
import System.IO qualified as IO
2114

15+
-- | Check a node configuration file by reading it the way 'readNodeConfig'
16+
-- does: every genesis file it names must exist, decode, and match the hash the
17+
-- configuration gives for it.
2218
runCheckNodeConfig :: CheckNodeConfigCmdArgs -> CIO e ()
2319
runCheckNodeConfig (CheckNodeConfigCmdArgs configFile) = do
24-
nodeConfig :: NodeConfig <- liftIO $ Yaml.decodeFileThrow configFilePath
25-
checkNodeGenesisConfiguration configFile nodeConfig
26-
liftIO $ putStrLn $ "Successfully checked node configuration file: " <> configFilePath
20+
_ <-
21+
fromExceptTCli . modifyError (DebugNodeConfigReadCmdError configFilePath) $
22+
readNodeConfig configFile
23+
liftIO $
24+
IO.hPutStrLn IO.stderr $
25+
"Successfully checked node configuration file: " <> configFilePath
2726
where
2827
configFilePath = unFile configFile
29-
30-
checkNodeGenesisConfiguration
31-
:: NodeConfigFile 'In
32-
-- ^ The node configuration file path. It's not read by this function, but used for producing error messages.
33-
-> NodeConfig
34-
-- ^ The parsed node configuration file
35-
-> CIO e ()
36-
checkNodeGenesisConfiguration configFile nodeConfig = do
37-
let byronGenFile = adjustFilepath $ ncByronGenesisFile nodeConfig
38-
alonzoGenFile = adjustFilepath $ ncAlonzoGenesisFile nodeConfig
39-
shelleyGenFile = adjustFilepath $ ncShelleyGenesisFile nodeConfig
40-
conwayGenFile = adjustFilepath $ ncConwayGenesisFile nodeConfig
41-
42-
liftIO $ putStrLn $ "Checking byron genesis file: " <> byronGenFile
43-
44-
let mExpectedByronHash = unGenesisHashByron <$> ncByronGenesisHash nodeConfig
45-
mExpectedAlonzoHash = Crypto.hashToTextAsHex . unGenesisHashAlonzo <$> ncAlonzoGenesisHash nodeConfig
46-
mExpectedShelleyHash = Crypto.hashToTextAsHex . unGenesisHashShelley <$> ncShelleyGenesisHash nodeConfig
47-
mExpectedConwayHash = Crypto.hashToTextAsHex . unGenesisHashConway <$> ncConwayGenesisHash nodeConfig
48-
49-
(_, Byron.GenesisHash byronHash) <- fromExceptTCli $ Byron.readGenesisData byronGenFile
50-
let actualByronHash = Text.pack $ show byronHash
51-
actualAlonzoHash <- Crypto.hashToTextAsHex <$> Read.readShelleyOnwardsGenesisAndHash alonzoGenFile
52-
actualShelleyHash <- Crypto.hashToTextAsHex <$> Read.readShelleyOnwardsGenesisAndHash shelleyGenFile
53-
actualConwayHash <- Crypto.hashToTextAsHex <$> Read.readShelleyOnwardsGenesisAndHash conwayGenFile
54-
55-
-- check only hashes which were specified for the genesis
56-
for_
57-
[ (mExpectedByronHash, actualByronHash, byronGenFile)
58-
, (mExpectedShelleyHash, actualShelleyHash, shelleyGenFile)
59-
, (mExpectedAlonzoHash, actualAlonzoHash, alonzoGenFile)
60-
, (mExpectedConwayHash, actualConwayHash, conwayGenFile)
61-
]
62-
$ \(mExpected, actual, genFile) ->
63-
for_ mExpected $ \expected ->
64-
when (actual /= expected) $
65-
throwCliError $
66-
DebugNodeConfigWrongGenesisHashCmdError configFilePath genFile actual expected
67-
where
68-
configFilePath = unFile configFile
69-
-- We make the genesis filepath relative to the node configuration file, like the node does:
70-
-- https://github.com/IntersectMBO/cardano-node/blob/9671e7b6a1b91f5a530722937949b86deafaad43/cardano-node/src/Cardano/Node/Configuration/POM.hs#L668
71-
-- Note that, if the genesis filepath is absolute, the node configuration file's directory is ignored (by property of </>)
72-
adjustFilepath (File f) = takeDirectory configFilePath </> f

‎cardano-cli/src/Cardano/CLI/Type/Error/DebugCmdError.hs‎

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@ where
77

88
import Cardano.Api
99
import Cardano.Api.Byron qualified as Byron
10+
import Cardano.Api.Ledger qualified as L
1011

1112
import Cardano.CLI.Type.Error.TxCmdError
13+
import Cardano.Configuration qualified as Cfg
1214

15+
import Data.Aeson.Key qualified as Aeson
16+
import Data.Aeson.Types qualified as Aeson
1317
import Data.Text.Lazy.Builder qualified as Text
1418
import Formatting.Buildable (build)
1519

@@ -18,17 +22,13 @@ data DebugCmdError
1822
| -- | @DebugNodeConfigGenesisDataCmdError filepath error@ represents an error when
1923
-- reading the node configuration at @filepath@
2024
DebugNodeConfigGenesisDataCmdError !FilePath !Byron.GenesisDataError
21-
| -- | @DebugNodeConfigWrongGenesisHashCmdError filepath eraGenesisPath actualHash expectedHash@ represents a user error
22-
-- that the hash of @eraGenesisPath@ in @filepath@ is @actualHash@, whereas it should be @expectedHash@
23-
DebugNodeConfigWrongGenesisHashCmdError
25+
| -- | @DebugNodeConfigReadCmdError filepath error@ represents an error when
26+
-- reading the node configuration at @filepath@, or the genesis files it names
27+
DebugNodeConfigReadCmdError
2428
!FilePath
2529
-- ^ The file path of the node configuration file
26-
!FilePath
27-
-- ^ The file path of the era configuration file whose hash is wrong
28-
!Text
29-
-- ^ The actual hash (the hash found by hashing the genesis file)
30-
!Text
31-
-- ^ The expected hash (the hash mentioned in the configuration file)
30+
!NodeConfigError
31+
-- ^ The error from reading the node configuration or a genesis file it names
3232
| DebugTxCmdError !TxCmdError
3333
deriving Show
3434

@@ -40,13 +40,26 @@ instance Error DebugCmdError where
4040
<> pretty fp
4141
<> ": "
4242
<> pretty (Text.toLazyText $ build err)
43-
DebugNodeConfigWrongGenesisHashCmdError nodeFp genesisFp actualHash expectedHash ->
44-
"Wrong genesis hash for "
45-
<> pretty genesisFp
46-
<> " in "
47-
<> pretty nodeFp
48-
<> ": when computing the hash, got: "
49-
<> pretty actualHash
50-
<> ", but the node configuration files states that this hash is expected: "
51-
<> pretty expectedHash
43+
DebugNodeConfigReadCmdError fp err -> case err of
44+
-- cardano-config says which genesis file is at fault, and which key names it
45+
NodeConfigParsingError
46+
Cfg.ConfigurationParsingError
47+
{ Cfg.errFile = L.SJust genesisFp
48+
, Cfg.errPath = [Aeson.Key key]
49+
, Cfg.errMessage = message
50+
}
51+
| genesisFp /= fp ->
52+
"Error reading the genesis file "
53+
<> pretty genesisFp
54+
<> " ("
55+
<> pretty (Aeson.toText key)
56+
<> " in "
57+
<> pretty fp
58+
<> "): "
59+
<> pretty message
60+
_ ->
61+
"Error reading node configuration at: "
62+
<> pretty fp
63+
<> ": "
64+
<> prettyError err
5265
DebugTxCmdError err -> renderTxCmdError err

0 commit comments

Comments
 (0)