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  }