github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/server/grpc/reflection/v2alpha1/reflection.go (about) 1 package v2alpha1 2 3 import ( 4 "context" 5 "fmt" 6 7 codectypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec/types" 8 9 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 10 11 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/tx" 12 13 "github.com/gogo/protobuf/proto" 14 "google.golang.org/grpc" 15 ) 16 17 type Config struct { 18 SigningModes map[string]int32 19 ChainID string 20 SdkConfig *sdk.Config 21 InterfaceRegistry codectypes.InterfaceRegistry 22 } 23 24 // Register registers the cosmos sdk reflection service 25 // to the provided *grpc.Server given a Config 26 func Register(srv *grpc.Server, conf Config) error { 27 reflectionServer, err := newReflectionServiceServer(srv, conf) 28 if err != nil { 29 return err 30 } 31 RegisterReflectionServiceServer(srv, reflectionServer) 32 return nil 33 } 34 35 type reflectionServiceServer struct { 36 desc *AppDescriptor 37 } 38 39 func (r reflectionServiceServer) GetAuthnDescriptor(_ context.Context, _ *GetAuthnDescriptorRequest) (*GetAuthnDescriptorResponse, error) { 40 return &GetAuthnDescriptorResponse{Authn: r.desc.Authn}, nil 41 } 42 43 func (r reflectionServiceServer) GetChainDescriptor(_ context.Context, _ *GetChainDescriptorRequest) (*GetChainDescriptorResponse, error) { 44 return &GetChainDescriptorResponse{Chain: r.desc.Chain}, nil 45 } 46 47 func (r reflectionServiceServer) GetCodecDescriptor(_ context.Context, _ *GetCodecDescriptorRequest) (*GetCodecDescriptorResponse, error) { 48 return &GetCodecDescriptorResponse{Codec: r.desc.Codec}, nil 49 } 50 51 func (r reflectionServiceServer) GetConfigurationDescriptor(_ context.Context, _ *GetConfigurationDescriptorRequest) (*GetConfigurationDescriptorResponse, error) { 52 return &GetConfigurationDescriptorResponse{Config: r.desc.Configuration}, nil 53 } 54 55 func (r reflectionServiceServer) GetQueryServicesDescriptor(_ context.Context, _ *GetQueryServicesDescriptorRequest) (*GetQueryServicesDescriptorResponse, error) { 56 return &GetQueryServicesDescriptorResponse{Queries: r.desc.QueryServices}, nil 57 } 58 59 func (r reflectionServiceServer) GetTxDescriptor(_ context.Context, _ *GetTxDescriptorRequest) (*GetTxDescriptorResponse, error) { 60 return &GetTxDescriptorResponse{Tx: r.desc.Tx}, nil 61 } 62 63 func newReflectionServiceServer(grpcSrv *grpc.Server, conf Config) (reflectionServiceServer, error) { 64 // set chain descriptor 65 chainDescriptor := &ChainDescriptor{Id: conf.ChainID} 66 // set configuration descriptor 67 configurationDescriptor := &ConfigurationDescriptor{ 68 Bech32AccountAddressPrefix: conf.SdkConfig.GetBech32AccountAddrPrefix(), 69 } 70 // set codec descriptor 71 codecDescriptor, err := newCodecDescriptor(conf.InterfaceRegistry) 72 if err != nil { 73 return reflectionServiceServer{}, fmt.Errorf("unable to create codec descriptor: %w", err) 74 } 75 // set query service descriptor 76 queryServiceDescriptor := newQueryServiceDescriptor(grpcSrv) 77 // set deliver descriptor 78 txDescriptor, err := newTxDescriptor(conf.InterfaceRegistry) 79 if err != nil { 80 return reflectionServiceServer{}, fmt.Errorf("unable to create deliver descriptor: %w", err) 81 } 82 authnDescriptor := newAuthnDescriptor(conf.SigningModes) 83 desc := &AppDescriptor{ 84 Authn: authnDescriptor, 85 Chain: chainDescriptor, 86 Codec: codecDescriptor, 87 Configuration: configurationDescriptor, 88 QueryServices: queryServiceDescriptor, 89 Tx: txDescriptor, 90 } 91 92 ifaceList := make([]string, len(desc.Codec.Interfaces)) 93 ifaceImplementers := make(map[string][]string, len(desc.Codec.Interfaces)) 94 for i, iface := range desc.Codec.Interfaces { 95 ifaceList[i] = iface.Fullname 96 impls := make([]string, len(iface.InterfaceImplementers)) 97 for j, impl := range iface.InterfaceImplementers { 98 impls[j] = impl.TypeUrl 99 } 100 ifaceImplementers[iface.Fullname] = impls 101 } 102 return reflectionServiceServer{ 103 desc: desc, 104 }, nil 105 } 106 107 // newCodecDescriptor describes the codec given the codectypes.InterfaceRegistry 108 func newCodecDescriptor(ir codectypes.InterfaceRegistry) (*CodecDescriptor, error) { 109 registeredInterfaces := ir.ListAllInterfaces() 110 interfaceDescriptors := make([]*InterfaceDescriptor, len(registeredInterfaces)) 111 112 for i, iface := range registeredInterfaces { 113 implementers := ir.ListImplementations(iface) 114 interfaceImplementers := make([]*InterfaceImplementerDescriptor, len(implementers)) 115 for j, implementer := range implementers { 116 pb, err := ir.Resolve(implementer) 117 if err != nil { 118 return nil, fmt.Errorf("unable to resolve implementing type %s for interface %s", implementer, iface) 119 } 120 pbName := proto.MessageName(pb) 121 if pbName == "" { 122 return nil, fmt.Errorf("unable to get proto name for implementing type %s for interface %s", implementer, iface) 123 } 124 interfaceImplementers[j] = &InterfaceImplementerDescriptor{ 125 Fullname: pbName, 126 TypeUrl: implementer, 127 } 128 } 129 interfaceDescriptors[i] = &InterfaceDescriptor{ 130 Fullname: iface, 131 // NOTE(fdymylja): this could be filled, but it won't be filled as of now 132 // doing this would require us to fully rebuild in a (dependency) transitive way the proto 133 // registry of the supported proto.Messages for the application, this could be easily 134 // done if we weren't relying on gogoproto which does not allow us to iterate over the 135 // registry. Achieving this right now would mean to start slowly building descriptors 136 // getting their files dependencies, building those dependencies then rebuilding the 137 // descriptor builder. It's too much work as of now. 138 InterfaceAcceptingMessages: nil, 139 InterfaceImplementers: interfaceImplementers, 140 } 141 } 142 143 return &CodecDescriptor{ 144 Interfaces: interfaceDescriptors, 145 }, nil 146 } 147 148 func newQueryServiceDescriptor(srv *grpc.Server) *QueryServicesDescriptor { 149 svcInfo := srv.GetServiceInfo() 150 queryServices := make([]*QueryServiceDescriptor, 0, len(svcInfo)) 151 for name, info := range svcInfo { 152 methods := make([]*QueryMethodDescriptor, len(info.Methods)) 153 for i, svcMethod := range info.Methods { 154 methods[i] = &QueryMethodDescriptor{ 155 Name: svcMethod.Name, 156 FullQueryPath: fmt.Sprintf("/%s/%s", name, svcMethod.Name), 157 } 158 } 159 queryServices = append(queryServices, &QueryServiceDescriptor{ 160 Fullname: name, 161 Methods: methods, 162 }) 163 } 164 return &QueryServicesDescriptor{QueryServices: queryServices} 165 } 166 167 func newTxDescriptor(ir codectypes.InterfaceRegistry) (*TxDescriptor, error) { 168 // get base tx type name 169 txPbName := proto.MessageName(&tx.Tx{}) 170 if txPbName == "" { 171 return nil, fmt.Errorf("unable to get *tx.Tx protobuf name") 172 } 173 // get msgs 174 sdkMsgImplementers := ir.ListImplementations(sdk.MsgInterfaceProtoName) 175 176 msgsDesc := make([]*MsgDescriptor, 0, len(sdkMsgImplementers)) 177 178 // process sdk.Msg 179 for _, msgTypeURL := range sdkMsgImplementers { 180 msgsDesc = append(msgsDesc, &MsgDescriptor{ 181 MsgTypeUrl: msgTypeURL, 182 }) 183 } 184 185 return &TxDescriptor{ 186 Fullname: txPbName, 187 Msgs: msgsDesc, 188 }, nil 189 } 190 191 func newAuthnDescriptor(signingModes map[string]int32) *AuthnDescriptor { 192 signModesDesc := make([]*SigningModeDescriptor, 0, len(signingModes)) 193 for i, m := range signingModes { 194 signModesDesc = append(signModesDesc, &SigningModeDescriptor{ 195 Name: i, 196 Number: m, 197 // NOTE(fdymylja): this cannot be filled as of now, auth and the sdk itself don't support as of now 198 // a service which allows to get authentication metadata for the provided sign mode. 199 AuthnInfoProviderMethodFullname: "", 200 }) 201 } 202 return &AuthnDescriptor{SignModes: signModesDesc} 203 }