From f3fb46f4367da7f14ead6c237caee769022d8479 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferrai Date: Tue, 26 May 2026 17:35:03 +0300 Subject: [PATCH 01/13] Integration for Node release 11.1 --- cabal.project | 67 +++++++++++++++++-- cardano-cli/cardano-cli.cabal | 7 +- .../src/Cardano/CLI/Byron/UpdateProposal.hs | 2 +- cardano-cli/src/Cardano/CLI/Byron/Vote.hs | 2 +- .../CLI/EraIndependent/Cip/Cip129/Run.hs | 13 ++-- .../EraIndependent/Debug/LogEpochState/Run.hs | 9 +++ .../Cardano/CLI/EraIndependent/Ping/Run.hs | 4 +- cardano-cli/src/Cardano/CLI/Orphan.hs | 8 --- cardano-cli/src/Cardano/CLI/Read.hs | 13 ++++ 9 files changed, 99 insertions(+), 26 deletions(-) diff --git a/cabal.project b/cabal.project index 3bb37cdadf..b2daa4ee24 100644 --- a/cabal.project +++ b/cabal.project @@ -16,10 +16,6 @@ index-state: , hackage.haskell.org 2026-06-02T21:49:32Z , cardano-haskell-packages 2026-06-02T21:14:32Z -active-repositories: - , :rest - , cardano-haskell-packages:override - packages: cardano-cli @@ -100,3 +96,66 @@ if impl(ghc >= 9.14) , with-utf8:base -- cabal-allow-newer end +source-repository-package + type: git + location: https://github.com/IntersectMBO/cardano-api.git + tag: 500e283a93fcb4c82b03febf243cb976431a613f + --sha256: sha256-aHpjdMQhjRpe0w5Fb9a5LeVGcO44VAl928CS7HoYB0Q= + subdir: + cardano-api + +source-repository-package + type: git + location: https://github.com/IntersectMBO/cardano-ledger.git + tag: 3f879bb37df4738ed8211e500c7d180443cfcbe4 + --sha256: sha256-uLjiIHiU1SzAmoKs+rynQphc3FUYXKeJLlOnp87uNdg= + subdir: + eras/allegra/impl + eras/alonzo/impl + eras/babbage/impl + eras/byron/chain/executable-spec + eras/byron/crypto + eras/byron/ledger/executable-spec + eras/byron/ledger/impl + eras/conway/impl + eras/dijkstra/impl + eras/mary/impl + eras/shelley-ma/test-suite + eras/shelley/impl + eras/shelley/test-suite + libs/cardano-data + libs/cardano-ledger-api + libs/cardano-ledger-binary + libs/cardano-ledger-core + libs/cardano-protocol-tpraos + libs/non-integral + libs/small-steps + libs/vector-map + +source-repository-package + type: git + location: https://github.com/f-f/kes-agent.git + tag: 0b362519f6915841c92869ed288ce83f89b17b73 + --sha256: sha256-8pZYF7MJZZ1tM19wIUhbLKORDL+OP2ckhueWJM4aG/c= + subdir: + kes-agent + kes-agent-crypto + +source-repository-package + type: git + location: https://github.com/IntersectMBO/ouroboros-consensus.git + tag: 0411b4d50dc62cab07bbbf75805cf585a7a1f8e7 + --sha256: sha256-DNnGHdo+oQDBbHzAl6UZ/VcPoS4TxGrC9eCOiMxgc8A= + subdir: + . + +source-repository-package + type: git + location: https://github.com/IntersectMBO/ouroboros-network.git + tag: 10e173b21a82f6142261f0f38da0ec14c8b8a91c + --sha256: sha256-l3lpFzcFj2xiKaj54A7Rvhuu3s6EtzIboaHyuGhBhG8= + subdir: + ./cardano-diffusion + ./monoidal-synchronisation + ./network-mux + ./ouroboros-network diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index 2e24f66059..246daff998 100644 --- a/cardano-cli/cardano-cli.cabal +++ b/cardano-cli/cardano-cli.cabal @@ -245,15 +245,15 @@ library cardano-api ^>=11.3, cardano-binary, cardano-crypto, - cardano-crypto-class ^>=2.3, + cardano-crypto-class ^>=2.5, cardano-crypto-wrapper ^>=1.7, cardano-data >=1.1, + cardano-diffusion:ping ^>=1.0, cardano-git-rev ^>=0.2.2, cardano-ledger-api, cardano-ledger-conway, cardano-ledger-core, cardano-ledger-dijkstra, - cardano-ping ^>=0.10, cardano-prelude, cardano-protocol-tpraos, cardano-slotting ^>=0.2.0.0, @@ -267,6 +267,7 @@ library exceptions, filepath, formatting, + fs-api, generic-lens, haskeline, http-client, @@ -292,7 +293,7 @@ library transformers, unliftio-core, utf8-string, - validation, + validation ^>=1.2, vary ^>=0.1.1.2, vector, yaml, diff --git a/cardano-cli/src/Cardano/CLI/Byron/UpdateProposal.hs b/cardano-cli/src/Cardano/CLI/Byron/UpdateProposal.hs index 79a3b7e146..d929c2a0cd 100644 --- a/cardano-cli/src/Cardano/CLI/Byron/UpdateProposal.hs +++ b/cardano-cli/src/Cardano/CLI/Byron/UpdateProposal.hs @@ -69,5 +69,5 @@ submitByronUpdateProposal submitByronUpdateProposal nodeSocketPath network proposalFp = do proposal <- readByronUpdateProposal proposalFp let genTx = toByronLedgerUpdateProposal proposal - traceWith stdoutTracer $ "Update proposal TxId: " ++ condense (txId genTx) + liftIO $ traceWith stdoutTracer $ "Update proposal TxId: " ++ condense (txId genTx) fromExceptTCli $ nodeSubmitTx nodeSocketPath network genTx diff --git a/cardano-cli/src/Cardano/CLI/Byron/Vote.hs b/cardano-cli/src/Cardano/CLI/Byron/Vote.hs index 10c99d15b2..6dea978de1 100644 --- a/cardano-cli/src/Cardano/CLI/Byron/Vote.hs +++ b/cardano-cli/src/Cardano/CLI/Byron/Vote.hs @@ -52,7 +52,7 @@ submitByronVote submitByronVote nodeSocketPath network voteFp = do vote <- readByronVote voteFp let genTx = toByronLedgertoByronVote vote - traceWith stdoutTracer ("Vote TxId: " ++ condense (txId genTx)) + liftIO $ traceWith stdoutTracer ("Vote TxId: " ++ condense (txId genTx)) fromExceptTCli $ nodeSubmitTx nodeSocketPath network genTx readByronVote :: FilePath -> CIO e ByronVote diff --git a/cardano-cli/src/Cardano/CLI/EraIndependent/Cip/Cip129/Run.hs b/cardano-cli/src/Cardano/CLI/EraIndependent/Cip/Cip129/Run.hs index 2c231cc6b3..78c5b6635c 100644 --- a/cardano-cli/src/Cardano/CLI/EraIndependent/Cip/Cip129/Run.hs +++ b/cardano-cli/src/Cardano/CLI/EraIndependent/Cip/Cip129/Run.hs @@ -22,7 +22,6 @@ import Data.ByteString (ByteString) import Data.ByteString qualified as BS import Data.ByteString.Char8 qualified as BSC import Data.Text.Encoding qualified as Text -import Data.Validation qualified as Valid import System.IO runCip129 :: Cip129 -> CIO e () @@ -32,9 +31,9 @@ runCip129 (Cip129DRep inp out) = do f <- liftIO $ fileOrPipe textEnvFp fromEitherIOCli $ readDrepVerificationKeyFile f InputHexText t -> do - fromEitherCli . Valid.toEither $ readDRepHexVerificationKeyText t + fromEitherCli . toEither $ readDRepHexVerificationKeyText t InputBech32Text t -> do - fromEitherCli . Valid.toEither $ readDRepBech32VerificationKeyText t + fromEitherCli . toEither $ readDRepBech32VerificationKeyText t let cip129Output = Text.encodeUtf8 $ encodeCip129DrepVerficationKeyText k renderOutput cip129Output out runCip129 (Cip129CommitteeHotKey inp out) = do @@ -43,9 +42,9 @@ runCip129 (Cip129CommitteeHotKey inp out) = do f <- liftIO $ fileOrPipe textEnvFp fromEitherIOCli $ readCommitteeHotVerificationKeyFile f InputHexText t -> - fromEitherCli . Valid.toEither $ readCommitteeHotHexVerificationKeyText t + fromEitherCli . toEither $ readCommitteeHotHexVerificationKeyText t InputBech32Text t -> - fromEitherCli . Valid.toEither $ readCommitteeHotBech32VerificationKeyText t + fromEitherCli . toEither $ readCommitteeHotBech32VerificationKeyText t let cip129Output = Text.encodeUtf8 $ encodeCip129CommitteeHotVerficationKeyText k renderOutput cip129Output out runCip129 (Cip129CommitteeColdKey inp out) = do @@ -54,9 +53,9 @@ runCip129 (Cip129CommitteeColdKey inp out) = do f <- liftIO $ fileOrPipe textEnvFp fromEitherIOCli $ readCommitteeColdVerificationKeyFile f InputHexText t -> - fromEitherCli . Valid.toEither $ readCommitteeColdHexVerificationKeyText t + fromEitherCli . toEither $ readCommitteeColdHexVerificationKeyText t InputBech32Text t -> - fromEitherCli . Valid.toEither $ readCommitteeColdBech32VerificationKeyText t + fromEitherCli . toEither $ readCommitteeColdBech32VerificationKeyText t let cip129Output = Text.encodeUtf8 $ encodeCip129CommitteeColdVerficationKeyText k renderOutput cip129Output out runCip129 (Cip129GovernanceAction inp out) = diff --git a/cardano-cli/src/Cardano/CLI/EraIndependent/Debug/LogEpochState/Run.hs b/cardano-cli/src/Cardano/CLI/EraIndependent/Debug/LogEpochState/Run.hs index 61093b9505..a786fbc52d 100644 --- a/cardano-cli/src/Cardano/CLI/EraIndependent/Debug/LogEpochState/Run.hs +++ b/cardano-cli/src/Cardano/CLI/EraIndependent/Debug/LogEpochState/Run.hs @@ -15,6 +15,11 @@ import Cardano.CLI.Orphan () import Data.Aeson qualified as Aeson import Data.ByteString.Lazy qualified as LBS +import System.Directory (makeAbsolute) +import System.FS.API (SomeHasFS (..)) +import System.FS.API.Types (MountPoint (MountPoint)) +import System.FS.IO (ioHasFS) +import System.FilePath (takeDirectory) import System.IO qualified as IO runLogEpochStateCmd @@ -28,9 +33,13 @@ runLogEpochStateCmd } = do LBS.appendFile outputFilePath "" + configDir <- takeDirectory <$> makeAbsolute (unFile configurationFile) + let fs = SomeHasFS (ioHasFS (MountPoint configDir)) + result <- runExceptT $ foldEpochState + fs configurationFile nodeSocketPath Api.QuickValidation diff --git a/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs b/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs index de66b74651..596d3540bf 100644 --- a/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs +++ b/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs @@ -19,7 +19,7 @@ import Control.Concurrent.Class.MonadSTM.Strict qualified as STM import Control.Exception (SomeException) import Control.Monad (forM, unless) import Control.Monad.Class.MonadAsync (MonadAsync (async, wait, waitCatch)) -import Control.Tracer (Tracer (..)) +import Control.Tracer (Tracer, mkTracer) import Data.List qualified as L import Data.List qualified as List import Network.Socket (AddrInfo) @@ -96,7 +96,7 @@ runPingCmd options = do -- Ping client thread handles caids <- forM addresses $ - liftIO . async . pingClient (Tracer $ doLog msgQueue) (Tracer doErrLog) options versions + liftIO . async . pingClient (mkTracer $ doLog msgQueue) (mkTracer doErrLog) options versions res <- L.zip addresses <$> mapM (liftIO . waitCatch) caids liftIO $ doLog msgQueue CNP.LogEnd liftIO $ wait laid diff --git a/cardano-cli/src/Cardano/CLI/Orphan.hs b/cardano-cli/src/Cardano/CLI/Orphan.hs index 4a81e7c75c..ec8a8112c7 100644 --- a/cardano-cli/src/Cardano/CLI/Orphan.hs +++ b/cardano-cli/src/Cardano/CLI/Orphan.hs @@ -15,7 +15,6 @@ import Cardano.Api.Experimental as Exp import Cardano.Api.Ledger qualified as L import Cardano.CLI.Type.Error.ScriptDecodeError -import Cardano.Ledger.Conway.Governance qualified as L import Cardano.Ledger.Conway.State qualified as L import Control.Exception @@ -24,13 +23,6 @@ import Data.List qualified as List import Data.Typeable import Data.Word -instance ToJSON L.DefaultVote where - toJSON defaultVote = - case defaultVote of - L.DefaultNo -> String "DefaultNo" - L.DefaultAbstain -> String "DefaultAbstain" - L.DefaultNoConfidence -> String "DefaultNoConfidence" - instance Error [Bech32DecodeError] where prettyError errs = vsep $ map prettyError errs diff --git a/cardano-cli/src/Cardano/CLI/Read.hs b/cardano-cli/src/Cardano/CLI/Read.hs index 93d64b2605..7e11c21e51 100644 --- a/cardano-cli/src/Cardano/CLI/Read.hs +++ b/cardano-cli/src/Cardano/CLI/Read.hs @@ -91,6 +91,8 @@ module Cardano.CLI.Read -- * utilities , readerFromParsecParser + , liftError + , toEither ) where @@ -134,6 +136,7 @@ import Data.Text qualified as T import Data.Text qualified as Text import Data.Text.Encoding qualified as Text import Data.Text.Encoding.Error qualified as Text +import Data.Validation (Validation (Failure, Success)) import GHC.IO.Handle (hClose, hIsSeekable) import GHC.IO.Handle.FD (openFileBlocking) import GHC.Stack @@ -819,6 +822,16 @@ readFileCli = withFrozenCallStack . readFileBinary readerFromParsecParser :: P.Parser a -> Opt.ReadM a readerFromParsecParser p = Opt.eitherReader (P.runParser p . T.pack) +liftError :: (e -> e') -> Either e a -> Validation e' a +liftError f = \case + Left e -> Failure (f e) + Right a -> Success a + +toEither :: Validation e a -> Either e a +toEither = \case + Failure e -> Left e + Success a -> Right a + -- TODO: Update to handle hex script bytes directly as well! readFilePlutusScript :: forall e era From 97968170496036b6c136530161cf1beff8e44412 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferrai Date: Tue, 16 Jun 2026 18:37:22 +0200 Subject: [PATCH 02/13] Use latest network --- cabal.project | 8 +- cardano-cli/cardano-cli.cabal | 6 +- .../CLI/EraBased/Transaction/Option.hs | 44 ++--- .../Cardano/CLI/EraIndependent/Ping/Option.hs | 2 +- .../Cardano/CLI/EraIndependent/Ping/Run.hs | 153 +++++------------- cardano-cli/src/Cardano/CLI/Option.hs | 9 +- cardano-cli/src/Cardano/CLI/Render.hs | 88 +++++----- 7 files changed, 119 insertions(+), 191 deletions(-) diff --git a/cabal.project b/cabal.project index b2daa4ee24..932878a7b6 100644 --- a/cabal.project +++ b/cabal.project @@ -135,8 +135,8 @@ source-repository-package source-repository-package type: git location: https://github.com/f-f/kes-agent.git - tag: 0b362519f6915841c92869ed288ce83f89b17b73 - --sha256: sha256-8pZYF7MJZZ1tM19wIUhbLKORDL+OP2ckhueWJM4aG/c= + tag: fdb4f4db05e3744ed413f83477020fdf43cf32a2 + --sha256: sha256-eyQc8Dk7+upSRQvH5eXZuj6asYhOLsH59ABJZDyvQ6I= subdir: kes-agent kes-agent-crypto @@ -152,8 +152,8 @@ source-repository-package source-repository-package type: git location: https://github.com/IntersectMBO/ouroboros-network.git - tag: 10e173b21a82f6142261f0f38da0ec14c8b8a91c - --sha256: sha256-l3lpFzcFj2xiKaj54A7Rvhuu3s6EtzIboaHyuGhBhG8= + tag: 1db937ff3acd9c5862af8bf7b30900a701e8dd46 + --sha256: sha256-P/9vK8PwRAp+ORGMeU5UUTDMotlUXFcqNXUReX5CQDw= subdir: ./cardano-diffusion ./monoidal-synchronisation diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index 246daff998..5fe34661d9 100644 --- a/cardano-cli/cardano-cli.cabal +++ b/cardano-cli/cardano-cli.cabal @@ -273,15 +273,13 @@ library http-client, http-client-tls, http-types, - io-classes, - io-classes:strict-stm, iproute, microlens, mmorph, mtl, network, network-uri, - optparse-applicative-fork, + optparse-applicative, ordered-containers, prettyprinter, prettyprinter-ansi-terminal, @@ -311,7 +309,7 @@ executable cardano-cli cardano-api, cardano-cli, cardano-crypto-class, - optparse-applicative-fork, + optparse-applicative, rio, terminal-size, diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Transaction/Option.hs b/cardano-cli/src/Cardano/CLI/EraBased/Transaction/Option.hs index 424a55915d..f290aea1f6 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Transaction/Option.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Transaction/Option.hs @@ -30,7 +30,7 @@ import Data.Time.Clock.POSIX (posixSecondsToUTCTime) import Data.Universe (Some) import Options.Applicative hiding (help, str) import Options.Applicative qualified as Opt -import Options.Applicative.Help qualified as H +-- import Options.Applicative.Help qualified as H import Prettyprinter (line) pTransactionCmds @@ -55,13 +55,13 @@ pTransactionCmds envCli = [ pretty @String "Build a transaction (low-level, inconvenient)" , line , line - , H.yellow $ - mconcat - [ "Please note " - , H.underline "the order" - , " of some cmd options is crucial. If used incorrectly may produce " - , "undesired tx body. See nested [] notation above for details." - ] + -- , H.yellow $ + -- mconcat + -- [ "Please note " + -- , H.underline "the order" + -- , " of some cmd options is crucial. If used incorrectly may produce " + -- , "undesired tx body. See nested [] notation above for details." + -- ] ] , pTransactionBuildCmd envCli , pTransactionBuildEstimateCmd envCli @@ -179,13 +179,13 @@ pTransactionBuildCmd envCli = do [ pretty @String "Build a balanced transaction (automatically calculates fees)" , line , line - , H.yellow $ - mconcat - [ "Please note " - , H.underline "the order" - , " of some cmd options is crucial. If used incorrectly may produce " - , "undesired tx body. See nested [] notation above for details." - ] + -- , H.yellow $ + -- mconcat + -- [ "Please note " + -- , H.underline "the order" + -- , " of some cmd options is crucial. If used incorrectly may produce " + -- , "undesired tx body. See nested [] notation above for details." + -- ] ] where pCmd era' = do @@ -243,13 +243,13 @@ pTransactionBuildEstimateCmd _envCli = do "Build a balanced transaction without access to a live node (automatically estimates fees)" , line , line - , H.yellow $ - mconcat - [ "Please note " - , H.underline "the order" - , " of some cmd options is crucial. If used incorrectly may produce " - , "undesired tx body. See nested [] notation above for details." - ] + -- , H.yellow $ + -- mconcat + -- [ "Please note " + -- , H.underline "the order" + -- , " of some cmd options is crucial. If used incorrectly may produce " + -- , "undesired tx body. See nested [] notation above for details." + -- ] ] where pCmd :: Parser (TransactionCmds era) diff --git a/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Option.hs b/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Option.hs index 5ec4a81d58..6743ebaddf 100644 --- a/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Option.hs +++ b/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Option.hs @@ -80,7 +80,7 @@ pPing = , Opt.short 'm' , Opt.metavar "MAGIC" , Opt.help "Network magic." - , Opt.value CNP.mainnetMagic + , Opt.value (CNP.unNetworkMagic CNP.mainnetMagic) ] ) <*> ( Opt.switch $ diff --git a/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs b/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs index 596d3540bf..7e00b51eaa 100644 --- a/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs +++ b/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs @@ -1,10 +1,8 @@ -{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE DataKinds #-} {-# LANGUAGE RankNTypes #-} module Cardano.CLI.EraIndependent.Ping.Run - ( PingClientCmdError (..) - , renderPingClientCmdError - , runPingCmd + ( runPingCmd ) where @@ -14,118 +12,51 @@ import Cardano.CLI.Compatible.Exception import Cardano.CLI.EraIndependent.Ping.Command import Cardano.Network.Ping qualified as CNP -import Control.Concurrent.Class.MonadSTM.Strict (StrictTMVar) -import Control.Concurrent.Class.MonadSTM.Strict qualified as STM -import Control.Exception (SomeException) -import Control.Monad (forM, unless) -import Control.Monad.Class.MonadAsync (MonadAsync (async, wait, waitCatch)) -import Control.Tracer (Tracer, mkTracer) -import Data.List qualified as L -import Data.List qualified as List -import Network.Socket (AddrInfo) -import Network.Socket qualified as Socket -import System.Exit qualified as IO -import System.IO qualified as IO +import Data.IP qualified as IP +import Text.Read (readMaybe) -data PingClientCmdError - = PingClientCmdError [(AddrInfo, SomeException)] - | PingClientMisconfigurationError String +newtype PingClientCmdError = PingClientMisconfigurationError String deriving Show instance Error PingClientCmdError where prettyError = renderPingClientCmdError -maybeHostEndPoint :: EndPoint -> Maybe String -maybeHostEndPoint = \case - HostEndPoint host -> Just host - UnixSockEndPoint _ -> Nothing - -maybeUnixSockEndPoint :: EndPoint -> Maybe String -maybeUnixSockEndPoint = \case - HostEndPoint _ -> Nothing - UnixSockEndPoint sock -> Just sock - -pingClient - :: Tracer IO CNP.LogMsg -> Tracer IO String -> PingCmd -> [CNP.NodeVersion] -> AddrInfo -> IO () -pingClient stdout stderr cmd = CNP.pingClient stdout stderr opts - where - opts = - CNP.PingOpts - { CNP.pingOptsQuiet = pingCmdQuiet cmd - , CNP.pingOptsJson = pingCmdJson cmd - , CNP.pingOptsCount = pingCmdCount cmd - , CNP.pingOptsHost = maybeHostEndPoint (pingCmdEndPoint cmd) - , CNP.pingOptsUnixSock = maybeUnixSockEndPoint (pingCmdEndPoint cmd) - , CNP.pingOptsPort = pingCmdPort cmd - , CNP.pingOptsMagic = pingCmdMagic cmd - , CNP.pingOptsHandshakeQuery = pingOptsHandshakeQuery cmd - , CNP.pingOptsGetTip = pingOptsGetTip cmd - } +renderPingClientCmdError :: PingClientCmdError -> Doc ann +renderPingClientCmdError (PingClientMisconfigurationError err) = pretty err runPingCmd :: PingCmd -> CIO e () -runPingCmd options - | Just err <- getConfigurationError options = - throwCliError $ PingClientMisconfigurationError err -runPingCmd options = do - let hints = Socket.defaultHints{Socket.addrSocketType = Socket.Stream} - - msgQueue <- liftIO STM.newEmptyTMVarIO - - -- 'addresses' are all the endpoints to connect to and 'versions' are the node protocol versions - -- to ping with. - (addresses, versions) <- case pingCmdEndPoint options of - HostEndPoint host -> do - addrs <- liftIO $ Socket.getAddrInfo (Just hints) (Just host) (Just (pingCmdPort options)) - return (addrs, CNP.supportedNodeToNodeVersions $ pingCmdMagic options) - UnixSockEndPoint fname -> do - let addr = - Socket.AddrInfo - [] - Socket.AF_UNIX - Socket.Stream - Socket.defaultProtocol - (Socket.SockAddrUnix fname) - Nothing - return ([addr], CNP.supportedNodeToClientVersions $ pingCmdMagic options) - - -- Logger async thread handle - laid <- - liftIO . async $ - CNP.logger msgQueue (pingCmdJson options) (pingOptsHandshakeQuery options) (pingOptsGetTip options) - - -- Ping client thread handles - caids <- - forM addresses $ - liftIO . async . pingClient (mkTracer $ doLog msgQueue) (mkTracer doErrLog) options versions - res <- L.zip addresses <$> mapM (liftIO . waitCatch) caids - liftIO $ doLog msgQueue CNP.LogEnd - liftIO $ wait laid - - -- Collect errors 'es' from failed pings and 'addrs' from successful pings. - let (es, addrs) = L.foldl' partition ([], []) res - - -- Report any errors - case (es, addrs) of - ([], _) -> liftIO IO.exitSuccess - (_, []) -> throwCliError $ PingClientCmdError es - (_, _) -> do - unless (pingCmdQuiet options) $ mapM_ (liftIO . IO.hPrint IO.stderr) es - liftIO IO.exitSuccess - where - partition - :: ([(AddrInfo, SomeException)], [AddrInfo]) - -> (AddrInfo, Either SomeException ()) - -> ([(AddrInfo, SomeException)], [AddrInfo]) - partition (es, as) (a, Left e) = ((a, e) : es, as) - partition (es, as) (a, Right _) = (es, a : as) - - doLog :: StrictTMVar IO CNP.LogMsg -> CNP.LogMsg -> IO () - doLog msgQueue msg = STM.atomically $ STM.putTMVar msgQueue msg - - doErrLog :: String -> IO () - doErrLog = IO.hPutStrLn IO.stderr - -renderPingClientCmdError :: PingClientCmdError -> Doc ann -renderPingClientCmdError = \case - PingClientCmdError es -> mconcat $ List.intersperse "\n" $ pshow <$> es - PingClientMisconfigurationError err -> pretty err +runPingCmd cmd + | Just err <- getConfigurationError cmd = + throwCliError (PingClientMisconfigurationError err) + | otherwise = + -- TODO(network): CNP.pingClients does its own output and exit handling, maybe we want to expose that? + liftIO (CNP.pingClients (toPingOpts cmd) [toAddress cmd]) + +toPingOpts :: PingCmd -> CNP.PingOpts +toPingOpts cmd = + CNP.PingOpts + { CNP.pingOptsCount = pingCmdCount cmd + , CNP.pingOptsMagic = CNP.NetworkMagic (pingCmdMagic cmd) + , CNP.pingOptsJson = if pingCmdJson cmd then CNP.AsJSON else CNP.AsText + , CNP.pingOptsQuiet = pingCmdQuiet cmd + , CNP.pingOptsMode = + if pingOptsGetTip cmd + then CNP.TipMode + else + if pingOptsHandshakeQuery cmd + then CNP.QueryMode + else CNP.PingMode + , -- cardano-cli has no flags for these yet, so use network's own defaults. + CNP.pingOptsSRVPrefix = "_cardano._tcp" + , CNP.pingOptsColor = CNP.ColorAuto + } + +toAddress :: PingCmd -> CNP.Address (CNP.Unresolved CNP.SRVOrFilePathUnresolved) +toAddress cmd = + case pingCmdEndPoint cmd of + UnixSockEndPoint path -> CNP.FilePathOrDomain path + -- TODO(network): we could export a parseAddress :: String -> Either String (Address ...) + HostEndPoint host -> + case (readMaybe host :: Maybe IP.IP, readMaybe (pingCmdPort cmd) :: Maybe Word) of + (Just ip, Just port) -> CNP.IP ip port + _ -> CNP.FilePathOrDomain (host <> ":" <> pingCmdPort cmd) diff --git a/cardano-cli/src/Cardano/CLI/Option.hs b/cardano-cli/src/Cardano/CLI/Option.hs index 328f78722f..0c491c0f4d 100644 --- a/cardano-cli/src/Cardano/CLI/Option.hs +++ b/cardano-cli/src/Cardano/CLI/Option.hs @@ -25,13 +25,14 @@ import Cardano.CLI.EraIndependent.Node.Option import Cardano.CLI.EraIndependent.Ping.Option (parsePingCmd) import Cardano.CLI.Legacy.Option (parseLegacyCmds) import Cardano.CLI.Parser -import Cardano.CLI.Render (customRenderHelp) +-- import Cardano.CLI.Render (customRenderHelp) import Cardano.CLI.Run (ClientCommand (..)) import Data.Foldable import Options.Applicative import Options.Applicative qualified as Opt -import Prettyprinter qualified as PP + +-- import Prettyprinter qualified as PP opts :: EnvCli -> ParserInfo ClientCommand opts envCli = @@ -51,8 +52,8 @@ pref = Opt.prefs $ mconcat [ showHelpOnEmpty - , helpEmbedBriefDesc PP.align - , helpRenderHelp customRenderHelp + -- , helpEmbedBriefDesc PP.align + -- , helpRenderHelp customRenderHelp ] addressCmdsTopLevel :: EnvCli -> Parser ClientCommand diff --git a/cardano-cli/src/Cardano/CLI/Render.hs b/cardano-cli/src/Cardano/CLI/Render.hs index d3043fd4ae..69c8b2a563 100644 --- a/cardano-cli/src/Cardano/CLI/Render.hs +++ b/cardano-cli/src/Cardano/CLI/Render.hs @@ -4,61 +4,59 @@ module Cardano.CLI.Render ) where -import Cardano.Api (textShow) - import Data.Text (Text) -import Data.Text qualified as T import Options.Applicative -import Options.Applicative.Help.Ann -import Options.Applicative.Help.Types (helpText, renderHelp) +import Options.Applicative.Help.Types (renderHelp) import Prettyprinter -import Prettyprinter.Render.Util.SimpleDocTree -import System.Environment qualified as IO -import System.IO.Unsafe qualified as IO -cliHelpTraceEnabled :: Bool -cliHelpTraceEnabled = IO.unsafePerformIO $ do - mValue <- IO.lookupEnv "CLI_HELP_TRACE" - return $ mValue == Just "1" -{-# NOINLINE cliHelpTraceEnabled #-} +-- import Cardano.Api (textShow) +-- import Data.Text qualified as T +-- import Options.Applicative.Help.Ann +-- import Options.Applicative.Help.Types (helpText) +-- import Prettyprinter.Render.Util.SimpleDocTree +-- import System.Environment qualified as IO +-- import System.IO.Unsafe qualified as IO +-- +-- cliHelpTraceEnabled :: Bool +-- cliHelpTraceEnabled = IO.unsafePerformIO $ do +-- mValue <- IO.lookupEnv "CLI_HELP_TRACE" +-- return $ mValue == Just "1" +-- {-# NOINLINE cliHelpTraceEnabled #-} +-- -- | Convert a help text to 'String'. When the CLI_HELP_TRACE environment variable is set -- to '1', the output will be in HTML so that it can be viewed in a browser where developer -- tools can be used to inspect tracing that aids in describing the structure of the output -- document. +-- customRenderHelpAsHtml :: Int -> ParserHelp -> String +-- customRenderHelpAsHtml cols = +-- T.unpack +-- . wrapper +-- . renderSimplyDecorated id renderElement +-- . treeForm +-- . layoutSmart (LayoutOptions (AvailablePerLine cols 1.0)) +-- . helpText +-- where +-- renderElement :: Ann -> Text -> Text +-- renderElement ann x = +-- if cliHelpTraceEnabled +-- then case ann of +-- AnnTrace _ name -> "" <> x <> "" +-- AnnStyle _ -> x +-- else x +-- wrapper = +-- if cliHelpTraceEnabled +-- then +-- id +-- . ("\n" <>) +-- . ("\n" <>) +-- . ("
\n" <>)
+--           . (<> "\n")
+--           . (<> "\n")
+--           . (<> "\n
") +-- else id customRenderHelp :: Int -> ParserHelp -> String -customRenderHelp = - if cliHelpTraceEnabled - then customRenderHelpAsHtml - else customRenderHelpAsAnsi - -customRenderHelpAsHtml :: Int -> ParserHelp -> String -customRenderHelpAsHtml cols = - T.unpack - . wrapper - . renderSimplyDecorated id renderElement - . treeForm - . layoutSmart (LayoutOptions (AvailablePerLine cols 1.0)) - . helpText - where - renderElement :: Ann -> Text -> Text - renderElement ann x = - if cliHelpTraceEnabled - then case ann of - AnnTrace _ name -> "" <> x <> "" - AnnStyle _ -> x - else x - wrapper = - if cliHelpTraceEnabled - then - id - . ("\n" <>) - . ("\n" <>) - . ("
\n" <>)
-          . (<> "\n")
-          . (<> "\n")
-          . (<> "\n
") - else id +customRenderHelp = customRenderHelpAsAnsi customRenderHelpAsAnsi :: Int -> ParserHelp -> String customRenderHelpAsAnsi = renderHelp From c8c4e4abd374e94a9496483cd003112f0d95a903 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferrai Date: Wed, 17 Jun 2026 15:42:30 +0200 Subject: [PATCH 03/13] WIP new network --- cabal.project | 4 +- cardano-cli/cardano-cli.cabal | 1 + .../Cardano/CLI/EraIndependent/Ping/Run.hs | 117 ++++++++++++++---- 3 files changed, 97 insertions(+), 25 deletions(-) diff --git a/cabal.project b/cabal.project index 932878a7b6..b967214d0c 100644 --- a/cabal.project +++ b/cabal.project @@ -152,8 +152,8 @@ source-repository-package source-repository-package type: git location: https://github.com/IntersectMBO/ouroboros-network.git - tag: 1db937ff3acd9c5862af8bf7b30900a701e8dd46 - --sha256: sha256-P/9vK8PwRAp+ORGMeU5UUTDMotlUXFcqNXUReX5CQDw= + tag: 1881340e26ca98b3ee2b89ea536348406b79e051 + --sha256: sha256-O1Th+YI6LZqCLM6n75tVV+3InA4W8sC0yHEi09u8Fyw= subdir: ./cardano-diffusion ./monoidal-synchronisation diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index 5fe34661d9..416746deca 100644 --- a/cardano-cli/cardano-cli.cabal +++ b/cardano-cli/cardano-cli.cabal @@ -273,6 +273,7 @@ library http-client, http-client-tls, http-types, + io-classes, iproute, microlens, mmorph, diff --git a/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs b/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs index 7e00b51eaa..56c3227ab2 100644 --- a/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs +++ b/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs @@ -1,8 +1,10 @@ -{-# LANGUAGE DataKinds #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE RankNTypes #-} module Cardano.CLI.EraIndependent.Ping.Run - ( runPingCmd + ( PingClientCmdError (..) + , renderPingClientCmdError + , runPingCmd ) where @@ -12,25 +14,71 @@ import Cardano.CLI.Compatible.Exception import Cardano.CLI.EraIndependent.Ping.Command import Cardano.Network.Ping qualified as CNP -import Data.IP qualified as IP -import Text.Read (readMaybe) +import Control.Exception (SomeException, toException) +import Control.Monad (unless) +import Control.Monad.Class.MonadAsync (mapConcurrently) +import Control.Tracer (mkTracer) +import Data.Aeson qualified as Aeson +import Data.Aeson.Text (encodeToLazyText) +import Data.List qualified as L +import Data.List qualified as List +import Data.Text qualified as T +import Data.Text.Lazy qualified as TL +import Data.Text.Lazy.IO qualified as TLIO +import Network.Socket (AddrInfo) +import Network.Socket qualified as Socket +import System.IO qualified as IO +import Text.Printf (printf) -newtype PingClientCmdError = PingClientMisconfigurationError String +data PingClientCmdError + = PingClientCmdError [(AddrInfo, SomeException)] + | PingClientMisconfigurationError String deriving Show instance Error PingClientCmdError where prettyError = renderPingClientCmdError -renderPingClientCmdError :: PingClientCmdError -> Doc ann -renderPingClientCmdError (PingClientMisconfigurationError err) = pretty err - runPingCmd :: PingCmd -> CIO e () -runPingCmd cmd - | Just err <- getConfigurationError cmd = - throwCliError (PingClientMisconfigurationError err) - | otherwise = - -- TODO(network): CNP.pingClients does its own output and exit handling, maybe we want to expose that? - liftIO (CNP.pingClients (toPingOpts cmd) [toAddress cmd]) +runPingCmd options + | Just err <- getConfigurationError options = + throwCliError $ PingClientMisconfigurationError err +runPingCmd options = do + let hints = Socket.defaultHints{Socket.addrSocketType = Socket.Stream} + + addresses <- case pingCmdEndPoint options of + HostEndPoint host -> + liftIO $ Socket.getAddrInfo (Just hints) (Just host) (Just (pingCmdPort options)) + UnixSockEndPoint fname -> + pure + [ Socket.AddrInfo + [] + Socket.AF_UNIX + Socket.Stream + Socket.defaultProtocol + (Socket.SockAddrUnix fname) + Nothing + ] + + let stdout = mkTracer (TLIO.putStrLn . renderLogMsg (pingCmdJson options)) + stderr = mkTracer (IO.hPutStrLn IO.stderr . renderPingWarning) + + res <- + liftIO $ + mapConcurrently + (\addr -> (,) addr <$> CNP.pingClient stdout stderr (toPingOpts options) addr) + addresses + + case L.foldl' partition ([], []) res of + ([], _) -> pure () + (_, []) -> throwCliError $ PingClientCmdError es + (_, _) -> unless (pingCmdQuiet options) $ mapM_ (liftIO . IO.hPrint IO.stderr) es + where + partition + :: ([(AddrInfo, SomeException)], [AddrInfo]) + -> (AddrInfo, Either CNP.PingClientException ()) + -> ([(AddrInfo, SomeException)], [AddrInfo]) + partition (es, as) (a, Left e) = ((a, toException e) : es, as) + partition (es, as) (a, Right _) = (es, a : as) toPingOpts :: PingCmd -> CNP.PingOpts toPingOpts cmd = @@ -51,12 +99,35 @@ toPingOpts cmd = , CNP.pingOptsColor = CNP.ColorAuto } -toAddress :: PingCmd -> CNP.Address (CNP.Unresolved CNP.SRVOrFilePathUnresolved) -toAddress cmd = - case pingCmdEndPoint cmd of - UnixSockEndPoint path -> CNP.FilePathOrDomain path - -- TODO(network): we could export a parseAddress :: String -> Either String (Address ...) - HostEndPoint host -> - case (readMaybe host :: Maybe IP.IP, readMaybe (pingCmdPort cmd) :: Maybe Word) of - (Just ip, Just port) -> CNP.IP ip port - _ -> CNP.FilePathOrDomain (host <> ":" <> pingCmdPort cmd) +-- | Format a ping log message. Mirrors the network library's internal +-- @format@/@ToText@ helpers, which are not exported. +renderLogMsg :: Bool -> CNP.WithHost CNP.LogMsg -> TL.Text +renderLogMsg True msg = encodeToLazyText (Aeson.toJSON msg) +renderLogMsg False (CNP.WithHost host logMsg) = + TL.pack (printf "%-47s" (show host <> ", ")) <> renderLogMsgText logMsg + +renderLogMsgText :: CNP.LogMsg -> TL.Text +renderLogMsgText = \case + CNP.LogChainSyncTip tip -> TL.pack (show tip) + CNP.LogStatPoint point -> TL.pack (show point) + CNP.LogNodeToClientVersionData version versionData -> + TL.pack (unwords [show version, either T.unpack show versionData]) + CNP.LogNodeToNodeVersionData version versionData -> + TL.pack (unwords [show version, either T.unpack show versionData]) + +-- | Format a ping warning. Mirrors the network library's internal +-- @formatPingWarning@, which is not exported. +renderPingWarning :: CNP.PingWarning -> String +renderPingWarning = \case + CNP.FilePathDoesNotExist path -> "WARNING: file path " <> show path <> " does not exist" + CNP.DNSError domain err -> "WARNING: dns: " <> show domain <> " " <> show err + CNP.DNSResolution domain ips port -> + show domain <> ": " <> List.intercalate ", " [show ip <> ":" <> show port | ip <- ips] + CNP.MissingPort ip -> "WARNING: missing port for " <> show ip + CNP.Error err -> "WARNING: " <> show err + CNP.ConnectError sockAddr err -> "WARNING: " <> show sockAddr <> " " <> show err + +renderPingClientCmdError :: PingClientCmdError -> Doc ann +renderPingClientCmdError = \case + PingClientCmdError es -> mconcat $ List.intersperse "\n" $ pshow <$> es + PingClientMisconfigurationError err -> pretty err From 9678a844fd2b53bc3777906d61b53fe0ff93e8ed Mon Sep 17 00:00:00 2001 From: Fabrizio Ferrai Date: Wed, 17 Jun 2026 20:50:42 +0200 Subject: [PATCH 04/13] Typo --- cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs b/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs index 56c3227ab2..8c0e8127ab 100644 --- a/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs +++ b/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs @@ -70,8 +70,8 @@ runPingCmd options = do case L.foldl' partition ([], []) res of ([], _) -> pure () - (_, []) -> throwCliError $ PingClientCmdError es - (_, _) -> unless (pingCmdQuiet options) $ mapM_ (liftIO . IO.hPrint IO.stderr) es + (es, []) -> throwCliError $ PingClientCmdError es + (es, _) -> unless (pingCmdQuiet options) $ mapM_ (liftIO . IO.hPrint IO.stderr) es where partition :: ([(AddrInfo, SomeException)], [AddrInfo]) From b698d1f0f5681da0ae43dc9db10f82b2de35c0c6 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferrai Date: Wed, 24 Jun 2026 16:54:10 +0300 Subject: [PATCH 05/13] Back to optparse-applicative-fork --- cabal.project | 26 +++--- cardano-cli/cardano-cli.cabal | 4 +- .../CLI/EraBased/Transaction/Option.hs | 44 +++++----- cardano-cli/src/Cardano/CLI/Option.hs | 9 +- cardano-cli/src/Cardano/CLI/Render.hs | 88 ++++++++++--------- 5 files changed, 89 insertions(+), 82 deletions(-) diff --git a/cabal.project b/cabal.project index b967214d0c..ac267481c3 100644 --- a/cabal.project +++ b/cabal.project @@ -96,19 +96,25 @@ if impl(ghc >= 9.14) , with-utf8:base -- cabal-allow-newer end +source-repository-package + type: git + location: https://github.com/input-output-hk/optparse-applicative + tag: 074b90b38c0415f87023be84221a92be6e3cea0e + --sha256: sha256-Ffkx3/Ol1M0YjGJpyngex0Q+Qb1Ov1Er9WaAkLXuSSk= + source-repository-package type: git location: https://github.com/IntersectMBO/cardano-api.git - tag: 500e283a93fcb4c82b03febf243cb976431a613f - --sha256: sha256-aHpjdMQhjRpe0w5Fb9a5LeVGcO44VAl928CS7HoYB0Q= + tag: bb64ad40f904040a9b4d99306cf13eef4650a6c9 + --sha256: sha256-302P+qj+UkY/uSWHt8YMT4VzNhRS9tWMz0G6rjr4eVk= subdir: cardano-api source-repository-package type: git location: https://github.com/IntersectMBO/cardano-ledger.git - tag: 3f879bb37df4738ed8211e500c7d180443cfcbe4 - --sha256: sha256-uLjiIHiU1SzAmoKs+rynQphc3FUYXKeJLlOnp87uNdg= + tag: 8dc1c431e06db2c8b5d44fb4b3cca6419197d763 + --sha256: sha256-xKtgNFxjbJE6UWGvTioGX81NgvlKH3mHEaYMWDm8/UA= subdir: eras/allegra/impl eras/alonzo/impl @@ -135,8 +141,8 @@ source-repository-package source-repository-package type: git location: https://github.com/f-f/kes-agent.git - tag: fdb4f4db05e3744ed413f83477020fdf43cf32a2 - --sha256: sha256-eyQc8Dk7+upSRQvH5eXZuj6asYhOLsH59ABJZDyvQ6I= + tag: 32c1ed675d22a30735d9f22f7afa436a3ef3e64a + --sha256: sha256-o7hFX1JnraS6Xq0WoXQwd9Z8GsPPv0Ls2DWvZ08o0ZU= subdir: kes-agent kes-agent-crypto @@ -144,16 +150,16 @@ source-repository-package source-repository-package type: git location: https://github.com/IntersectMBO/ouroboros-consensus.git - tag: 0411b4d50dc62cab07bbbf75805cf585a7a1f8e7 - --sha256: sha256-DNnGHdo+oQDBbHzAl6UZ/VcPoS4TxGrC9eCOiMxgc8A= + tag: e6fad063078894cefece2a535a2e2b4d9a092e73 + --sha256: sha256-SPtbQ1+zN4uYiVx3rej2kMasbpfhSAyjRD5bdrnK3Rs= subdir: . source-repository-package type: git location: https://github.com/IntersectMBO/ouroboros-network.git - tag: 1881340e26ca98b3ee2b89ea536348406b79e051 - --sha256: sha256-O1Th+YI6LZqCLM6n75tVV+3InA4W8sC0yHEi09u8Fyw= + tag: 8b4dcb898b64615f574a7fbdcf119f77c7fbc598 + --sha256: sha256-t1tGV5uZwyKnSSCbaJJAteMYKnQYeO39hUUycMRuC2M= subdir: ./cardano-diffusion ./monoidal-synchronisation diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index 416746deca..18e5339748 100644 --- a/cardano-cli/cardano-cli.cabal +++ b/cardano-cli/cardano-cli.cabal @@ -280,7 +280,7 @@ library mtl, network, network-uri, - optparse-applicative, + optparse-applicative-fork, ordered-containers, prettyprinter, prettyprinter-ansi-terminal, @@ -310,7 +310,7 @@ executable cardano-cli cardano-api, cardano-cli, cardano-crypto-class, - optparse-applicative, + optparse-applicative-fork, rio, terminal-size, diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Transaction/Option.hs b/cardano-cli/src/Cardano/CLI/EraBased/Transaction/Option.hs index f290aea1f6..424a55915d 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Transaction/Option.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Transaction/Option.hs @@ -30,7 +30,7 @@ import Data.Time.Clock.POSIX (posixSecondsToUTCTime) import Data.Universe (Some) import Options.Applicative hiding (help, str) import Options.Applicative qualified as Opt --- import Options.Applicative.Help qualified as H +import Options.Applicative.Help qualified as H import Prettyprinter (line) pTransactionCmds @@ -55,13 +55,13 @@ pTransactionCmds envCli = [ pretty @String "Build a transaction (low-level, inconvenient)" , line , line - -- , H.yellow $ - -- mconcat - -- [ "Please note " - -- , H.underline "the order" - -- , " of some cmd options is crucial. If used incorrectly may produce " - -- , "undesired tx body. See nested [] notation above for details." - -- ] + , H.yellow $ + mconcat + [ "Please note " + , H.underline "the order" + , " of some cmd options is crucial. If used incorrectly may produce " + , "undesired tx body. See nested [] notation above for details." + ] ] , pTransactionBuildCmd envCli , pTransactionBuildEstimateCmd envCli @@ -179,13 +179,13 @@ pTransactionBuildCmd envCli = do [ pretty @String "Build a balanced transaction (automatically calculates fees)" , line , line - -- , H.yellow $ - -- mconcat - -- [ "Please note " - -- , H.underline "the order" - -- , " of some cmd options is crucial. If used incorrectly may produce " - -- , "undesired tx body. See nested [] notation above for details." - -- ] + , H.yellow $ + mconcat + [ "Please note " + , H.underline "the order" + , " of some cmd options is crucial. If used incorrectly may produce " + , "undesired tx body. See nested [] notation above for details." + ] ] where pCmd era' = do @@ -243,13 +243,13 @@ pTransactionBuildEstimateCmd _envCli = do "Build a balanced transaction without access to a live node (automatically estimates fees)" , line , line - -- , H.yellow $ - -- mconcat - -- [ "Please note " - -- , H.underline "the order" - -- , " of some cmd options is crucial. If used incorrectly may produce " - -- , "undesired tx body. See nested [] notation above for details." - -- ] + , H.yellow $ + mconcat + [ "Please note " + , H.underline "the order" + , " of some cmd options is crucial. If used incorrectly may produce " + , "undesired tx body. See nested [] notation above for details." + ] ] where pCmd :: Parser (TransactionCmds era) diff --git a/cardano-cli/src/Cardano/CLI/Option.hs b/cardano-cli/src/Cardano/CLI/Option.hs index 0c491c0f4d..328f78722f 100644 --- a/cardano-cli/src/Cardano/CLI/Option.hs +++ b/cardano-cli/src/Cardano/CLI/Option.hs @@ -25,14 +25,13 @@ import Cardano.CLI.EraIndependent.Node.Option import Cardano.CLI.EraIndependent.Ping.Option (parsePingCmd) import Cardano.CLI.Legacy.Option (parseLegacyCmds) import Cardano.CLI.Parser --- import Cardano.CLI.Render (customRenderHelp) +import Cardano.CLI.Render (customRenderHelp) import Cardano.CLI.Run (ClientCommand (..)) import Data.Foldable import Options.Applicative import Options.Applicative qualified as Opt - --- import Prettyprinter qualified as PP +import Prettyprinter qualified as PP opts :: EnvCli -> ParserInfo ClientCommand opts envCli = @@ -52,8 +51,8 @@ pref = Opt.prefs $ mconcat [ showHelpOnEmpty - -- , helpEmbedBriefDesc PP.align - -- , helpRenderHelp customRenderHelp + , helpEmbedBriefDesc PP.align + , helpRenderHelp customRenderHelp ] addressCmdsTopLevel :: EnvCli -> Parser ClientCommand diff --git a/cardano-cli/src/Cardano/CLI/Render.hs b/cardano-cli/src/Cardano/CLI/Render.hs index 69c8b2a563..d3043fd4ae 100644 --- a/cardano-cli/src/Cardano/CLI/Render.hs +++ b/cardano-cli/src/Cardano/CLI/Render.hs @@ -4,59 +4,61 @@ module Cardano.CLI.Render ) where +import Cardano.Api (textShow) + import Data.Text (Text) +import Data.Text qualified as T import Options.Applicative -import Options.Applicative.Help.Types (renderHelp) +import Options.Applicative.Help.Ann +import Options.Applicative.Help.Types (helpText, renderHelp) import Prettyprinter +import Prettyprinter.Render.Util.SimpleDocTree +import System.Environment qualified as IO +import System.IO.Unsafe qualified as IO --- import Cardano.Api (textShow) --- import Data.Text qualified as T --- import Options.Applicative.Help.Ann --- import Options.Applicative.Help.Types (helpText) --- import Prettyprinter.Render.Util.SimpleDocTree --- import System.Environment qualified as IO --- import System.IO.Unsafe qualified as IO --- --- cliHelpTraceEnabled :: Bool --- cliHelpTraceEnabled = IO.unsafePerformIO $ do --- mValue <- IO.lookupEnv "CLI_HELP_TRACE" --- return $ mValue == Just "1" --- {-# NOINLINE cliHelpTraceEnabled #-} --- +cliHelpTraceEnabled :: Bool +cliHelpTraceEnabled = IO.unsafePerformIO $ do + mValue <- IO.lookupEnv "CLI_HELP_TRACE" + return $ mValue == Just "1" +{-# NOINLINE cliHelpTraceEnabled #-} -- | Convert a help text to 'String'. When the CLI_HELP_TRACE environment variable is set -- to '1', the output will be in HTML so that it can be viewed in a browser where developer -- tools can be used to inspect tracing that aids in describing the structure of the output -- document. --- customRenderHelpAsHtml :: Int -> ParserHelp -> String --- customRenderHelpAsHtml cols = --- T.unpack --- . wrapper --- . renderSimplyDecorated id renderElement --- . treeForm --- . layoutSmart (LayoutOptions (AvailablePerLine cols 1.0)) --- . helpText --- where --- renderElement :: Ann -> Text -> Text --- renderElement ann x = --- if cliHelpTraceEnabled --- then case ann of --- AnnTrace _ name -> "" <> x <> "" --- AnnStyle _ -> x --- else x --- wrapper = --- if cliHelpTraceEnabled --- then --- id --- . ("\n" <>) --- . ("\n" <>) --- . ("
\n" <>)
---           . (<> "\n")
---           . (<> "\n")
---           . (<> "\n
") --- else id customRenderHelp :: Int -> ParserHelp -> String -customRenderHelp = customRenderHelpAsAnsi +customRenderHelp = + if cliHelpTraceEnabled + then customRenderHelpAsHtml + else customRenderHelpAsAnsi + +customRenderHelpAsHtml :: Int -> ParserHelp -> String +customRenderHelpAsHtml cols = + T.unpack + . wrapper + . renderSimplyDecorated id renderElement + . treeForm + . layoutSmart (LayoutOptions (AvailablePerLine cols 1.0)) + . helpText + where + renderElement :: Ann -> Text -> Text + renderElement ann x = + if cliHelpTraceEnabled + then case ann of + AnnTrace _ name -> "" <> x <> "" + AnnStyle _ -> x + else x + wrapper = + if cliHelpTraceEnabled + then + id + . ("\n" <>) + . ("\n" <>) + . ("
\n" <>)
+          . (<> "\n")
+          . (<> "\n")
+          . (<> "\n
") + else id customRenderHelpAsAnsi :: Int -> ParserHelp -> String customRenderHelpAsAnsi = renderHelp From f826af9753a2958ec8fedab729e2b8c8e1a08145 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferrai Date: Fri, 26 Jun 2026 18:03:45 +0300 Subject: [PATCH 06/13] Fix golden tests --- cabal.project | 16 ++--- cardano-cli/cardano-cli.cabal | 3 + .../EraBased/Genesis/CreateTestnetData/Run.hs | 46 +++++++----- .../src/Cardano/CLI/EraBased/Genesis/Run.hs | 71 +++++++++++-------- .../Test/Golden/CreateStaked.hs | 16 ++++- .../Test/Golden/CreateTestnetData.hs | 29 ++++++-- ...ustom-lovelace-supply-shelley-genesis.json | 11 +++ flake.lock | 6 +- 8 files changed, 131 insertions(+), 67 deletions(-) diff --git a/cabal.project b/cabal.project index ac267481c3..b36a69d24a 100644 --- a/cabal.project +++ b/cabal.project @@ -14,7 +14,7 @@ repository cardano-haskell-packages -- you need to run if you change them index-state: , hackage.haskell.org 2026-06-02T21:49:32Z - , cardano-haskell-packages 2026-06-02T21:14:32Z + , cardano-haskell-packages 2026-06-23T21:17:32Z packages: cardano-cli @@ -96,17 +96,11 @@ if impl(ghc >= 9.14) , with-utf8:base -- cabal-allow-newer end -source-repository-package - type: git - location: https://github.com/input-output-hk/optparse-applicative - tag: 074b90b38c0415f87023be84221a92be6e3cea0e - --sha256: sha256-Ffkx3/Ol1M0YjGJpyngex0Q+Qb1Ov1Er9WaAkLXuSSk= - source-repository-package type: git location: https://github.com/IntersectMBO/cardano-api.git - tag: bb64ad40f904040a9b4d99306cf13eef4650a6c9 - --sha256: sha256-302P+qj+UkY/uSWHt8YMT4VzNhRS9tWMz0G6rjr4eVk= + tag: a775a6a9d581e2216ebc31f27572f4ae1c499e48 + --sha256: sha256-U0UDIuhsDfJ4PDV1BqDTY7/2gWpf8c/Z2IVqUGMNhKQ= subdir: cardano-api @@ -158,8 +152,8 @@ source-repository-package source-repository-package type: git location: https://github.com/IntersectMBO/ouroboros-network.git - tag: 8b4dcb898b64615f574a7fbdcf119f77c7fbc598 - --sha256: sha256-t1tGV5uZwyKnSSCbaJJAteMYKnQYeO39hUUycMRuC2M= + tag: d7736b7c4c51f7328bd9462dc75df0c04a7b06d0 + --sha256: sha256-9sWmBNESHApZmwOi0CpSwn619NIw6/msvV5vH57eqx8= subdir: ./cardano-diffusion ./monoidal-synchronisation diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index 18e5339748..add22cacac 100644 --- a/cardano-cli/cardano-cli.cabal +++ b/cardano-cli/cardano-cli.cabal @@ -254,6 +254,7 @@ library cardano-ledger-conway, cardano-ledger-core, cardano-ledger-dijkstra, + cardano-ledger-shelley, cardano-prelude, cardano-protocol-tpraos, cardano-slotting ^>=0.2.0.0, @@ -440,6 +441,8 @@ test-suite cardano-cli-golden cardano-cli, cardano-cli:cardano-cli-test-lib, cardano-crypto-wrapper, + cardano-ledger-conway, + cardano-ledger-shelley, cardano-strict-containers ^>=0.1, cborg, directory, diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Genesis/CreateTestnetData/Run.hs b/cardano-cli/src/Cardano/CLI/EraBased/Genesis/CreateTestnetData/Run.hs index 9da22e9bf4..76a778f50d 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Genesis/CreateTestnetData/Run.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Genesis/CreateTestnetData/Run.hs @@ -60,6 +60,8 @@ import Cardano.CLI.Type.Error.NodeCmdError import Cardano.CLI.Type.Error.StakePoolCmdError import Cardano.CLI.Type.Key import Cardano.Crypto.Hash qualified as Crypto +import Cardano.Ledger.Conway.Genesis (ConwayExtraConfig (..)) +import Cardano.Ledger.Shelley.Genesis (InjectionData (..), ShelleyExtraConfig (..)) import Cardano.Prelude (canonicalEncodePretty) import Cardano.Protocol.Crypto qualified as C @@ -488,8 +490,16 @@ runGenesisCreateTestNetDataCmd cgInitialDReps <- initialDReps (L.ucppDRepDeposit $ L.cgUpgradePParams conwayGenesis) dRepKeys pure $ conwayGenesis - { L.cgDelegs = delegs (zip stakingKeys (case dRepKeys of [] -> []; _ -> cycle dRepKeys)) - , L.cgInitialDReps + { L.cgDelegs = mempty + , L.cgInitialDReps = mempty + , L.cgExtraConfig = + L.SJust + ConwayExtraConfig + { cecDelegs = + EmbeddedInjection $ + delegs (zip stakingKeys (case dRepKeys of [] -> []; _ -> cycle dRepKeys)) + , cecInitialDReps = EmbeddedInjection cgInitialDReps + } } where delegs @@ -523,7 +533,7 @@ runGenesisCreateTestNetDataCmd , L.drepAnchor = SNothing , L.drepDeposit , L.drepDelegs = Set.empty -- We don't need to populate this field (field "initialDReps"."keyHash-*"."delegators" in the JSON) - -- because its content is derived from the "delegs" field ("cgDelegs" above). In other words, when the Conway genesis is applied, + -- because its content is derived from the "delegs" field ("cecDelegs" above). In other words, when the Conway genesis is applied, -- DRep delegations are computed from the "delegs" field. In the future the "delegators" field may -- be omitted altogether from the JSON representation, but it remains in the Haskell type. -- More details are provided here: https://github.com/IntersectMBO/cardano-ledger/issues/4782 @@ -875,20 +885,24 @@ updateOutputTemplate { sgSystemStart , sgMaxLovelaceSupply = totalSupply , sgGenDelegs = shelleyDelKeys - , sgInitialFunds = - fromList - [ (toShelleyAddr addr, v) - | (addr, v) <- - distribute nonDelegCoin nUtxoAddrsNonDeleg utxoAddrsNonDeleg - ++ distribute delegCoin nUtxoAddrsDeleg utxoAddrsDeleg - ++ mkStuffedUtxo stuffedUtxoAddrs - ] - , sgStaking = - ShelleyGenesisStaking - { sgsPools = ListMap pools - , sgsStake = ListMap stake - } + , sgInitialFunds = mempty + , sgStaking = mempty , sgProtocolParams + , sgExtraConfig = + L.SJust + ShelleyExtraConfig + { secInitialFunds = + EmbeddedInjection $ + fromList + [ (toShelleyAddr addr, v) + | (addr, v) <- + distribute nonDelegCoin nUtxoAddrsNonDeleg utxoAddrsNonDeleg + ++ distribute delegCoin nUtxoAddrsDeleg utxoAddrsDeleg + ++ mkStuffedUtxo stuffedUtxoAddrs + ] + , secStakePools = EmbeddedInjection (ListMap pools) + , secStakeCredentials = EmbeddedInjection (ListMap stake) + } } where nonDelegCoin = getCoinForDistribution nonDelegCoinRaw diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Genesis/Run.hs b/cardano-cli/src/Cardano/CLI/EraBased/Genesis/Run.hs index 5ee356a133..093c768e38 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Genesis/Run.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Genesis/Run.hs @@ -69,6 +69,7 @@ import Cardano.Crypto qualified as CC import Cardano.Crypto.Hash qualified as Crypto import Cardano.Crypto.Signing qualified as Byron import Cardano.Ledger.BaseTypes (unNonZero) +import Cardano.Ledger.Shelley.Genesis (InjectionData (..), ShelleyExtraConfig (..)) import Cardano.Protocol.Crypto qualified as C import Control.DeepSeq (NFData, force) @@ -795,20 +796,24 @@ updateOutputTemplate { sgSystemStart , sgMaxLovelaceSupply = fromIntegral $ nonDelegCoin + delegCoin , sgGenDelegs = shelleyDelKeys - , sgInitialFunds = - fromList - [ (toShelleyAddr addr, v) - | (addr, v) <- - distribute (nonDelegCoin - subtractForTreasury) nUtxoAddrsNonDeleg utxoAddrsNonDeleg - ++ distribute (delegCoin - subtractForTreasury) nUtxoAddrsDeleg utxoAddrsDeleg - ++ mkStuffedUtxo stuffedUtxoAddrs - ] - , sgStaking = - ShelleyGenesisStaking - { sgsPools = ListMap pools - , sgsStake = ListMap stake - } + , sgInitialFunds = mempty + , sgStaking = mempty , sgProtocolParams + , sgExtraConfig = + L.SJust + ShelleyExtraConfig + { secInitialFunds = + EmbeddedInjection $ + fromList + [ (toShelleyAddr addr, v) + | (addr, v) <- + distribute (nonDelegCoin - subtractForTreasury) nUtxoAddrsNonDeleg utxoAddrsNonDeleg + ++ distribute (delegCoin - subtractForTreasury) nUtxoAddrsDeleg utxoAddrsDeleg + ++ mkStuffedUtxo stuffedUtxoAddrs + ] + , secStakePools = EmbeddedInjection (ListMap pools) + , secStakeCredentials = EmbeddedInjection (ListMap stake) + } } where maximumLovelaceSupply :: Word64 @@ -1114,24 +1119,30 @@ updateTemplate { sgSystemStart = start , sgMaxLovelaceSupply = fromIntegral $ nonDelegCoin + delegCoin , sgGenDelegs = shelleyDelKeys - , sgInitialFunds = - fromList - [ (toShelleyAddr addr, v) - | (addr, v) <- - distribute (nonDelegCoin - subtractForTreasury) utxoAddrsNonDeleg - ++ distribute (delegCoin - subtractForTreasury) utxoAddrsDeleg - ++ mkStuffedUtxo stuffedUtxoAddrs - ] - , sgStaking = - ShelleyGenesisStaking - { sgsPools = - fromList - [ (L.sppId poolParams, poolParams) - | poolParams <- Map.elems poolSpecs - ] - , sgsStake = ListMap.fromMap $ L.sppId <$> poolSpecs - } + , sgInitialFunds = mempty + , sgStaking = mempty , sgProtocolParams = pparamsFromTemplate + , sgExtraConfig = + L.SJust + ShelleyExtraConfig + { secInitialFunds = + EmbeddedInjection $ + fromList + [ (toShelleyAddr addr, v) + | (addr, v) <- + distribute (nonDelegCoin - subtractForTreasury) utxoAddrsNonDeleg + ++ distribute (delegCoin - subtractForTreasury) utxoAddrsDeleg + ++ mkStuffedUtxo stuffedUtxoAddrs + ] + , secStakePools = + EmbeddedInjection $ + fromList + [ (L.sppId poolParams, poolParams) + | poolParams <- Map.elems poolSpecs + ] + , secStakeCredentials = + EmbeddedInjection (ListMap.fromMap $ L.sppId <$> poolSpecs) + } } shelleyGenesis where diff --git a/cardano-cli/test/cardano-cli-golden/Test/Golden/CreateStaked.hs b/cardano-cli/test/cardano-cli-golden/Test/Golden/CreateStaked.hs index 154fb83563..b12cb3b66b 100644 --- a/cardano-cli/test/cardano-cli-golden/Test/Golden/CreateStaked.hs +++ b/cardano-cli/test/cardano-cli-golden/Test/Golden/CreateStaked.hs @@ -3,11 +3,15 @@ module Test.Golden.CreateStaked where import Cardano.Api +import Cardano.Api.Ledger (StrictMaybe (..)) + +import Cardano.Ledger.Shelley.Genesis (InjectionData (..), ShelleyExtraConfig (..)) import Control.Monad (filterM, void) import Data.Aeson qualified as Aeson import Data.ByteString.Lazy qualified as LBS import Data.List (intercalate, sort) +import GHC.Exts (IsList (..)) import System.Directory import System.FilePath @@ -29,6 +33,10 @@ tree root = do subTrees <- mapM tree subs return $ files ++ concat subTrees +injectionToList :: InjectionData k v -> [(k, v)] +injectionToList (EmbeddedInjection lm) = toList lm +injectionToList _ = [] + hprop_golden_create_staked :: Property hprop_golden_create_staked = watchdogProp . propertyOnce $ moduleWorkspace "tmp" $ \tempDir -> do @@ -88,5 +96,9 @@ hprop_golden_create_staked = genesis :: ShelleyGenesis <- Aeson.throwDecode bs H.assert (sgNetworkMagic genesis == networkMagic) - H.assert ((length . sgsPools . sgStaking $ genesis) == numPools) - H.assert ((length . sgsStake . sgStaking $ genesis) == numStake) + + extraConfig <- case sgExtraConfig genesis of + SJust ec -> pure ec + SNothing -> H.failure + H.assert (length (injectionToList (secStakePools extraConfig)) == numPools) + H.assert (length (injectionToList (secStakeCredentials extraConfig)) == numStake) diff --git a/cardano-cli/test/cardano-cli-golden/Test/Golden/CreateTestnetData.hs b/cardano-cli/test/cardano-cli-golden/Test/Golden/CreateTestnetData.hs index dcdc01cd4b..8a7c53ac91 100644 --- a/cardano-cli/test/cardano-cli-golden/Test/Golden/CreateTestnetData.hs +++ b/cardano-cli/test/cardano-cli-golden/Test/Golden/CreateTestnetData.hs @@ -8,6 +8,9 @@ import Cardano.Api import Cardano.Api.Ledger (ConwayGenesis (..)) import Cardano.Api.Ledger qualified as L +import Cardano.Ledger.Conway.Genesis (ConwayExtraConfig (..)) +import Cardano.Ledger.Shelley.Genesis (InjectionData (..), ShelleyExtraConfig (..)) + import Control.Monad import Data.List (intercalate, sort) import Data.Sequence.Strict qualified as Seq @@ -77,6 +80,10 @@ tree root = do subTrees <- mapM tree subs return $ files ++ concat subTrees +injectionToList :: InjectionData k v -> [(k, v)] +injectionToList (EmbeddedInjection lm) = toList lm +injectionToList _ = [] + -- Execute this test with: -- @cabal test cardano-cli-golden --test-options '-p "/golden create testnet data/"'@ hprop_golden_create_testnet_data :: Property @@ -128,9 +135,14 @@ golden_create_testnet_data mShelleyTemplate = H.readJsonFileOk $ outputDir "shelley-genesis.json" sgNetworkMagic shelleyGenesis H.=== networkMagic - length (L.sgsPools $ sgStaking shelleyGenesis) H.=== numPools - forM_ (L.sgsPools $ sgStaking shelleyGenesis) $ \pool -> + shelleyExtraConfig <- case sgExtraConfig shelleyGenesis of + L.SJust ec -> pure ec + L.SNothing -> H.failure + let pools = injectionToList (secStakePools shelleyExtraConfig) + length pools H.=== numPools + + forM_ pools $ \(_, pool) -> Seq.length (L.sppRelays pool) H.=== 1 actualNumCCs <- liftIO $ listDirectories $ outputDir "cc-keys" @@ -147,9 +159,13 @@ golden_create_testnet_data mShelleyTemplate = length (L.committeeMembers $ cgCommittee conwayGenesis) H.=== numCommitteeKeys - length (cgInitialDReps conwayGenesis) H.=== numDReps + conwayExtraConfig <- case cgExtraConfig conwayGenesis of + L.SJust ec -> pure ec + L.SNothing -> H.failure + + length (injectionToList (cecInitialDReps conwayExtraConfig)) H.=== numDReps - length (cgDelegs conwayGenesis) H.=== numStakeDelegs + length (injectionToList (cecDelegs conwayExtraConfig)) H.=== numStakeDelegs -- Execute this test with: -- @cabal test cardano-cli-golden --test-options '-p "/golden create testnet data deleg non deleg/"'@ @@ -179,7 +195,10 @@ hprop_golden_create_testnet_data_deleg_non_deleg = -- Because we don't test this elsewhere in this file: sgMaxLovelaceSupply genesis H.=== fromIntegral totalSupply - let initialFunds = toList $ sgInitialFunds genesis + extraConfig <- case sgExtraConfig genesis of + L.SJust ec -> pure ec + L.SNothing -> H.failure + let initialFunds = injectionToList (secInitialFunds extraConfig) -- This checks that there is actually only one funded address length initialFunds H.=== 1 diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/conway/custom-lovelace-supply-shelley-genesis.json b/cardano-cli/test/cardano-cli-golden/files/golden/conway/custom-lovelace-supply-shelley-genesis.json index 4a80e5579c..9016b27cec 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/conway/custom-lovelace-supply-shelley-genesis.json +++ b/cardano-cli/test/cardano-cli-golden/files/golden/conway/custom-lovelace-supply-shelley-genesis.json @@ -1,6 +1,17 @@ { "activeSlotsCoeff": 0.99, "epochLength": 21600, + "extraConfig": { + "initialFunds": { + "data": {} + }, + "stakeCredentials": { + "data": {} + }, + "stakePools": { + "data": {} + } + }, "genDelegs": "", "initialFunds": {}, "maxKESEvolutions": 1080000, diff --git a/flake.lock b/flake.lock index 6d0ead243c..ad241ec27c 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "CHaP": { "flake": false, "locked": { - "lastModified": 1780436322, - "narHash": "sha256-3YDsDhjAcm5QatdluTKuQ9WeDdwrxZMnKH587pVyv9o=", + "lastModified": 1782403175, + "narHash": "sha256-vlajHUGiEHUMmWQyJQI3ziq5faST+oIG88ZfGs1qHNE=", "owner": "intersectmbo", "repo": "cardano-haskell-packages", - "rev": "bc93f1caabfdc4d38c5b44e6eea8f5b8f535775a", + "rev": "8a35d09d5f3f43da9caf8b53285c26108e64045e", "type": "github" }, "original": { From 44fe2bc491e73b66bbd1d08f651d4c57f7c7e862 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferrai Date: Tue, 30 Jun 2026 15:14:00 +0300 Subject: [PATCH 07/13] Update srps --- cabal.project | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cabal.project b/cabal.project index b36a69d24a..92dc6d19c7 100644 --- a/cabal.project +++ b/cabal.project @@ -107,8 +107,8 @@ source-repository-package source-repository-package type: git location: https://github.com/IntersectMBO/cardano-ledger.git - tag: 8dc1c431e06db2c8b5d44fb4b3cca6419197d763 - --sha256: sha256-xKtgNFxjbJE6UWGvTioGX81NgvlKH3mHEaYMWDm8/UA= + tag: 245e63dcd335e3ca29823609e4aaa8f5f096a425 + --sha256: sha256-chsapfNnY/V7y1snBzjP0LSVnYl/Axt6GjahTPNOKj0= subdir: eras/allegra/impl eras/alonzo/impl @@ -152,8 +152,8 @@ source-repository-package source-repository-package type: git location: https://github.com/IntersectMBO/ouroboros-network.git - tag: d7736b7c4c51f7328bd9462dc75df0c04a7b06d0 - --sha256: sha256-9sWmBNESHApZmwOi0CpSwn619NIw6/msvV5vH57eqx8= + tag: 66dcc42e550cc7e1536a839902edb1985b1ac09f + --sha256: sha256-4nPl4QZ+2VYUrKQg773B0wvDvyOnBRSDyNJ92WB2Vtk= subdir: ./cardano-diffusion ./monoidal-synchronisation From 134c5463bfec220cb696bce2a84ef29436416c90 Mon Sep 17 00:00:00 2001 From: Marcin Szamotulski Date: Fri, 26 Jun 2026 10:52:33 +0200 Subject: [PATCH 08/13] cardano-cli ping - using cardano-diffusion:ping parser --- ...5_145525_cardano-cli_work_prepare_11_1.yml | 41 ++++++ cabal.project | 5 +- cardano-cli/cardano-cli.cabal | 1 - .../CLI/EraIndependent/Ping/Command.hs | 36 +---- .../Cardano/CLI/EraIndependent/Ping/Option.hs | 90 +----------- .../Cardano/CLI/EraIndependent/Ping/Run.hs | 128 +----------------- flake.lock | 6 +- 7 files changed, 61 insertions(+), 246 deletions(-) create mode 100644 .changes/20260625_145525_cardano-cli_work_prepare_11_1.yml diff --git a/.changes/20260625_145525_cardano-cli_work_prepare_11_1.yml b/.changes/20260625_145525_cardano-cli_work_prepare_11_1.yml new file mode 100644 index 0000000000..b5ba6a6527 --- /dev/null +++ b/.changes/20260625_145525_cardano-cli_work_prepare_11_1.yml @@ -0,0 +1,41 @@ +description: |- + new `cardano-cli ping` api + + `cardano-cli ping` allows now to ping multiple servers, does domain name + resolution and supports SRV records (as specified in + https://cips.cardano.org/cip/CIP-0155) + + Some examples: + + Run a ping against two ip addresses, ipv4 & ipv6 + ```bash + cardano-cli ping 127.0.0.1:3001 [::1]:3001 + ``` + + Run a ping against a domain name: + ```bash + cardano-cli ping my.domain.com:3001 + ``` + + Run a ping against an SRV domain. + According to CIP#0155 the SRV record needs to be registered at + `_cardano._tcp.srv.domain.com` + ```bash + cardano-cli ping srv.domain.com + ``` + + Run a ping against unix socket + ```bash + cardano-cli ping /var/run/cardano-node.socket + ``` + + `cardano-cli` ping has three modes of operation: + + * ping mode: `--mode ping` (the default) + * tip mode `--mode tip` + * query handshake parameters: `--mode query` +kind: +- breaking +- feature +pr: 1391 +project: cardano-cli diff --git a/cabal.project b/cabal.project index 92dc6d19c7..4b61dffb84 100644 --- a/cabal.project +++ b/cabal.project @@ -14,7 +14,7 @@ repository cardano-haskell-packages -- you need to run if you change them index-state: , hackage.haskell.org 2026-06-02T21:49:32Z - , cardano-haskell-packages 2026-06-23T21:17:32Z + , cardano-haskell-packages 2026-06-29T12:05:19Z packages: cardano-cli @@ -56,6 +56,9 @@ package text package formatting flags: +no-double-conversion +package cardano-diffusion + flags: +optparse-applicative-fork + tests: True test-show-details: direct diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index add22cacac..53b3bb6146 100644 --- a/cardano-cli/cardano-cli.cabal +++ b/cardano-cli/cardano-cli.cabal @@ -274,7 +274,6 @@ library http-client, http-client-tls, http-types, - io-classes, iproute, microlens, mmorph, diff --git a/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Command.hs b/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Command.hs index 4d8732f365..db2eee6f39 100644 --- a/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Command.hs +++ b/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Command.hs @@ -1,38 +1,12 @@ module Cardano.CLI.EraIndependent.Ping.Command - ( EndPoint (..) - , PingCmd (..) - , getConfigurationError + ( PingCmd (..) + , Address ) where -import Data.Word - -data EndPoint - = HostEndPoint String - | UnixSockEndPoint String - deriving (Eq, Show) +import Cardano.Network.Ping data PingCmd = PingCmd - { pingCmdCount :: !Word32 - , pingCmdEndPoint :: !EndPoint - , pingCmdPort :: !String - , pingCmdMagic :: !Word32 - , pingCmdJson :: !Bool - , pingCmdQuiet :: !Bool - , pingOptsHandshakeQuery :: !Bool - , pingOptsGetTip :: !Bool + { pingOpts :: PingOpts + , pingAddresses :: [Address (Unresolved SRVOrFilePathUnresolved)] } - deriving (Eq, Show) - -getConfigurationError :: PingCmd -> Maybe String -getConfigurationError - PingCmd - { pingCmdEndPoint = endPoint - , pingOptsGetTip = getTip - , pingOptsHandshakeQuery = query - } = - case endPoint of - UnixSockEndPoint{} - | query || getTip -> Nothing - | otherwise -> Just "Unix sockets only support queries for available versions or a tip." - HostEndPoint{} -> Nothing diff --git a/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Option.hs b/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Option.hs index 6743ebaddf..021d821645 100644 --- a/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Option.hs +++ b/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Option.hs @@ -6,9 +6,8 @@ module Cardano.CLI.EraIndependent.Ping.Option where import Cardano.CLI.Command (ClientCommand (CliPingCommand)) -import Cardano.CLI.EraBased.Common.Option (integralReader) import Cardano.CLI.EraIndependent.Ping.Command -import Cardano.Network.Ping qualified as CNP +import Cardano.Network.Ping qualified as Ping import Control.Applicative import Options.Applicative qualified as Opt @@ -25,90 +24,5 @@ parsePingCmd = , PP.pretty @String "It negotiates a handshake and keeps sending keep alive messages." ] -pHost :: Opt.Parser String -pHost = - Opt.strOption $ - mconcat - [ Opt.long "host" - , Opt.short 'h' - , Opt.metavar "HOST" - , Opt.help "Hostname/IP, e.g. relay.iohk.example." - ] - -pUnixSocket :: Opt.Parser String -pUnixSocket = - Opt.strOption $ - mconcat - [ Opt.long "unixsock" - , Opt.short 'u' - , Opt.metavar "SOCKET" - , Opt.help "Unix socket, e.g. file.socket." - ] - -pEndPoint :: Opt.Parser EndPoint -pEndPoint = fmap HostEndPoint pHost <|> fmap UnixSockEndPoint pUnixSocket - pPing :: Opt.Parser PingCmd -pPing = - PingCmd - <$> ( Opt.option integralReader $ - mconcat - [ Opt.long "count" - , Opt.short 'c' - , Opt.metavar "COUNT" - , Opt.help $ - mconcat - [ "Stop after sending count requests and receiving count responses. " - , "If this option is not specified, ping will operate until interrupted. " - ] - , Opt.value maxBound - ] - ) - <*> pEndPoint - <*> ( Opt.strOption $ - mconcat - [ Opt.long "port" - , Opt.short 'p' - , Opt.metavar "PORT" - , Opt.help "Port number, e.g. 1234." - , Opt.value "3001" - ] - ) - <*> ( Opt.option integralReader $ - mconcat - [ Opt.long "magic" - , Opt.short 'm' - , Opt.metavar "MAGIC" - , Opt.help "Network magic." - , Opt.value (CNP.unNetworkMagic CNP.mainnetMagic) - ] - ) - <*> ( Opt.switch $ - mconcat - [ Opt.long "json" - , Opt.short 'j' - , Opt.help "JSON output flag." - ] - ) - <*> ( Opt.switch $ - mconcat - [ Opt.long "quiet" - , Opt.short 'q' - , Opt.help "Quiet flag, CSV/JSON only output" - ] - ) - <*> ( Opt.switch $ - mconcat - [ Opt.long "query-versions" - , Opt.short 'Q' - , Opt.help - "Query the supported protocol versions using the handshake protocol and terminate the connection." - ] - ) - <*> ( Opt.switch $ - mconcat - [ Opt.long "tip" - , Opt.short 't' - , Opt.help "Request tip then exit." - ] - ) +pPing = uncurry PingCmd <$> Ping.cmdlineParser diff --git a/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs b/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs index 8c0e8127ab..a3220bfe58 100644 --- a/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs +++ b/cardano-cli/src/Cardano/CLI/EraIndependent/Ping/Run.hs @@ -1,133 +1,17 @@ -{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE RankNTypes #-} module Cardano.CLI.EraIndependent.Ping.Run - ( PingClientCmdError (..) - , renderPingClientCmdError - , runPingCmd + ( runPingCmd ) where import Cardano.Api -import Cardano.CLI.Compatible.Exception +import Cardano.CLI.Compatible.Exception (CIO) import Cardano.CLI.EraIndependent.Ping.Command -import Cardano.Network.Ping qualified as CNP - -import Control.Exception (SomeException, toException) -import Control.Monad (unless) -import Control.Monad.Class.MonadAsync (mapConcurrently) -import Control.Tracer (mkTracer) -import Data.Aeson qualified as Aeson -import Data.Aeson.Text (encodeToLazyText) -import Data.List qualified as L -import Data.List qualified as List -import Data.Text qualified as T -import Data.Text.Lazy qualified as TL -import Data.Text.Lazy.IO qualified as TLIO -import Network.Socket (AddrInfo) -import Network.Socket qualified as Socket -import System.IO qualified as IO -import Text.Printf (printf) - -data PingClientCmdError - = PingClientCmdError [(AddrInfo, SomeException)] - | PingClientMisconfigurationError String - deriving Show - -instance Error PingClientCmdError where - prettyError = renderPingClientCmdError +import Cardano.Network.Ping qualified as Ping runPingCmd :: PingCmd -> CIO e () -runPingCmd options - | Just err <- getConfigurationError options = - throwCliError $ PingClientMisconfigurationError err -runPingCmd options = do - let hints = Socket.defaultHints{Socket.addrSocketType = Socket.Stream} - - addresses <- case pingCmdEndPoint options of - HostEndPoint host -> - liftIO $ Socket.getAddrInfo (Just hints) (Just host) (Just (pingCmdPort options)) - UnixSockEndPoint fname -> - pure - [ Socket.AddrInfo - [] - Socket.AF_UNIX - Socket.Stream - Socket.defaultProtocol - (Socket.SockAddrUnix fname) - Nothing - ] - - let stdout = mkTracer (TLIO.putStrLn . renderLogMsg (pingCmdJson options)) - stderr = mkTracer (IO.hPutStrLn IO.stderr . renderPingWarning) - - res <- - liftIO $ - mapConcurrently - (\addr -> (,) addr <$> CNP.pingClient stdout stderr (toPingOpts options) addr) - addresses - - case L.foldl' partition ([], []) res of - ([], _) -> pure () - (es, []) -> throwCliError $ PingClientCmdError es - (es, _) -> unless (pingCmdQuiet options) $ mapM_ (liftIO . IO.hPrint IO.stderr) es - where - partition - :: ([(AddrInfo, SomeException)], [AddrInfo]) - -> (AddrInfo, Either CNP.PingClientException ()) - -> ([(AddrInfo, SomeException)], [AddrInfo]) - partition (es, as) (a, Left e) = ((a, toException e) : es, as) - partition (es, as) (a, Right _) = (es, a : as) - -toPingOpts :: PingCmd -> CNP.PingOpts -toPingOpts cmd = - CNP.PingOpts - { CNP.pingOptsCount = pingCmdCount cmd - , CNP.pingOptsMagic = CNP.NetworkMagic (pingCmdMagic cmd) - , CNP.pingOptsJson = if pingCmdJson cmd then CNP.AsJSON else CNP.AsText - , CNP.pingOptsQuiet = pingCmdQuiet cmd - , CNP.pingOptsMode = - if pingOptsGetTip cmd - then CNP.TipMode - else - if pingOptsHandshakeQuery cmd - then CNP.QueryMode - else CNP.PingMode - , -- cardano-cli has no flags for these yet, so use network's own defaults. - CNP.pingOptsSRVPrefix = "_cardano._tcp" - , CNP.pingOptsColor = CNP.ColorAuto - } - --- | Format a ping log message. Mirrors the network library's internal --- @format@/@ToText@ helpers, which are not exported. -renderLogMsg :: Bool -> CNP.WithHost CNP.LogMsg -> TL.Text -renderLogMsg True msg = encodeToLazyText (Aeson.toJSON msg) -renderLogMsg False (CNP.WithHost host logMsg) = - TL.pack (printf "%-47s" (show host <> ", ")) <> renderLogMsgText logMsg - -renderLogMsgText :: CNP.LogMsg -> TL.Text -renderLogMsgText = \case - CNP.LogChainSyncTip tip -> TL.pack (show tip) - CNP.LogStatPoint point -> TL.pack (show point) - CNP.LogNodeToClientVersionData version versionData -> - TL.pack (unwords [show version, either T.unpack show versionData]) - CNP.LogNodeToNodeVersionData version versionData -> - TL.pack (unwords [show version, either T.unpack show versionData]) - --- | Format a ping warning. Mirrors the network library's internal --- @formatPingWarning@, which is not exported. -renderPingWarning :: CNP.PingWarning -> String -renderPingWarning = \case - CNP.FilePathDoesNotExist path -> "WARNING: file path " <> show path <> " does not exist" - CNP.DNSError domain err -> "WARNING: dns: " <> show domain <> " " <> show err - CNP.DNSResolution domain ips port -> - show domain <> ": " <> List.intercalate ", " [show ip <> ":" <> show port | ip <- ips] - CNP.MissingPort ip -> "WARNING: missing port for " <> show ip - CNP.Error err -> "WARNING: " <> show err - CNP.ConnectError sockAddr err -> "WARNING: " <> show sockAddr <> " " <> show err - -renderPingClientCmdError :: PingClientCmdError -> Doc ann -renderPingClientCmdError = \case - PingClientCmdError es -> mconcat $ List.intersperse "\n" $ pshow <$> es - PingClientMisconfigurationError err -> pretty err +runPingCmd PingCmd{pingOpts, pingAddresses} = + liftIO $ Ping.pingClients pingOpts pingAddresses diff --git a/flake.lock b/flake.lock index ad241ec27c..e636828240 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "CHaP": { "flake": false, "locked": { - "lastModified": 1782403175, - "narHash": "sha256-vlajHUGiEHUMmWQyJQI3ziq5faST+oIG88ZfGs1qHNE=", + "lastModified": 1782769557, + "narHash": "sha256-tCYMTwH15mNajHybvC3KGVPBPMlLlqIOYE0ZgcqRkJU=", "owner": "intersectmbo", "repo": "cardano-haskell-packages", - "rev": "8a35d09d5f3f43da9caf8b53285c26108e64045e", + "rev": "3ee6b1ecce230d62f0083590f38c4ae3457da226", "type": "github" }, "original": { From f18aed13783974f957eaf19b5fa3c67dfbaab1ca Mon Sep 17 00:00:00 2001 From: Fabrizio Ferrai Date: Tue, 30 Jun 2026 16:04:21 +0300 Subject: [PATCH 09/13] Update network srp --- cabal.project | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cabal.project b/cabal.project index 4b61dffb84..076645d374 100644 --- a/cabal.project +++ b/cabal.project @@ -155,8 +155,8 @@ source-repository-package source-repository-package type: git location: https://github.com/IntersectMBO/ouroboros-network.git - tag: 66dcc42e550cc7e1536a839902edb1985b1ac09f - --sha256: sha256-4nPl4QZ+2VYUrKQg773B0wvDvyOnBRSDyNJ92WB2Vtk= + tag: b47dbc2c29108e593cc47524cffb75008b88fe90 + --sha256: sha256-7TwcI1/m6aEBmiGYPXKHbIWlxzRja4qFyqr+apcR9p4= subdir: ./cardano-diffusion ./monoidal-synchronisation From 7826047f6cdc9d0c86b3753a9c7bb5a27b799072 Mon Sep 17 00:00:00 2001 From: Marcin Szamotulski Date: Thu, 25 Jun 2026 13:01:07 +0200 Subject: [PATCH 10/13] pSingHostAddress - require port number The port number for a single host address must be given. Otherwise one should use an SRV record. --- cardano-cli/src/Cardano/CLI/EraBased/Common/Option.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Common/Option.hs b/cardano-cli/src/Cardano/CLI/EraBased/Common/Option.hs index 2da5c31d0f..b206a960aa 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Common/Option.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Common/Option.hs @@ -2627,7 +2627,7 @@ pMultiHostName = pSingleHostName :: Parser StakePoolRelay pSingleHostName = - StakePoolRelayDnsARecord <$> pDNSName <*> optional pPort + StakePoolRelayDnsARecord <$> pDNSName <*> (Just <$> pPort) where pDNSName :: Parser ByteString pDNSName = From 714f30ec596b881b71e5f472c80f66c2b35fc9b5 Mon Sep 17 00:00:00 2001 From: Marcin Szamotulski Date: Thu, 25 Jun 2026 12:57:30 +0200 Subject: [PATCH 11/13] cardano-cli stake-pool registration Validate address information passed through: * --single-host-pool-relay, --pool-relay-port * --multip-host-pool-relay with `cardano-diffusion:ping`. --- .../Cardano/CLI/Compatible/StakePool/Run.hs | 50 ++++++++++++++++++- .../src/Cardano/CLI/EraBased/StakePool/Run.hs | 29 +++++++++++ .../CLI/Type/Error/StakePoolCmdError.hs | 10 ++++ 3 files changed, 88 insertions(+), 1 deletion(-) diff --git a/cardano-cli/src/Cardano/CLI/Compatible/StakePool/Run.hs b/cardano-cli/src/Cardano/CLI/Compatible/StakePool/Run.hs index adc8ce7e7c..0e9b3edcb5 100644 --- a/cardano-cli/src/Cardano/CLI/Compatible/StakePool/Run.hs +++ b/cardano-cli/src/Cardano/CLI/Compatible/StakePool/Run.hs @@ -6,13 +6,18 @@ module Cardano.CLI.Compatible.StakePool.Run ( runCompatibleStakePoolCmds + , stakePoolRelayToAddr ) where import Cardano.Api import Cardano.Api.Compatible.Certificate import Cardano.Api.Experimental qualified as Exp -import Cardano.Api.Experimental.Certificate (StakePoolParameters (..), toShelleyPoolParams) +import Cardano.Api.Experimental.Certificate + ( StakePoolParameters (..) + , StakePoolRelay (..) + , toShelleyPoolParams + ) import Cardano.CLI.Compatible.Exception import Cardano.CLI.Compatible.StakePool.Command @@ -23,8 +28,12 @@ import Cardano.CLI.Read import Cardano.CLI.Type.Common import Cardano.CLI.Type.Error.StakePoolCmdError import Cardano.CLI.Type.Key (readVerificationKeyOrFile) +import Cardano.Network.Ping qualified as Ping import Control.Monad +import Control.Tracer (nullTracer, (>$<)) +import Data.ByteString.Char8 qualified as BSC +import Data.IP (IP (..)) runCompatibleStakePoolCmds :: () @@ -53,6 +62,31 @@ runStakePoolRegistrationCertificateCmd , outFile } = shelleyBasedEraConstraints sbe $ do + let pingOpts = + Ping.PingOpts + { Ping.pingOptsCount = 1 + , Ping.pingOptsMagic = toNetworkMagic network + , Ping.pingOptsJson = Ping.AsText + , Ping.pingOptsQuiet = True + , Ping.pingOptsSRVPrefix = "_cardano._tcp" + , Ping.pingOptsColor = Ping.ColorNever + , Ping.pingOptsMode = Ping.TipMode + } + pingErrs <- liftIO $ do + stderr <- Ping.mkStdErrTracer + headerTracer <- Ping.mkHeaderTracer pingOpts stderr + Ping.pingClients' + (Ping.format Ping.AsText >$< stderr) + nullTracer + headerTracer + (Ping.toText >$< stderr) + pingOpts + Ping.AddressIsNotAFilePath + (concatMap stakePoolRelayToAddr relays) + + unless (null pingErrs) $ + throwCliError (StakePoolCmdRelayPingErrors pingErrs) + -- Pool verification key stakePoolVerKey <- getVerificationKeyFromStakePoolVerificationKeySource poolVerificationKeyOrFile let stakePoolId' = anyStakePoolVerificationKeyHash stakePoolVerKey @@ -100,3 +134,17 @@ runStakePoolRegistrationCertificateCmd where registrationCertDesc :: TextEnvelopeDescr registrationCertDesc = "Stake Pool Registration Certificate" + +stakePoolRelayToAddr + :: StakePoolRelay + -> [Ping.Address (Ping.Unresolved Ping.SRVOrFilePathUnresolved)] +stakePoolRelayToAddr (StakePoolRelayIp (Just ipv4) Nothing (Just port)) = [Ping.IP (IPv4 ipv4) (fromIntegral port)] +stakePoolRelayToAddr (StakePoolRelayIp Nothing (Just ipv6) (Just port)) = [Ping.IP (IPv6 ipv6) (fromIntegral port)] +stakePoolRelayToAddr (StakePoolRelayIp (Just ipv4) (Just ipv6) (Just port)) = [Ping.IP (IPv6 ipv6) (fromIntegral port), Ping.IP (IPv4 ipv4) (fromIntegral port)] +-- the pSingHostAddress parser always includes a port number +stakePoolRelayToAddr (StakePoolRelayIp _ _ Nothing) = error "unexpected happend" +-- the pSingHostAddress parser always includes at least one ip address +stakePoolRelayToAddr (StakePoolRelayIp Nothing Nothing _) = error "unexpected happend" +stakePoolRelayToAddr (StakePoolRelayDnsARecord dns (Just port)) = [Ping.mkAddress (BSC.unpack dns ++ ":" ++ show port)] +stakePoolRelayToAddr (StakePoolRelayDnsARecord dns Nothing) = [Ping.mkAddress (BSC.unpack dns)] +stakePoolRelayToAddr (StakePoolRelayDnsSrvRecord srv) = [Ping.mkAddress (BSC.unpack srv)] diff --git a/cardano-cli/src/Cardano/CLI/EraBased/StakePool/Run.hs b/cardano-cli/src/Cardano/CLI/EraBased/StakePool/Run.hs index 6258298819..045efb2696 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/StakePool/Run.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/StakePool/Run.hs @@ -27,6 +27,7 @@ import Cardano.Api.Experimental.Certificate import Cardano.Api.Ledger qualified as L import Cardano.CLI.Compatible.Exception +import Cardano.CLI.Compatible.StakePool.Run (stakePoolRelayToAddr) import Cardano.CLI.EraBased.StakePool.Command import Cardano.CLI.EraBased.StakePool.Command qualified as Cmd import Cardano.CLI.EraBased.StakePool.Internal.Metadata (carryHashChecks) @@ -41,7 +42,10 @@ import Cardano.CLI.Type.Common import Cardano.CLI.Type.Error.HashCmdError (FetchURLError (..)) import Cardano.CLI.Type.Error.StakePoolCmdError import Cardano.CLI.Type.Key (readVerificationKeyOrFile) +import Cardano.Network.Ping qualified as Ping +import Control.Monad (unless) +import Control.Tracer (nullTracer, (>$<)) import Data.ByteString.Char8 qualified as BS import Data.ByteString.Lazy qualified as LBS import Data.Function ((&)) @@ -86,6 +90,31 @@ runStakePoolRegistrationCertificateCmd , outFile } = obtainCommonConstraints era $ do + let pingOpts = + Ping.PingOpts + { Ping.pingOptsCount = 1 + , Ping.pingOptsMagic = toNetworkMagic network + , Ping.pingOptsJson = Ping.AsText + , Ping.pingOptsQuiet = True + , Ping.pingOptsSRVPrefix = "_cardano._tcp" + , Ping.pingOptsColor = Ping.ColorNever + , Ping.pingOptsMode = Ping.TipMode + } + pingErrs <- liftIO $ do + stderr <- Ping.mkStdErrTracer + headerTracer <- Ping.mkHeaderTracer pingOpts stderr + Ping.pingClients' + (Ping.format Ping.AsText >$< stderr) + nullTracer + headerTracer + (Ping.toText >$< stderr) + pingOpts + Ping.AddressIsNotAFilePath + (concatMap stakePoolRelayToAddr relays) + + unless (null pingErrs) $ + throwCliError (StakePoolCmdRelayPingErrors pingErrs) + -- Pool verification key stakePoolVerKey <- getVerificationKeyFromStakePoolVerificationKeySource poolVerificationKeyOrFile let stakePoolId' = anyStakePoolVerificationKeyHash stakePoolVerKey diff --git a/cardano-cli/src/Cardano/CLI/Type/Error/StakePoolCmdError.hs b/cardano-cli/src/Cardano/CLI/Type/Error/StakePoolCmdError.hs index 4c29bf54f2..9cb87e2a73 100644 --- a/cardano-cli/src/Cardano/CLI/Type/Error/StakePoolCmdError.hs +++ b/cardano-cli/src/Cardano/CLI/Type/Error/StakePoolCmdError.hs @@ -16,6 +16,10 @@ import Cardano.Api.Experimental.Certificate ) import Cardano.CLI.Type.Error.HashCmdError (FetchURLError) +import Cardano.Network.Ping (PingException) + +import Control.Exception (displayException) +import Prettyprinter qualified as PP data StakePoolCmdError = StakePoolCmdReadFileError !(FileError TextEnvelopeError) @@ -27,6 +31,7 @@ data StakePoolCmdError !(Hash StakePoolMetadata) -- ^ Actual hash | StakePoolCmdFetchURLError !FetchURLError + | StakePoolCmdRelayPingErrors ![PingException] deriving Show instance Error StakePoolCmdError where @@ -47,3 +52,8 @@ instance Error StakePoolCmdError where <+> pretty (show actualHash) StakePoolCmdFetchURLError fetchErr -> "Error fetching stake pool metadata: " <> prettyException fetchErr + StakePoolCmdRelayPingErrors errs -> + PP.vsep + [ "Errors validating stake pool relays:" + , PP.indent 2 $ PP.vsep (PP.pretty . displayException <$> errs) + ] From 10fe74f96f373936851da714d63d1016dd4b3dc4 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferrai Date: Wed, 1 Jul 2026 10:29:28 +0300 Subject: [PATCH 12/13] Fix build --- cabal.project | 28 +++++++++++++++++-- .../Cardano/CLI/Compatible/Json/Friendly.hs | 2 +- flake.lock | 6 ++-- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/cabal.project b/cabal.project index 076645d374..6f3adf047a 100644 --- a/cabal.project +++ b/cabal.project @@ -13,7 +13,7 @@ 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-06-02T21:49:32Z + , hackage.haskell.org 2026-06-29T22:49:53Z , cardano-haskell-packages 2026-06-29T12:05:19Z packages: @@ -73,6 +73,11 @@ write-ghc-environment-files: always -- Do NOT add more source-repository-package stanzas here unless they are strictly -- temporary! Please read the section in CONTRIBUTING about updating dependencies. +-- TODO: temporary until we relax aeson upstream +allow-newer: + , aeson + , http-api-data:text-iso8601 + -- cabal-allow-newer begin if impl(ghc >= 9.14) allow-newer: @@ -99,6 +104,23 @@ if impl(ghc >= 9.14) , with-utf8:base -- cabal-allow-newer end +source-repository-package + type: git + location: https://github.com/IntersectMBO/cardano-base.git + tag: 490b0d7af06c3d214dd4b64bb609375982bde846 + --sha256: sha256-oC/QWvL4BGWottuyUqYAdHIgqgYvaVlB/0noLE2i9Po= + subdir: + base-deriving-via + cardano-base + cardano-binary + cardano-crypto-class + cardano-crypto-praos + cardano-git-rev + cardano-slotting + cardano-strict-containers + heapwords + measures + source-repository-package type: git location: https://github.com/IntersectMBO/cardano-api.git @@ -147,8 +169,8 @@ source-repository-package source-repository-package type: git location: https://github.com/IntersectMBO/ouroboros-consensus.git - tag: e6fad063078894cefece2a535a2e2b4d9a092e73 - --sha256: sha256-SPtbQ1+zN4uYiVx3rej2kMasbpfhSAyjRD5bdrnK3Rs= + tag: cb5b3c1ab46b562810d058b51fbce0ee407ce3ae + --sha256: sha256-42StkJb5M3tEwNtJ9Y4CL7FCLnsz7AmNyYKMAF2amDY= subdir: . diff --git a/cardano-cli/src/Cardano/CLI/Compatible/Json/Friendly.hs b/cardano-cli/src/Cardano/CLI/Compatible/Json/Friendly.hs index d9f79d31fc..3717faed9e 100644 --- a/cardano-cli/src/Cardano/CLI/Compatible/Json/Friendly.hs +++ b/cardano-cli/src/Cardano/CLI/Compatible/Json/Friendly.hs @@ -381,7 +381,7 @@ renderPurpose era purpose = case era of [ labelPurpose spendingLabel . renderLedgerInput . unAsIxItem <$> L.toSpendingPurpose p , labelPurpose mintingLabel . unAsIxItem <$> L.toMintingPurpose p , labelPurpose certifyingLabel . unAsIxItem <$> L.toCertifyingPurpose p - , labelPurpose rewardingLabel . unAsIxItem <$> L.toRewardingPurpose p + , labelPurpose rewardingLabel . unAsIxItem <$> L.toWithdrawingPurpose p ] conwayView diff --git a/flake.lock b/flake.lock index e636828240..c645f2caaa 100644 --- a/flake.lock +++ b/flake.lock @@ -209,11 +209,11 @@ "hackageNix": { "flake": false, "locked": { - "lastModified": 1780437449, - "narHash": "sha256-DhOIrGPtRfqqYjKhO8ETnKLhcuPAnPHx1iUoWoyGw4Y=", + "lastModified": 1782826502, + "narHash": "sha256-G6bt7DeWkDXJWI/fHME467V/SOaUdfG6hk7bTRuWyKg=", "owner": "input-output-hk", "repo": "hackage.nix", - "rev": "c791c3f52a6985d49316d1f76317ed36d7f0a915", + "rev": "6a87e2657c145eb81d5f0f53702d4f26c08f9cbf", "type": "github" }, "original": { From cfeadc5a03473ddfec809abe49ddfe287c186648 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferrai Date: Fri, 3 Jul 2026 17:26:25 +0300 Subject: [PATCH 13/13] Remove aeson allow-newer --- cabal.project | 15 +++++---------- flake.lock | 6 +++--- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/cabal.project b/cabal.project index 6f3adf047a..bc4c3d9d52 100644 --- a/cabal.project +++ b/cabal.project @@ -14,7 +14,7 @@ repository cardano-haskell-packages -- you need to run if you change them index-state: , hackage.haskell.org 2026-06-29T22:49:53Z - , cardano-haskell-packages 2026-06-29T12:05:19Z + , cardano-haskell-packages 2026-07-02T10:10:00Z packages: cardano-cli @@ -73,11 +73,6 @@ write-ghc-environment-files: always -- Do NOT add more source-repository-package stanzas here unless they are strictly -- temporary! Please read the section in CONTRIBUTING about updating dependencies. --- TODO: temporary until we relax aeson upstream -allow-newer: - , aeson - , http-api-data:text-iso8601 - -- cabal-allow-newer begin if impl(ghc >= 9.14) allow-newer: @@ -169,16 +164,16 @@ source-repository-package source-repository-package type: git location: https://github.com/IntersectMBO/ouroboros-consensus.git - tag: cb5b3c1ab46b562810d058b51fbce0ee407ce3ae - --sha256: sha256-42StkJb5M3tEwNtJ9Y4CL7FCLnsz7AmNyYKMAF2amDY= + tag: e37ba209ffdbdcb3cc8e7a9cb0fb6d6fa7cce8a3 + --sha256: sha256-srdli4YUIo3HtdWwpk2Tq5okk4GQ5Fpn/ipFO8eykVU= subdir: . source-repository-package type: git location: https://github.com/IntersectMBO/ouroboros-network.git - tag: b47dbc2c29108e593cc47524cffb75008b88fe90 - --sha256: sha256-7TwcI1/m6aEBmiGYPXKHbIWlxzRja4qFyqr+apcR9p4= + tag: 0a614a36c8969e53fd6a1c3890b36da5aff3b0a2 + --sha256: sha256-p32/Y6jXwiSwa0yVspdx246KHaCBmqe2zB+UpxudeJc= subdir: ./cardano-diffusion ./monoidal-synchronisation diff --git a/flake.lock b/flake.lock index c645f2caaa..6d2b0abcc8 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "CHaP": { "flake": false, "locked": { - "lastModified": 1782769557, - "narHash": "sha256-tCYMTwH15mNajHybvC3KGVPBPMlLlqIOYE0ZgcqRkJU=", + "lastModified": 1782990451, + "narHash": "sha256-U0o77JuGp6ADqym7TtGV3AwzRn5SFuiTRyCOR6qfxGA=", "owner": "intersectmbo", "repo": "cardano-haskell-packages", - "rev": "3ee6b1ecce230d62f0083590f38c4ae3457da226", + "rev": "def6ba6e0324e451802f5a17b12a00bd64639e14", "type": "github" }, "original": {