-
Notifications
You must be signed in to change notification settings - Fork 4.1k
feat: wire new handlers to grpc #22333
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
Changes from 6 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 = "github.com/cosmos/cosmos-sdk/server/v2/api/grpc"; | ||
|
|
||
|
Contributor
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. Package directory structure needs adjustment The package "cosmos.base.grpc.v2" should be within a directory "cosmos/base/grpc/v2" relative to root, but it's currently in "proto/cosmos/base/grpc/v2". This mismatch could cause issues with buf and other Protocol Buffer tools. Consider moving the file to the correct directory structure or adjusting the package name to match the current directory structure. 🧰 Tools🪛 buf
|
||
| 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 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -71,6 +71,8 @@ func (s *Server[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logger log.L | |||||||||||
| // Reflection allows external clients to see what services and methods the gRPC server exposes. | ||||||||||||
| gogoreflection.Register(grpcSrv, slices.Collect(maps.Keys(methodsMap)), logger.With("sub-module", "grpc-reflection")) | ||||||||||||
|
|
||||||||||||
| RegisterV2Service(grpcSrv, appI) | ||||||||||||
|
|
||||||||||||
|
||||||||||||
| RegisterV2Service(grpcSrv, appI) | |
| // Register the v2 gRPC service for handling queries | |
| if err := RegisterV2Service(grpcSrv, appI); err != nil { | |
| return fmt.Errorf("failed to register v2 service: %w", err) | |
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,88 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package grpc | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "context" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "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]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
randygrok marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if server == nil || app == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| panic("server and app must not be nil") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if server == nil || app == nil { | |
| panic("server and app must not be nil") | |
| } | |
| if server == nil || app == nil { | |
| return errors.New("server and app must not be nil") | |
| } |
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:
if !exists {
- return nil, status.Errorf(codes.NotFound, "handler not found for %s", msgName)
+ return nil, status.Error(codes.NotFound, "handler not found")
}
if err := proto.Unmarshal(request.Request.Value, protoMsg); err != nil {
- return nil, status.Errorf(codes.InvalidArgument, "failed to unmarshal request: %v", err)
+ return nil, status.Error(codes.InvalidArgument, "invalid request format")
}
if err != nil {
- return nil, status.Errorf(codes.Internal, "query failed: %v", err)
+ return nil, status.Error(codes.Internal, "internal server error")
}Also applies to: 52-53, 57-58
Outdated
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.
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 comment
The 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.
Fixed
Show fixed
Hide fixed
Outdated
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.
Ensure deterministic iteration over map to avoid non-determinism
Iterating over a map in Go does not guarantee order, which may lead to non-deterministic results. If the order of handlerDescriptors is important, consider sorting the handler names before iterating over them.
Apply this diff to sort the handler names:
+import (
+ "sort"
+ // other imports
+)
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),
})
}This ensures that the handlers are processed in a consistent order.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 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), | |
| }) | |
| } |
Uh oh!
There was an error while loading. Please reload this page.