github.com/Finschia/finschia-sdk@v0.48.1/server/grpc/reflection/v2/reflection.go (about)

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