From 2b1704adf77bb15e79226e9626b3c136f9b1d22a Mon Sep 17 00:00:00 2001 From: Jordan Millar Date: Fri, 25 Apr 2025 16:29:10 -0400 Subject: [PATCH 1/7] Add gRPC to cardano-node --- .github/workflows/haskell.yml | 20 +- .../src/Cardano/TxGenerator/Setup/Plutus.hs | 1 + bench/tx-generator/tx-generator.cabal | 1 + cabal.project | 26 +++ cardano-node/cardano-node.cabal | 3 + .../src/Cardano/Node/Configuration/POM.hs | 28 ++- cardano-node/src/Cardano/Node/Parsers.hs | 40 +++- cardano-node/src/Cardano/Node/Run.hs | 72 ++++--- cardano-node/src/Cardano/Node/Types.hs | 11 ++ .../test/Test/Cardano/Node/FilePermissions.hs | 5 +- cardano-node/test/Test/Cardano/Node/POM.hs | 8 + cardano-testnet/cardano-testnet.cabal | 7 + cardano-testnet/src/Cardano/Testnet.hs | 1 + cardano-testnet/src/Parsers/Cardano.hs | 23 ++- cardano-testnet/src/Testnet/Runtime.hs | 4 +- cardano-testnet/src/Testnet/Start/Cardano.hs | 2 + cardano-testnet/src/Testnet/Start/Types.hs | 14 +- cardano-testnet/src/Testnet/Types.hs | 6 + .../Cardano/Testnet/Test/Cli/Query.hs | 2 + .../Cardano/Testnet/Test/Rpc/Query.hs | 182 ++++++++++++++++++ .../Cardano/Testnet/Test/Rpc/Transaction.hs | 158 +++++++++++++++ .../cardano-testnet-test.hs | 6 + nix/haskell.nix | 6 +- 23 files changed, 577 insertions(+), 49 deletions(-) create mode 100644 cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/Query.hs create mode 100644 cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/Transaction.hs diff --git a/.github/workflows/haskell.yml b/.github/workflows/haskell.yml index adb6ca5f00e..291c89f7c40 100644 --- a/.github/workflows/haskell.yml +++ b/.github/workflows/haskell.yml @@ -38,7 +38,7 @@ jobs: # If you edit these versions, make sure the version in the lonely macos-latest job below is updated accordingly # TODO add 9.8 again to the versions list when GHC-9.8 gets released with stm > 2.5.2, # see https://github.com/haskell/stm/issues/76 - ghc: ["9.6", "9.12"] + ghc: ["9.6", "9.10"] cabal: ["3.12"] sys: - { os: windows-latest, shell: 'C:/msys64/usr/bin/bash.exe -e {0}' } @@ -97,6 +97,18 @@ jobs: with: use-sodium-vrf: true # default is true + - name: "[Linux] Install grpc dependencies" + if: runner.os == 'Linux' + run: sudo apt install libsnappy-dev protobuf-compiler + + - name: "[Windows] Install grpc dependencies" + if: runner.os == 'Windows' + run: /usr/bin/pacman --noconfirm -S mingw-w64-x86_64-snappy mingw-w64-x86_64-protobuf + + - name: "[macOS] Install grpc dependencies" + if: runner.os == 'macOS' + run: brew install snappy protobuf + - uses: actions/checkout@v4 - name: Cabal update @@ -230,9 +242,9 @@ jobs: # and will silently fail if msys2 is not in path. See the "Run tests" step. # # - name: Setup tmate session - # if: ${{ failure() }} - # uses: mxschmitt/action-tmate@v3 - # with: + # if: ${{ failure() }} + # uses: mxschmitt/action-tmate@v3 + # with: # limit-access-to-actor: true build-complete: diff --git a/bench/tx-generator/src/Cardano/TxGenerator/Setup/Plutus.hs b/bench/tx-generator/src/Cardano/TxGenerator/Setup/Plutus.hs index e07a895c10b..85f7c9c3b40 100644 --- a/bench/tx-generator/src/Cardano/TxGenerator/Setup/Plutus.hs +++ b/bench/tx-generator/src/Cardano/TxGenerator/Setup/Plutus.hs @@ -41,6 +41,7 @@ import Cardano.Benchmarking.PlutusScripts (findPlutusScript) #endif import Control.Exception (SomeException (..), try) import System.FilePath ((<.>), ()) +import RIO (runRIO) import Paths_tx_generator diff --git a/bench/tx-generator/tx-generator.cabal b/bench/tx-generator/tx-generator.cabal index 282e8bb4908..7facabe9e55 100644 --- a/bench/tx-generator/tx-generator.cabal +++ b/bench/tx-generator/tx-generator.cabal @@ -142,6 +142,7 @@ library , network , network-mux , optparse-applicative-fork + , rio , ouroboros-consensus >= 0.6 , ouroboros-consensus-cardano >= 0.5 , ouroboros-consensus-diffusion >= 0.7.0 diff --git a/cabal.project b/cabal.project index 25874410b4e..c4e9774e85a 100644 --- a/cabal.project +++ b/cabal.project @@ -61,6 +61,13 @@ package plutus-scripts-bench allow-newer: , katip:Win32 + +if impl (ghc >= 9.10) + allow-newer: + -- TODO: remove - this is for protolens + , *:base + , *:ghc-prim + if impl (ghc >= 9.12) allow-newer: -- https://github.com/kapralVV/Unique/issues/11 @@ -72,3 +79,22 @@ if impl (ghc >= 9.12) -- IMPORTANT -- Do NOT add more source-repository-package stanzas here unless they are strictly -- temporary! Please read the section in CONTRIBUTING about updating dependencies. + + +source-repository-package + type: git + location: https://github.com/intersectmbo/cardano-api + -- mgalazyn/feature/add-utxorpc-protocol-parameters-query + tag: 87b2afaaa037b78d1bed92257413fa9fdf2f156c + --sha256: sha256-VZv++ErHQZoG/OokIoQKGfqpKAcdm7dXPD8BzXKAkxU= + subdir: cardano-api + cardano-api-gen + cardano-rpc + +source-repository-package + type: git + location: https://github.com/intersectmbo/cardano-cli + -- mgalazyn/chore/remove-upstreamed-instances + tag: 386b22edd41820584857537203ca39caca61d158 + --sha256: sha256-wsP5leh9EIgmG0wVLuaPizHFylvS8LGt7D2erLZbs5s= + subdir: cardano-cli diff --git a/cardano-node/cardano-node.cabal b/cardano-node/cardano-node.cabal index e4618effea2..f5511acff8c 100644 --- a/cardano-node/cardano-node.cabal +++ b/cardano-node/cardano-node.cabal @@ -158,6 +158,7 @@ library , cardano-prelude , cardano-protocol-tpraos >= 1.4 , cardano-slotting >= 0.2 + , cardano-rpc ^>= 10.0 , cborg ^>= 0.2.4 , containers , contra-tracer @@ -222,6 +223,7 @@ library , typed-protocols-stateful >= 0.3 , yaml + executable cardano-node import: project-config hs-source-dirs: app @@ -257,6 +259,7 @@ test-suite cardano-node-test , cardano-crypto-class , cardano-crypto-wrapper , cardano-api + , cardano-rpc , cardano-protocol-tpraos , cardano-node , cardano-slotting diff --git a/cardano-node/src/Cardano/Node/Configuration/POM.hs b/cardano-node/src/Cardano/Node/Configuration/POM.hs index 7091e9b2e62..568222c0b18 100644 --- a/cardano-node/src/Cardano/Node/Configuration/POM.hs +++ b/cardano-node/src/Cardano/Node/Configuration/POM.hs @@ -10,6 +10,8 @@ {-# OPTIONS_GHC -Wno-noncanonical-monoid-instances #-} +{- HLINT ignore "Functor law" -} + module Cardano.Node.Configuration.POM ( NodeConfiguration (..) , ResponderCoreAffinityPolicy (..) @@ -35,6 +37,8 @@ import Cardano.Node.Configuration.Socket (SocketConfig (..)) import Cardano.Node.Handlers.Shutdown import Cardano.Node.Protocol.Types (Protocol (..)) import Cardano.Node.Types +import Cardano.Rpc.Server.Config (PartialRpcConfig, RpcConfig, RpcConfigF (..), + makeRpcConfig) import Cardano.Tracing.Config import Cardano.Tracing.OrphanInstances.Network () import qualified Ouroboros.Cardano.Network.Diffusion.Configuration as Cardano @@ -202,6 +206,9 @@ data NodeConfiguration , ncGenesisConfig :: GenesisConfig , ncResponderCoreAffinityPolicy :: ResponderCoreAffinityPolicy + + -- gRPC + , ncRpcConfig :: RpcConfig } deriving (Eq, Show) -- | We expose the `Ouroboros.Network.Mux.ForkPolicy` as a `NodeConfiguration` field. @@ -283,13 +290,13 @@ data PartialNodeConfiguration , pncSyncTargetOfKnownBigLedgerPeers :: !(Last Int) , pncSyncTargetOfEstablishedBigLedgerPeers :: !(Last Int) , pncSyncTargetOfActiveBigLedgerPeers :: !(Last Int) + -- Consensus mode for diffusion layer + , pncConsensusMode :: !(Last ConsensusMode) + -- Minimum number of active big ledger peers we must be connected to -- in Genesis mode , pncMinBigLedgerPeersForTrustedState :: !(Last NumberOfBigLedgerPeers) - -- Consensus mode for diffusion layer - , pncConsensusMode :: !(Last ConsensusMode) - -- Network P2P mode , pncEnableP2P :: !(Last NetworkP2PMode) @@ -300,6 +307,9 @@ data PartialNodeConfiguration , pncGenesisConfigFlags :: !(Last GenesisConfigFlags) , pncResponderCoreAffinityPolicy :: !(Last ResponderCoreAffinityPolicy) + + -- gRPC + , pncRpcConfig :: !PartialRpcConfig } deriving (Eq, Generic, Show) instance AdjustFilePaths PartialNodeConfiguration where @@ -418,6 +428,12 @@ instance FromJSON PartialNodeConfiguration where <$> v .:? "ResponderCoreAffinityPolicy" <*> v .:? "ForkPolicy" -- deprecated + pncRpcConfig <- + RpcConfig + <$> (Last <$> v .:? "EnableRpc") + <*> (Last <$> v .:? "RpcSocketPath") + <*> pure mempty + pure PartialNodeConfiguration { pncProtocolConfig , pncSocketConfig = Last . Just $ SocketConfig mempty mempty mempty pncSocketPath @@ -463,6 +479,7 @@ instance FromJSON PartialNodeConfiguration where , pncPeerSharing , pncGenesisConfigFlags , pncResponderCoreAffinityPolicy + , pncRpcConfig } where parseMempoolCapacityBytesOverride v = parseNoOverride <|> parseOverride @@ -710,6 +727,7 @@ defaultPartialNodeConfiguration = , pncGenesisConfigFlags = Last (Just defaultGenesisConfigFlags) -- https://ouroboros-consensus.cardano.intersectmbo.org/haddocks/ouroboros-consensus-diffusion/Ouroboros-Consensus-Node-Genesis.html#v:defaultGenesisConfigFlags , pncResponderCoreAffinityPolicy = Last $ Just NoResponderCoreAffinity + , pncRpcConfig = mempty } lastOption :: Parser a -> Parser (Last a) @@ -850,6 +868,9 @@ makeNodeConfiguration pnc = do experimentalProtocols <- lastToEither "Missing ExperimentalProtocolsEnabled" $ pncExperimentalProtocolsEnabled pnc + + ncRpcConfig <- makeRpcConfig $ (pncRpcConfig pnc){nodeSocketPath=ncSocketPath socketConfig} + return $ NodeConfiguration { ncConfigFile = configFile , ncTopologyFile = topologyFile @@ -898,6 +919,7 @@ makeNodeConfiguration pnc = do , ncConsensusMode , ncGenesisConfig , ncResponderCoreAffinityPolicy + , ncRpcConfig } ncProtocol :: NodeConfiguration -> Protocol diff --git a/cardano-node/src/Cardano/Node/Parsers.hs b/cardano-node/src/Cardano/Node/Parsers.hs index 39f997e0c5c..efc2399b6f4 100644 --- a/cardano-node/src/Cardano/Node/Parsers.hs +++ b/cardano-node/src/Cardano/Node/Parsers.hs @@ -15,27 +15,26 @@ module Cardano.Node.Parsers import Cardano.Logging.Types import qualified Cardano.Logging.Types as Net -import Cardano.Node.Configuration.NodeAddress ( - NodeHostIPv4Address (NodeHostIPv4Address), File (..), +import Cardano.Node.Configuration.NodeAddress (File (..), + NodeHostIPv4Address (NodeHostIPv4Address), NodeHostIPv6Address (NodeHostIPv6Address), PortNumber, SocketPath) import Cardano.Node.Configuration.POM (PartialNodeConfiguration (..), lastOption) import Cardano.Node.Configuration.Socket import Cardano.Node.Handlers.Shutdown import Cardano.Node.Types import Cardano.Prelude (ConvertText (..)) +import Cardano.Rpc.Server.Config (PartialRpcConfig, RpcConfigF (..)) import Ouroboros.Consensus.Ledger.SupportsMempool import Ouroboros.Consensus.Node -import Data.Foldable import Data.Char (isDigit) +import Data.Foldable import Data.Maybe (fromMaybe) import Data.Monoid (Last (..)) import Data.Text (Text) import qualified Data.Text as Text import Data.Word (Word16, Word32) import Options.Applicative hiding (str, switch) --- Don't use switch. It will not allow to set an option in a configuration --- file. See `parseStartAsNonProducingNode` and `parseValidateDB`. import qualified Options.Applicative as Opt import qualified Options.Applicative.Help as OptI import System.Posix.Types (Fd (..)) @@ -56,7 +55,7 @@ nodeRunParser = do topFp <- lastOption parseTopologyFile dbFp <- lastOption parseNodeDatabasePaths validate <- lastOption parseValidateDB - socketFp <- lastOption $ parseSocketPath "Path to a cardano-node socket" + socketFp <- lastOption $ parseSocketPath "socket-path" "Path to a cardano-node socket" traceForwardSocket <- lastOption parseTracerSocketMode nodeConfigFp <- lastOption parseConfigFile @@ -83,6 +82,9 @@ nodeRunParser = do -- Hidden options (to be removed eventually) maybeMempoolCapacityOverride <- lastOption parseMempoolCapacityOverride + -- gRPC + pncRpcConfig <- parseRpcConfig + pure $ PartialNodeConfiguration { pncSocketConfig = Last . Just $ SocketConfig @@ -141,12 +143,15 @@ nodeRunParser = do , pncPeerSharing = mempty , pncGenesisConfigFlags = mempty , pncResponderCoreAffinityPolicy = mempty + , pncRpcConfig } -parseSocketPath :: Text -> Parser SocketPath -parseSocketPath helpMessage = +parseSocketPath :: Text -- ^ option name + -> Text -- ^ help text + -> Parser SocketPath +parseSocketPath optionName helpMessage = fmap File $ strOption $ mconcat - [ long "socket-path" + [ long (toS optionName) , help (toS helpMessage) , completer (bashCompleter "file") , metavar "FILEPATH" @@ -420,6 +425,23 @@ parseStartAsNonProducingNode = ] ] +parseRpcConfig :: Parser PartialRpcConfig +parseRpcConfig = do + isEnabled <- lastOption parseRpcToggle + socketPath <- lastOption parseRpcSocketPath + pure $ RpcConfig isEnabled socketPath mempty + where + parseRpcToggle :: Parser Bool + parseRpcToggle = + Opt.switch ( + long "grpc-enable" + <> help "[EXPERIMENTAL] Enable node gRPC endpoint." + ) + parseRpcSocketPath :: Parser SocketPath + parseRpcSocketPath = + parseSocketPath + "gprc-socket-path" + "[EXPERIMENTAL] gRPC socket path. Defaults to rpc.sock in the same directory as node socket." -- | Produce just the brief help header for a given CLI option parser, -- without the options. diff --git a/cardano-node/src/Cardano/Node/Run.hs b/cardano-node/src/Cardano/Node/Run.hs index 18a83515fd8..b806732eb71 100644 --- a/cardano-node/src/Cardano/Node/Run.hs +++ b/cardano-node/src/Cardano/Node/Run.hs @@ -22,7 +22,7 @@ module Cardano.Node.Run , checkVRFFilePermissions ) where -import Cardano.Api (File (..), FileDirection (..)) +import Cardano.Api (File (..), FileDirection (..), NetworkMagic, fromNetworkMagic) import Cardano.Api.Error (displayError) import qualified Cardano.Api as Api import System.Random (randomIO) @@ -40,7 +40,7 @@ import Cardano.Node.Configuration.POM (NodeConfiguration (..), PartialNodeConfiguration (..), SomeNetworkP2PMode (..), TimeoutOverride (..), defaultPartialNodeConfiguration, makeNodeConfiguration, parseNodeConfigurationFP, getForkPolicy) import Cardano.Node.Configuration.Socket (SocketOrSocketInfo' (..), - gatherConfiguredSockets, getSocketOrSocketInfoAddr) + gatherConfiguredSockets, getSocketOrSocketInfoAddr, SocketConfig (..)) import qualified Cardano.Node.Configuration.Topology as TopologyNonP2P import Cardano.Node.Configuration.TopologyP2P import qualified Cardano.Node.Configuration.TopologyP2P as TopologyP2P @@ -52,6 +52,8 @@ import Cardano.Node.Protocol.Shelley (PraosLeaderCredentialsError (..) ShelleyProtocolInstantiationError (PraosLeaderCredentialsError)) import Cardano.Node.Protocol.Types import Cardano.Node.Queries +import Cardano.Rpc.Server +import Cardano.Rpc.Server.Config import Cardano.Node.Startup import Cardano.Node.TraceConstraints (TraceConstraints) import Cardano.Node.Tracing.API @@ -127,6 +129,7 @@ import Ouroboros.Network.Subscription (DnsSubscriptionTarget (..), import Control.Applicative (empty) import Control.Concurrent (killThread, mkWeakThreadId, myThreadId, getNumCapabilities) +import Control.Concurrent.Async import Control.Concurrent.Class.MonadSTM.Strict import Control.Exception (try, Exception, IOException) import qualified Control.Exception as Exception @@ -159,6 +162,7 @@ import Network.HostName (getHostName) import Network.Socket (Socket) import System.Directory (canonicalizePath, createDirectoryIfMissing, makeAbsolute) import System.Environment (lookupEnv) +import System.FilePath (takeDirectory, ()) import System.IO (hPutStrLn) #ifdef UNIX import GHC.Weak (deRefWeak) @@ -171,6 +175,7 @@ import System.Win32.File import Paths_cardano_node (version) import Paths_cardano_node (version) +import GHC.Stack {- HLINT ignore "Fuse concatMap/map" -} {- HLINT ignore "Redundant <$>" -} @@ -180,37 +185,58 @@ runNode :: PartialNodeConfiguration -> IO () runNode cmdPc = do - installSigTermHandler + installSigTermHandler - Crypto.cryptoInit + Crypto.cryptoInit - configYamlPc <- parseNodeConfigurationFP . getLast $ pncConfigFile cmdPc + let earlyTracer = stdoutTracer + nc@NodeConfiguration + { ncProtocolConfig + , ncProtocolFiles=ncProtocolFiles@ProtocolFilepaths{shelleyVRFFile=mShelleyVrfFile} + } <- buildNodeConfiguration cmdPc - nc <- case makeNodeConfiguration $ defaultPartialNodeConfiguration <> configYamlPc <> cmdPc of - Left err -> error $ "Error in creating the NodeConfiguration: " <> err - Right nc' -> return nc' + traceWith earlyTracer $ "Node configuration: " <> show nc - putStrLn $ "Node configuration: " <> show nc + forM_ mShelleyVrfFile $ + runThrowExceptT . checkVRFFilePermissions earlyTracer . File - case ncProtocolFiles nc of - ProtocolFilepaths{shelleyVRFFile=Just vrfFp} -> - runThrowExceptT $ - checkVRFFilePermissions stdoutTracer (File vrfFp) - _ -> pure () - - consensusProtocol <- - runThrowExceptT $ - mkConsensusProtocol - (ncProtocolConfig nc) - -- TODO: Convert ncProtocolFiles to Maybe as relay nodes - -- don't need these. - (Just $ ncProtocolFiles nc) + consensusProtocol@(SomeConsensusProtocol _ runP) <- + runThrowExceptT $ + mkConsensusProtocol + ncProtocolConfig + -- TODO: Convert ncProtocolFiles to Maybe as relay nodes + -- don't need these. + (Just ncProtocolFiles) + let ProtocolInfo{pInfoConfig} = fst $ Api.protocolInfo @IO runP + networkMagic :: Api.NetworkMagic = getNetworkMagic $ Consensus.configBlock pInfoConfig + -- TODO move initialisation somewhere else, so that the correct tracer is used, instead of stdout default one + withAsync (runRpcServer earlyTracer $ buildRpcConfiguration networkMagic cmdPc) $ \_ -> handleNodeWithTracers cmdPc nc consensusProtocol runThrowExceptT :: Exception e => ExceptT e IO a -> IO a runThrowExceptT act = runExceptT act >>= either Exception.throwIO pure +-- | Read node configuration from a file specified in 'PartialNodeConfiguration' +buildNodeConfiguration :: HasCallStack + => PartialNodeConfiguration -- ^ defaults + -> IO NodeConfiguration +buildNodeConfiguration partialConf = do + configYamlPc <- parseNodeConfigurationFP . getLast $ pncConfigFile partialConf + either + (\err -> error $ "Error in creating the NodeConfiguration: " <> err) + pure + $ makeNodeConfiguration (defaultPartialNodeConfiguration <> configYamlPc <> partialConf) + +-- | Build RPC configuration. Reads the configuration file again. Allows RPC server to dynamically reload configuration from disk again. +buildRpcConfiguration :: HasCallStack + => NetworkMagic + -> PartialNodeConfiguration + -> IO (RpcConfig, NetworkMagic) +buildRpcConfiguration networkMagic partialConf = do + NodeConfiguration{ncRpcConfig} <- buildNodeConfiguration partialConf + pure (ncRpcConfig, networkMagic) + -- | Workaround to ensure that the main thread throws an async exception on -- receiving a SIGTERM signal. installSigTermHandler :: IO () @@ -749,6 +775,8 @@ handleSimpleNode blockType runP p2pMode tracers nc onKernel = do -- SIGHUP Handlers -------------------------------------------------------------------------------- +-- TODO add SIGHUP handler for RPC configuration reloading + -- | The P2P SIGHUP handler can update block forging & reconfigure network topology. -- installP2PSigHUPHandler :: Tracer IO (StartupTrace blk) diff --git a/cardano-node/src/Cardano/Node/Types.hs b/cardano-node/src/Cardano/Node/Types.hs index cd2efbffe75..6560a27cc07 100644 --- a/cardano-node/src/Cardano/Node/Types.hs +++ b/cardano-node/src/Cardano/Node/Types.hs @@ -46,6 +46,7 @@ import qualified Cardano.Crypto.Hash as Crypto import Cardano.Network.ConsensusMode (ConsensusMode (..)) import Cardano.Node.Configuration.Socket (SocketConfig (..)) import Cardano.Node.Orphans () +import Cardano.Rpc.Server.Config (RpcConfigF (..)) import Ouroboros.Network.NodeToNode (DiffusionMode (..)) import Control.Exception @@ -480,6 +481,16 @@ instance AdjustFilePaths a => AdjustFilePaths (Maybe a) where instance AdjustFilePaths a => AdjustFilePaths (Last a) where adjustFilePaths f = fmap (adjustFilePaths f) +instance AdjustFilePaths (File a b) where + adjustFilePaths f (File p) = File $ f p + +instance Functor f => AdjustFilePaths (RpcConfigF f) where + adjustFilePaths f (RpcConfig isEnabled rpcSocketPath nodeSocketPath) = + RpcConfig + isEnabled + (adjustFilePaths f <$> rpcSocketPath) + (adjustFilePaths f <$> nodeSocketPath) + data VRFPrivateKeyFilePermissionError = OtherPermissionsExist FilePath | GroupPermissionsExist FilePath diff --git a/cardano-node/test/Test/Cardano/Node/FilePermissions.hs b/cardano-node/test/Test/Cardano/Node/FilePermissions.hs index 524e1ee3593..0aa16e86453 100644 --- a/cardano-node/test/Test/Cardano/Node/FilePermissions.hs +++ b/cardano-node/test/Test/Cardano/Node/FilePermissions.hs @@ -39,6 +39,7 @@ import Hedgehog.Internal.Property (Group (..), failWith) import System.IO (FilePath, IO) import Text.Show (Show (..)) import Cardano.Node.Types (VRFPrivateKeyFilePermissionError (..)) +import Control.Exception (bracket) #ifdef UNIX @@ -47,7 +48,7 @@ import System.Posix.IO (closeFd, createFile) import System.Posix.Types (FileMode) import Hedgehog -import Hedgehog.Extras +import qualified Hedgehog.Extras as H import qualified Hedgehog.Gen as Gen #endif @@ -134,7 +135,7 @@ prop_sanityCheck_checkVRFFilePermissions = (const . liftIO . runExceptT $ checkVRFFilePermissions capturingTracer vrfPrivateKeyGroup) case groupResult of Left (GroupPermissionsExist _) -> do - note_ "Group permissions check should not fail" + H.note_ "Group permissions check should not fail" failure Left err -> failWith Nothing $ "checkVRFFilePermissions should not have failed with error: " diff --git a/cardano-node/test/Test/Cardano/Node/POM.hs b/cardano-node/test/Test/Cardano/Node/POM.hs index ff996959fc2..0e58bde9a73 100644 --- a/cardano-node/test/Test/Cardano/Node/POM.hs +++ b/cardano-node/test/Test/Cardano/Node/POM.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE TemplateHaskell #-} @@ -13,6 +14,7 @@ import Cardano.Node.Configuration.POM import Cardano.Node.Configuration.Socket import Cardano.Node.Handlers.Shutdown import Cardano.Node.Types +import Cardano.Rpc.Server.Config (makeRpcConfig) import Cardano.Tracing.Config (PartialTraceOptions (..), defaultPartialTraceConfiguration, partialTraceSelectionToEither) import Ouroboros.Cardano.Network.Diffusion.Configuration (defaultNumberOfBigLedgerPeers) @@ -28,7 +30,9 @@ import Ouroboros.Network.NodeToNode (AcceptedConnectionsLimit (..), DiffusionMode (InitiatorAndResponderDiffusionMode)) import Ouroboros.Network.PeerSelection.PeerSharing (PeerSharing (..)) +import Data.Bifunctor (first) import Data.Monoid (Last (..)) +import Data.String import Data.Text (Text) import Hedgehog (Property, discover, withTests, (===)) @@ -170,6 +174,7 @@ testPartialYamlConfig = , pncResponderCoreAffinityPolicy = mempty , pncLedgerDbConfig = mempty , pncEgressPollInterval = mempty + , pncRpcConfig = mempty } -- | Example partial configuration theoretically created @@ -221,6 +226,7 @@ testPartialCliConfig = , pncResponderCoreAffinityPolicy = mempty , pncLedgerDbConfig = mempty , pncEgressPollInterval = mempty + , pncRpcConfig = mempty } -- | Expected final NodeConfiguration @@ -228,6 +234,7 @@ eExpectedConfig :: Either Text NodeConfiguration eExpectedConfig = do traceOptions <- partialTraceSelectionToEither (return $ PartialTracingOnLegacy defaultPartialTraceConfiguration) + ncRpcConfig <- first fromString $ makeRpcConfig mempty return $ NodeConfiguration { ncSocketConfig = SocketConfig mempty mempty mempty mempty , ncShutdownConfig = ShutdownConfig Nothing (Just . ASlot $ SlotNo 42) @@ -278,6 +285,7 @@ eExpectedConfig = do , ncGenesisConfig = disableGenesisConfig , ncResponderCoreAffinityPolicy = NoResponderCoreAffinity , ncLedgerDbConfig = LedgerDbConfiguration DefaultNumOfDiskSnapshots DefaultSnapshotInterval DefaultQueryBatchSize V2InMemory noDeprecatedOptions + , ncRpcConfig } -- ----------------------------------------------------------------------------- diff --git a/cardano-testnet/cardano-testnet.cabal b/cardano-testnet/cardano-testnet.cabal index d81890ce526..fcd1736cc02 100644 --- a/cardano-testnet/cardano-testnet.cabal +++ b/cardano-testnet/cardano-testnet.cabal @@ -57,6 +57,7 @@ library , cardano-node , cardano-ping ^>= 0.8 , cardano-prelude + , cardano-rpc , contra-tracer , containers , data-default-class @@ -223,6 +224,8 @@ test-suite cardano-testnet-test Cardano.Testnet.Test.Gov.TreasuryDonation Cardano.Testnet.Test.Gov.TreasuryGrowth Cardano.Testnet.Test.Gov.TreasuryWithdrawal + Cardano.Testnet.Test.Rpc.Query + Cardano.Testnet.Test.Rpc.Transaction Cardano.Testnet.Test.Misc Cardano.Testnet.Test.Node.Shutdown Cardano.Testnet.Test.MainnetParams @@ -242,12 +245,15 @@ test-suite cardano-testnet-test , bytestring , cardano-api , cardano-cli:{cardano-cli, cardano-cli-test-lib} + , cardano-ledger-api , cardano-crypto-class + , cardano-ledger-binary , cardano-ledger-conway , cardano-ledger-core , cardano-ledger-shelley , cardano-node , cardano-prelude + , cardano-rpc , cardano-slotting , cardano-strict-containers ^>= 0.1 , cardano-testnet @@ -265,6 +271,7 @@ test-suite cardano-testnet-test , monad-control , mtl , process + , rio , regex-compat , rio , tasty ^>= 1.5 diff --git a/cardano-testnet/src/Cardano/Testnet.hs b/cardano-testnet/src/Cardano/Testnet.hs index a5c88dee0e6..ec467f46ae9 100644 --- a/cardano-testnet/src/Cardano/Testnet.hs +++ b/cardano-testnet/src/Cardano/Testnet.hs @@ -46,6 +46,7 @@ module Cardano.Testnet ( TestnetNode(..), isTestnetNodeSpo, nodeSocketPath, + nodeRpcSocketPath, ) where import Testnet.Components.Query diff --git a/cardano-testnet/src/Parsers/Cardano.hs b/cardano-testnet/src/Parsers/Cardano.hs index f9c5e184fa4..f4692d6be45 100644 --- a/cardano-testnet/src/Parsers/Cardano.hs +++ b/cardano-testnet/src/Parsers/Cardano.hs @@ -5,11 +5,15 @@ module Parsers.Cardano , cmdCreateEnv ) where -import Cardano.Api (AnyShelleyBasedEra(..)) +import Cardano.Api (AnyShelleyBasedEra (..), EraInEon (..), prettyShow) + +import Cardano.CLI.Environment import Cardano.CLI.EraBased.Common.Option (bounded, command') +import Cardano.CLI.EraBased.Common.Option hiding (pNetworkId) + import Prelude -import Control.Applicative((<|>), optional) +import Control.Applicative (optional, (<|>)) import Data.Default.Class (def) import qualified Data.List as L import Data.Maybe (fromMaybe) @@ -50,10 +54,10 @@ pCardanoTestnetCliOptions = CardanoTestnetOptions <*> pure (AnyShelleyBasedEra defaultEra) <*> pMaxLovelaceSupply <*> OA.option (OA.eitherReader readNodeLoggingFormat) - ( OA.long "nodeLoggingFormat" + ( OA.long "node-logging-format" <> OA.help "Node logging format (json|text)" <> OA.metavar "LOGGING_FORMAT" - <> OA.showDefault + <> OA.showDefaultWith prettyShow <> OA.value (cardanoNodeLoggingFormat def) ) <*> OA.option OA.auto @@ -63,7 +67,7 @@ pCardanoTestnetCliOptions = CardanoTestnetOptions <> OA.showDefault <> OA.value 3 ) - <*> OA.flag False True + <*> OA.switch ( OA.long "enable-new-epoch-state-logging" <> OA.help "Enable new epoch state logging to logs/ledger-epoch-state.log" <> OA.showDefault @@ -73,6 +77,15 @@ pCardanoTestnetCliOptions = CardanoTestnetOptions <> OA.help "Directory where to store files, sockets, and so on. It is created if it doesn't exist. If unset, a temporary directory is used." <> OA.metavar "DIRECTORY" ))) + <*> OA.switch + ( OA.long "enable-grpc" + <> OA.help "[EXPERIMENTAL] Enable gRPC endpoint on all of testnet nodes. The listening socket file will be the same directory as node's N2C socket." + <> OA.showDefault + ) + where + pAnyShelleyBasedEra' :: Parser AnyShelleyBasedEra + pAnyShelleyBasedEra' = + pAnyShelleyBasedEra envCli <&> (\(EraInEon x) -> AnyShelleyBasedEra x) pTestnetNodeOptions :: Parser [NodeOption] pTestnetNodeOptions = diff --git a/cardano-testnet/src/Testnet/Runtime.hs b/cardano-testnet/src/Testnet/Runtime.hs index 4ca93877e14..1ef57cbf9cb 100644 --- a/cardano-testnet/src/Testnet/Runtime.hs +++ b/cardano-testnet/src/Testnet/Runtime.hs @@ -20,8 +20,8 @@ import Cardano.Api import qualified Cardano.Api as Api import qualified Cardano.Ledger.Api as L -import qualified Cardano.Ledger.Shelley.State as L import qualified Cardano.Ledger.Shelley.LedgerState as L +import qualified Cardano.Ledger.Shelley.State as L import Prelude @@ -144,7 +144,7 @@ startNode tp node ipv4 port _testnetMagic nodeCmd = GHC.withFrozenCallStack $ do left MaxSprocketLengthExceededError let socketAbsPath = H.sprocketSystemName sprocket - completeNodeCmd = nodeCmd ++ + completeNodeCmd = nodeCmd <> [ "--socket-path", H.sprocketArgumentName sprocket , "--port", show port , "--host-addr", showIpv4Address ipv4 diff --git a/cardano-testnet/src/Testnet/Start/Cardano.hs b/cardano-testnet/src/Testnet/Start/Cardano.hs index bb3ddea34c9..f8e9d6e2f04 100644 --- a/cardano-testnet/src/Testnet/Start/Cardano.hs +++ b/cardano-testnet/src/Testnet/Start/Cardano.hs @@ -220,6 +220,7 @@ cardanoTestnet { cardanoNodeLoggingFormat=nodeLoggingFormat , cardanoEnableNewEpochStateLogging=enableNewEpochStateLogging , cardanoNodes + , cardanoEnableRpc } = testnetOptions nPools = cardanoNumPools testnetOptions nodeConfigFile = tmpAbsPath "configuration.yaml" @@ -350,6 +351,7 @@ cardanoTestnet ] <> spoNodeCliArgs <> extraCliArgs nodeOptions + <> ["--grpc-enable" | cardanoEnableRpc] pure $ eRuntime <&> \rt -> rt{poolKeys=mKeys} let (failedNodes, testnetNodes') = partitionEithers eTestnetNodes diff --git a/cardano-testnet/src/Testnet/Start/Types.hs b/cardano-testnet/src/Testnet/Start/Types.hs index b9e557be742..e230ec98411 100644 --- a/cardano-testnet/src/Testnet/Start/Types.hs +++ b/cardano-testnet/src/Testnet/Start/Types.hs @@ -1,5 +1,6 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE DerivingVia #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE NumericUnderscores #-} {-# LANGUAGE OverloadedStrings #-} @@ -185,6 +186,8 @@ data CardanoTestnetOptions = CardanoTestnetOptions , cardanoNumDReps :: NumDReps -- ^ The number of DReps to generate at creation , cardanoEnableNewEpochStateLogging :: Bool -- ^ if epoch state logging is enabled , cardanoOutputDir :: UserProvidedEnv -- ^ The output directory where to store files, sockets, and so on. If unset, a temporary directory is used. + , cardanoEnableRpc :: Bool + -- ^ True to enable gRPC endpoints in all testnet nodes } deriving (Eq, Show) -- | Path to the configuration file of the node, specified by the user @@ -220,6 +223,7 @@ instance Default CardanoTestnetOptions where , cardanoNumDReps = 3 , cardanoEnableNewEpochStateLogging = True , cardanoOutputDir = def + , cardanoEnableRpc = False } -- | Options that are implemented by writing fields in the Shelley genesis file. @@ -270,7 +274,15 @@ cardanoDefaultTestnetNodeOptions = , RelayNodeOptions [] ] -data NodeLoggingFormat = NodeLoggingFormatAsJson | NodeLoggingFormatAsText deriving (Eq, Show) +data NodeLoggingFormat + = NodeLoggingFormatAsJson + | NodeLoggingFormatAsText + deriving (Eq, Show) + +instance Pretty NodeLoggingFormat where + pretty = \case + NodeLoggingFormatAsJson -> "json" + NodeLoggingFormatAsText -> "text" data NodeConfiguration diff --git a/cardano-testnet/src/Testnet/Types.hs b/cardano-testnet/src/Testnet/Types.hs index 1330b2e3dcb..a998771d609 100644 --- a/cardano-testnet/src/Testnet/Types.hs +++ b/cardano-testnet/src/Testnet/Types.hs @@ -21,6 +21,7 @@ module Testnet.Types , testnetSprockets , TestnetNode(..) , nodeSocketPath + , nodeRpcSocketPath , nodeConnectionInfo , isTestnetNodeSpo , SpoNodeKeys(..) @@ -52,6 +53,7 @@ import Cardano.Crypto.ProtocolMagic (RequiresNetworkMagic (..)) import Cardano.Node.Configuration.POM import qualified Cardano.Node.Protocol.Byron as Byron import Cardano.Node.Types +import Cardano.Rpc.Server.Config (nodeSocketPathToRpcSocketPath) import Prelude @@ -149,6 +151,10 @@ isTestnetNodeSpo = isJust . poolKeys nodeSocketPath :: TestnetNode -> SocketPath nodeSocketPath = File . H.sprocketSystemName . nodeSprocket +-- | Provide a default RPC socket path +nodeRpcSocketPath :: TestnetNode -> SocketPath +nodeRpcSocketPath = nodeSocketPathToRpcSocketPath . nodeSocketPath + -- | Connection data for a node in the testnet nodeConnectionInfo :: MonadTest m => TestnetRuntime diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/Query.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/Query.hs index d1e10d11df7..facab515bf5 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/Query.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/Query.hs @@ -69,6 +69,8 @@ import qualified Hedgehog as H import Hedgehog.Extras (MonadAssertion, readJsonFile) import qualified Hedgehog.Extras as H +import RIO (runRIO) + -- | Test CLI queries -- Execute me with: -- @DISABLE_RETRIES=1 cabal test cardano-testnet-test --test-options '-p "/CliQueries/"'@ diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/Query.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/Query.hs new file mode 100644 index 00000000000..a4d5e4930e4 --- /dev/null +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/Query.hs @@ -0,0 +1,182 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE OverloadedLabels #-} +{-# LANGUAGE OverloadedLists #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} + +module Cardano.Testnet.Test.Rpc.Query + ( hprop_rpc_query_pparams + ) +where + +import Cardano.Api +import qualified Cardano.Api.Ledger as L + +import Cardano.CLI.Type.Output (QueryTipLocalStateOutput (..)) +import qualified Cardano.Ledger.Api as L +import qualified Cardano.Ledger.Binary.Version as L +import qualified Cardano.Ledger.Conway.Core as L +import qualified Cardano.Ledger.Conway.PParams as L +import qualified Cardano.Ledger.Plutus as L +import qualified Cardano.Rpc.Client as Rpc +import qualified Cardano.Rpc.Proto.Api.UtxoRpc.Query as UtxoRpc +import Cardano.Rpc.Server.Internal.UtxoRpc.Query () +import Cardano.Testnet + +import Prelude + +import qualified Data.ByteString.Short as SBS +import Data.Default.Class +import qualified Data.Map.Strict as M +import Lens.Micro + +import Testnet.Components.Query +import Testnet.Process.Run +import Testnet.Property.Util (integrationRetryWorkspace) +import Testnet.Start.Types + +import Hedgehog +import qualified Hedgehog as H +import qualified Hedgehog.Extras.Test.Base as H +import qualified Hedgehog.Extras.Test.TestWatchdog as H + +hprop_rpc_query_pparams :: Property +hprop_rpc_query_pparams = integrationRetryWorkspace 2 "rpc-query-pparams" $ \tempAbsBasePath' -> H.runWithDefaultWatchdog_ $ do + conf@Conf{tempAbsPath} <- mkConf tempAbsBasePath' + let tempAbsPath' = unTmpAbsPath tempAbsPath + + let ceo = ConwayEraOnwardsConway + sbe = convert ceo + eraName = eraToString sbe + options = def{cardanoNodeEra = AnyShelleyBasedEra sbe, cardanoEnableRpc = True} + + TestnetRuntime + { testnetMagic + , configurationFile + , testnetNodes = node0@TestnetNode{nodeSprocket} : _ + } <- + createAndRunTestnet options def conf + + execConfig <- mkExecConfig tempAbsPath' nodeSprocket testnetMagic + epochStateView <- getEpochStateView configurationFile (nodeSocketPath node0) + pparams <- unLedgerProtocolParameters <$> getProtocolParams epochStateView ceo + -- H.noteShowPretty_ pparams + utxos <- findAllUtxos epochStateView sbe + H.noteShowPretty_ utxos + rpcSocket <- H.note . unFile $ nodeRpcSocketPath node0 + + ---------- + -- Get tip + ---------- + QueryTipLocalStateOutput{localStateChainTip} <- + H.noteShowM $ execCliStdoutToJson execConfig [eraName, "query", "tip"] + (slot, blockHash, blockNo) <- case localStateChainTip of + ChainTipAtGenesis -> H.failure + ChainTip (SlotNo slot) (HeaderHash hash) (BlockNo blockNo) -> pure (slot, SBS.fromShort hash, blockNo) + + -------------- + -- RPC queries + -------------- + let rpcServer = Rpc.ServerUnix rpcSocket + (pparamsResponse, utxosResponse) <- H.noteShowM . H.evalIO . Rpc.withConnection def rpcServer $ \conn -> do + pparams' <- do + let req = Rpc.defMessage + Rpc.nonStreaming conn (Rpc.rpc @(Rpc.Protobuf UtxoRpc.QueryService "readParams")) req + + utxos' <- do + let req = Rpc.defMessage + Rpc.nonStreaming conn (Rpc.rpc @(Rpc.Protobuf UtxoRpc.QueryService "readUtxos")) req + pure (pparams', utxos') + + ------------------------ + -- Test readParams response + ------------------------ + pparamsResponse ^. #ledgerTip . #slot === slot + pparamsResponse ^. #ledgerTip . #hash === blockHash + pparamsResponse ^. #ledgerTip . #height === blockNo + pparamsResponse ^. #ledgerTip . #timestamp === 0 -- not possible to implement at this moment + + -- https://docs.cardano.org/about-cardano/explore-more/parameter-guide + let chainParams = pparamsResponse ^. #values . #cardano + babbageEraOnwardsConstraints (convert ceo) $ do + pparams ^. L.ppCoinsPerUTxOByteL . to L.unCoinPerByte . to L.unCoin + === chainParams ^. #coinsPerUtxoByte . to fromIntegral + pparams ^. L.ppMaxTxSizeL === chainParams ^. #maxTxSize . to fromIntegral + pparams ^. L.ppMinFeeBL === chainParams ^. #minFeeCoefficient . to fromIntegral + pparams ^. L.ppMinFeeAL === chainParams ^. #minFeeConstant . to fromIntegral + pparams ^. L.ppMaxBBSizeL === chainParams ^. #maxBlockBodySize . to fromIntegral + pparams ^. L.ppMaxBHSizeL === chainParams ^. #maxBlockHeaderSize . to fromIntegral + pparams ^. L.ppKeyDepositL === chainParams ^. #stakeKeyDeposit . to fromIntegral + pparams ^. L.ppPoolDepositL === chainParams ^. #poolDeposit . to fromIntegral + pparams ^. L.ppEMaxL . to L.unEpochInterval === chainParams ^. #poolRetirementEpochBound . to fromIntegral + pparams ^. L.ppNOptL === chainParams ^. #desiredNumberOfPools . to fromIntegral + pparams ^. L.ppA0L . to L.unboundRational === chainParams ^. #poolInfluence . to inject + pparams ^. L.ppNOptL === chainParams ^. #desiredNumberOfPools . to fromIntegral + pparams ^. L.ppRhoL . to L.unboundRational === chainParams ^. #monetaryExpansion . to inject + pparams ^. L.ppMinPoolCostL === chainParams ^. #minPoolCost . to fromIntegral + ( pparams ^. L.ppProtocolVersionL . to L.pvMajor . to L.getVersion + , pparams ^. L.ppProtocolVersionL . to L.pvMinor + ) + === ( chainParams ^. #protocolVersion . #major + , chainParams ^. #protocolVersion . #minor . to fromIntegral + ) + pparams ^. L.ppMaxValSizeL === chainParams ^. #maxValueSize . to fromIntegral + pparams ^. L.ppCollateralPercentageL === chainParams ^. #collateralPercentage . to fromIntegral + pparams ^. L.ppMaxCollateralInputsL === chainParams ^. #maxCollateralInputs . to fromIntegral + let pparamsCostModels = L.getCostModelParams <$> pparams ^. L.ppCostModelsL . to L.costModelsValid + M.lookup L.PlutusV1 pparamsCostModels === chainParams ^. #costModels . #plutusV1 . #values . to Just + M.lookup L.PlutusV2 pparamsCostModels === chainParams ^. #costModels . #plutusV2 . #values . to Just + M.lookup L.PlutusV3 pparamsCostModels === chainParams ^. #costModels . #plutusV3 . #values . to Just + pparams ^. L.ppPricesL . to L.prSteps . to L.unboundRational === chainParams ^. #prices . #steps . to inject + pparams ^. L.ppPricesL . to L.prMem . to L.unboundRational === chainParams ^. #prices . #memory . to inject + pparams ^. L.ppMaxTxExUnitsL === chainParams ^. #maxExecutionUnitsPerTransaction . to inject + pparams ^. L.ppMaxBlockExUnitsL === chainParams ^. #maxExecutionUnitsPerBlock . to inject + pparams ^. L.ppMinFeeRefScriptCostPerByteL . to L.unboundRational + === chainParams ^. #minFeeScriptRefCostPerByte . to inject + let poolVotingThresholds :: L.PoolVotingThresholds = + conwayEraOnwardsConstraints ceo $ + pparams ^. L.ppPoolVotingThresholdsL + ( L.unboundRational + <$> [ poolVotingThresholds ^. L.pvtMotionNoConfidenceL + , poolVotingThresholds ^. L.pvtCommitteeNormalL + , poolVotingThresholds ^. L.pvtCommitteeNoConfidenceL + , poolVotingThresholds ^. L.pvtHardForkInitiationL + , poolVotingThresholds ^. L.pvtPPSecurityGroupL + ] + ) + === chainParams ^. #poolVotingThresholds . #thresholds . to (map inject) + let drepVotingThresholds :: L.DRepVotingThresholds = + conwayEraOnwardsConstraints ceo $ + pparams ^. L.ppDRepVotingThresholdsL + ( L.unboundRational + <$> [ drepVotingThresholds ^. L.dvtMotionNoConfidenceL + , drepVotingThresholds ^. L.dvtCommitteeNormalL + , drepVotingThresholds ^. L.dvtCommitteeNoConfidenceL + , drepVotingThresholds ^. L.dvtUpdateToConstitutionL + , drepVotingThresholds ^. L.dvtHardForkInitiationL + , drepVotingThresholds ^. L.dvtPPNetworkGroupL + , drepVotingThresholds ^. L.dvtPPEconomicGroupL + , drepVotingThresholds ^. L.dvtPPTechnicalGroupL + , drepVotingThresholds ^. L.dvtPPGovGroupL + , drepVotingThresholds ^. L.dvtTreasuryWithdrawalL + ] + ) + === chainParams ^. #drepVotingThresholds . #thresholds . to (map inject) + pparams ^. L.ppCommitteeMinSizeL === chainParams ^. #minCommitteeSize . to fromIntegral + pparams ^. L.ppCommitteeMaxTermLengthL . to L.unEpochInterval + === chainParams ^. #committeeTermLimit . to fromIntegral + pparams ^. L.ppGovActionLifetimeL . to L.unEpochInterval + === chainParams ^. #governanceActionValidityPeriod . to fromIntegral + pparams ^. L.ppGovActionDepositL === chainParams ^. #governanceActionDeposit . to fromIntegral + pparams ^. L.ppDRepDepositL === chainParams ^. #drepDeposit . to fromIntegral + pparams ^. L.ppDRepActivityL . to L.unEpochInterval === chainParams ^. #drepInactivityPeriod . to fromIntegral + + -------------------------- + -- Test readUtxos response + -------------------------- + + _ <- H.noteShowPretty $ utxos + _ <- H.noteShowPretty $ utxosResponse + H.failure diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/Transaction.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/Transaction.hs new file mode 100644 index 00000000000..eef09eb9418 --- /dev/null +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/Transaction.hs @@ -0,0 +1,158 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE NumericUnderscores #-} +{-# LANGUAGE OverloadedLabels #-} +{-# LANGUAGE OverloadedLists #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeOperators #-} + +module Cardano.Testnet.Test.Rpc.Transaction + ( hprop_rpc_transaction + ) +where + +import Cardano.Api +import qualified Cardano.Api.Ledger as L + +import Cardano.Rpc.Client (Proto) +import qualified Cardano.Rpc.Client as Rpc +import qualified Cardano.Rpc.Proto.Api.UtxoRpc.Query as UtxoRpc +import qualified Cardano.Rpc.Proto.Api.UtxoRpc.Submit as UtxoRpc +import Cardano.Rpc.Server.Internal.UtxoRpc.Query () +import Cardano.Rpc.Server.Internal.UtxoRpc.Type +import Cardano.Testnet + +import Prelude + +import Control.Monad +import Control.Monad.Fix +import Data.Default.Class +import qualified Data.Text.Encoding as T +import GHC.Stack +import Lens.Micro + +import Testnet.Property.Util (integrationRetryWorkspace) +import Testnet.Types + +import Hedgehog +import qualified Hedgehog as H +import qualified Hedgehog.Extras.Test.Base as H +import qualified Hedgehog.Extras.Test.TestWatchdog as H + +import RIO (threadDelay) + +hprop_rpc_transaction :: Property +hprop_rpc_transaction = integrationRetryWorkspace 2 "rpc-tx" $ \tempAbsBasePath' -> H.runWithDefaultWatchdog_ $ do + conf <- mkConf tempAbsBasePath' + let (ceo, eraProxy) = + (conwayBasedEra, asType) :: era ~ ConwayEra => (ConwayEraOnwards era, AsType era) + sbe = convert ceo + options = def{cardanoNodeEra = AnyShelleyBasedEra sbe, cardanoEnableRpc = True} + + TestnetRuntime + { testnetNodes = node0 : _ + , wallets = wallet0@(PaymentKeyInfo _ addrTxt0) : (PaymentKeyInfo _ addrTxt1) : _ + } <- + createAndRunTestnet options def conf + + rpcSocket <- H.note . unFile $ nodeRpcSocketPath node0 + + -- prepare tx inputs and output address + H.noteShow_ addrTxt0 + addr0 <- H.nothingFail $ deserialiseAddress (AsAddressInEra eraProxy) addrTxt0 + + H.noteShow_ addrTxt1 + addr1 <- H.nothingFail $ deserialiseAddress (AsAddressInEra eraProxy) addrTxt1 + + -- read key witnesses + wit0 :: ShelleyWitnessSigningKey <- + H.leftFailM . H.evalIO $ + readFileTextEnvelopeAnyOf + [FromSomeType asType WitnessGenesisUTxOKey] + (signingKey $ paymentKeyInfoPair wallet0) + + -------------- + -- RPC queries + -------------- + let rpcServer = Rpc.ServerUnix rpcSocket + (pparamsResponse, utxosResponse) <- H.noteShowM . H.evalIO . Rpc.withConnection def rpcServer $ \conn -> do + pparams' <- do + let req = def + Rpc.nonStreaming conn (Rpc.rpc @(Rpc.Protobuf UtxoRpc.QueryService "readParams")) req + + utxos' <- do + let req = def & #addresses . #items .~ [T.encodeUtf8 addrTxt0] + Rpc.nonStreaming conn (Rpc.rpc @(Rpc.Protobuf UtxoRpc.QueryService "readUtxos")) req + pure (pparams', utxos') + + pparams <- H.leftFail $ utxoRpcPParamsToProtocolParams (convert ceo) $ pparamsResponse ^. #values . #cardano + + txOut0 : _ <- H.noteShow $ utxosResponse ^. #items + txIn0 <- txoRefToTxIn $ txOut0 ^. #txoRef + + let outputCoin = txOut0 ^. #cardano . #coin . to fromIntegral + amount = 200_000_000 + fee = 500 + change = outputCoin - amount - fee + txOut = TxOut addr1 (lovelaceToTxOutValue sbe $ L.Coin amount) TxOutDatumNone ReferenceScriptNone + changeTxOut = TxOut addr0 (lovelaceToTxOutValue sbe $ L.Coin change) TxOutDatumNone ReferenceScriptNone + content = + defaultTxBodyContent sbe + & setTxIns [(txIn0, pure $ KeyWitness KeyWitnessForSpending)] + & setTxFee (TxFeeExplicit sbe 500) + & setTxOuts [txOut, changeTxOut] + & setTxProtocolParams (pure . pure $ LedgerProtocolParameters pparams) + + txBody <- H.leftFail $ createTransactionBody sbe content + + let signedTx = signShelleyTransaction sbe txBody [wit0] + txId' <- H.noteShow . getTxId $ getTxBody signedTx + + H.noteShowPretty_ utxosResponse + + (utxos, submitResponse) <- H.noteShowM . H.evalIO . Rpc.withConnection def rpcServer $ \conn -> do + submitResponse <- + Rpc.nonStreaming conn (Rpc.rpc @(Rpc.Protobuf UtxoRpc.SubmitService "submitTx")) $ + def & #tx .~ [def & #raw .~ serialiseToCBOR signedTx] + + fix $ \loop -> do + resp <- Rpc.nonStreaming conn (Rpc.rpc @(Rpc.Protobuf UtxoRpc.QueryService "readParams")) def + + let previousBlockNo = pparamsResponse ^. #ledgerTip . #height + currentBlockNo = resp ^. #ledgerTip . #height + -- wait for 2 blocks + when (previousBlockNo + 1 >= currentBlockNo) $ do + threadDelay 500_000 + loop + + utxos <- + Rpc.nonStreaming conn (Rpc.rpc @(Rpc.Protobuf UtxoRpc.QueryService "readUtxos")) $ + def & #addresses . #items .~ [T.encodeUtf8 addrTxt1] + pure (utxos, submitResponse) + + submittedTxIds <- forM (submitResponse ^. #results) $ \res -> do + let mErr = res ^. #maybe'errorMessage + mTxId = res ^. #maybe'ref + case (mErr, mTxId) of + (Just err, Nothing) -> H.noteShow_ err >> H.failure + (Nothing, Just txId'') -> + H.leftFail $ deserialiseFromRawBytes AsTxId txId'' + _ -> do + H.note_ $ "Protocol error: " <> show res + H.failure + + H.note_ "Ensure that submitted transaction ID is in the submitted transactions list" + [txId'] === submittedTxIds + + H.note_ $ "Enxure that there are 2 UTXOs in the address " <> show addrTxt1 + 2 === length (utxos ^. #items) + + let outputsAmounts = map (^. #cardano . #coin) $ utxos ^. #items + H.note_ $ "Ensure that the output sent is one of the utxos for the address " <> show addrTxt1 + H.assertWith outputsAmounts $ elem (fromIntegral amount) + +txoRefToTxIn :: (HasCallStack, MonadTest m) => Proto UtxoRpc.TxoRef -> m TxIn +txoRefToTxIn r = withFrozenCallStack $ do + txId' <- H.leftFail $ deserialiseFromRawBytes AsTxId $ r ^. #hash + pure $ TxIn txId' (TxIx . fromIntegral $ r ^. #index) diff --git a/cardano-testnet/test/cardano-testnet-test/cardano-testnet-test.hs b/cardano-testnet/test/cardano-testnet-test/cardano-testnet-test.hs index fb74ff0ff81..5c0c591df59 100644 --- a/cardano-testnet/test/cardano-testnet-test/cardano-testnet-test.hs +++ b/cardano-testnet/test/cardano-testnet-test/cardano-testnet-test.hs @@ -29,6 +29,8 @@ import qualified Cardano.Testnet.Test.Gov.TreasuryWithdrawal as Gov import qualified Cardano.Testnet.Test.Node.Shutdown import qualified Cardano.Testnet.Test.MainnetParams import qualified Cardano.Testnet.Test.P2PTopology +import qualified Cardano.Testnet.Test.Rpc.Query +import qualified Cardano.Testnet.Test.Rpc.Transaction import qualified Cardano.Testnet.Test.RunTestnet import qualified Cardano.Testnet.Test.SanityCheck as LedgerEvents import qualified Cardano.Testnet.Test.SubmitApi.Transaction @@ -124,6 +126,10 @@ tests = do , T.testGroup "SubmitApi" [ ignoreOnMacAndWindows "transaction" Cardano.Testnet.Test.SubmitApi.Transaction.hprop_transaction ] + , T.testGroup "RPC" + [ ignoreOnWindows "RPC Query Protocol Params" Cardano.Testnet.Test.Rpc.Query.hprop_rpc_query_pparams + , ignoreOnWindows "RPC Transaction Submit" Cardano.Testnet.Test.Rpc.Transaction.hprop_rpc_transaction + ] ] main :: IO () diff --git a/nix/haskell.nix b/nix/haskell.nix index abc0b6b9036..67f7d168726 100644 --- a/nix/haskell.nix +++ b/nix/haskell.nix @@ -308,7 +308,11 @@ let # also needs them to be quoted) export WORKDIR=$TMP/testTracerExt ''; - }) + }) + ({pkgs, ...}: { + packages.proto-lens-protobuf-types.components.library.build-tools = [ pkgs.protobuf ]; + packages.cardano-rpc.components.library.build-tools = [ pkgs.protobuf ]; + }) ({ lib, pkgs, ... }: lib.mkIf (!pkgs.stdenv.hostPlatform.isDarwin) { # Needed for profiled builds to fix an issue loading recursion-schemes part of makeBaseFunctor # that is missing from the `_p` output. See https://gitlab.haskell.org/ghc/ghc/-/issues/18320 From 0b74ce4193026bcffc600d8fd70a0e3a66d24a30 Mon Sep 17 00:00:00 2001 From: Mateusz Galazyn Date: Mon, 28 Jul 2025 13:40:43 +0200 Subject: [PATCH 2/7] update deps --- cabal.project | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cabal.project b/cabal.project index c4e9774e85a..c96ab03843c 100644 --- a/cabal.project +++ b/cabal.project @@ -84,9 +84,9 @@ if impl (ghc >= 9.12) source-repository-package type: git location: https://github.com/intersectmbo/cardano-api - -- mgalazyn/feature/add-utxorpc-protocol-parameters-query - tag: 87b2afaaa037b78d1bed92257413fa9fdf2f156c - --sha256: sha256-VZv++ErHQZoG/OokIoQKGfqpKAcdm7dXPD8BzXKAkxU= + -- master @ Fri Jul 25 18:47:11 2025 + tag: 4a6ce60b0028e3062d666980574aebf6acfee9b3 + --sha256: sha256-N+eiMtiKvNyzSa9uMZjdGGhYwEpXvI0oXH5GOvp5WyE= subdir: cardano-api cardano-api-gen cardano-rpc @@ -94,7 +94,7 @@ source-repository-package source-repository-package type: git location: https://github.com/intersectmbo/cardano-cli - -- mgalazyn/chore/remove-upstreamed-instances - tag: 386b22edd41820584857537203ca39caca61d158 - --sha256: sha256-wsP5leh9EIgmG0wVLuaPizHFylvS8LGt7D2erLZbs5s= + -- master @ Fri Jul 18 14:45:44 2025 + tag: 5dc410f1ec0b234a572e4470c3801fbac783bbeb + --sha256: sha256-f3RviGvNoDu5WX79BgAzPo9bL6PsNBqm+Qt1UlJGe5E= subdir: cardano-cli From d209e2cdda1e47d8d8b737a65fefd6ef13a8ffc5 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Wed, 30 Jul 2025 15:08:36 +0200 Subject: [PATCH 3/7] Add scripts for starting testnet and funding an address --- scripts-demo/fund.sh | 11 +++++++++++ scripts-demo/start-testnet.sh | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100755 scripts-demo/fund.sh create mode 100755 scripts-demo/start-testnet.sh diff --git a/scripts-demo/fund.sh b/scripts-demo/fund.sh new file mode 100755 index 00000000000..6fd80d16df0 --- /dev/null +++ b/scripts-demo/fund.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +# Example usage: +# ./scripts-demo/fund.sh addr_test1vq922scgdwrrfa3n2pzu3empkju9ekregg0tza0xnveya3gfl0ycn 1000000000 +export CARDANO_NODE_SOCKET_PATH=./testnet-data/socket/node1/sock +export CARDANO_NODE_NETWORK_ID=42 +SRC_ADDR=$(cat testnet-data/utxo-keys/utxo1/utxo.addr) +SRC_UTXO=$(cabal run cardano-cli -- latest query utxo --address $SRC_ADDR | jq -r 'keys'[0]) +cabal run cardano-cli -- latest transaction build --tx-in $SRC_UTXO --tx-out $1+$2 --change-address $SRC_ADDR --out-file funding.txbody +cabal run cardano-cli -- latest transaction sign --tx-body-file funding.txbody --signing-key-file testnet-data/utxo-keys/utxo1/utxo.skey --out-file funding.tx +cabal run cardano-cli -- latest transaction submit --tx-file funding.tx +rm -f funding.txbody funding.tx diff --git a/scripts-demo/start-testnet.sh b/scripts-demo/start-testnet.sh new file mode 100755 index 00000000000..b889902cfad --- /dev/null +++ b/scripts-demo/start-testnet.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +rm -fr ./testnet-data +rm -fr ../cardano-api/rpc.socket +cabal build cardano-node cardano-cli cardano-testnet +( + tries=0 + while [ $tries -lt 60 ]; do + if [ -S ./testnet-data/socket/node1/rpc.sock ]; then + break + fi + sleep 1 + tries=$((tries + 1)) + done + + if [ $tries -eq 60 ]; then + echo "Timeout: Socket not found in 60 seconds." >&2 + exit 1 + fi + + ln -sf ./testnet-data/socket/node1/rpc.sock ../cardano-api/rpc.socket +) & cabal run cardano-testnet -- cardano --testnet-magic 42 --enable-grpc --output-dir ./testnet-data From c799de250363a011514831ffe57291fc48727379 Mon Sep 17 00:00:00 2001 From: Mateusz Galazyn Date: Fri, 1 Aug 2025 11:26:02 +0200 Subject: [PATCH 4/7] Fix funding script --- scripts-demo/fund.sh | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/scripts-demo/fund.sh b/scripts-demo/fund.sh index 6fd80d16df0..e5f956e32b6 100755 --- a/scripts-demo/fund.sh +++ b/scripts-demo/fund.sh @@ -1,11 +1,20 @@ #!/usr/bin/env bash # Example usage: # ./scripts-demo/fund.sh addr_test1vq922scgdwrrfa3n2pzu3empkju9ekregg0tza0xnveya3gfl0ycn 1000000000 + +set -euo pipefail + +trap 'rm -f fundint.txbody' EXIT +rm -f funding.txbody funding.tx + +run_cardano_cli() { + cabal run -v0 cardano-cli -- "$@" +} + export CARDANO_NODE_SOCKET_PATH=./testnet-data/socket/node1/sock export CARDANO_NODE_NETWORK_ID=42 SRC_ADDR=$(cat testnet-data/utxo-keys/utxo1/utxo.addr) -SRC_UTXO=$(cabal run cardano-cli -- latest query utxo --address $SRC_ADDR | jq -r 'keys'[0]) -cabal run cardano-cli -- latest transaction build --tx-in $SRC_UTXO --tx-out $1+$2 --change-address $SRC_ADDR --out-file funding.txbody -cabal run cardano-cli -- latest transaction sign --tx-body-file funding.txbody --signing-key-file testnet-data/utxo-keys/utxo1/utxo.skey --out-file funding.tx -cabal run cardano-cli -- latest transaction submit --tx-file funding.tx -rm -f funding.txbody funding.tx +SRC_UTXO=$(run_cardano-cli latest query utxo --address "$SRC_ADDR" | jq -r 'keys[0]') +run_cardano-cli latest transaction build --tx-in "$SRC_UTXO" --tx-out "$1+$2" --change-address "$SRC_ADDR" --out-file funding.txbody +run_cardano-cli latest transaction sign --tx-body-file funding.txbody --signing-key-file testnet-data/utxo-keys/utxo1/utxo.skey --out-file funding.tx +run_cardano-cli latest transaction submit --tx-file funding.tx From a7242f097c0d4207d9b73269e4622c5668723512 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Sun, 3 Aug 2025 18:12:37 +0200 Subject: [PATCH 5/7] Update deps and fix fund script --- cabal.project | 4 ++-- scripts-demo/fund.sh | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cabal.project b/cabal.project index c96ab03843c..658341125a7 100644 --- a/cabal.project +++ b/cabal.project @@ -85,8 +85,8 @@ source-repository-package type: git location: https://github.com/intersectmbo/cardano-api -- master @ Fri Jul 25 18:47:11 2025 - tag: 4a6ce60b0028e3062d666980574aebf6acfee9b3 - --sha256: sha256-N+eiMtiKvNyzSa9uMZjdGGhYwEpXvI0oXH5GOvp5WyE= + tag: 1765e37a04a8ed3dd7455e0434c1b2b09fa609a5 + --sha256: sha256-XkoP1eBoyQGjmq1n3Oma0OJgxRos5oW4QCQ8HSfAexo= subdir: cardano-api cardano-api-gen cardano-rpc diff --git a/scripts-demo/fund.sh b/scripts-demo/fund.sh index e5f956e32b6..733a52ec0bb 100755 --- a/scripts-demo/fund.sh +++ b/scripts-demo/fund.sh @@ -14,7 +14,7 @@ run_cardano_cli() { export CARDANO_NODE_SOCKET_PATH=./testnet-data/socket/node1/sock export CARDANO_NODE_NETWORK_ID=42 SRC_ADDR=$(cat testnet-data/utxo-keys/utxo1/utxo.addr) -SRC_UTXO=$(run_cardano-cli latest query utxo --address "$SRC_ADDR" | jq -r 'keys[0]') -run_cardano-cli latest transaction build --tx-in "$SRC_UTXO" --tx-out "$1+$2" --change-address "$SRC_ADDR" --out-file funding.txbody -run_cardano-cli latest transaction sign --tx-body-file funding.txbody --signing-key-file testnet-data/utxo-keys/utxo1/utxo.skey --out-file funding.tx -run_cardano-cli latest transaction submit --tx-file funding.tx +SRC_UTXO=$(run_cardano_cli latest query utxo --address "$SRC_ADDR" | jq -r 'keys[0]') +run_cardano_cli latest transaction build --tx-in "$SRC_UTXO" --tx-out "$1+$2" --change-address "$SRC_ADDR" --out-file funding.txbody +run_cardano_cli latest transaction sign --tx-body-file funding.txbody --signing-key-file testnet-data/utxo-keys/utxo1/utxo.skey --out-file funding.tx +run_cardano_cli latest transaction submit --tx-file funding.tx From 1ea0332ad6cbba88cab301d800ae3b025c3a0f29 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Mon, 4 Aug 2025 01:43:23 +0200 Subject: [PATCH 6/7] Ensure files are deleted after funding --- scripts-demo/fund.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts-demo/fund.sh b/scripts-demo/fund.sh index 733a52ec0bb..cf06e62bcab 100755 --- a/scripts-demo/fund.sh +++ b/scripts-demo/fund.sh @@ -4,7 +4,7 @@ set -euo pipefail -trap 'rm -f fundint.txbody' EXIT +trap 'rm -f funding.txbody' EXIT rm -f funding.txbody funding.tx run_cardano_cli() { @@ -18,3 +18,4 @@ SRC_UTXO=$(run_cardano_cli latest query utxo --address "$SRC_ADDR" | jq -r 'keys run_cardano_cli latest transaction build --tx-in "$SRC_UTXO" --tx-out "$1+$2" --change-address "$SRC_ADDR" --out-file funding.txbody run_cardano_cli latest transaction sign --tx-body-file funding.txbody --signing-key-file testnet-data/utxo-keys/utxo1/utxo.skey --out-file funding.tx run_cardano_cli latest transaction submit --tx-file funding.tx +rm -f funding.txbody funding.tx From 0ec9ea7734f4df1a5cd88cb6e271b49b5642f328 Mon Sep 17 00:00:00 2001 From: Mateusz Galazyn Date: Fri, 5 Sep 2025 18:21:18 +0200 Subject: [PATCH 7/7] Update for cardano-api#945 --- bench/locli/locli.cabal | 2 +- cardano-node-chairman/cardano-node-chairman.cabal | 2 +- cardano-node/cardano-node.cabal | 2 +- cardano-testnet/cardano-testnet.cabal | 2 +- cardano-testnet/src/Parsers/Cardano.hs | 9 ++------- .../Cardano/Testnet/Test/Cli/Query.hs | 1 - .../Cardano/Testnet/Test/Rpc/Transaction.hs | 4 ++-- 7 files changed, 8 insertions(+), 14 deletions(-) diff --git a/bench/locli/locli.cabal b/bench/locli/locli.cabal index 336d0186b4d..6d2da39d698 100644 --- a/bench/locli/locli.cabal +++ b/bench/locli/locli.cabal @@ -212,7 +212,7 @@ test-suite test-locli build-depends: cardano-prelude , containers , hedgehog - , hedgehog-extras ^>= 0.8 + , hedgehog-extras ^>= 0.10 , locli , text diff --git a/cardano-node-chairman/cardano-node-chairman.cabal b/cardano-node-chairman/cardano-node-chairman.cabal index 22cd7bdeb4a..0fac28196d8 100644 --- a/cardano-node-chairman/cardano-node-chairman.cabal +++ b/cardano-node-chairman/cardano-node-chairman.cabal @@ -75,7 +75,7 @@ test-suite chairman-tests , data-default-class , filepath , hedgehog - , hedgehog-extras ^>= 0.8 + , hedgehog-extras ^>= 0.10 , network , process , random diff --git a/cardano-node/cardano-node.cabal b/cardano-node/cardano-node.cabal index f5511acff8c..8e68738cbfa 100644 --- a/cardano-node/cardano-node.cabal +++ b/cardano-node/cardano-node.cabal @@ -268,7 +268,7 @@ test-suite cardano-node-test , filepath , hedgehog , hedgehog-corpus - , hedgehog-extras ^>= 0.8 + , hedgehog-extras ^>= 0.10 , iproute , mtl , ouroboros-consensus diff --git a/cardano-testnet/cardano-testnet.cabal b/cardano-testnet/cardano-testnet.cabal index fcd1736cc02..b04327aa255 100644 --- a/cardano-testnet/cardano-testnet.cabal +++ b/cardano-testnet/cardano-testnet.cabal @@ -71,7 +71,7 @@ library , extra , filepath , hedgehog - , hedgehog-extras ^>= 0.8 + , hedgehog-extras ^>= 0.10 , http-conduit , lens-aeson , microlens diff --git a/cardano-testnet/src/Parsers/Cardano.hs b/cardano-testnet/src/Parsers/Cardano.hs index f4692d6be45..5e0a9d13b55 100644 --- a/cardano-testnet/src/Parsers/Cardano.hs +++ b/cardano-testnet/src/Parsers/Cardano.hs @@ -5,10 +5,9 @@ module Parsers.Cardano , cmdCreateEnv ) where -import Cardano.Api (AnyShelleyBasedEra (..), EraInEon (..), prettyShow) +import Cardano.Api.Era (AnyShelleyBasedEra (..)) +import Cardano.Api.Pretty -import Cardano.CLI.Environment -import Cardano.CLI.EraBased.Common.Option (bounded, command') import Cardano.CLI.EraBased.Common.Option hiding (pNetworkId) import Prelude @@ -82,10 +81,6 @@ pCardanoTestnetCliOptions = CardanoTestnetOptions <> OA.help "[EXPERIMENTAL] Enable gRPC endpoint on all of testnet nodes. The listening socket file will be the same directory as node's N2C socket." <> OA.showDefault ) - where - pAnyShelleyBasedEra' :: Parser AnyShelleyBasedEra - pAnyShelleyBasedEra' = - pAnyShelleyBasedEra envCli <&> (\(EraInEon x) -> AnyShelleyBasedEra x) pTestnetNodeOptions :: Parser [NodeOption] pTestnetNodeOptions = diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/Query.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/Query.hs index facab515bf5..7bde9dedec7 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/Query.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Cli/Query.hs @@ -62,7 +62,6 @@ import Testnet.Property.Util (integrationWorkspace) import Testnet.Start.Types (GenesisOptions (..), NumPools (..), cardanoNumPools) import Testnet.TestQueryCmds (TestQueryCmds (..), forallQueryCommands) import Testnet.Types -import RIO (runRIO) import Hedgehog import qualified Hedgehog as H diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/Transaction.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/Transaction.hs index eef09eb9418..61fe119418c 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/Transaction.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Rpc/Transaction.hs @@ -82,7 +82,7 @@ hprop_rpc_transaction = integrationRetryWorkspace 2 "rpc-tx" $ \tempAbsBasePath' Rpc.nonStreaming conn (Rpc.rpc @(Rpc.Protobuf UtxoRpc.QueryService "readParams")) req utxos' <- do - let req = def & #addresses . #items .~ [T.encodeUtf8 addrTxt0] + let req = def & #cardanoAddresses . #items .~ [T.encodeUtf8 addrTxt0] Rpc.nonStreaming conn (Rpc.rpc @(Rpc.Protobuf UtxoRpc.QueryService "readUtxos")) req pure (pparams', utxos') @@ -128,7 +128,7 @@ hprop_rpc_transaction = integrationRetryWorkspace 2 "rpc-tx" $ \tempAbsBasePath' utxos <- Rpc.nonStreaming conn (Rpc.rpc @(Rpc.Protobuf UtxoRpc.QueryService "readUtxos")) $ - def & #addresses . #items .~ [T.encodeUtf8 addrTxt1] + def & #cardanoAddresses . #items .~ [T.encodeUtf8 addrTxt1] pure (utxos, submitResponse) submittedTxIds <- forM (submitResponse ^. #results) $ \res -> do