github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/baseapp/grpcrouter.go (about) 1 package baseapp 2 3 import ( 4 "fmt" 5 6 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/grpc/reflection" 7 codectypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec/types" 8 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 9 abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 10 11 gogogrpc "github.com/gogo/protobuf/grpc" 12 "google.golang.org/grpc" 13 "google.golang.org/grpc/encoding" 14 "google.golang.org/grpc/encoding/proto" 15 ) 16 17 var protoCodec = encoding.GetCodec(proto.Name) 18 19 // GRPCQueryRouter routes ABCI Query requests to GRPC handlers 20 type GRPCQueryRouter struct { 21 routes map[string]GRPCQueryHandler 22 interfaceRegistry codectypes.InterfaceRegistry 23 serviceData []serviceData 24 } 25 26 // serviceData represents a gRPC service, along with its handler. 27 type serviceData struct { 28 serviceDesc *grpc.ServiceDesc 29 handler interface{} 30 } 31 32 var _ gogogrpc.Server = &GRPCQueryRouter{} 33 34 // NewGRPCQueryRouter creates a new GRPCQueryRouter 35 func NewGRPCQueryRouter() *GRPCQueryRouter { 36 return &GRPCQueryRouter{ 37 routes: map[string]GRPCQueryHandler{}, 38 } 39 } 40 41 // GRPCQueryHandler defines a function type which handles ABCI Query requests 42 // using gRPC 43 type GRPCQueryHandler = func(ctx sdk.Context, req abci.RequestQuery) (abci.ResponseQuery, error) 44 45 // Route returns the GRPCQueryHandler for a given query route path or nil 46 // if not found 47 func (qrt *GRPCQueryRouter) Route(path string) GRPCQueryHandler { 48 handler, found := qrt.routes[path] 49 if !found { 50 return nil 51 } 52 return handler 53 } 54 55 // RegisterService implements the gRPC Server.RegisterService method. sd is a gRPC 56 // service description, handler is an object which implements that gRPC service/ 57 // 58 // This functions PANICS: 59 // - if a protobuf service is registered twice. 60 func (qrt *GRPCQueryRouter) RegisterService(sd *grpc.ServiceDesc, handler interface{}) { 61 // adds a top-level query handler based on the gRPC service name 62 for _, method := range sd.Methods { 63 fqName := fmt.Sprintf("/%s/%s", sd.ServiceName, method.MethodName) 64 methodHandler := method.Handler 65 66 // Check that each service is only registered once. If a service is 67 // registered more than once, then we should error. Since we can't 68 // return an error (`Server.RegisterService` interface restriction) we 69 // panic (at startup). 70 _, found := qrt.routes[fqName] 71 if found { 72 panic( 73 fmt.Errorf( 74 "gRPC query service %s has already been registered. Please make sure to only register each service once. "+ 75 "This usually means that there are conflicting modules registering the same gRPC query service", 76 fqName, 77 ), 78 ) 79 } 80 81 qrt.routes[fqName] = func(ctx sdk.Context, req abci.RequestQuery) (abci.ResponseQuery, error) { 82 // call the method handler from the service description with the handler object, 83 // a wrapped sdk.Context with proto-unmarshaled data from the ABCI request data 84 res, err := methodHandler(handler, sdk.WrapSDKContext(ctx), func(i interface{}) error { 85 err := protoCodec.Unmarshal(req.Data, i) 86 if err != nil { 87 return err 88 } 89 if qrt.interfaceRegistry != nil { 90 return codectypes.UnpackInterfaces(i, qrt.interfaceRegistry) 91 } 92 93 return nil 94 }, nil) 95 96 if err != nil { 97 return abci.ResponseQuery{}, err 98 } 99 100 // proto marshal the result bytes 101 resBytes, err := protoCodec.Marshal(res) 102 if err != nil { 103 return abci.ResponseQuery{}, err 104 } 105 106 // return the result bytes as the response value 107 return abci.ResponseQuery{ 108 Height: req.Height, 109 Value: resBytes, 110 }, nil 111 } 112 } 113 qrt.serviceData = append(qrt.serviceData, serviceData{ 114 serviceDesc: sd, 115 handler: handler, 116 }) 117 } 118 119 // SetInterfaceRegistry sets the interface registry for the router. This will 120 // also register the interface reflection gRPC service. 121 func (qrt *GRPCQueryRouter) SetInterfaceRegistry(interfaceRegistry codectypes.InterfaceRegistry) { 122 qrt.interfaceRegistry = interfaceRegistry 123 124 // Once we have an interface registry, we can register the interface 125 // registry reflection gRPC service. 126 reflection.RegisterReflectionServiceServer( 127 qrt, 128 reflection.NewReflectionServiceServer(interfaceRegistry), 129 ) 130 }