Skip to content

Commit feb1b0e

Browse files
authored
Merge pull request #4788 from input-output-hk/newhoggy/better-error-message-for-query-utxo-without-oops
Better error message for query utxo without oops
2 parents fe973a5 + 3ff371c commit feb1b0e

File tree

7 files changed

+81
-68
lines changed

7 files changed

+81
-68
lines changed

cabal.project

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ repository cardano-haskell-packages
1212

1313
-- See CONTRIBUTING for information about these, including some Nix commands
1414
-- you need to run if you change them
15-
index-state: 2022-12-11T00:00:00Z
15+
index-state: 2023-01-20T05:50:56Z
1616

1717
index-state:
18-
, hackage.haskell.org 2022-12-11T00:00:00Z
18+
, hackage.haskell.org 2023-01-20T05:50:56Z
1919
, cardano-haskell-packages 2022-12-14T00:40:15Z
2020

2121
packages:

cardano-api/cardano-api.cabal

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ library
166166
, text
167167
, time
168168
, transformers
169-
, transformers-except
169+
, transformers-except ^>= 0.1.3
170170
, typed-protocols ^>= 0.1
171171
, unordered-containers >= 0.2.11
172172
, vector

cardano-api/src/Cardano/Api.hs

+1
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,7 @@ module Cardano.Api (
620620
UTxO(..),
621621
queryNodeLocalState,
622622
executeQueryCardanoMode,
623+
UnsupportedNtcVersionError(..),
623624

624625
-- *** Local tx monitoring
625626
LocalTxMonitorClient(..),

cardano-api/src/Cardano/Api/IPC.hs

+4-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ module Cardano.Api.IPC (
7777
consensusModeOnly,
7878
toAcquiringFailure,
7979

80-
NodeToClientVersion(..)
80+
NodeToClientVersion(..),
81+
82+
UnsupportedNtcVersionError(..),
8183
) where
8284

8385
import Prelude
@@ -130,6 +132,7 @@ import qualified Ouroboros.Consensus.Shelley.Ledger.Block as Consensus
130132
import Cardano.Api.Block
131133
import Cardano.Api.HasTypeProxy
132134
import Cardano.Api.InMode
135+
import Cardano.Api.IPC.Version
133136
import Cardano.Api.Modes
134137
import Cardano.Api.NetworkId
135138
import Cardano.Api.Protocol

cardano-api/src/Cardano/Api/IPC/Monad.hs

+23-15
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,15 @@ module Cardano.Api.IPC.Monad
99
, determineEraExpr
1010
) where
1111

12-
import Control.Applicative
12+
import Prelude
13+
1314
import Control.Concurrent.STM
1415
import Control.Monad
1516
import Control.Monad.IO.Class
1617
import Control.Monad.Reader
1718
import Control.Monad.Trans.Cont
19+
import Control.Monad.Trans.Except (ExceptT (..), runExceptT)
1820
import Data.Bifunctor (first)
19-
import Data.Either
20-
import Data.Function
21-
import Data.Maybe
22-
import System.IO
2321

2422
import Cardano.Ledger.Shelley.Scripts ()
2523
import qualified Ouroboros.Network.Protocol.LocalStateQuery.Client as Net.Query
@@ -28,6 +26,7 @@ import qualified Ouroboros.Network.Protocol.LocalStateQuery.Type as Net.Query
2826
import Cardano.Api.Block
2927
import Cardano.Api.Eras
3028
import Cardano.Api.IPC
29+
import Cardano.Api.IPC.Version
3130
import Cardano.Api.Modes
3231

3332

@@ -97,21 +96,30 @@ setupLocalStateQueryExpr waitDone mPointVar' resultVar' ntcVersion f =
9796
pure $ Net.Query.SendMsgDone ()
9897
}
9998

99+
-- | Get the node server's Node-to-Client version.
100+
getNtcVersion :: LocalStateQueryExpr block point (QueryInMode mode) r IO NodeToClientVersion
101+
getNtcVersion = LocalStateQueryExpr ask
102+
100103
-- | Use 'queryExpr' in a do block to construct monadic local state queries.
101-
queryExpr :: QueryInMode mode a -> LocalStateQueryExpr block point (QueryInMode mode) r IO a
102-
queryExpr q =
103-
LocalStateQueryExpr . ReaderT $ \_ -> ContT $ \f -> pure $
104-
Net.Query.SendMsgQuery q $
105-
Net.Query.ClientStQuerying
106-
{ Net.Query.recvMsgResult = f
107-
}
104+
queryExpr :: QueryInMode mode a -> LocalStateQueryExpr block point (QueryInMode mode) r IO (Either UnsupportedNtcVersionError a)
105+
queryExpr q = do
106+
let minNtcVersion = nodeToClientVersionOf q
107+
ntcVersion <- getNtcVersion
108+
if ntcVersion >= minNtcVersion
109+
then
110+
fmap Right . LocalStateQueryExpr . ReaderT $ \_ -> ContT $ \f -> pure $
111+
Net.Query.SendMsgQuery q $
112+
Net.Query.ClientStQuerying
113+
{ Net.Query.recvMsgResult = f
114+
}
115+
else pure (Left (UnsupportedNtcVersionError minNtcVersion ntcVersion))
108116

109117
-- | A monad expression that determines what era the node is in.
110118
determineEraExpr ::
111119
ConsensusModeParams mode
112-
-> LocalStateQueryExpr block point (QueryInMode mode) r IO AnyCardanoEra
113-
determineEraExpr cModeParams =
120+
-> LocalStateQueryExpr block point (QueryInMode mode) r IO (Either UnsupportedNtcVersionError AnyCardanoEra)
121+
determineEraExpr cModeParams = runExceptT $
114122
case consensusModeOnly cModeParams of
115123
ByronMode -> return $ AnyCardanoEra ByronEra
116124
ShelleyMode -> return $ AnyCardanoEra ShelleyEra
117-
CardanoMode -> queryExpr $ QueryCurrentEra CardanoModeIsMultiEra
125+
CardanoMode -> ExceptT $ queryExpr $ QueryCurrentEra CardanoModeIsMultiEra

cardano-cli/cardano-cli.cabal

+1-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ library
147147
, text
148148
, time
149149
, transformers
150-
, transformers-except
150+
, transformers-except ^>= 0.1.3
151151
, unliftio-core
152152
, utf8-string
153153
, vector

cardano-cli/src/Cardano/CLI/Shelley/Run/Query.hs

+49-48
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import Cardano.Api.Shelley
3636

3737
import Control.Monad.Trans.Except (except)
3838
import Control.Monad.Trans.Except.Extra (firstExceptT, handleIOExceptT, hoistEither,
39-
hoistMaybe, left, newExceptT)
39+
hoistMaybe, left, newExceptT, onLeft, onNothing)
4040
import Data.Aeson as Aeson
4141
import Data.Aeson.Encode.Pretty (encodePretty)
4242
import Data.Aeson.Types as Aeson
@@ -89,7 +89,7 @@ import Cardano.Slotting.EpochInfo (EpochInfo (..), epochInfoSlotToUTCT
8989
import Ouroboros.Consensus.BlockchainTime.WallClock.Types (RelativeTime (..),
9090
toRelativeTime)
9191
import Ouroboros.Consensus.Cardano.Block as Consensus (EraMismatch (..))
92-
import Ouroboros.Consensus.Protocol.TPraos ( StandardCrypto )
92+
import Ouroboros.Consensus.Protocol.TPraos (StandardCrypto)
9393
import Ouroboros.Network.Block (Serialised (..))
9494

9595
import qualified Ouroboros.Consensus.HardFork.History as Consensus
@@ -129,6 +129,7 @@ data ShelleyQueryCmdError
129129
-- ^ Operational certificate of the unknown stake pool.
130130
| ShelleyQueryCmdPoolStateDecodeError DecoderError
131131
| ShelleyQueryCmdStakeSnapshotDecodeError DecoderError
132+
| ShelleyQueryCmdUnsupportedNtcVersion !UnsupportedNtcVersionError
132133

133134
deriving Show
134135

@@ -168,6 +169,10 @@ renderShelleyQueryCmdError err =
168169
"Failed to decode PoolState. Error: " <> Text.pack (show decoderError)
169170
ShelleyQueryCmdStakeSnapshotDecodeError decoderError ->
170171
"Failed to decode StakeSnapshot. Error: " <> Text.pack (show decoderError)
172+
ShelleyQueryCmdUnsupportedNtcVersion (UnsupportedNtcVersionError minNtcVersion ntcVersion) ->
173+
"Unsupported feature for the node-to-client protocol version.\n" <>
174+
"This query requires at least " <> show minNtcVersion <> " but the node negotiated " <> show ntcVersion <> ".\n" <>
175+
"Later node versions support later protocol versions (but development protocol versions are not enabled in the node by default)."
171176

172177
runQueryCmd :: QueryCmd -> ExceptT ShelleyQueryCmdError IO ()
173178
runQueryCmd cmd =
@@ -210,7 +215,8 @@ runQueryProtocolParameters (AnyConsensusModeParams cModeParams) network mOutFile
210215
let localNodeConnInfo = LocalNodeConnectInfo cModeParams network sockPath
211216

212217
result <- liftIO $ executeLocalStateQueryExpr localNodeConnInfo Nothing $ runExceptT $ do
213-
anyE@(AnyCardanoEra era) <- lift $ determineEraExpr cModeParams
218+
anyE@(AnyCardanoEra era) <- lift (determineEraExpr cModeParams)
219+
& onLeft (left . ShelleyQueryCmdUnsupportedNtcVersion)
214220

215221
case cardanoEraStyle era of
216222
LegacyByronEra -> left ShelleyQueryCmdByronEra
@@ -220,11 +226,12 @@ runQueryProtocolParameters (AnyConsensusModeParams cModeParams) network mOutFile
220226
eInMode <- toEraInMode era cMode
221227
& hoistMaybe (ShelleyQueryCmdEraConsensusModeMismatch (AnyConsensusMode cMode) anyE)
222228

223-
ppResult <- lift . queryExpr $ QueryInEra eInMode $ QueryInShelleyBasedEra sbe QueryProtocolParameters
224-
225-
except ppResult & firstExceptT ShelleyQueryCmdEraMismatch
229+
lift (queryExpr $ QueryInEra eInMode $ QueryInShelleyBasedEra sbe QueryProtocolParameters)
230+
& onLeft (left . ShelleyQueryCmdUnsupportedNtcVersion)
231+
& onLeft (left . ShelleyQueryCmdEraMismatch)
226232

227233
writeProtocolParameters mOutFile =<< except (join (first ShelleyQueryCmdAcquireFailure result))
234+
228235
where
229236
writeProtocolParameters
230237
:: Maybe OutputFile
@@ -277,45 +284,36 @@ runQueryTip
277284
-> Maybe OutputFile
278285
-> ExceptT ShelleyQueryCmdError IO ()
279286
runQueryTip (AnyConsensusModeParams cModeParams) network mOutFile = do
280-
SocketPath sockPath <- firstExceptT ShelleyQueryCmdEnvVarSocketErr
281-
$ newExceptT readEnvSocketPath
287+
SocketPath sockPath <- lift readEnvSocketPath & onLeft (left . ShelleyQueryCmdEnvVarSocketErr)
282288

283289
case consensusModeOnly cModeParams of
284290
CardanoMode -> do
285291
let localNodeConnInfo = LocalNodeConnectInfo cModeParams network sockPath
286292

287-
eLocalState <- liftIO $ executeLocalStateQueryExpr localNodeConnInfo Nothing $ do
288-
ntcVersion <- ask
289-
era <- queryExpr (QueryCurrentEra CardanoModeIsMultiEra)
290-
eraHistory <- queryExpr (QueryEraHistory CardanoModeIsMultiEra)
291-
mChainBlockNo <- if ntcVersion >= NodeToClientV_10
292-
then Just <$> queryExpr QueryChainBlockNo
293-
else return Nothing
294-
mChainPoint <- if ntcVersion >= NodeToClientV_10
295-
then Just <$> queryExpr (QueryChainPoint CardanoMode)
296-
else return Nothing
297-
mSystemStart <- if ntcVersion >= NodeToClientV_9
298-
then Just <$> queryExpr QuerySystemStart
299-
else return Nothing
300-
301-
return O.QueryTipLocalState
302-
{ O.era = era
303-
, O.eraHistory = eraHistory
304-
, O.mSystemStart = mSystemStart
305-
, O.mChainTip = makeChainTip <$> mChainBlockNo <*> mChainPoint
306-
}
293+
eLocalState <- ExceptT $ fmap sequence $
294+
executeLocalStateQueryExpr localNodeConnInfo Nothing $ runExceptT $ do
295+
era <- lift (queryExpr (QueryCurrentEra CardanoModeIsMultiEra)) & onLeft (left . ShelleyQueryCmdUnsupportedNtcVersion)
296+
eraHistory <- lift (queryExpr (QueryEraHistory CardanoModeIsMultiEra)) & onLeft (left . ShelleyQueryCmdUnsupportedNtcVersion)
297+
mChainBlockNo <- lift (queryExpr QueryChainBlockNo) & onLeft (left . ShelleyQueryCmdUnsupportedNtcVersion) & fmap Just
298+
mChainPoint <- lift (queryExpr (QueryChainPoint CardanoMode)) & onLeft (left . ShelleyQueryCmdUnsupportedNtcVersion) & fmap Just
299+
mSystemStart <- lift (queryExpr QuerySystemStart) & onLeft (left . ShelleyQueryCmdUnsupportedNtcVersion) & fmap Just
300+
301+
return O.QueryTipLocalState
302+
{ O.era = era
303+
, O.eraHistory = eraHistory
304+
, O.mSystemStart = mSystemStart
305+
, O.mChainTip = makeChainTip <$> mChainBlockNo <*> mChainPoint
306+
}
307307

308308
mLocalState <- hushM (first ShelleyQueryCmdAcquireFailure eLocalState) $ \e ->
309309
liftIO . T.hPutStrLn IO.stderr $ "Warning: Local state unavailable: " <> renderShelleyQueryCmdError e
310310

311-
chainTip <- case mLocalState >>= O.mChainTip of
312-
Just chainTip -> return chainTip
313-
311+
chainTip <- pure (mLocalState >>= O.mChainTip)
314312
-- The chain tip is unavailable via local state query because we are connecting with an older
315313
-- node to client protocol so we use chain sync instead which necessitates another connection.
316314
-- At some point when we can stop supporting the older node to client protocols, this fallback
317315
-- can be removed.
318-
Nothing -> queryChainTipViaChainSync localNodeConnInfo
316+
& onNothing (queryChainTipViaChainSync localNodeConnInfo)
319317

320318
let tipSlotNo :: SlotNo = case chainTip of
321319
ChainTipAtGenesis -> 0
@@ -1018,30 +1016,33 @@ runQueryStakePools
10181016
-> ExceptT ShelleyQueryCmdError IO ()
10191017
runQueryStakePools (AnyConsensusModeParams cModeParams)
10201018
network mOutFile = do
1021-
SocketPath sockPath <- firstExceptT ShelleyQueryCmdEnvVarSocketErr
1022-
$ newExceptT readEnvSocketPath
1019+
SocketPath sockPath <- lift readEnvSocketPath & onLeft (left . ShelleyQueryCmdEnvVarSocketErr)
10231020

10241021
let localNodeConnInfo = LocalNodeConnectInfo cModeParams network sockPath
10251022

1026-
result <- ExceptT . fmap (join . first ShelleyQueryCmdAcquireFailure) $
1027-
executeLocalStateQueryExpr localNodeConnInfo Nothing $ runExceptT @ShelleyQueryCmdError $ do
1028-
anyE@(AnyCardanoEra era) <- case consensusModeOnly cModeParams of
1029-
ByronMode -> return $ AnyCardanoEra ByronEra
1030-
ShelleyMode -> return $ AnyCardanoEra ShelleyEra
1031-
CardanoMode -> lift . queryExpr $ QueryCurrentEra CardanoModeIsMultiEra
1023+
poolIds <-
1024+
( lift $ executeLocalStateQueryExpr localNodeConnInfo Nothing $ runExceptT @ShelleyQueryCmdError $ do
1025+
anyE@(AnyCardanoEra era) <- case consensusModeOnly cModeParams of
1026+
ByronMode -> return $ AnyCardanoEra ByronEra
1027+
ShelleyMode -> return $ AnyCardanoEra ShelleyEra
1028+
CardanoMode ->
1029+
lift (queryExpr $ QueryCurrentEra CardanoModeIsMultiEra)
1030+
& onLeft (left . ShelleyQueryCmdUnsupportedNtcVersion)
10321031

1033-
let cMode = consensusModeOnly cModeParams
1032+
let cMode = consensusModeOnly cModeParams
10341033

1035-
case toEraInMode era cMode of
1036-
Just eInMode -> do
1037-
sbe <- getSbe $ cardanoEraStyle era
1034+
eInMode <- toEraInMode era cMode
1035+
& hoistMaybe (ShelleyQueryCmdEraConsensusModeMismatch (AnyConsensusMode cMode) anyE)
10381036

1039-
firstExceptT ShelleyQueryCmdEraMismatch . ExceptT $
1040-
queryExpr . QueryInEra eInMode . QueryInShelleyBasedEra sbe $ QueryStakePools
1037+
sbe <- getSbe $ cardanoEraStyle era
10411038

1042-
Nothing -> left $ ShelleyQueryCmdEraConsensusModeMismatch (AnyConsensusMode cMode) anyE
1039+
lift (queryExpr (QueryInEra eInMode $ QueryInShelleyBasedEra sbe $ QueryStakePools))
1040+
& onLeft (left . ShelleyQueryCmdUnsupportedNtcVersion)
1041+
& onLeft (left . ShelleyQueryCmdEraMismatch)
1042+
) & onLeft (left . ShelleyQueryCmdAcquireFailure)
1043+
& onLeft left
10431044

1044-
writeStakePools mOutFile result
1045+
writeStakePools mOutFile poolIds
10451046

10461047
writeStakePools
10471048
:: Maybe OutputFile

0 commit comments

Comments
 (0)