diff --git a/baseapp/grpcrouter.go b/baseapp/grpcrouter.go index d555560955..efefe4a852 100644 --- a/baseapp/grpcrouter.go +++ b/baseapp/grpcrouter.go @@ -17,6 +17,14 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +type QueryRouter interface { + HybridHandlerByRequestName(name string) []func(ctx context.Context, req, resp protoiface.MessageV1) error + RegisterService(sd *grpc.ServiceDesc, handler interface{}) + ResponseNameByRequestName(requestName string) string + Route(path string) GRPCQueryHandler + SetInterfaceRegistry(interfaceRegistry codectypes.InterfaceRegistry) +} + // GRPCQueryRouter routes ABCI Query requests to GRPC handlers type GRPCQueryRouter struct { // routes maps query handlers used in ABCIQuery. @@ -40,7 +48,10 @@ type serviceData struct { handler interface{} } -var _ gogogrpc.Server = &GRPCQueryRouter{} +var ( + _ gogogrpc.Server = &GRPCQueryRouter{} + _ QueryRouter = &GRPCQueryRouter{} +) // NewGRPCQueryRouter creates a new GRPCQueryRouter func NewGRPCQueryRouter() *GRPCQueryRouter { diff --git a/core/appmodule/environment.go b/core/appmodule/environment.go index d65c32a5f8..6b5c09bb4f 100644 --- a/core/appmodule/environment.go +++ b/core/appmodule/environment.go @@ -5,4 +5,5 @@ import ( ) // Environment is used to get all services to their respective module +// Contract: All fields of environment are always populated. type Environment = appmodule.Environment diff --git a/core/appmodule/v2/environment.go b/core/appmodule/v2/environment.go index 4ce732de4a..6d64d9b1eb 100644 --- a/core/appmodule/v2/environment.go +++ b/core/appmodule/v2/environment.go @@ -12,6 +12,7 @@ import ( ) // Environment is used to get all services to their respective module +// Contract: All fields of environment are always populated. type Environment struct { Logger log.Logger diff --git a/runtime/environment.go b/runtime/environment.go index d7f6cf9467..3fc3c86395 100644 --- a/runtime/environment.go +++ b/runtime/environment.go @@ -1,11 +1,18 @@ package runtime import ( + "context" + + "google.golang.org/grpc" + "google.golang.org/protobuf/runtime/protoiface" + "cosmossdk.io/core/appmodule" "cosmossdk.io/core/log" "cosmossdk.io/core/store" "github.com/cosmos/cosmos-sdk/baseapp" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" ) // NewEnvironment creates a new environment for the application @@ -24,6 +31,9 @@ func NewEnvironment( GasService: GasService{}, TransactionService: TransactionService{}, KVStoreService: kvService, + MsgRouterService: NewMsgRouterService(failingMsgRouter{}), + QueryRouterService: NewQueryRouterService(failingQueryRouter{}), + MemStoreService: failingMemStore{}, } for _, opt := range opts { @@ -52,3 +62,61 @@ func EnvWithMemStoreService(memStoreService store.MemoryStoreService) EnvOption env.MemStoreService = memStoreService } } + +// failingMsgRouter is a message router that panics when accessed +// this is to ensure all fields are set by in environment +type failingMsgRouter struct { + baseapp.MessageRouter +} + +func (failingMsgRouter) Handler(msg sdk.Msg) baseapp.MsgServiceHandler { + panic("message router not set") +} + +func (failingMsgRouter) HandlerByTypeURL(typeURL string) baseapp.MsgServiceHandler { + panic("message router not set") +} + +func (failingMsgRouter) ResponseNameByMsgName(msgName string) string { + panic("message router not set") +} + +func (failingMsgRouter) HybridHandlerByMsgName(msgName string) func(ctx context.Context, req, resp protoiface.MessageV1) error { + panic("message router not set") +} + +// failingQueryRouter is a query router that panics when accessed +// this is to ensure all fields are set by in environment +type failingQueryRouter struct { + baseapp.QueryRouter +} + +func (failingQueryRouter) HybridHandlerByRequestName(name string) []func(ctx context.Context, req, resp protoiface.MessageV1) error { + panic("query router not set") +} + +func (failingQueryRouter) RegisterService(sd *grpc.ServiceDesc, handler interface{}) { + panic("query router not set") +} + +func (failingQueryRouter) ResponseNameByRequestName(requestName string) string { + panic("query router not set") +} + +func (failingQueryRouter) Route(path string) baseapp.GRPCQueryHandler { + panic("query router not set") +} + +func (failingQueryRouter) SetInterfaceRegistry(interfaceRegistry codectypes.InterfaceRegistry) { + panic("query router not set") +} + +// failingMemStore is a memstore that panics when accessed +// this is to ensure all fields are set by in environment +type failingMemStore struct { + store.MemoryStoreService +} + +func (failingMemStore) OpenMemoryStore(context.Context) store.KVStore { + panic("memory store not set") +} diff --git a/runtime/router.go b/runtime/router.go index d99c71252b..f674488756 100644 --- a/runtime/router.go +++ b/runtime/router.go @@ -80,7 +80,7 @@ func (m *msgRouterService) InvokeUntyped(ctx context.Context, msg protoiface.Mes } // NewQueryRouterService implements router.Service. -func NewQueryRouterService(queryRouter *baseapp.GRPCQueryRouter) router.Service { +func NewQueryRouterService(queryRouter baseapp.QueryRouter) router.Service { return &queryRouterService{ router: queryRouter, } @@ -89,7 +89,7 @@ func NewQueryRouterService(queryRouter *baseapp.GRPCQueryRouter) router.Service var _ router.Service = (*queryRouterService)(nil) type queryRouterService struct { - router *baseapp.GRPCQueryRouter + router baseapp.QueryRouter } // CanInvoke returns an error if the given request cannot be invoked.