diff --git a/.changes/20261022_cardano_api_11_11.yml b/.changes/20261022_cardano_api_11_11.yml new file mode 100644 index 0000000000..1c0bfabe79 --- /dev/null +++ b/.changes/20261022_cardano_api_11_11.yml @@ -0,0 +1,5 @@ +project: cardano-cli +pr: 1482 +kind: + - maintenance +description: Update to cardano-api 11.11 and adapt sub-transaction guards and node configuration hash checks to the new API types. diff --git a/cabal.project b/cabal.project index cc4ec9ab5f..e0b7a426cf 100644 --- a/cabal.project +++ b/cabal.project @@ -13,8 +13,8 @@ repository cardano-haskell-packages -- See CONTRIBUTING for information about these, including some Nix commands -- 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 + , hackage.haskell.org 2026-09-29T11:48:37Z + , cardano-haskell-packages 2026-10-22T19:34:43Z packages: cardano-cli diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index 8fdc9294f6..5bf27e9675 100644 --- a/cardano-cli/cardano-cli.cabal +++ b/cardano-cli/cardano-cli.cabal @@ -186,11 +186,11 @@ library Cardano.CLI.Legacy.Option Cardano.CLI.Legacy.Run Cardano.CLI.LocalStateQuery - Cardano.CLI.OS.Posix Cardano.CLI.Option Cardano.CLI.Option.Flag Cardano.CLI.Option.Flag.Type Cardano.CLI.Orphan + Cardano.CLI.OS.Posix Cardano.CLI.Parser Cardano.CLI.Read Cardano.CLI.Read.Committee.ColdKey @@ -250,7 +250,7 @@ library binary, bytestring, canonical-json, - cardano-api ^>=11.9, + cardano-api ^>=11.11, cardano-binary, cardano-crypto, cardano-crypto-class ^>=2.6, diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Transaction/SubTransaction/Run.hs b/cardano-cli/src/Cardano/CLI/EraBased/Transaction/SubTransaction/Run.hs index b28af3cf30..9a64e22ab1 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Transaction/SubTransaction/Run.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Transaction/SubTransaction/Run.hs @@ -260,8 +260,8 @@ validateGuardRedeemer credential script hasRedeemer | otherwise = unless hasRedeemer $ Left $ TxCmdPlutusGuardMissingRedeemer credential --- | The API currently collects witnesses for the six pre-Dijkstra purposes. --- Add guarding witnesses before canonicalisation/signing and update the script +-- | Guard credentials are passed to the API without witnesses below. +-- Add their witnesses before canonicalisation/signing and update the script -- integrity hash to cover the complete redeemer set. Guard indices include key -- and native-script guards, and preserve the body's OSet order. addGuardWitnesses @@ -423,6 +423,10 @@ constructSubTx TxMetadataInEra _ mDat -> mDat validatedDirectDeposits <- convertDirectDeposits directDeposits + validatedGuards <- + first TxCmdGuardsError $ + obtainCommonConstraints (Exp.useEra @era) $ + Exp.mkTxGuards [(credential, Nothing) | credential <- Foldable.toList guards] validatedMintValue <- createTxMintValue valuesWithScriptWits validatedVotingProcedures <- first (TxCmdVotingError . TxVotingError) $ @@ -448,7 +452,7 @@ constructSubTx & maybe id (Exp.setTxCurrentTreasuryValue . unTxCurrentTreasuryValue) mCurrentTreasury & maybe id (Exp.setTxTreasuryDonation . unTxTreasuryDonation) mTreasuryDonation & Exp.setTxSupplementalDatums suppDatums - & Exp.setTxGuards guards + & Exp.setTxGuards validatedGuards & Exp.setTxRequiredTopLevelGuards requiredTopLevelGuards ) diff --git a/cardano-cli/src/Cardano/CLI/EraIndependent/Debug/CheckNodeConfiguration/Run.hs b/cardano-cli/src/Cardano/CLI/EraIndependent/Debug/CheckNodeConfiguration/Run.hs index fc2466caf6..72cef1a24a 100644 --- a/cardano-cli/src/Cardano/CLI/EraIndependent/Debug/CheckNodeConfiguration/Run.hs +++ b/cardano-cli/src/Cardano/CLI/EraIndependent/Debug/CheckNodeConfiguration/Run.hs @@ -1,72 +1,16 @@ -{-# LANGUAGE DataKinds #-} {-# LANGUAGE RankNTypes #-} -{-# LANGUAGE ScopedTypeVariables #-} 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 Control.Monad (void) 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 - 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 + -- The API loader reads the genesis files and validates their configured hashes. + void $ fromExceptTCli $ readNodeConfig configFile + liftIO $ putStrLn $ "Successfully checked node configuration file: " <> unFile configFile diff --git a/cardano-cli/src/Cardano/CLI/Type/Error/TxCmdError.hs b/cardano-cli/src/Cardano/CLI/Type/Error/TxCmdError.hs index cf1a4b195e..e808e5efb6 100644 --- a/cardano-cli/src/Cardano/CLI/Type/Error/TxCmdError.hs +++ b/cardano-cli/src/Cardano/CLI/Type/Error/TxCmdError.hs @@ -88,6 +88,7 @@ data TxCmdError | TxCmdSubTxByronWitnessUnsupported | TxCmdDuplicateDirectDeposits ![StakeAddress] | TxCmdDuplicateGuards ![L.Credential L.Guard] + | TxCmdGuardsError !Exp.TxGuardsError | TxCmdPlutusGuardMissingRedeemer !(L.Credential L.Guard) | TxCmdNativeGuardWithRedeemer !(L.Credential L.Guard) | TxCmdTopLevelGuardMissingDatum !FilePath @@ -225,6 +226,7 @@ renderTxCmdError = \case <> hsep (map (pretty . serialiseAddress) addresses) TxCmdDuplicateGuards credentials -> "Duplicate guards: " <> hsep (map (pretty . L.credToText) credentials) + TxCmdGuardsError err -> prettyError err TxCmdPlutusGuardMissingRedeemer credential -> "Plutus guard " <> pretty (L.credToText credential) diff --git a/cardano-cli/test/cardano-cli-test/Test/Cli/CheckNodeConfiguration.hs b/cardano-cli/test/cardano-cli-test/Test/Cli/CheckNodeConfiguration.hs index a9d9a714da..3e5a7d3d8e 100644 --- a/cardano-cli/test/cardano-cli-test/Test/Cli/CheckNodeConfiguration.hs +++ b/cardano-cli/test/cardano-cli-test/Test/Cli/CheckNodeConfiguration.hs @@ -60,8 +60,7 @@ hprop_check_node_configuration_failure = do watchdogProp . propertyOnce $ forM_ supplyValues $ \(nodeConfigPath, fiddleKind) -> H.moduleWorkspace "tmp" $ \tempDir -> do let finalInputConfig = tempDir "node-config-changed.json" - -- TODO why is that writing to "AlonzoGenesisHash" writes one more 0 than specified here? (and hence the need for this hack) - wrongHash = Text.pack $ replicate (case fiddleKind of FiddleByron -> 65; FiddleNonByron -> 64) '0' + wrongHash = Text.replicate 64 "0" -- Install the genesis files in the sandbox forM_ @@ -106,9 +105,8 @@ hprop_check_node_configuration_failure = do , "--node-configuration-file" , finalInputConfig ] - -- H.success -- Temporarily disabled. H.assertWith exitCode (ExitSuccess /=) - H.assertWith stderr ("Wrong genesis hash" `isInfixOf`) + H.assertWith stderr ("GenesisHashMismatch" `isInfixOf`) -- | The JSON key of the genesis hash for the given era. eraToGenesisHashKey :: AnyCardanoEra -> Text.Text diff --git a/cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.conway.spec.json b/cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.conway.spec.json index cb36a9387f..0d70ca9f6f 100644 --- a/cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.conway.spec.json +++ b/cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.conway.spec.json @@ -25,7 +25,7 @@ "dRepDeposit": 0, "dRepActivity": 0, "minFeeRefScriptCostPerByte": 0, - "plutusV3CostModel": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "plutusV3CostModel": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], "constitution": { "anchor": { "url": "", diff --git a/cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/node-config.json b/cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/node-config.json index 355d0d8be1..18e65c5fd5 100644 --- a/cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/node-config.json +++ b/cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/node-config.json @@ -4,11 +4,11 @@ "ByronGenesisFile": "genesis.byron.spec.json", "ByronGenesisHash": "b91cb9a87b244fbb6f8d60a809475705594b6aa9a9aa5dcb6be8020549def9f5", "ConwayGenesisFile": "genesis.conway.spec.json", - "ConwayGenesisHash": "65d481eec0b24ef90f7bbeaf6933fdf9629ce89afe88238e5da4ec79977a28d1", + "ConwayGenesisHash": "d01d83041d13012ab6628f825efb836e7ff4a85f4bcd73a936de6189e0628f5b", "EnableLogMetrics": false, "EnableLogging": true, "EnableP2P": false, - "ExperimentalHardForksEnabled": true, + "ExperimentalHardForksEnabled": false, "ExperimentalProtocolsEnabled": true, "LastKnownBlockVersion-Alt": 0, "LastKnownBlockVersion-Major": 2, diff --git a/cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/node-config.yaml b/cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/node-config.yaml index 48542dcfcb..5119a1d51e 100644 --- a/cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/node-config.yaml +++ b/cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/node-config.yaml @@ -8,7 +8,7 @@ AlonzoGenesisHash: 2418fe881f57d2f5851a018214634aa6d1b7f10f130c3bdf8c13210c0ed2f ByronGenesisFile: genesis.byron.spec.json ByronGenesisHash: b91cb9a87b244fbb6f8d60a809475705594b6aa9a9aa5dcb6be8020549def9f5 ConwayGenesisFile: genesis.conway.spec.json -ConwayGenesisHash: 65d481eec0b24ef90f7bbeaf6933fdf9629ce89afe88238e5da4ec79977a28d1 +ConwayGenesisHash: d01d83041d13012ab6628f825efb836e7ff4a85f4bcd73a936de6189e0628f5b ShelleyGenesisFile: genesis.shelley.spec.json ShelleyGenesisHash: 9ae14531b6f0a3cd958b050310fd9fca9474b94c85fc9a2f79f9353f4ed0cf7f diff --git a/flake.lock b/flake.lock index 395fe6e3ae..82dc6c2fb5 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "CHaP": { "flake": false, "locked": { - "lastModified": 1791917061, - "narHash": "sha256-lSMHtX/jzGBocXaJ6rv5oP3Hwppdyn1wfAjsCCl/mvo=", + "lastModified": 1792680696, + "narHash": "sha256-z90C2qAhtryoy14UNhFvDa1gxHg6EcRE0mYDtosUV4E=", "owner": "intersectmbo", "repo": "cardano-haskell-packages", - "rev": "32245bbb4131b82b3eddb67dca61970d37ae733a", + "rev": "07b90e324606d0e5c534c63bec42cf12d068bd3c", "type": "github" }, "original": { @@ -384,11 +384,11 @@ "hackageNix": { "flake": false, "locked": { - "lastModified": 1788358854, - "narHash": "sha256-NIF+y/9ctwQILbHsCZCOFN7dxuwWXKnFn5T0+ya49+Y=", + "lastModified": 1792698177, + "narHash": "sha256-kzyf8/TUNkBkie9lbpk72DK7zwCpmfzewduWUUnuskU=", "owner": "input-output-hk", "repo": "hackage.nix", - "rev": "04149d44d879f7115282c442f8904b5eb5a78c4e", + "rev": "608b787e026dd68be2eca0d8df9d6cdc43e0d1ac", "type": "github" }, "original": {