diff --git a/baseapp/msg_service_router.go b/baseapp/msg_service_router.go index 21ba4371e426..f4f8d86f22f0 100644 --- a/baseapp/msg_service_router.go +++ b/baseapp/msg_service_router.go @@ -3,6 +3,7 @@ package baseapp import ( "context" "fmt" + "reflect" abci "github.com/cometbft/cometbft/abci/types" gogogrpc "github.com/cosmos/gogoproto/grpc" @@ -139,12 +140,14 @@ func (msr *MsgServiceRouter) registerMsgServiceHandler(sd *grpc.ServiceDesc, met methodHandler := method.Handler var requestTypeName string + var theMsg sdk.Msg // NOTE: This is how we pull the concrete request type for each handler for registering in the InterfaceRegistry. // This approach is maybe a bit hacky, but less hacky than reflecting on the handler object itself. // We use a no-op interceptor to avoid actually calling into the handler itself. _, _ = methodHandler(nil, context.Background(), func(i interface{}) error { - msg, ok := i.(sdk.Msg) + var ok bool + theMsg, ok = i.(sdk.Msg) if !ok { // We panic here because there is no other alternative and the app cannot be initialized correctly // this should only happen if there is a problem with code generation in which case the app won't @@ -152,7 +155,7 @@ func (msr *MsgServiceRouter) registerMsgServiceHandler(sd *grpc.ServiceDesc, met panic(fmt.Errorf("unable to register service method %s: %T does not implement sdk.Msg", fqMethod, i)) } - requestTypeName = sdk.MsgTypeURL(msg) + requestTypeName = sdk.MsgTypeURL(theMsg) return nil }, noopInterceptor) @@ -171,6 +174,9 @@ func (msr *MsgServiceRouter) registerMsgServiceHandler(sd *grpc.ServiceDesc, met requestTypeName, ) } + if reflect.TypeOf(reqType) != reflect.TypeOf(theMsg) { + return fmt.Errorf("the type registered with the interface registry %T does not match the type in the handler %T", reqType, theMsg) + } // Check that each service is only registered once. If a service is // registered more than once, then we should error. Since we can't diff --git a/types/msgservice/msg_service.go b/types/msgservice/msg_service.go index 4c39753022fa..0653668344b9 100644 --- a/types/msgservice/msg_service.go +++ b/types/msgservice/msg_service.go @@ -1,18 +1,10 @@ package msgservice import ( - "bytes" - "compress/gzip" - "fmt" - "io" "reflect" "github.com/cosmos/gogoproto/proto" "google.golang.org/grpc" - proto2 "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protodesc" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/types/descriptorpb" "cosmossdk.io/core/registry" @@ -21,54 +13,28 @@ import ( ) // RegisterMsgServiceDesc registers all type_urls from Msg services described -// in `sd` into the registry. +// in `sd` into the registry. The ServiceDesc must be a standard gRPC ServiceDesc +// from a generated file as this function will use reflection to extract the +// concrete types and expects the HandlerType to follow the normal +// generated type conventions. func RegisterMsgServiceDesc(registrar registry.InterfaceRegistrar, sd *grpc.ServiceDesc) { - fdBytesUnzipped := unzip(proto.FileDescriptor(sd.Metadata.(string))) - if fdBytesUnzipped == nil { - panic(fmt.Errorf("error unzipping file description for MsgService %s", sd.ServiceName)) + handlerType := reflect.TypeOf(sd.HandlerType).Elem() + msgType := reflect.TypeOf((*proto.Message)(nil)).Elem() + numMethods := handlerType.NumMethod() + for i := 0; i < numMethods; i++ { + method := handlerType.Method(i) + numIn := method.Type.NumIn() + numOut := method.Type.NumOut() + if numIn != 2 || numOut != 2 { + continue + } + reqType := method.Type.In(1) + resType := method.Type.Out(0) + if reqType.AssignableTo(msgType) && resType.AssignableTo(msgType) { + req := reflect.New(reqType.Elem()).Interface() + registrar.RegisterImplementations((*sdk.Msg)(nil), req.(proto.Message)) + res := reflect.New(resType.Elem()).Interface() + registrar.RegisterImplementations((*tx.MsgResponse)(nil), res.(proto.Message)) + } } - - fdRaw := &descriptorpb.FileDescriptorProto{} - err := proto2.Unmarshal(fdBytesUnzipped, fdRaw) - if err != nil { - panic(err) - } - - fd, err := protodesc.FileOptions{ - AllowUnresolvable: true, - }.New(fdRaw, nil) - if err != nil { - panic(err) - } - - prefSd := fd.Services().ByName(protoreflect.FullName(sd.ServiceName).Name()) - for i := 0; i < prefSd.Methods().Len(); i++ { - md := prefSd.Methods().Get(i) - requestDesc := md.Input() - responseDesc := md.Output() - - reqTyp := proto.MessageType(string(requestDesc.FullName())) - respTyp := proto.MessageType(string(responseDesc.FullName())) - - // Register sdk.Msg and sdk.MsgResponse to the registry. - registrar.RegisterImplementations((*sdk.Msg)(nil), reflect.New(reqTyp).Elem().Interface().(proto.Message)) - registrar.RegisterImplementations((*tx.MsgResponse)(nil), reflect.New(respTyp).Elem().Interface().(proto.Message)) - } -} - -func unzip(b []byte) []byte { - if b == nil { - return nil - } - r, err := gzip.NewReader(bytes.NewReader(b)) - if err != nil { - panic(err) - } - - unzipped, err := io.ReadAll(r) - if err != nil { - panic(err) - } - - return unzipped }