-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
feat: wire new handlers to grpc #22333
Changes from 11 commits
8d2dd2a
1f1dd1b
56a87f4
d959c05
1f9ff63
f08976a
76a4019
e4bf954
6863035
5248508
466e937
72a7f3c
d520f90
c1646fd
c312f13
af319d3
31419b2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
syntax = "proto3"; | ||
package cosmos.base.grpc.v2; | ||
|
||
import "google/protobuf/any.proto"; | ||
|
||
option go_package = "cosmossdk.io/server/v2/api/grpc"; | ||
|
||
service Service { | ||
rpc Query(QueryRequest) returns (QueryResponse) {} | ||
|
||
rpc ListQueryHandlers(ListQueryHandlersRequest) returns (ListQueryHandlersResponse) {} | ||
} | ||
|
||
message QueryRequest { | ||
google.protobuf.Any request = 1; | ||
} | ||
|
||
message QueryResponse { | ||
google.protobuf.Any response = 1; | ||
} | ||
|
||
message ListQueryHandlersRequest {} | ||
|
||
message ListQueryHandlersResponse { | ||
repeated Handler handlers = 1; | ||
} | ||
|
||
message Handler { | ||
string request_name = 1; | ||
string response_name = 2; | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,91 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
package grpc | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"context" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"errors" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
"google.golang.org/grpc" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"google.golang.org/grpc/codes" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"google.golang.org/grpc/status" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
"cosmossdk.io/core/transaction" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
serverv2 "cosmossdk.io/server/v2" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"github.com/cosmos/gogoproto/proto" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
gogoproto "github.com/cosmos/gogoproto/types/any" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
// RegisterV2Service registers the V2 gRPC service implementation with the given server. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
// It takes a generic type T that implements the transaction.Tx interface. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
func RegisterV2Service[T transaction.Tx](server *grpc.Server, app serverv2.AppI[T]) error { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if server == nil || app == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return errors.New("nil server or app when registering service") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
RegisterServiceServer(server, NewV2Service(app)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
return nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
// V2Service implements the gRPC service interface for handling queries and listing handlers. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
type V2Service[T transaction.Tx] struct { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
app serverv2.AppI[T] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
// NewV2Service creates a new instance of V2Service with the provided app. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
func NewV2Service[T transaction.Tx](app serverv2.AppI[T]) *V2Service[T] { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return &V2Service[T]{app: app} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Query handles incoming query requests by unmarshaling the request, processing it, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
// and returning the response in an Any protobuf message. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
func (s V2Service[T]) Query(ctx context.Context, request *QueryRequest) (*QueryResponse, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if request == nil || request.Request == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return nil, status.Error(codes.InvalidArgument, "empty request") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
msgName := request.Request.TypeUrl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
handlers := s.app.QueryHandlers() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
handler, exists := handlers[msgName] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if !exists { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return nil, status.Errorf(codes.NotFound, "handler not found for %s", msgName) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
protoMsg := handler.MakeMsg() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if err := proto.Unmarshal(request.Request.Value, protoMsg); err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return nil, status.Errorf(codes.InvalidArgument, "failed to unmarshal request: %v", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
queryResp, err := s.app.Query(ctx, 0, protoMsg) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this only works for latest height, we should add a way to query historical info as well There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment should be done in a follow-up indeed. Let's track this. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return nil, status.Errorf(codes.Internal, "query failed: %v", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
respBytes, err := proto.Marshal(queryResp) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return nil, status.Errorf(codes.Internal, "failed to marshal response: %v", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
anyResp := &gogoproto.Any{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
TypeUrl: "/" + proto.MessageName(queryResp), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Value: respBytes, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
return &QueryResponse{Response: anyResp}, nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
func (s V2Service[T]) ListQueryHandlers(_ context.Context, _ *ListQueryHandlersRequest) (*ListQueryHandlersResponse, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
handlersMap := s.app.QueryHandlers() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
var handlerDescriptors []*Handler | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
for handlerName := range handlersMap { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
msg := handlersMap[handlerName].MakeMsg() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
resp := handlersMap[handlerName].MakeMsgResp() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
handlerDescriptors = append(handlerDescriptors, &Handler{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
RequestName: proto.MessageName(msg), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
ResponseName: proto.MessageName(resp), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
for handlerName := range handlersMap { | |
msg := handlersMap[handlerName].MakeMsg() | |
resp := handlersMap[handlerName].MakeMsgResp() | |
handlerDescriptors = append(handlerDescriptors, &Handler{ | |
RequestName: proto.MessageName(msg), | |
ResponseName: proto.MessageName(resp), | |
}) | |
} | |
var handlerDescriptors []*Handler | |
var handlerNames []string | |
for handlerName := range handlersMap { | |
handlerNames = append(handlerNames, handlerName) | |
} | |
sort.Strings(handlerNames) | |
for _, handlerName := range handlerNames { | |
msg := handlersMap[handlerName].MakeMsg() | |
resp := handlersMap[handlerName].MakeMsgResp() | |
handlerDescriptors = append(handlerDescriptors, &Handler{ | |
RequestName: proto.MessageName(msg), | |
ResponseName: proto.MessageName(resp), | |
}) | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid exposing internal error details to clients
Returning detailed error messages can leak internal information and pose security risks. Consider returning generic error messages to the client and logging the detailed errors internally.
Apply this diff to adjust the error messages:
Also applies to: 52-53, 57-58