-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add gRPC server & reflection (#6463)
* Add gRPC proxy * Make GRPC disabled by default * WIP on integration tests * WIP on integration tests * Start setting up in process tests * Start setting up in process tests * Make it compile * Add start server to network util * Add Println * Use go routine * Fix scopelint * Move to proxy_test * Add response type cache * Remove proxy * Tweaks * Use channel to handle error * Use error chan * Update server/start.go Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> * Use %w * Add sdk.Context * Add comments * Fix lint * Add header and tests * Address comments * Factorize some code * Fix lint * Add height and prove in req metadata * Add reflection test * Fix lint * Put grpc test in server/grpc * Update baseapp/grpcserver.go * Update baseapp/grpcserver.go * Remove proof header Co-authored-by: Amaury Martiny <amaury.martiny@protonmail.com> Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Alexander Bezobchuk <alexanderbez@users.noreply.github.com> Co-authored-by: SaReN <sahithnarahari@gmail.com>
- Loading branch information
1 parent
20488b4
commit e9534b0
Showing
17 changed files
with
384 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package baseapp | ||
|
||
import ( | ||
"context" | ||
"strconv" | ||
|
||
gogogrpc "github.com/gogo/protobuf/grpc" | ||
"google.golang.org/grpc" | ||
"google.golang.org/grpc/codes" | ||
"google.golang.org/grpc/metadata" | ||
"google.golang.org/grpc/status" | ||
|
||
servergrpc "github.com/cosmos/cosmos-sdk/server/grpc" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
) | ||
|
||
// GRPCQueryRouter returns the GRPCQueryRouter of a BaseApp. | ||
func (app *BaseApp) GRPCQueryRouter() *GRPCQueryRouter { return app.grpcQueryRouter } | ||
|
||
// RegisterGRPCServer registers gRPC services directly with the gRPC server. | ||
func (app *BaseApp) RegisterGRPCServer(server gogogrpc.Server) { | ||
// Define an interceptor for all gRPC queries: this interceptor will create | ||
// a new sdk.Context, and pass it into the query handler. | ||
interceptor := func(grpcCtx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { | ||
// If there's some metadata in the context, retrieve it. | ||
md, ok := metadata.FromIncomingContext(grpcCtx) | ||
if !ok { | ||
return nil, status.Error(codes.Internal, "unable to retrieve metadata") | ||
} | ||
|
||
// Get height header from the request context, if present. | ||
var height int64 | ||
if heightHeaders := md.Get(servergrpc.GRPCBlockHeightHeader); len(heightHeaders) > 0 { | ||
height, err = strconv.ParseInt(heightHeaders[0], 10, 64) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
// Create the sdk.Context. Passing false as 2nd arg, as we can't | ||
// actually support proofs with gRPC right now. | ||
sdkCtx, err := app.createQueryContext(height, false) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Attach the sdk.Context into the gRPC's context.Context. | ||
grpcCtx = context.WithValue(grpcCtx, sdk.SdkContextKey, sdkCtx) | ||
|
||
// Add relevant gRPC headers | ||
if height == 0 { | ||
height = sdkCtx.BlockHeight() // If height was not set in the request, set it to the latest | ||
} | ||
md = metadata.Pairs(servergrpc.GRPCBlockHeightHeader, strconv.FormatInt(height, 10)) | ||
grpc.SetHeader(grpcCtx, md) | ||
|
||
return handler(grpcCtx, req) | ||
} | ||
|
||
// Loop through all services and methods, add the interceptor, and register | ||
// the service. | ||
for _, data := range app.GRPCQueryRouter().serviceData { | ||
desc := data.serviceDesc | ||
newMethods := make([]grpc.MethodDesc, len(desc.Methods)) | ||
|
||
for i, method := range desc.Methods { | ||
methodHandler := method.Handler | ||
newMethods[i] = grpc.MethodDesc{ | ||
MethodName: method.MethodName, | ||
Handler: func(srv interface{}, ctx context.Context, dec func(interface{}) error, _ grpc.UnaryServerInterceptor) (interface{}, error) { | ||
return methodHandler(srv, ctx, dec, interceptor) | ||
}, | ||
} | ||
} | ||
|
||
newDesc := &grpc.ServiceDesc{ | ||
ServiceName: desc.ServiceName, | ||
HandlerType: desc.HandlerType, | ||
Methods: newMethods, | ||
Streams: desc.Streams, | ||
Metadata: desc.Metadata, | ||
} | ||
|
||
server.RegisterService(newDesc, data.handler) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package grpc | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
"time" | ||
|
||
"google.golang.org/grpc" | ||
"google.golang.org/grpc/reflection" | ||
|
||
"github.com/cosmos/cosmos-sdk/server/types" | ||
) | ||
|
||
const ( | ||
// GRPCBlockHeightHeader is the gRPC header for block height. | ||
GRPCBlockHeightHeader = "x-cosmos-block-height" | ||
) | ||
|
||
// StartGRPCServer starts a gRPC server on the given address. | ||
func StartGRPCServer(app types.Application, address string) (*grpc.Server, error) { | ||
grpcSrv := grpc.NewServer() | ||
app.RegisterGRPCServer(grpcSrv) | ||
|
||
// Reflection allows external clients to see what services and methods | ||
// the gRPC server exposes. | ||
reflection.Register(grpcSrv) | ||
|
||
listener, err := net.Listen("tcp", address) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
errCh := make(chan error) | ||
go func() { | ||
err = grpcSrv.Serve(listener) | ||
if err != nil { | ||
errCh <- fmt.Errorf("failed to serve: %w", err) | ||
} | ||
}() | ||
|
||
select { | ||
case err := <-errCh: | ||
return nil, err | ||
case <-time.After(5 * time.Second): // assume server started successfully | ||
return grpcSrv, nil | ||
} | ||
} |
Oops, something went wrong.