feat: add autocli app wiring + remote info support (#13281)
This commit is contained in:
+13
-1
@@ -4,10 +4,14 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1"
|
||||
"cosmossdk.io/core/appmodule"
|
||||
|
||||
appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
|
||||
@@ -49,6 +53,8 @@ type App struct {
|
||||
endBlockers []func(sdk.Context, abci.RequestEndBlock) []abci.ValidatorUpdate
|
||||
baseAppOptions []BaseAppOption
|
||||
msgServiceRouter *baseapp.MsgServiceRouter
|
||||
appConfig *appv1alpha1.Config
|
||||
appModules map[string]appmodule.AppModule
|
||||
}
|
||||
|
||||
// RegisterModules registers the provided modules with the module manager and
|
||||
@@ -76,6 +82,12 @@ func (a *App) RegisterModules(modules ...module.AppModule) error {
|
||||
|
||||
// Load finishes all initialization operations and loads the app.
|
||||
func (a *App) Load(loadLatest bool) error {
|
||||
// register runtime module services
|
||||
err := a.registerRuntimeServices()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.configurator = module.NewConfigurator(a.cdc, a.MsgServiceRouter(), a.GRPCQueryRouter())
|
||||
a.ModuleManager.RegisterServices(a.configurator)
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1"
|
||||
)
|
||||
|
||||
// AppQueryService implements the cosmos.app.v1alpha1.Query service
|
||||
type AppQueryService struct {
|
||||
appv1alpha1.UnimplementedQueryServer
|
||||
appConfig *appv1alpha1.Config
|
||||
}
|
||||
|
||||
func NewAppQueryService(appConfig *appv1alpha1.Config) *AppQueryService {
|
||||
return &AppQueryService{appConfig: appConfig}
|
||||
}
|
||||
|
||||
func (a *AppQueryService) Config(context.Context, *appv1alpha1.QueryConfigRequest) (*appv1alpha1.QueryConfigResponse, error) {
|
||||
return &appv1alpha1.QueryConfigResponse{Config: a.appConfig}, nil
|
||||
}
|
||||
|
||||
var _ appv1alpha1.QueryServer = &AppQueryService{}
|
||||
@@ -0,0 +1,37 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
"cosmossdk.io/core/appmodule"
|
||||
)
|
||||
|
||||
// AutoCLIQueryService implements the cosmos.autocli.v1.Query service.
|
||||
type AutoCLIQueryService struct {
|
||||
autocliv1.UnimplementedQueryServer
|
||||
|
||||
moduleOptions map[string]*autocliv1.ModuleOptions
|
||||
}
|
||||
|
||||
func NewAutoCLIQueryService(appModules map[string]appmodule.AppModule) *AutoCLIQueryService {
|
||||
moduleOptions := map[string]*autocliv1.ModuleOptions{}
|
||||
for modName, mod := range appModules {
|
||||
if autoCliMod, ok := mod.(interface {
|
||||
AutoCLIOptions() *autocliv1.ModuleOptions
|
||||
}); ok {
|
||||
moduleOptions[modName] = autoCliMod.AutoCLIOptions()
|
||||
}
|
||||
}
|
||||
return &AutoCLIQueryService{
|
||||
moduleOptions: moduleOptions,
|
||||
}
|
||||
}
|
||||
|
||||
func (a AutoCLIQueryService) AppOptions(context.Context, *autocliv1.AppOptionsRequest) (*autocliv1.AppOptionsResponse, error) {
|
||||
return &autocliv1.AppOptionsResponse{
|
||||
ModuleOptions: a.moduleOptions,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var _ autocliv1.QueryServer = &AutoCLIQueryService{}
|
||||
@@ -0,0 +1,73 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"io"
|
||||
|
||||
reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1"
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
"golang.org/x/exp/slices"
|
||||
protov2 "google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protodesc"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
)
|
||||
|
||||
// ReflectionService implements the cosmos.reflection.v1 service.
|
||||
type ReflectionService struct {
|
||||
reflectionv1.UnimplementedReflectionServiceServer
|
||||
files *descriptorpb.FileDescriptorSet
|
||||
}
|
||||
|
||||
func NewReflectionService() (*ReflectionService, error) {
|
||||
fds := &descriptorpb.FileDescriptorSet{}
|
||||
|
||||
// load gogo proto file descriptors
|
||||
allFds := proto.AllFileDescriptors()
|
||||
haveFileDescriptor := map[string]bool{}
|
||||
for _, compressedBz := range allFds {
|
||||
rdr, err := gzip.NewReader(bytes.NewReader(compressedBz))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bz, err := io.ReadAll(rdr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fd := &descriptorpb.FileDescriptorProto{}
|
||||
err = protov2.Unmarshal(bz, fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fds.File = append(fds.File, fd)
|
||||
haveFileDescriptor[*fd.Name] = true
|
||||
}
|
||||
|
||||
// load any protoregistry file descriptors not in gogo
|
||||
protoregistry.GlobalFiles.RangeFiles(func(fileDescriptor protoreflect.FileDescriptor) bool {
|
||||
if !haveFileDescriptor[fileDescriptor.Path()] {
|
||||
fds.File = append(fds.File, protodesc.ToFileDescriptorProto(fileDescriptor))
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
slices.SortFunc(fds.File, func(x, y *descriptorpb.FileDescriptorProto) bool {
|
||||
return *x.Name < *y.Name
|
||||
})
|
||||
|
||||
return &ReflectionService{files: fds}, nil
|
||||
}
|
||||
|
||||
func (r ReflectionService) FileDescriptors(_ context.Context, _ *reflectionv1.FileDescriptorsRequest) (*reflectionv1.FileDescriptorsResponse, error) {
|
||||
return &reflectionv1.FileDescriptorsResponse{
|
||||
Files: r.files.File,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var _ reflectionv1.ReflectionServiceServer = &ReflectionService{}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1"
|
||||
appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1"
|
||||
"cosmossdk.io/core/appmodule"
|
||||
"cosmossdk.io/depinject"
|
||||
|
||||
@@ -77,10 +78,12 @@ func ProvideCodecs(moduleBasics map[string]AppModuleBasicWrapper) (
|
||||
type appInputs struct {
|
||||
depinject.In
|
||||
|
||||
AppConfig *appv1alpha1.Config
|
||||
Config *runtimev1alpha1.Module
|
||||
AppBuilder *AppBuilder
|
||||
Modules map[string]AppModuleWrapper
|
||||
BaseAppOptions []BaseAppOption
|
||||
AppModules map[string]appmodule.AppModule
|
||||
}
|
||||
|
||||
func SetupAppBuilder(inputs appInputs) {
|
||||
@@ -92,6 +95,8 @@ func SetupAppBuilder(inputs appInputs) {
|
||||
app.baseAppOptions = inputs.BaseAppOptions
|
||||
app.config = inputs.Config
|
||||
app.ModuleManager = mm
|
||||
app.appConfig = inputs.AppConfig
|
||||
app.appModules = inputs.AppModules
|
||||
}
|
||||
|
||||
func registerStoreKey(wrapper *AppBuilder, key storetypes.StoreKey) {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package runtime
|
||||
|
||||
import (
|
||||
appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1"
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/runtime/internal/services"
|
||||
)
|
||||
|
||||
func (a *App) registerRuntimeServices() error {
|
||||
appv1alpha1.RegisterQueryServer(a.GRPCQueryRouter(), services.NewAppQueryService(a.appConfig))
|
||||
autocliv1.RegisterQueryServer(a.GRPCQueryRouter(), services.NewAutoCLIQueryService(a.appModules))
|
||||
|
||||
reflectionSvc, err := services.NewReflectionService()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reflectionv1.RegisterReflectionServiceServer(a.GRPCQueryRouter(), reflectionSvc)
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user