From ffb870ec88343013be066b60ad2ef4b2650e0623 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 17:23:08 +0100 Subject: [PATCH] fix(server/v2/cometbft): proper query error (backport #22746) (#22759) Co-authored-by: Julien Robert --- server/v2/cometbft/abci.go | 11 ++++----- server/v2/cometbft/go.mod | 4 ++-- server/v2/cometbft/go.sum | 4 ++-- server/v2/cometbft/utils.go | 45 +++++++++++++++++++++++++++++++++---- 4 files changed, 51 insertions(+), 13 deletions(-) diff --git a/server/v2/cometbft/abci.go b/server/v2/cometbft/abci.go index c8fc58649e..c376f4ac26 100644 --- a/server/v2/cometbft/abci.go +++ b/server/v2/cometbft/abci.go @@ -188,7 +188,7 @@ func (c *consensus[T]) Query(ctx context.Context, req *abciproto.QueryRequest) ( // it must be an app/p2p/store query path := splitABCIQueryPath(req.Path) if len(path) == 0 { - return QueryResult(errorsmod.Wrap(cometerrors.ErrUnknownRequest, "no query path provided"), c.cfg.AppTomlConfig.Trace), nil + return queryResult(errorsmod.Wrap(cometerrors.ErrUnknownRequest, "no query path provided"), c.cfg.AppTomlConfig.Trace), nil } switch path[0] { @@ -202,11 +202,11 @@ func (c *consensus[T]) Query(ctx context.Context, req *abciproto.QueryRequest) ( resp, err = c.handleQueryP2P(path) default: - resp = QueryResult(errorsmod.Wrapf(cometerrors.ErrUnknownRequest, "unknown query path %s", req.Path), c.cfg.AppTomlConfig.Trace) + resp = queryResult(errorsmod.Wrapf(cometerrors.ErrUnknownRequest, "unknown query path %s", req.Path), c.cfg.AppTomlConfig.Trace) } if err != nil { - return QueryResult(err, c.cfg.AppTomlConfig.Trace), nil + return queryResult(err, c.cfg.AppTomlConfig.Trace), nil } return resp, nil @@ -291,11 +291,12 @@ func (c *consensus[T]) maybeRunGRPCQuery(ctx context.Context, req *abci.QueryReq if err != nil { return nil, true, fmt.Errorf("unable to decode gRPC request with path %s from ABCI.Query: %w", req.Path, err) } + res, err := c.app.Query(ctx, uint64(req.Height), protoRequest) if err != nil { - resp := QueryResult(err, c.cfg.AppTomlConfig.Trace) + resp := gRPCErrorToSDKError(err) resp.Height = req.Height - return resp, true, err + return resp, true, nil } resp, err = queryResponse(res, req.Height) diff --git a/server/v2/cometbft/go.mod b/server/v2/cometbft/go.mod index 0a05e656af..46f832a4e1 100644 --- a/server/v2/cometbft/go.mod +++ b/server/v2/cometbft/go.mod @@ -6,7 +6,7 @@ replace ( // pseudo version lower than the latest tag cosmossdk.io/api => cosmossdk.io/api v0.7.3-0.20240924065902-eb7653cfecdf // main // pseudo version lower than the latest tag - cosmossdk.io/store => cosmossdk.io/store v1.0.0-rc.0.0.20241202115147-f350775d0ed2 // main + cosmossdk.io/store => cosmossdk.io/store v1.0.0-rc.0.0.20241204123127-eb3bf8b0469d // main cosmossdk.io/x/bank => ../../../x/bank cosmossdk.io/x/consensus => ../../../x/consensus cosmossdk.io/x/staking => ../../../x/staking @@ -17,6 +17,7 @@ require ( cosmossdk.io/api v0.8.0 cosmossdk.io/collections v0.4.1-0.20241128094659-bd76b47e1d8b // main cosmossdk.io/core v1.0.0-alpha.6 + cosmossdk.io/errors v1.0.1 cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 cosmossdk.io/log v1.5.0 cosmossdk.io/schema v0.3.1-0.20241128094659-bd76b47e1d8b //main @@ -42,7 +43,6 @@ require ( buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.35.2-20240130113600-88ef6483f90f.1 // indirect cosmossdk.io/core/testing v0.0.0-20241108153815-606544c7be7e // indirect cosmossdk.io/depinject v1.1.0 // indirect - cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/math v1.4.0 // indirect cosmossdk.io/store v1.1.1-0.20240909133312-50288938d1b6 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect diff --git a/server/v2/cometbft/go.sum b/server/v2/cometbft/go.sum index 6aad37908d..a99a7b3ceb 100644 --- a/server/v2/cometbft/go.sum +++ b/server/v2/cometbft/go.sum @@ -30,8 +30,8 @@ cosmossdk.io/server/v2/appmanager v0.0.0-20241203212527-7d117425d880 h1:0mtB8fSv cosmossdk.io/server/v2/appmanager v0.0.0-20241203212527-7d117425d880/go.mod h1:elhlrldWtm+9U4PxE0G3wjz83yQwVVGVAOncXJPY1Xc= cosmossdk.io/server/v2/stf v0.0.0-20241204101618-7fa2356c07aa h1:2V9nqgL50nw45HcQw1UBRQ/y0QBzrgfLIStPSxFnMtY= cosmossdk.io/server/v2/stf v0.0.0-20241204101618-7fa2356c07aa/go.mod h1:4e9SzLyeGptQ3tSR6nKCNwCu7Ye4uUS2WIJih29dG2c= -cosmossdk.io/store v1.0.0-rc.0.0.20241202115147-f350775d0ed2 h1:UCe04NMBR+1M5JRpZJvM+I0EZzD3zXrk9YOm2RZdKDg= -cosmossdk.io/store v1.0.0-rc.0.0.20241202115147-f350775d0ed2/go.mod h1:oZBBY4BrkYnghr6MFL0MP5mGqpkPedHcWkXwXddd6tU= +cosmossdk.io/store v1.0.0-rc.0.0.20241204123127-eb3bf8b0469d h1:KQM4Q6kjwlM4HuDZRV8/ZDXX3whjfStndYNTsRrbboQ= +cosmossdk.io/store v1.0.0-rc.0.0.20241204123127-eb3bf8b0469d/go.mod h1:oZBBY4BrkYnghr6MFL0MP5mGqpkPedHcWkXwXddd6tU= cosmossdk.io/store/v2 v2.0.0-20241203212527-7d117425d880 h1:oQiiB1e2yg6/ttUCKLBAdbLuyUp9UYW2K8QGnCs7dWg= cosmossdk.io/store/v2 v2.0.0-20241203212527-7d117425d880/go.mod h1:1DbksNgjyQ1XxlCYqkU82WqBGWcxmgciO5dBf6dRhKM= cosmossdk.io/x/tx v1.0.0-alpha.2 h1:UW80FMm7B0fiAMsrfe5+HabSJ3XBg+tQa6/GK9prqWk= diff --git a/server/v2/cometbft/utils.go b/server/v2/cometbft/utils.go index 3929debe65..d4c3ccf86b 100644 --- a/server/v2/cometbft/utils.go +++ b/server/v2/cometbft/utils.go @@ -12,16 +12,19 @@ import ( cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" gogoproto "github.com/cosmos/gogoproto/proto" gogoany "github.com/cosmos/gogoproto/types/any" + "google.golang.org/grpc/codes" + grpcstatus "google.golang.org/grpc/status" appmodulev2 "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/comet" "cosmossdk.io/core/event" "cosmossdk.io/core/server" "cosmossdk.io/core/transaction" - errorsmod "cosmossdk.io/errors/v2" + errorsmod "cosmossdk.io/errors" // we aren't using errors/v2 as it doesn't support grpc status codes "cosmossdk.io/x/consensus/types" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) func queryResponse(res transaction.Msg, height int64) (*abci.QueryResponse, error) { @@ -258,9 +261,8 @@ func ToSDKExtendedCommitInfo(commit abci.ExtendedCommitInfo) comet.CommitInfo { return ci } -// QueryResult returns a ResponseQuery from an error. It will try to parse ABCI -// info from the error. -func QueryResult(err error, debug bool) *abci.QueryResponse { +// queryResult returns a ResponseQuery from an error. It will try to parse ABCI info from the error. +func queryResult(err error, debug bool) *abci.QueryResponse { space, code, log := errorsmod.ABCIInfo(err, debug) return &abci.QueryResponse{ Codespace: space, @@ -269,6 +271,41 @@ func QueryResult(err error, debug bool) *abci.QueryResponse { } } +func gRPCErrorToSDKError(err error) *abci.QueryResponse { + toQueryResp := func(sdkErr *errorsmod.Error, err error) *abci.QueryResponse { + res := &abci.QueryResponse{ + Code: sdkErr.ABCICode(), + Codespace: sdkErr.Codespace(), + } + type grpcStatus interface{ GRPCStatus() *grpcstatus.Status } + if grpcErr, ok := err.(grpcStatus); ok { + res.Log = grpcErr.GRPCStatus().Message() + } else { + res.Log = err.Error() + } + return res + + } + + status, ok := grpcstatus.FromError(err) + if !ok { + return toQueryResp(sdkerrors.ErrInvalidRequest, err) + } + + switch status.Code() { + case codes.NotFound: + return toQueryResp(sdkerrors.ErrKeyNotFound, err) + case codes.InvalidArgument: + return toQueryResp(sdkerrors.ErrInvalidRequest, err) + case codes.FailedPrecondition: + return toQueryResp(sdkerrors.ErrInvalidRequest, err) + case codes.Unauthenticated: + return toQueryResp(sdkerrors.ErrUnauthorized, err) + default: + return toQueryResp(sdkerrors.ErrUnknownRequest, err) + } +} + func (c *consensus[T]) validateFinalizeBlockHeight(req *abci.FinalizeBlockRequest) error { if req.Height < 1 { return fmt.Errorf("invalid height: %d", req.Height)