Skip to content

Better error message for query utxo 2 #3358

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from

Conversation

newhoggy
Copy link
Contributor

@newhoggy newhoggy commented Nov 10, 2021

This PR adds better messages for query utxo. It replaces an earlier PR #2957.

This PR improves on the earlier version by making it so that the monadic expressions no longer need to know what version each query requires. If the node that is connected to does not support the query being made, then the query expression throws QueryErrorUnsupportedVersion which can be handled in a convenient top-level location.

@newhoggy newhoggy force-pushed the better-error-message-for-query-utxo-2 branch 2 times, most recently from b8420d5 to a05cf06 Compare November 16, 2021 11:18
@@ -42,15 +50,15 @@ import qualified Ouroboros.Network.Protocol.LocalStateQuery.Type as Net.Query
-- In order to make pipelining still possible we can explore the use of Selective Functors
-- which would allow us to straddle both worlds.
newtype LocalStateQueryExpr block point query r m a = LocalStateQueryExpr
{ runLocalStateQueryExpr :: ContT (Net.Query.ClientStAcquired block point query m r) m a
{ runLocalStateQueryExpr :: ReaderT NodeToClientVersion (ContT (Net.Query.ClientStAcquired block point query m r) m) a
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ReaderT allows the monad expression to know the node to client version of the node server.

else return Nothing
mSystemStart <- if ntcVersion >= NodeToClientV_9
then Just <$> queryExpr QuerySystemStart
else return Nothing
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is simplified a lot. Not only is it shorter, but we no longer need to know what node version a given query requires. Instead if the query is not supported by the node then Nothing is returned.

@@ -846,10 +851,12 @@ determineEra cModeParams localNodeConnInfo =
ByronMode -> return $ AnyCardanoEra ByronEra
ShelleyMode -> return $ AnyCardanoEra ShelleyEra
CardanoMode -> do
eraQ <- liftIO . queryNodeLocalState localNodeConnInfo Nothing
$ QueryCurrentEra CardanoModeIsMultiEra
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We no longer need queryNodeLocalState because they can all by replaced by executeLocalStateQueryExpr/queryExpr.

@@ -327,20 +333,15 @@ readCustomRedeemerFromTx fp (AnyConsensusModeParams cModeParams) network = do
(ConsensusModeMismatch (AnyConsensusMode CardanoMode) (AnyCardanoEra cEra))
$ toEraInMode cEra CardanoMode

eResult <-
liftIO $ executeLocalStateQueryExpr localNodeConnInfo Nothing
$ \ntcVersion -> do
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We no longer need to worry about ntcVersion lambda when executing queries because of the use of ReaderT.

Copy link
Contributor

@Jimbo4350 Jimbo4350 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right direction, a couple of comments 👍

@@ -298,6 +303,12 @@ runQueryTip (AnyConsensusModeParams cModeParams) network mOutFile = do
-- via the local state query protocol.
--

minNtcVersionForQueryUTxOFilter :: QueryUTxOFilter -> NodeToClientVersion
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably add a comment like "See data NodeToClientVersion in ouroboros-network for more details". There also appears to be more version related information by data QueryVersion. We should aim to have all queries in the cli accounted for here so when we have a new query the type checker complains we have a missing pattern match.

Copy link
Contributor Author

@newhoggy newhoggy Nov 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what happened in the review presentation, but minNtcVersionForQueryUTxOFilter doesn't exist anymore. Maybe I had unpushed changes.

@@ -347,7 +359,7 @@ runQueryPoolParams (AnyConsensusModeParams cModeParams) network poolid = do
& hoistMaybe (ShelleyQueryCmdEraConsensusModeMismatch (AnyConsensusMode cMode) anyE)

let qInMode = QueryInEra eInMode . QueryInShelleyBasedEra sbe $ QueryDebugLedgerState
result <- executeQuery era cModeParams localNodeConnInfo qInMode
result <- executeQuery era cModeParams NodeToClientV_1 localNodeConnInfo qInMode
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is the type of situation we don't want. If we can implement a function that takes qInMode and returns a minimum required node version, that would be ideal.

Copy link
Contributor Author

@newhoggy newhoggy Nov 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as my previous comment. #3358 (comment)

@@ -141,6 +144,11 @@ runQueryCmd cmd =
QueryUTxO' consensusModeParams qFilter networkId mOutFile ->
runQueryUTxO consensusModeParams qFilter networkId mOutFile

queryErrorToShelleyQueryCmdError :: QueryError ShelleyQueryCmdError -> ShelleyQueryCmdError
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not add an additional constructor to ShelleyQueryCmdError? E.g ShelleyQueryRelatedCmdError QueryError

@newhoggy newhoggy force-pushed the better-error-message-for-query-utxo-2 branch from 84d1d98 to b70ed67 Compare November 19, 2021 09:20
@newhoggy newhoggy requested a review from Jimbo4350 November 19, 2021 09:46
* Better error message for query utxo
* Use connectToLocalNode instead of connectToLocalNodeWithVersion where possible
* Introduce QueryError type
* Reader monad for NtcVersion to simplify code
* NtcVersionOf type class with instances
* Introduce maybeQueryExpr to make it easy to handle optional queries
* Delete queryNodeLocalStateWithVersion
* Replace all uses of queryNodeLocalState with executeLocalStateQueryExpr
@newhoggy newhoggy force-pushed the better-error-message-for-query-utxo-2 branch from b70ed67 to df3209a Compare November 19, 2021 22:57
@newhoggy newhoggy dismissed Jimbo4350’s stale review November 22, 2021 09:05

Comments addressed

Copy link
Contributor

@Jimbo4350 Jimbo4350 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple more comments but right direction

@@ -475,43 +486,41 @@ convLocalStateQueryClient mode =
-- | Establish a connection to a node and execute a single query using the
-- local state query protocol.
--
queryNodeLocalState :: forall mode result.
queryNodeLocalState :: forall e mode result.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why make this polymorphic vs IO (Either QueryError result)?

Copy link
Contributor Author

@newhoggy newhoggy Nov 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason is I want to be able to return errors other than those described by the QueryError constructor in monad query expressions.

For example:

And many more.

The idea is that any user code can construct a complex monadic expression and be able to throw their own errors that are not QueryErrors.

Without this, we would be required to express the error in the return value instead, in which the return value would have to have the type Either e a, but you don't get exception semantics with Either.

Using Either is error prone because it doesn't have exception semantics. The user would have to pattern match for the error to handle it at the use site and also bubble it up. In some cases the user could forget to bubble up the error so it can get forgotten and left unhandled.

LocalNodeConnectInfo mode
-> Maybe ChainPoint
-> (QueryError -> e)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see. I think returning QueryError as the error type and leaving the error conversion to the consumer is a better API.

-> (NodeToClientVersion -> LocalStateQueryExpr (BlockInMode mode) ChainPoint (QueryInMode mode) () IO a)
-> IO (Either AcquireFailure a)
executeLocalStateQueryExpr connectInfo mpoint f = do
-> (QueryError -> e)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. We should return QueryError rather than returning e.

}
-- | Get the node server's Node-to-Client version.
getNtcVersion :: LocalStateQueryExpr block point (QueryInMode mode) r IO (Either QueryError NodeToClientVersion)
getNtcVersion = LocalStateQueryExpr . ReaderT $ pure . Right
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not:

 LocalStateQueryExpr $ do
   v <- ask
   pure $ Right v

In my mind it's clearer as to what's going on but I'd be interested to hear what you think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works for me :D

@@ -136,6 +141,10 @@ runQueryCmd cmd =
QueryUTxO' consensusModeParams qFilter networkId mOutFile ->
runQueryUTxO consensusModeParams qFilter networkId mOutFile

mapQueryError :: QueryError -> ShelleyQueryCmdError
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be additional data constructors in ShelleyQueryCmdError. Generally we use firstExceptT ... to wrap the underlying error types.

@@ -113,6 +113,8 @@ data ShelleyTxCmdError
| ShelleyTxCmdTxInsDoNotExist ![TxIn]
| ShelleyTxCmdMinimumUTxOErr !MinimumUTxOError
| ShelleyTxCmdPParamsErr !ProtocolParametersError
| ShelleyTxCmdUnsupportedVersion !MinNodeToClientVersion !NodeToClientVersion
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this should be ShelleyTxCmdQueryError QueryError

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I merged ShelleyQueryCmdAcquireFailure and ShelleyQueryCmdUnsupportedVersion constructors into ShelleyQueryCmdQueryError, I think this was what you meant?

@@ -243,6 +243,7 @@ data ScriptContextError = NoScriptsInByronEra
| QueryError ShelleyQueryCmdError
| ConsensusModeMismatch AnyConsensusMode AnyCardanoEra
| EraMismatch !Consensus.EraMismatch
| ScriptContextUnsupportedVersion !MinNodeToClientVersion !MinNodeToClientVersion
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And likewise here ScriptContextUnsupportedVersion QueryError

@newhoggy newhoggy force-pushed the better-error-message-for-query-utxo-2 branch from 0242e81 to ceb47f3 Compare November 24, 2021 10:06
…sion constructors into ShelleyQueryCmdQueryError
@newhoggy newhoggy requested a review from Jimbo4350 November 24, 2021 13:29
@newhoggy newhoggy dismissed Jimbo4350’s stale review November 24, 2021 13:30

Addressed some comments and explained motivation for some code.

@newhoggy newhoggy requested a review from cleverca22 as a code owner February 17, 2022 01:26
@newhoggy
Copy link
Contributor Author

Re-implemented in #4788

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants