Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
project: cardano-cli
pr: 1475
kind:
- breaking
description: |
`debug check-node-configuration` now reads the configuration with cardano-config. It accepts both the old flat format and the new cardano-config format.
Genesis hashes are now required. Before, a configuration without them was accepted, and only the hashes it gave were checked.
Every genesis file is now decoded, not only hashed.
With `ExperimentalHardForksEnabled`, the configuration must also name a `DijkstraGenesisFile` and its `DijkstraGenesisHash`, and that file is checked too.
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.
The success message now goes to stderr instead of stdout.
`DebugNodeConfigWrongGenesisHashCmdError` is replaced by `DebugNodeConfigReadCmdError`, which carries the configuration file path and cardano-api's `NodeConfigError`.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ cardano-cli/test/cardano-cli-test/files/input/example_anchor_data2.txt -text
cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.alonzo.spec.json -text
cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.byron.spec.json -text
cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.conway.spec.json -text
cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.dijkstra.spec.json -text
cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.shelley.spec.json -text
2 changes: 1 addition & 1 deletion cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ repository cardano-haskell-packages
-- you need to run if you change them
index-state:
, hackage.haskell.org 2026-09-02T14:05:07Z
, cardano-haskell-packages 2026-10-13T14:57:01Z
, cardano-haskell-packages 2026-10-21T13:12:35Z

packages:
cardano-cli
Expand Down
3 changes: 2 additions & 1 deletion cardano-cli/cardano-cli.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,9 @@ library
binary,
bytestring,
canonical-json,
cardano-api ^>=11.9,
cardano-api ^>=11.10,
cardano-binary,
cardano-config ^>=2.2.2,
cardano-crypto,
cardano-crypto-class ^>=2.6,
cardano-crypto-wrapper ^>=1.8,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,68 +5,23 @@
module Cardano.CLI.EraIndependent.Debug.CheckNodeConfiguration.Run (runCheckNodeConfig) where

import Cardano.Api
import Cardano.Api.Byron qualified as Byron

import Cardano.CLI.Compatible.Exception
import Cardano.CLI.EraIndependent.Debug.CheckNodeConfiguration.Command
import Cardano.CLI.Read qualified as Read
import Cardano.CLI.Type.Error.DebugCmdError
import Cardano.Crypto.Hash qualified as Crypto

import Control.Monad
import Data.Foldable (for_)
import Data.Text qualified as Text
import Data.Yaml qualified as Yaml
import System.FilePath
import System.IO qualified as IO

-- | Check a node configuration file by reading it the way 'readNodeConfig'
-- does: every genesis file it names must exist, decode, and match the hash the
-- configuration gives for it.
runCheckNodeConfig :: CheckNodeConfigCmdArgs -> CIO e ()
runCheckNodeConfig (CheckNodeConfigCmdArgs configFile) = do
nodeConfig :: NodeConfig <- liftIO $ Yaml.decodeFileThrow configFilePath
checkNodeGenesisConfiguration configFile nodeConfig
liftIO $ putStrLn $ "Successfully checked node configuration file: " <> configFilePath
_ <-
fromExceptTCli . modifyError (DebugNodeConfigReadCmdError configFilePath) $
readNodeConfig configFile
liftIO $
IO.hPutStrLn IO.stderr $
"Successfully checked node configuration file: " <> configFilePath
where
configFilePath = unFile configFile

checkNodeGenesisConfiguration
:: NodeConfigFile 'In
-- ^ The node configuration file path. It's not read by this function, but used for producing error messages.
-> NodeConfig
-- ^ The parsed node configuration file
-> CIO e ()
checkNodeGenesisConfiguration configFile nodeConfig = do
let byronGenFile = adjustFilepath $ ncByronGenesisFile nodeConfig
alonzoGenFile = adjustFilepath $ ncAlonzoGenesisFile nodeConfig
shelleyGenFile = adjustFilepath $ ncShelleyGenesisFile nodeConfig
conwayGenFile = adjustFilepath $ ncConwayGenesisFile nodeConfig

liftIO $ putStrLn $ "Checking byron genesis file: " <> byronGenFile

let mExpectedByronHash = unGenesisHashByron <$> ncByronGenesisHash nodeConfig
mExpectedAlonzoHash = Crypto.hashToTextAsHex . unGenesisHashAlonzo <$> ncAlonzoGenesisHash nodeConfig
mExpectedShelleyHash = Crypto.hashToTextAsHex . unGenesisHashShelley <$> ncShelleyGenesisHash nodeConfig
mExpectedConwayHash = Crypto.hashToTextAsHex . unGenesisHashConway <$> ncConwayGenesisHash nodeConfig

(_, Byron.GenesisHash byronHash) <- fromExceptTCli $ Byron.readGenesisData byronGenFile
let actualByronHash = Text.pack $ show byronHash
actualAlonzoHash <- Crypto.hashToTextAsHex <$> Read.readShelleyOnwardsGenesisAndHash alonzoGenFile
actualShelleyHash <- Crypto.hashToTextAsHex <$> Read.readShelleyOnwardsGenesisAndHash shelleyGenFile
actualConwayHash <- Crypto.hashToTextAsHex <$> Read.readShelleyOnwardsGenesisAndHash conwayGenFile

-- check only hashes which were specified for the genesis
for_
[ (mExpectedByronHash, actualByronHash, byronGenFile)
, (mExpectedShelleyHash, actualShelleyHash, shelleyGenFile)
, (mExpectedAlonzoHash, actualAlonzoHash, alonzoGenFile)
, (mExpectedConwayHash, actualConwayHash, conwayGenFile)
]
$ \(mExpected, actual, genFile) ->
for_ mExpected $ \expected ->
when (actual /= expected) $
throwCliError $
DebugNodeConfigWrongGenesisHashCmdError configFilePath genFile actual expected
where
configFilePath = unFile configFile
-- We make the genesis filepath relative to the node configuration file, like the node does:
-- https://github.com/IntersectMBO/cardano-node/blob/9671e7b6a1b91f5a530722937949b86deafaad43/cardano-node/src/Cardano/Node/Configuration/POM.hs#L668
-- Note that, if the genesis filepath is absolute, the node configuration file's directory is ignored (by property of </>)
adjustFilepath (File f) = takeDirectory configFilePath </> f
49 changes: 31 additions & 18 deletions cardano-cli/src/Cardano/CLI/Type/Error/DebugCmdError.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ where

import Cardano.Api
import Cardano.Api.Byron qualified as Byron
import Cardano.Api.Ledger qualified as L

import Cardano.CLI.Type.Error.TxCmdError
import Cardano.Configuration qualified as Cfg

import Data.Aeson.Key qualified as Aeson
import Data.Aeson.Types qualified as Aeson
import Data.Text.Lazy.Builder qualified as Text
import Formatting.Buildable (build)

Expand All @@ -18,17 +22,13 @@ data DebugCmdError
| -- | @DebugNodeConfigGenesisDataCmdError filepath error@ represents an error when
-- reading the node configuration at @filepath@
DebugNodeConfigGenesisDataCmdError !FilePath !Byron.GenesisDataError
| -- | @DebugNodeConfigWrongGenesisHashCmdError filepath eraGenesisPath actualHash expectedHash@ represents a user error
-- that the hash of @eraGenesisPath@ in @filepath@ is @actualHash@, whereas it should be @expectedHash@
DebugNodeConfigWrongGenesisHashCmdError
| -- | @DebugNodeConfigReadCmdError filepath error@ represents an error when
-- reading the node configuration at @filepath@, or the genesis files it names
DebugNodeConfigReadCmdError
!FilePath
-- ^ The file path of the node configuration file
!FilePath
-- ^ The file path of the era configuration file whose hash is wrong
!Text
-- ^ The actual hash (the hash found by hashing the genesis file)
!Text
-- ^ The expected hash (the hash mentioned in the configuration file)
!NodeConfigError
-- ^ The error from reading the node configuration or a genesis file it names
| DebugTxCmdError !TxCmdError
deriving Show

Expand All @@ -40,13 +40,26 @@ instance Error DebugCmdError where
<> pretty fp
<> ": "
<> pretty (Text.toLazyText $ build err)
DebugNodeConfigWrongGenesisHashCmdError nodeFp genesisFp actualHash expectedHash ->
"Wrong genesis hash for "
<> pretty genesisFp
<> " in "
<> pretty nodeFp
<> ": when computing the hash, got: "
<> pretty actualHash
<> ", but the node configuration files states that this hash is expected: "
<> pretty expectedHash
DebugNodeConfigReadCmdError fp err -> case err of
-- cardano-config says which genesis file is at fault, and which key names it
NodeConfigParsingError
Cfg.ConfigurationParsingError
{ Cfg.errFile = L.SJust genesisFp
, Cfg.errPath = [Aeson.Key key]
, Cfg.errMessage = message
}
| genesisFp /= fp ->
"Error reading the genesis file "
<> pretty genesisFp
<> " ("
<> pretty (Aeson.toText key)
<> " in "
<> pretty fp
<> "): "
<> pretty message
_ ->
"Error reading node configuration at: "
<> pretty fp
<> ": "
<> prettyError err
DebugTxCmdError err -> renderTxCmdError err
Loading
Loading