refactor(server/v2): extend the use of generic transaction type all the way up (#20789)
This commit is contained in:
parent
fe9157b1a3
commit
9e89aace91
@ -19,7 +19,7 @@ import (
|
||||
"cosmossdk.io/server/v2/stf"
|
||||
)
|
||||
|
||||
var _ AppI[transaction.Tx] = (*App)(nil)
|
||||
var _ AppI[transaction.Tx] = (*App[transaction.Tx])(nil)
|
||||
|
||||
// AppI is an interface that defines the methods required by the App.
|
||||
type AppI[T transaction.Tx] interface {
|
||||
@ -33,7 +33,7 @@ type AppI[T transaction.Tx] interface {
|
||||
QueryWithState(ctx context.Context, state store.ReaderMap, request transaction.Msg) (transaction.Msg, error)
|
||||
|
||||
Logger() log.Logger
|
||||
ModuleManager() *MM
|
||||
ModuleManager() *MM[T]
|
||||
Close() error
|
||||
}
|
||||
|
||||
@ -46,11 +46,11 @@ type AppI[T transaction.Tx] interface {
|
||||
// App can be used to create a hybrid app.go setup where some configuration is
|
||||
// done declaratively with an app config and the rest of it is done the old way.
|
||||
// See simapp/app_v2.go for an example of this setup.
|
||||
type App struct {
|
||||
*appmanager.AppManager[transaction.Tx]
|
||||
type App[T transaction.Tx] struct {
|
||||
*appmanager.AppManager[T]
|
||||
|
||||
// app manager dependencies
|
||||
stf *stf.STF[transaction.Tx]
|
||||
stf *stf.STF[T]
|
||||
msgRouterBuilder *stf.MsgRouterBuilder
|
||||
queryRouterBuilder *stf.MsgRouterBuilder
|
||||
db Store
|
||||
@ -64,47 +64,47 @@ type App struct {
|
||||
storeKeys []string
|
||||
interfaceRegistrar registry.InterfaceRegistrar
|
||||
amino legacy.Amino
|
||||
moduleManager *MM
|
||||
moduleManager *MM[T]
|
||||
}
|
||||
|
||||
// Logger returns the app logger.
|
||||
func (a *App) Logger() log.Logger {
|
||||
func (a *App[T]) Logger() log.Logger {
|
||||
return a.logger
|
||||
}
|
||||
|
||||
// ModuleManager returns the module manager.
|
||||
func (a *App) ModuleManager() *MM {
|
||||
func (a *App[T]) ModuleManager() *MM[T] {
|
||||
return a.moduleManager
|
||||
}
|
||||
|
||||
// DefaultGenesis returns a default genesis from the registered modules.
|
||||
func (a *App) DefaultGenesis() map[string]json.RawMessage {
|
||||
func (a *App[T]) DefaultGenesis() map[string]json.RawMessage {
|
||||
return a.moduleManager.DefaultGenesis()
|
||||
}
|
||||
|
||||
// LoadLatest loads the latest version.
|
||||
func (a *App) LoadLatest() error {
|
||||
func (a *App[T]) LoadLatest() error {
|
||||
return a.db.LoadLatestVersion()
|
||||
}
|
||||
|
||||
// LoadHeight loads a particular height
|
||||
func (a *App) LoadHeight(height uint64) error {
|
||||
func (a *App[T]) LoadHeight(height uint64) error {
|
||||
return a.db.LoadVersion(height)
|
||||
}
|
||||
|
||||
// Close is called in start cmd to gracefully cleanup resources.
|
||||
func (a *App) Close() error {
|
||||
func (a *App[T]) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetStoreKeys returns all the app store keys.
|
||||
func (a *App) GetStoreKeys() []string {
|
||||
func (a *App[T]) GetStoreKeys() []string {
|
||||
return a.storeKeys
|
||||
}
|
||||
|
||||
// UnsafeFindStoreKey fetches a registered StoreKey from the App in linear time.
|
||||
// NOTE: This should only be used in testing.
|
||||
func (a *App) UnsafeFindStoreKey(storeKey string) (string, error) {
|
||||
func (a *App[T]) UnsafeFindStoreKey(storeKey string) (string, error) {
|
||||
i := slices.IndexFunc(a.storeKeys, func(s string) bool { return s == storeKey })
|
||||
if i == -1 {
|
||||
return "", errors.New("store key not found")
|
||||
@ -114,19 +114,19 @@ func (a *App) UnsafeFindStoreKey(storeKey string) (string, error) {
|
||||
}
|
||||
|
||||
// GetStore returns the app store.
|
||||
func (a *App) GetStore() Store {
|
||||
func (a *App[T]) GetStore() Store {
|
||||
return a.db
|
||||
}
|
||||
|
||||
// GetLogger returns the app logger.
|
||||
func (a *App) GetLogger() log.Logger {
|
||||
func (a *App[T]) GetLogger() log.Logger {
|
||||
return a.logger
|
||||
}
|
||||
|
||||
func (a *App) ExecuteGenesisTx(_ []byte) error {
|
||||
func (a *App[T]) ExecuteGenesisTx(_ []byte) error {
|
||||
panic("App.ExecuteGenesisTx not supported in runtime/v2")
|
||||
}
|
||||
|
||||
func (a *App) GetAppManager() *appmanager.AppManager[transaction.Tx] {
|
||||
func (a *App[T]) GetAppManager() *appmanager.AppManager[T] {
|
||||
return a.AppManager
|
||||
}
|
||||
|
||||
@ -19,24 +19,24 @@ import (
|
||||
// AppBuilder is a type that is injected into a container by the runtime/v2 module
|
||||
// (as *AppBuilder) which can be used to create an app which is compatible with
|
||||
// the existing app.go initialization conventions.
|
||||
type AppBuilder struct {
|
||||
app *App
|
||||
type AppBuilder[T transaction.Tx] struct {
|
||||
app *App[T]
|
||||
storeOptions *rootstore.FactoryOptions
|
||||
|
||||
// the following fields are used to overwrite the default
|
||||
branch func(state store.ReaderMap) store.WriterMap
|
||||
txValidator func(ctx context.Context, tx transaction.Tx) error
|
||||
postTxExec func(ctx context.Context, tx transaction.Tx, success bool) error
|
||||
txValidator func(ctx context.Context, tx T) error
|
||||
postTxExec func(ctx context.Context, tx T, success bool) error
|
||||
}
|
||||
|
||||
// DefaultGenesis returns a default genesis from the registered AppModule's.
|
||||
func (a *AppBuilder) DefaultGenesis() map[string]json.RawMessage {
|
||||
func (a *AppBuilder[T]) DefaultGenesis() map[string]json.RawMessage {
|
||||
return a.app.moduleManager.DefaultGenesis()
|
||||
}
|
||||
|
||||
// RegisterModules registers the provided modules with the module manager.
|
||||
// This is the primary hook for integrating with modules which are not registered using the app config.
|
||||
func (a *AppBuilder) RegisterModules(modules ...appmodulev2.AppModule) error {
|
||||
func (a *AppBuilder[T]) RegisterModules(modules ...appmodulev2.AppModule) error {
|
||||
for _, appModule := range modules {
|
||||
if mod, ok := appModule.(appmodule.HasName); ok {
|
||||
name := mod.Name()
|
||||
@ -62,7 +62,7 @@ func (a *AppBuilder) RegisterModules(modules ...appmodulev2.AppModule) error {
|
||||
// This method should only be used for registering extra stores
|
||||
// wiich is necessary for modules that not registered using the app config.
|
||||
// To be used in combination of RegisterModules.
|
||||
func (a *AppBuilder) RegisterStores(keys ...string) {
|
||||
func (a *AppBuilder[T]) RegisterStores(keys ...string) {
|
||||
a.app.storeKeys = append(a.app.storeKeys, keys...)
|
||||
if a.storeOptions != nil {
|
||||
a.storeOptions.StoreKeys = append(a.storeOptions.StoreKeys, keys...)
|
||||
@ -70,7 +70,7 @@ func (a *AppBuilder) RegisterStores(keys ...string) {
|
||||
}
|
||||
|
||||
// Build builds an *App instance.
|
||||
func (a *AppBuilder) Build(opts ...AppBuilderOption) (*App, error) {
|
||||
func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) {
|
||||
for _, opt := range opts {
|
||||
opt(a)
|
||||
}
|
||||
@ -87,7 +87,7 @@ func (a *AppBuilder) Build(opts ...AppBuilderOption) (*App, error) {
|
||||
|
||||
// default post tx exec
|
||||
if a.postTxExec == nil {
|
||||
a.postTxExec = func(ctx context.Context, tx transaction.Tx, success bool) error {
|
||||
a.postTxExec = func(ctx context.Context, tx T, success bool) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@ -98,7 +98,7 @@ func (a *AppBuilder) Build(opts ...AppBuilderOption) (*App, error) {
|
||||
|
||||
endBlocker, valUpdate := a.app.moduleManager.EndBlock()
|
||||
|
||||
stf, err := stf.NewSTF[transaction.Tx](
|
||||
stf, err := stf.NewSTF[T](
|
||||
a.app.logger.With("module", "stf"),
|
||||
a.app.msgRouterBuilder,
|
||||
a.app.queryRouterBuilder,
|
||||
@ -122,7 +122,7 @@ func (a *AppBuilder) Build(opts ...AppBuilderOption) (*App, error) {
|
||||
}
|
||||
a.app.db = rs
|
||||
|
||||
appManagerBuilder := appmanager.Builder[transaction.Tx]{
|
||||
appManagerBuilder := appmanager.Builder[T]{
|
||||
STF: a.app.stf,
|
||||
DB: a.app.db,
|
||||
ValidateTxGasLimit: a.app.config.GasConfig.ValidateTxGasLimit,
|
||||
@ -155,33 +155,33 @@ func (a *AppBuilder) Build(opts ...AppBuilderOption) (*App, error) {
|
||||
}
|
||||
|
||||
// AppBuilderOption is a function that can be passed to AppBuilder.Build to customize the resulting app.
|
||||
type AppBuilderOption func(*AppBuilder)
|
||||
type AppBuilderOption[T transaction.Tx] func(*AppBuilder[T])
|
||||
|
||||
// AppBuilderWithBranch sets a custom branch implementation for the app.
|
||||
func AppBuilderWithBranch(branch func(state store.ReaderMap) store.WriterMap) AppBuilderOption {
|
||||
return func(a *AppBuilder) {
|
||||
func AppBuilderWithBranch[T transaction.Tx](branch func(state store.ReaderMap) store.WriterMap) AppBuilderOption[T] {
|
||||
return func(a *AppBuilder[T]) {
|
||||
a.branch = branch
|
||||
}
|
||||
}
|
||||
|
||||
// AppBuilderWithTxValidator sets the tx validator for the app.
|
||||
// It overrides all default tx validators defined by modules.
|
||||
func AppBuilderWithTxValidator(txValidators func(ctx context.Context, tx transaction.Tx) error) AppBuilderOption {
|
||||
return func(a *AppBuilder) {
|
||||
func AppBuilderWithTxValidator[T transaction.Tx](txValidators func(ctx context.Context, tx T) error) AppBuilderOption[T] {
|
||||
return func(a *AppBuilder[T]) {
|
||||
a.txValidator = txValidators
|
||||
}
|
||||
}
|
||||
|
||||
// AppBuilderWithPostTxExec sets logic that will be executed after each transaction.
|
||||
// When not provided, a no-op function will be used.
|
||||
func AppBuilderWithPostTxExec(
|
||||
func AppBuilderWithPostTxExec[T transaction.Tx](
|
||||
postTxExec func(
|
||||
ctx context.Context,
|
||||
tx transaction.Tx,
|
||||
tx T,
|
||||
success bool,
|
||||
) error,
|
||||
) AppBuilderOption {
|
||||
return func(a *AppBuilder) {
|
||||
) AppBuilderOption[T] {
|
||||
return func(a *AppBuilder[T]) {
|
||||
a.postTxExec = postTxExec
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ import (
|
||||
"cosmossdk.io/server/v2/stf"
|
||||
)
|
||||
|
||||
type MM struct {
|
||||
type MM[T transaction.Tx] struct {
|
||||
logger log.Logger
|
||||
config *runtimev2.Module
|
||||
modules map[string]appmodulev2.AppModule
|
||||
@ -34,11 +34,11 @@ type MM struct {
|
||||
|
||||
// NewModuleManager is the constructor for the module manager
|
||||
// It handles all the interactions between the modules and the application
|
||||
func NewModuleManager(
|
||||
func NewModuleManager[T transaction.Tx](
|
||||
logger log.Logger,
|
||||
config *runtimev2.Module,
|
||||
modules map[string]appmodulev2.AppModule,
|
||||
) *MM {
|
||||
) *MM[T] {
|
||||
// good defaults for the module manager order
|
||||
modulesName := maps.Keys(modules)
|
||||
if len(config.PreBlockers) == 0 {
|
||||
@ -63,7 +63,7 @@ func NewModuleManager(
|
||||
config.OrderMigrations = defaultMigrationsOrder(modulesName)
|
||||
}
|
||||
|
||||
mm := &MM{
|
||||
mm := &MM[T]{
|
||||
logger: logger,
|
||||
config: config,
|
||||
modules: modules,
|
||||
@ -78,12 +78,12 @@ func NewModuleManager(
|
||||
}
|
||||
|
||||
// Modules returns the modules registered in the module manager
|
||||
func (m *MM) Modules() map[string]appmodulev2.AppModule {
|
||||
func (m *MM[T]) Modules() map[string]appmodulev2.AppModule {
|
||||
return m.modules
|
||||
}
|
||||
|
||||
// RegisterLegacyAminoCodec registers all module codecs
|
||||
func (m *MM) RegisterLegacyAminoCodec(cdc legacy.Amino) {
|
||||
func (m *MM[T]) RegisterLegacyAminoCodec(cdc legacy.Amino) {
|
||||
for _, b := range m.modules {
|
||||
if mod, ok := b.(appmodule.HasAminoCodec); ok {
|
||||
mod.RegisterLegacyAminoCodec(cdc)
|
||||
@ -92,7 +92,7 @@ func (m *MM) RegisterLegacyAminoCodec(cdc legacy.Amino) {
|
||||
}
|
||||
|
||||
// RegisterInterfaces registers all module interface types
|
||||
func (m *MM) RegisterInterfaces(registry registry.InterfaceRegistrar) {
|
||||
func (m *MM[T]) RegisterInterfaces(registry registry.InterfaceRegistrar) {
|
||||
for _, b := range m.modules {
|
||||
if mod, ok := b.(appmodulev2.HasRegisterInterfaces); ok {
|
||||
mod.RegisterInterfaces(registry)
|
||||
@ -101,7 +101,7 @@ func (m *MM) RegisterInterfaces(registry registry.InterfaceRegistrar) {
|
||||
}
|
||||
|
||||
// DefaultGenesis provides default genesis information for all modules
|
||||
func (m *MM) DefaultGenesis() map[string]json.RawMessage {
|
||||
func (m *MM[T]) DefaultGenesis() map[string]json.RawMessage {
|
||||
genesisData := make(map[string]json.RawMessage)
|
||||
for name, b := range m.modules {
|
||||
if mod, ok := b.(appmodule.HasGenesisBasics); ok {
|
||||
@ -117,7 +117,7 @@ func (m *MM) DefaultGenesis() map[string]json.RawMessage {
|
||||
}
|
||||
|
||||
// ValidateGenesis performs genesis state validation for all modules
|
||||
func (m *MM) ValidateGenesis(genesisData map[string]json.RawMessage) error {
|
||||
func (m *MM[T]) ValidateGenesis(genesisData map[string]json.RawMessage) error {
|
||||
for name, b := range m.modules {
|
||||
if mod, ok := b.(appmodule.HasGenesisBasics); ok {
|
||||
if err := mod.ValidateGenesis(genesisData[mod.Name()]); err != nil {
|
||||
@ -134,7 +134,7 @@ func (m *MM) ValidateGenesis(genesisData map[string]json.RawMessage) error {
|
||||
}
|
||||
|
||||
// InitGenesisJSON performs init genesis functionality for modules from genesis data in JSON format
|
||||
func (m *MM) InitGenesisJSON(
|
||||
func (m *MM[T]) InitGenesisJSON(
|
||||
ctx context.Context,
|
||||
genesisData map[string]json.RawMessage,
|
||||
txHandler func(json.RawMessage) error,
|
||||
@ -190,7 +190,7 @@ func (m *MM) InitGenesisJSON(
|
||||
}
|
||||
|
||||
// ExportGenesisForModules performs export genesis functionality for modules
|
||||
func (m *MM) ExportGenesisForModules(
|
||||
func (m *MM[T]) ExportGenesisForModules(
|
||||
ctx context.Context,
|
||||
modulesToExport ...string,
|
||||
) (map[string]json.RawMessage, error) {
|
||||
@ -247,7 +247,7 @@ func (m *MM) ExportGenesisForModules(
|
||||
}
|
||||
|
||||
// checkModulesExists verifies that all modules in the list exist in the app
|
||||
func (m *MM) checkModulesExists(moduleName []string) error {
|
||||
func (m *MM[T]) checkModulesExists(moduleName []string) error {
|
||||
for _, name := range moduleName {
|
||||
if _, ok := m.modules[name]; !ok {
|
||||
return fmt.Errorf("module %s does not exist", name)
|
||||
@ -258,7 +258,7 @@ func (m *MM) checkModulesExists(moduleName []string) error {
|
||||
}
|
||||
|
||||
// BeginBlock runs the begin-block logic of all modules
|
||||
func (m *MM) BeginBlock() func(ctx context.Context) error {
|
||||
func (m *MM[T]) BeginBlock() func(ctx context.Context) error {
|
||||
return func(ctx context.Context) error {
|
||||
for _, moduleName := range m.config.BeginBlockers {
|
||||
if module, ok := m.modules[moduleName].(appmodulev2.HasBeginBlocker); ok {
|
||||
@ -278,7 +278,7 @@ type hasABCIEndBlock interface {
|
||||
}
|
||||
|
||||
// EndBlock runs the end-block logic of all modules and tx validator updates
|
||||
func (m *MM) EndBlock() (
|
||||
func (m *MM[T]) EndBlock() (
|
||||
endBlockFunc func(ctx context.Context) error,
|
||||
valUpdateFunc func(ctx context.Context) ([]appmodulev2.ValidatorUpdate, error),
|
||||
) {
|
||||
@ -336,8 +336,8 @@ func (m *MM) EndBlock() (
|
||||
}
|
||||
|
||||
// PreBlocker runs the pre-block logic of all modules
|
||||
func (m *MM) PreBlocker() func(ctx context.Context, txs []transaction.Tx) error {
|
||||
return func(ctx context.Context, txs []transaction.Tx) error {
|
||||
func (m *MM[T]) PreBlocker() func(ctx context.Context, txs []T) error {
|
||||
return func(ctx context.Context, txs []T) error {
|
||||
for _, moduleName := range m.config.PreBlockers {
|
||||
if module, ok := m.modules[moduleName].(appmodulev2.HasPreBlocker); ok {
|
||||
if err := module.PreBlock(ctx); err != nil {
|
||||
@ -351,10 +351,10 @@ func (m *MM) PreBlocker() func(ctx context.Context, txs []transaction.Tx) error
|
||||
}
|
||||
|
||||
// TxValidators validates incoming transactions
|
||||
func (m *MM) TxValidators() func(ctx context.Context, tx transaction.Tx) error {
|
||||
return func(ctx context.Context, tx transaction.Tx) error {
|
||||
func (m *MM[T]) TxValidators() func(ctx context.Context, tx T) error {
|
||||
return func(ctx context.Context, tx T) error {
|
||||
for _, moduleName := range m.config.TxValidators {
|
||||
if module, ok := m.modules[moduleName].(appmodulev2.HasTxValidator[transaction.Tx]); ok {
|
||||
if module, ok := m.modules[moduleName].(appmodulev2.HasTxValidator[T]); ok {
|
||||
if err := module.TxValidator(ctx, tx); err != nil {
|
||||
return fmt.Errorf("failed to run tx validator for %s: %w", moduleName, err)
|
||||
}
|
||||
@ -367,7 +367,7 @@ func (m *MM) TxValidators() func(ctx context.Context, tx transaction.Tx) error {
|
||||
|
||||
// TODO write as descriptive godoc as module manager v1.
|
||||
// TODO include feedback from https://github.com/cosmos/cosmos-sdk/issues/15120
|
||||
func (m *MM) RunMigrations(ctx context.Context, fromVM appmodulev2.VersionMap) (appmodulev2.VersionMap, error) {
|
||||
func (m *MM[T]) RunMigrations(ctx context.Context, fromVM appmodulev2.VersionMap) (appmodulev2.VersionMap, error) {
|
||||
updatedVM := appmodulev2.VersionMap{}
|
||||
for _, moduleName := range m.config.OrderMigrations {
|
||||
module := m.modules[moduleName]
|
||||
@ -417,7 +417,7 @@ func (m *MM) RunMigrations(ctx context.Context, fromVM appmodulev2.VersionMap) (
|
||||
}
|
||||
|
||||
// RegisterServices registers all module services.
|
||||
func (m *MM) RegisterServices(app *App) error {
|
||||
func (m *MM[T]) RegisterServices(app *App[T]) error {
|
||||
for _, module := range m.modules {
|
||||
// register msg + query
|
||||
if services, ok := module.(appmodule.HasServices); ok {
|
||||
@ -441,7 +441,7 @@ func (m *MM) RegisterServices(app *App) error {
|
||||
|
||||
// validateConfig validates the module manager configuration
|
||||
// it asserts that all modules are defined in the configuration and that no modules are forgotten
|
||||
func (m *MM) validateConfig() error {
|
||||
func (m *MM[T]) validateConfig() error {
|
||||
if err := m.assertNoForgottenModules("PreBlockers", m.config.PreBlockers, func(moduleName string) bool {
|
||||
module := m.modules[moduleName]
|
||||
_, hasBlock := module.(appmodulev2.HasPreBlocker)
|
||||
@ -472,7 +472,7 @@ func (m *MM) validateConfig() error {
|
||||
|
||||
if err := m.assertNoForgottenModules("TxValidators", m.config.TxValidators, func(moduleName string) bool {
|
||||
module := m.modules[moduleName]
|
||||
_, hasTxValidator := module.(appmodulev2.HasTxValidator[transaction.Tx])
|
||||
_, hasTxValidator := module.(appmodulev2.HasTxValidator[T])
|
||||
return !hasTxValidator
|
||||
}); err != nil {
|
||||
return err
|
||||
@ -520,7 +520,7 @@ func (m *MM) validateConfig() error {
|
||||
// assertNoForgottenModules checks that we didn't forget any modules in the *runtimev2.Module config.
|
||||
// `pass` is a closure which allows one to omit modules from `moduleNames`.
|
||||
// If you provide non-nil `pass` and it returns true, the module would not be subject of the assertion.
|
||||
func (m *MM) assertNoForgottenModules(
|
||||
func (m *MM[T]) assertNoForgottenModules(
|
||||
setOrderFnName string,
|
||||
moduleNames []string,
|
||||
pass func(moduleName string) bool,
|
||||
@ -549,7 +549,7 @@ func (m *MM) assertNoForgottenModules(
|
||||
return nil
|
||||
}
|
||||
|
||||
func registerServices(s appmodule.HasServices, app *App, registry *protoregistry.Files) error {
|
||||
func registerServices[T transaction.Tx](s appmodule.HasServices, app *App[T], registry *protoregistry.Files) error {
|
||||
c := &configurator{
|
||||
stfQueryRouter: app.queryRouterBuilder,
|
||||
stfMsgRouter: app.msgRouterBuilder,
|
||||
|
||||
@ -23,6 +23,7 @@ import (
|
||||
"cosmossdk.io/core/log"
|
||||
"cosmossdk.io/core/registry"
|
||||
"cosmossdk.io/core/store"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/depinject/appconfig"
|
||||
"cosmossdk.io/runtime/v2/services"
|
||||
@ -31,18 +32,18 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
_ appmodulev2.AppModule = appModule{}
|
||||
_ appmodule.HasServices = appModule{}
|
||||
_ appmodulev2.AppModule = appModule[transaction.Tx]{}
|
||||
_ appmodule.HasServices = appModule[transaction.Tx]{}
|
||||
)
|
||||
|
||||
type appModule struct {
|
||||
app *App
|
||||
type appModule[T transaction.Tx] struct {
|
||||
app *App[T]
|
||||
}
|
||||
|
||||
func (m appModule) IsOnePerModuleType() {}
|
||||
func (m appModule) IsAppModule() {}
|
||||
func (m appModule[T]) IsOnePerModuleType() {}
|
||||
func (m appModule[T]) IsAppModule() {}
|
||||
|
||||
func (m appModule) RegisterServices(registar grpc.ServiceRegistrar) error {
|
||||
func (m appModule[T]) RegisterServices(registar grpc.ServiceRegistrar) error {
|
||||
autoCliQueryService, err := services.NewAutoCLIQueryService(m.app.moduleManager.modules)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -59,7 +60,7 @@ func (m appModule) RegisterServices(registar grpc.ServiceRegistrar) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m appModule) AutoCLIOptions() *autocliv1.ModuleOptions {
|
||||
func (m appModule[T]) AutoCLIOptions() *autocliv1.ModuleOptions {
|
||||
return &autocliv1.ModuleOptions{
|
||||
Query: &autocliv1.ServiceCommandDescriptor{
|
||||
Service: appv1alpha1.Query_ServiceDesc.ServiceName,
|
||||
@ -96,22 +97,22 @@ func (m appModule) AutoCLIOptions() *autocliv1.ModuleOptions {
|
||||
func init() {
|
||||
appconfig.Register(&runtimev2.Module{},
|
||||
appconfig.Provide(
|
||||
ProvideAppBuilder,
|
||||
ProvideEnvironment,
|
||||
ProvideModuleManager,
|
||||
ProvideGenesisTxHandler,
|
||||
ProvideAppBuilder[transaction.Tx],
|
||||
ProvideEnvironment[transaction.Tx],
|
||||
ProvideModuleManager[transaction.Tx],
|
||||
ProvideGenesisTxHandler[transaction.Tx],
|
||||
ProvideCometService,
|
||||
ProvideAppVersionModifier,
|
||||
ProvideAppVersionModifier[transaction.Tx],
|
||||
),
|
||||
appconfig.Invoke(SetupAppBuilder),
|
||||
)
|
||||
}
|
||||
|
||||
func ProvideAppBuilder(
|
||||
func ProvideAppBuilder[T transaction.Tx](
|
||||
interfaceRegistrar registry.InterfaceRegistrar,
|
||||
amino legacy.Amino,
|
||||
) (
|
||||
*AppBuilder,
|
||||
*AppBuilder[T],
|
||||
*stf.MsgRouterBuilder,
|
||||
appmodulev2.AppModule,
|
||||
protodesc.Resolver,
|
||||
@ -128,16 +129,16 @@ func ProvideAppBuilder(
|
||||
}
|
||||
|
||||
msgRouterBuilder := stf.NewMsgRouterBuilder()
|
||||
app := &App{
|
||||
app := &App[T]{
|
||||
storeKeys: nil,
|
||||
interfaceRegistrar: interfaceRegistrar,
|
||||
amino: amino,
|
||||
msgRouterBuilder: msgRouterBuilder,
|
||||
queryRouterBuilder: stf.NewMsgRouterBuilder(), // TODO dedicated query router
|
||||
}
|
||||
appBuilder := &AppBuilder{app: app}
|
||||
appBuilder := &AppBuilder[T]{app: app}
|
||||
|
||||
return appBuilder, msgRouterBuilder, appModule{app}, protoFiles, protoTypes
|
||||
return appBuilder, msgRouterBuilder, appModule[T]{app}, protoFiles, protoTypes
|
||||
}
|
||||
|
||||
type AppInputs struct {
|
||||
@ -145,8 +146,8 @@ type AppInputs struct {
|
||||
|
||||
AppConfig *appv1alpha1.Config
|
||||
Config *runtimev2.Module
|
||||
AppBuilder *AppBuilder
|
||||
ModuleManager *MM
|
||||
AppBuilder *AppBuilder[transaction.Tx]
|
||||
ModuleManager *MM[transaction.Tx]
|
||||
InterfaceRegistrar registry.InterfaceRegistrar
|
||||
LegacyAmino legacy.Amino
|
||||
Logger log.Logger
|
||||
@ -169,16 +170,16 @@ func SetupAppBuilder(inputs AppInputs) {
|
||||
}
|
||||
}
|
||||
|
||||
func ProvideModuleManager(
|
||||
func ProvideModuleManager[T transaction.Tx](
|
||||
logger log.Logger,
|
||||
config *runtimev2.Module,
|
||||
modules map[string]appmodulev2.AppModule,
|
||||
) *MM {
|
||||
return NewModuleManager(logger, config, modules)
|
||||
) *MM[T] {
|
||||
return NewModuleManager[T](logger, config, modules)
|
||||
}
|
||||
|
||||
// ProvideEnvironment provides the environment for keeper modules, while maintaining backward compatibility and provide services directly as well.
|
||||
func ProvideEnvironment(logger log.Logger, config *runtimev2.Module, key depinject.ModuleKey, appBuilder *AppBuilder) (
|
||||
func ProvideEnvironment[T transaction.Tx](logger log.Logger, config *runtimev2.Module, key depinject.ModuleKey, appBuilder *AppBuilder[T]) (
|
||||
appmodulev2.Environment,
|
||||
store.KVStoreService,
|
||||
store.MemoryStoreService,
|
||||
@ -222,7 +223,7 @@ func ProvideEnvironment(logger log.Logger, config *runtimev2.Module, key depinje
|
||||
return env, kvService, memKvService
|
||||
}
|
||||
|
||||
func registerStoreKey(wrapper *AppBuilder, key string) {
|
||||
func registerStoreKey[T transaction.Tx](wrapper *AppBuilder[T], key string) {
|
||||
wrapper.app.storeKeys = append(wrapper.app.storeKeys, key)
|
||||
}
|
||||
|
||||
@ -236,7 +237,7 @@ func storeKeyOverride(config *runtimev2.Module, moduleName string) *runtimev2.St
|
||||
return nil
|
||||
}
|
||||
|
||||
func ProvideGenesisTxHandler(appBuilder *AppBuilder) genesis.TxHandler {
|
||||
func ProvideGenesisTxHandler[T transaction.Tx](appBuilder *AppBuilder[T]) genesis.TxHandler {
|
||||
return appBuilder.app
|
||||
}
|
||||
|
||||
@ -246,6 +247,6 @@ func ProvideCometService() comet.Service {
|
||||
|
||||
// ProvideAppVersionModifier returns nil, `app.VersionModifier` is a feature of BaseApp and neither used nor required for runtim/v2.
|
||||
// nil is acceptable, see: https://github.com/cosmos/cosmos-sdk/blob/0a6ee406a02477ae8ccbfcbe1b51fc3930087f4c/x/upgrade/keeper/keeper.go#L438
|
||||
func ProvideAppVersionModifier(app *AppBuilder) app.VersionModifier {
|
||||
func ProvideAppVersionModifier[T transaction.Tx](app *AppBuilder[T]) app.VersionModifier {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ import (
|
||||
|
||||
const serverName = "grpc-server"
|
||||
|
||||
type GRPCServer struct {
|
||||
type GRPCServer[AppT serverv2.AppI[T], T transaction.Tx] struct {
|
||||
logger log.Logger
|
||||
config *Config
|
||||
|
||||
@ -35,13 +35,13 @@ type GRPCService interface {
|
||||
RegisterGRPCServer(gogogrpc.Server)
|
||||
}
|
||||
|
||||
func New() *GRPCServer {
|
||||
return &GRPCServer{}
|
||||
func New[AppT serverv2.AppI[T], T transaction.Tx]() *GRPCServer[AppT, T] {
|
||||
return &GRPCServer[AppT, T]{}
|
||||
}
|
||||
|
||||
// Init returns a correctly configured and initialized gRPC server.
|
||||
// Note, the caller is responsible for starting the server.
|
||||
func (g *GRPCServer) Init(appI serverv2.AppI[transaction.Tx], v *viper.Viper, logger log.Logger) error {
|
||||
func (g *GRPCServer[AppT, T]) Init(appI AppT, v *viper.Viper, logger log.Logger) error {
|
||||
cfg := DefaultConfig()
|
||||
if v != nil {
|
||||
if err := v.Sub(serverName).Unmarshal(&cfg); err != nil {
|
||||
@ -68,11 +68,11 @@ func (g *GRPCServer) Init(appI serverv2.AppI[transaction.Tx], v *viper.Viper, lo
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GRPCServer) Name() string {
|
||||
func (g *GRPCServer[AppT, T]) Name() string {
|
||||
return serverName
|
||||
}
|
||||
|
||||
func (g *GRPCServer) Start(ctx context.Context) error {
|
||||
func (g *GRPCServer[AppT, T]) Start(ctx context.Context) error {
|
||||
listener, err := net.Listen("tcp", g.config.Address)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to listen on address %s: %w", g.config.Address, err)
|
||||
@ -95,14 +95,14 @@ func (g *GRPCServer) Start(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (g *GRPCServer) Stop(ctx context.Context) error {
|
||||
func (g *GRPCServer[AppT, T]) Stop(ctx context.Context) error {
|
||||
g.logger.Info("stopping gRPC server...", "address", g.config.Address)
|
||||
g.grpcSrv.GracefulStop()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GRPCServer) Config() any {
|
||||
func (g *GRPCServer[AppT, T]) Config() any {
|
||||
if g.config == nil || g.config == (&Config{}) {
|
||||
return DefaultConfig()
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/version"
|
||||
)
|
||||
|
||||
func (s *CometBFTServer[T]) rpcClient(cmd *cobra.Command) (rpc.CometRPC, error) {
|
||||
func (s *CometBFTServer[AppT, T]) rpcClient(cmd *cobra.Command) (rpc.CometRPC, error) {
|
||||
if s.config.Standalone {
|
||||
client, err := rpchttp.New(client.GetConfigFromCmd(cmd).RPC.ListenAddress)
|
||||
if err != nil {
|
||||
@ -52,7 +52,7 @@ func (s *CometBFTServer[T]) rpcClient(cmd *cobra.Command) (rpc.CometRPC, error)
|
||||
}
|
||||
|
||||
// StatusCommand returns the command to return the status of the network.
|
||||
func (s *CometBFTServer[T]) StatusCommand() *cobra.Command {
|
||||
func (s *CometBFTServer[AppT, T]) StatusCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "status",
|
||||
Short: "Query remote node for status",
|
||||
@ -83,7 +83,7 @@ func (s *CometBFTServer[T]) StatusCommand() *cobra.Command {
|
||||
}
|
||||
|
||||
// ShowNodeIDCmd - ported from CometBFT, dump node ID to stdout
|
||||
func (s *CometBFTServer[T]) ShowNodeIDCmd() *cobra.Command {
|
||||
func (s *CometBFTServer[AppT, T]) ShowNodeIDCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "show-node-id",
|
||||
Short: "Show this node's ID",
|
||||
@ -101,7 +101,7 @@ func (s *CometBFTServer[T]) ShowNodeIDCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
// ShowValidatorCmd - ported from CometBFT, show this node's validator info
|
||||
func (s *CometBFTServer[T]) ShowValidatorCmd() *cobra.Command {
|
||||
func (s *CometBFTServer[AppT, T]) ShowValidatorCmd() *cobra.Command {
|
||||
cmd := cobra.Command{
|
||||
Use: "show-validator",
|
||||
Short: "Show this node's CometBFT validator info",
|
||||
@ -135,7 +135,7 @@ func (s *CometBFTServer[T]) ShowValidatorCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
// ShowAddressCmd - show this node's validator address
|
||||
func (s *CometBFTServer[T]) ShowAddressCmd() *cobra.Command {
|
||||
func (s *CometBFTServer[AppT, T]) ShowAddressCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "show-address",
|
||||
Short: "Shows this node's CometBFT validator consensus address",
|
||||
@ -154,7 +154,7 @@ func (s *CometBFTServer[T]) ShowAddressCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
// VersionCmd prints CometBFT and ABCI version numbers.
|
||||
func (s *CometBFTServer[T]) VersionCmd() *cobra.Command {
|
||||
func (s *CometBFTServer[AppT, T]) VersionCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print CometBFT libraries' version",
|
||||
@ -182,7 +182,7 @@ func (s *CometBFTServer[T]) VersionCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
// QueryBlocksCmd returns a command to search through blocks by events.
|
||||
func (s *CometBFTServer[T]) QueryBlocksCmd() *cobra.Command {
|
||||
func (s *CometBFTServer[AppT, T]) QueryBlocksCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "blocks",
|
||||
Short: "Query for paginated blocks that match a set of events",
|
||||
@ -232,7 +232,7 @@ for. Each module documents its respective events under 'xx_events.md'.
|
||||
}
|
||||
|
||||
// QueryBlockCmd implements the default command for a Block query.
|
||||
func (s *CometBFTServer[T]) QueryBlockCmd() *cobra.Command {
|
||||
func (s *CometBFTServer[AppT, T]) QueryBlockCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "block --type=[height|hash] [height|hash]",
|
||||
Short: "Query for a committed block by height, hash, or event(s)",
|
||||
@ -319,7 +319,7 @@ $ %s query block --%s=%s <hash>
|
||||
}
|
||||
|
||||
// QueryBlockResultsCmd implements the default command for a BlockResults query.
|
||||
func (s *CometBFTServer[T]) QueryBlockResultsCmd() *cobra.Command {
|
||||
func (s *CometBFTServer[AppT, T]) QueryBlockResultsCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "block-results [height]",
|
||||
Short: "Query for a committed block's results by height",
|
||||
@ -384,7 +384,7 @@ func parseOptionalHeight(heightStr string) (*int64, error) {
|
||||
return &tmp, nil
|
||||
}
|
||||
|
||||
func (s *CometBFTServer[T]) BootstrapStateCmd() *cobra.Command {
|
||||
func (s *CometBFTServer[AppT, T]) BootstrapStateCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "bootstrap-state",
|
||||
Short: "Bootstrap CometBFT state at an arbitrary block height using a light client",
|
||||
@ -414,7 +414,7 @@ func (s *CometBFTServer[T]) BootstrapStateCmd() *cobra.Command {
|
||||
|
||||
func printOutput(cmd *cobra.Command, out []byte) error {
|
||||
// Get flags output
|
||||
outFlag, err := cmd.Flags().GetString(flags.FlagOutput)
|
||||
outFlag, err := cmd.Flags().GetString(flags.FlagOutput)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -45,11 +45,15 @@ const (
|
||||
FlagTrace = "trace"
|
||||
)
|
||||
|
||||
var _ serverv2.ServerComponent[transaction.Tx] = (*CometBFTServer[transaction.Tx])(nil)
|
||||
var _ serverv2.HasCLICommands = (*CometBFTServer[transaction.Tx])(nil)
|
||||
var _ serverv2.HasStartFlags = (*CometBFTServer[transaction.Tx])(nil)
|
||||
var (
|
||||
_ serverv2.ServerComponent[
|
||||
serverv2.AppI[transaction.Tx], transaction.Tx,
|
||||
] = (*CometBFTServer[serverv2.AppI[transaction.Tx], transaction.Tx])(nil)
|
||||
_ serverv2.HasCLICommands = (*CometBFTServer[serverv2.AppI[transaction.Tx], transaction.Tx])(nil)
|
||||
_ serverv2.HasStartFlags = (*CometBFTServer[serverv2.AppI[transaction.Tx], transaction.Tx])(nil)
|
||||
)
|
||||
|
||||
type CometBFTServer[T transaction.Tx] struct {
|
||||
type CometBFTServer[AppT serverv2.AppI[T], T transaction.Tx] struct {
|
||||
Node *node.Node
|
||||
App *Consensus[T]
|
||||
logger log.Logger
|
||||
@ -65,14 +69,14 @@ type App[T transaction.Tx] interface {
|
||||
GetStore() types.Store
|
||||
}
|
||||
|
||||
func New[T transaction.Tx](txCodec transaction.Codec[T]) *CometBFTServer[T] {
|
||||
func New[AppT serverv2.AppI[T], T transaction.Tx](txCodec transaction.Codec[T]) *CometBFTServer[AppT, T] {
|
||||
consensus := &Consensus[T]{txCodec: txCodec}
|
||||
return &CometBFTServer[T]{
|
||||
return &CometBFTServer[AppT, T]{
|
||||
App: consensus,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], v *viper.Viper, logger log.Logger) error {
|
||||
func (s *CometBFTServer[AppT, T]) Init(appI AppT, v *viper.Viper, logger log.Logger) error {
|
||||
store := appI.GetStore().(types.Store)
|
||||
|
||||
cfg := Config{CmtConfig: GetConfigFromViper(v), ConsensusAuthority: appI.GetConsensusAuthority()}
|
||||
@ -109,11 +113,11 @@ func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], v *viper.Viper, logger l
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *CometBFTServer[T]) Name() string {
|
||||
func (s *CometBFTServer[AppT, T]) Name() string {
|
||||
return "cometbft"
|
||||
}
|
||||
|
||||
func (s *CometBFTServer[T]) Start(ctx context.Context) error {
|
||||
func (s *CometBFTServer[AppT, T]) Start(ctx context.Context) error {
|
||||
viper := ctx.Value(corectx.ViperContextKey{}).(*viper.Viper)
|
||||
cometConfig := GetConfigFromViper(viper)
|
||||
|
||||
@ -152,7 +156,7 @@ func (s *CometBFTServer[T]) Start(ctx context.Context) error {
|
||||
return s.Node.Start()
|
||||
}
|
||||
|
||||
func (s *CometBFTServer[T]) Stop(context.Context) error {
|
||||
func (s *CometBFTServer[AppT, T]) Stop(context.Context) error {
|
||||
if s.Node != nil && s.Node.IsRunning() {
|
||||
return s.Node.Stop()
|
||||
}
|
||||
@ -198,7 +202,7 @@ func getGenDocProvider(cfg *cmtcfg.Config) func() (node.ChecksummedGenesisDoc, e
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CometBFTServer[T]) StartCmdFlags() *pflag.FlagSet {
|
||||
func (s *CometBFTServer[AppT, T]) StartCmdFlags() *pflag.FlagSet {
|
||||
flags := pflag.NewFlagSet("cometbft", pflag.ExitOnError)
|
||||
flags.Bool(flagWithComet, true, "Run abci app embedded in-process with CometBFT")
|
||||
flags.String(flagAddress, "tcp://127.0.0.1:26658", "Listen address")
|
||||
@ -213,7 +217,7 @@ func (s *CometBFTServer[T]) StartCmdFlags() *pflag.FlagSet {
|
||||
return flags
|
||||
}
|
||||
|
||||
func (s *CometBFTServer[T]) CLICommands() serverv2.CLIConfig {
|
||||
func (s *CometBFTServer[AppT, T]) CLICommands() serverv2.CLIConfig {
|
||||
return serverv2.CLIConfig{
|
||||
Commands: []*cobra.Command{
|
||||
s.StatusCommand(),
|
||||
@ -230,7 +234,7 @@ func (s *CometBFTServer[T]) CLICommands() serverv2.CLIConfig {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CometBFTServer[T]) WriteDefaultConfigAt(configPath string) error {
|
||||
func (s *CometBFTServer[AppT, T]) WriteDefaultConfigAt(configPath string) error {
|
||||
cometConfig := cmtcfg.DefaultConfig()
|
||||
cmtcfg.WriteConfigFile(filepath.Join(configPath, "config.toml"), cometConfig)
|
||||
return nil
|
||||
|
||||
@ -33,7 +33,12 @@ func Execute(rootCmd *cobra.Command, envPrefix, defaultHome string) error {
|
||||
return rootCmd.Execute()
|
||||
}
|
||||
|
||||
func Commands(rootCmd *cobra.Command, newApp AppCreator[transaction.Tx], logger log.Logger, components ...ServerComponent[transaction.Tx]) (CLIConfig, error) {
|
||||
func Commands[AppT AppI[T], T transaction.Tx](
|
||||
rootCmd *cobra.Command,
|
||||
newApp AppCreator[AppT, T],
|
||||
logger log.Logger,
|
||||
components ...ServerComponent[AppT, T],
|
||||
) (CLIConfig, error) {
|
||||
if len(components) == 0 {
|
||||
return CLIConfig{}, errors.New("no components provided")
|
||||
}
|
||||
@ -94,7 +99,12 @@ func Commands(rootCmd *cobra.Command, newApp AppCreator[transaction.Tx], logger
|
||||
return cmds, nil
|
||||
}
|
||||
|
||||
func AddCommands(rootCmd *cobra.Command, newApp AppCreator[transaction.Tx], logger log.Logger, components ...ServerComponent[transaction.Tx]) error {
|
||||
func AddCommands[AppT AppI[T], T transaction.Tx](
|
||||
rootCmd *cobra.Command,
|
||||
newApp AppCreator[AppT, T],
|
||||
logger log.Logger,
|
||||
components ...ServerComponent[AppT, T],
|
||||
) error {
|
||||
cmds, err := Commands(rootCmd, newApp, logger, components...)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -125,7 +135,7 @@ func AddCommands(rootCmd *cobra.Command, newApp AppCreator[transaction.Tx], logg
|
||||
}
|
||||
|
||||
// configHandle writes the default config to the home directory if it does not exist and sets the server context
|
||||
func configHandle(s *Server, home string, cmd *cobra.Command) error {
|
||||
func configHandle[AppT AppI[T], T transaction.Tx](s *Server[AppT, T], home string, cmd *cobra.Command) error {
|
||||
configDir := filepath.Join(home, "config")
|
||||
|
||||
// we need to check app.toml as the config folder can already exist for the client.toml
|
||||
|
||||
@ -18,12 +18,12 @@ import (
|
||||
)
|
||||
|
||||
// ServerComponent is a server module that can be started and stopped.
|
||||
type ServerComponent[T transaction.Tx] interface {
|
||||
type ServerComponent[AppT AppI[T], T transaction.Tx] interface {
|
||||
Name() string
|
||||
|
||||
Start(context.Context) error
|
||||
Stop(context.Context) error
|
||||
Init(AppI[T], *viper.Viper, log.Logger) error
|
||||
Init(AppT, *viper.Viper, log.Logger) error
|
||||
}
|
||||
|
||||
// HasCLICommands is a server module that has CLI commands.
|
||||
@ -41,7 +41,7 @@ type HasStartFlags interface {
|
||||
StartCmdFlags() *pflag.FlagSet
|
||||
}
|
||||
|
||||
var _ ServerComponent[transaction.Tx] = (*Server)(nil)
|
||||
var _ ServerComponent[AppI[transaction.Tx], transaction.Tx] = (*Server[AppI[transaction.Tx], transaction.Tx])(nil)
|
||||
|
||||
// Configs returns a viper instance of the config file
|
||||
func ReadConfig(configPath string) (*viper.Viper, error) {
|
||||
@ -63,24 +63,26 @@ func ReadConfig(configPath string) (*viper.Viper, error) {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
type Server[AppT AppI[T], T transaction.Tx] struct {
|
||||
logger log.Logger
|
||||
components []ServerComponent[transaction.Tx]
|
||||
components []ServerComponent[AppT, T]
|
||||
}
|
||||
|
||||
func NewServer(logger log.Logger, components ...ServerComponent[transaction.Tx]) *Server {
|
||||
return &Server{
|
||||
func NewServer[AppT AppI[T], T transaction.Tx](
|
||||
logger log.Logger, components ...ServerComponent[AppT, T],
|
||||
) *Server[AppT, T] {
|
||||
return &Server[AppT, T]{
|
||||
logger: logger,
|
||||
components: components,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) Name() string {
|
||||
func (s *Server[AppT, T]) Name() string {
|
||||
return "server"
|
||||
}
|
||||
|
||||
// Start starts all components concurrently.
|
||||
func (s *Server) Start(ctx context.Context) error {
|
||||
func (s *Server[AppT, T]) Start(ctx context.Context) error {
|
||||
s.logger.Info("starting servers...")
|
||||
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
@ -104,7 +106,7 @@ func (s *Server) Start(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// Stop stops all components concurrently.
|
||||
func (s *Server) Stop(ctx context.Context) error {
|
||||
func (s *Server[AppT, T]) Stop(ctx context.Context) error {
|
||||
s.logger.Info("stopping servers...")
|
||||
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
@ -119,7 +121,7 @@ func (s *Server) Stop(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// CLICommands returns all CLI commands of all components.
|
||||
func (s *Server) CLICommands() CLIConfig {
|
||||
func (s *Server[AppT, T]) CLICommands() CLIConfig {
|
||||
compart := func(name string, cmds ...*cobra.Command) *cobra.Command {
|
||||
if len(cmds) == 1 && strings.HasPrefix(cmds[0].Use, name) {
|
||||
return cmds[0]
|
||||
@ -147,7 +149,7 @@ func (s *Server) CLICommands() CLIConfig {
|
||||
}
|
||||
|
||||
// Configs returns all configs of all server components.
|
||||
func (s *Server) Configs() map[string]any {
|
||||
func (s *Server[AppT, T]) Configs() map[string]any {
|
||||
cfgs := make(map[string]any)
|
||||
for _, mod := range s.components {
|
||||
if configmod, ok := mod.(HasConfig); ok {
|
||||
@ -160,8 +162,8 @@ func (s *Server) Configs() map[string]any {
|
||||
}
|
||||
|
||||
// Configs returns all configs of all server components.
|
||||
func (s *Server) Init(appI AppI[transaction.Tx], v *viper.Viper, logger log.Logger) error {
|
||||
var components []ServerComponent[transaction.Tx]
|
||||
func (s *Server[AppT, T]) Init(appI AppT, v *viper.Viper, logger log.Logger) error {
|
||||
var components []ServerComponent[AppT, T]
|
||||
for _, mod := range s.components {
|
||||
mod := mod
|
||||
if err := mod.Init(appI, v, logger); err != nil {
|
||||
@ -177,7 +179,7 @@ func (s *Server) Init(appI AppI[transaction.Tx], v *viper.Viper, logger log.Logg
|
||||
|
||||
// WriteConfig writes the config to the given path.
|
||||
// Note: it does not use viper.WriteConfigAs because we do not want to store flag values in the config.
|
||||
func (s *Server) WriteConfig(configPath string) error {
|
||||
func (s *Server[AppT, T]) WriteConfig(configPath string) error {
|
||||
cfgs := s.Configs()
|
||||
b, err := toml.Marshal(cfgs)
|
||||
if err != nil {
|
||||
@ -206,7 +208,7 @@ func (s *Server) WriteConfig(configPath string) error {
|
||||
}
|
||||
|
||||
// Flags returns all flags of all server components.
|
||||
func (s *Server) StartFlags() []*pflag.FlagSet {
|
||||
func (s *Server[AppT, T]) StartFlags() []*pflag.FlagSet {
|
||||
flags := []*pflag.FlagSet{}
|
||||
for _, mod := range s.components {
|
||||
if startmod, ok := mod.(HasStartFlags); ok {
|
||||
|
||||
@ -58,7 +58,7 @@ func TestServer(t *testing.T) {
|
||||
}
|
||||
|
||||
logger := log.NewLogger(os.Stdout)
|
||||
grpcServer := grpc.New()
|
||||
grpcServer := grpc.New[serverv2.AppI[transaction.Tx], transaction.Tx]()
|
||||
if err := grpcServer.Init(&mockApp[transaction.Tx]{}, v, logger); err != nil {
|
||||
t.Log(err)
|
||||
t.Fail()
|
||||
|
||||
@ -9,7 +9,7 @@ import (
|
||||
"cosmossdk.io/server/v2/appmanager"
|
||||
)
|
||||
|
||||
type AppCreator[T transaction.Tx] func(log.Logger, *viper.Viper) AppI[T]
|
||||
type AppCreator[AppT AppI[T], T transaction.Tx] func(log.Logger, *viper.Viper) AppT
|
||||
|
||||
type AppI[T transaction.Tx] interface {
|
||||
GetAppManager() *appmanager.AppManager[T]
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
coreapp "cosmossdk.io/core/app"
|
||||
"cosmossdk.io/core/legacy"
|
||||
"cosmossdk.io/core/log"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/runtime/v2"
|
||||
serverv2 "cosmossdk.io/server/v2"
|
||||
@ -48,8 +49,8 @@ var DefaultNodeHome string
|
||||
// SimApp extends an ABCI application, but with most of its parameters exported.
|
||||
// They are exported for convenience in creating helper functions, as object
|
||||
// capabilities aren't needed for testing.
|
||||
type SimApp struct {
|
||||
*runtime.App
|
||||
type SimApp[T transaction.Tx] struct {
|
||||
*runtime.App[T]
|
||||
legacyAmino legacy.Amino
|
||||
appCodec codec.Codec
|
||||
txConfig client.TxConfig
|
||||
@ -91,18 +92,18 @@ func AppConfig() depinject.Config {
|
||||
}
|
||||
|
||||
// NewSimApp returns a reference to an initialized SimApp.
|
||||
func NewSimApp(
|
||||
func NewSimApp[T transaction.Tx](
|
||||
logger log.Logger,
|
||||
viper *viper.Viper,
|
||||
) *SimApp {
|
||||
) *SimApp[T] {
|
||||
viper.Set(serverv2.FlagHome, DefaultNodeHome) // TODO possibly set earlier when viper is created
|
||||
scRawDb, err := db.NewGoLevelDB("application", filepath.Join(DefaultNodeHome, "data"), nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var (
|
||||
app = &SimApp{}
|
||||
appBuilder *runtime.AppBuilder
|
||||
app = &SimApp[T]{}
|
||||
appBuilder *runtime.AppBuilder[T]
|
||||
|
||||
// merge the AppConfig and other configuration in one config
|
||||
appConfig = depinject.Configs(
|
||||
@ -231,26 +232,26 @@ func NewSimApp(
|
||||
//
|
||||
// NOTE: This is solely to be used for testing purposes as it may be desirable
|
||||
// for modules to register their own custom testing types.
|
||||
func (app *SimApp) AppCodec() codec.Codec {
|
||||
func (app *SimApp[T]) AppCodec() codec.Codec {
|
||||
return app.appCodec
|
||||
}
|
||||
|
||||
// InterfaceRegistry returns SimApp's InterfaceRegistry.
|
||||
func (app *SimApp) InterfaceRegistry() coreapp.InterfaceRegistry {
|
||||
func (app *SimApp[T]) InterfaceRegistry() coreapp.InterfaceRegistry {
|
||||
return app.interfaceRegistry
|
||||
}
|
||||
|
||||
// TxConfig returns SimApp's TxConfig.
|
||||
func (app *SimApp) TxConfig() client.TxConfig {
|
||||
func (app *SimApp[T]) TxConfig() client.TxConfig {
|
||||
return app.txConfig
|
||||
}
|
||||
|
||||
// GetConsensusAuthority gets the consensus authority.
|
||||
func (app *SimApp) GetConsensusAuthority() string {
|
||||
func (app *SimApp[T]) GetConsensusAuthority() string {
|
||||
return app.ConsensusParamsKeeper.GetAuthority()
|
||||
}
|
||||
|
||||
// GetStore gets the app store.
|
||||
func (app *SimApp) GetStore() any {
|
||||
func (app *SimApp[T]) GetStore() any {
|
||||
return app.App.GetStore()
|
||||
}
|
||||
|
||||
@ -5,6 +5,6 @@ import (
|
||||
)
|
||||
|
||||
// ExportAppStateAndValidators exports the state of the application for a genesis file.
|
||||
func (app *SimApp) ExportAppStateAndValidators(forZeroHeight bool, jailAllowedAddrs, modulesToExport []string) (servertypes.ExportedApp, error) {
|
||||
func (app *SimApp[T]) ExportAppStateAndValidators(forZeroHeight bool, jailAllowedAddrs, modulesToExport []string) (servertypes.ExportedApp, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
@ -32,30 +32,56 @@ import (
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
var _ transaction.Codec[transaction.Tx] = &temporaryTxDecoder{}
|
||||
var _ transaction.Codec[transaction.Tx] = &temporaryTxDecoder[transaction.Tx]{}
|
||||
|
||||
type temporaryTxDecoder struct {
|
||||
type temporaryTxDecoder[T transaction.Tx] struct {
|
||||
txConfig client.TxConfig
|
||||
}
|
||||
|
||||
// Decode implements transaction.Codec.
|
||||
func (t *temporaryTxDecoder) Decode(bz []byte) (transaction.Tx, error) {
|
||||
return t.txConfig.TxDecoder()(bz)
|
||||
func (t *temporaryTxDecoder[T]) Decode(bz []byte) (T, error) {
|
||||
var out T
|
||||
tx, err := t.txConfig.TxDecoder()(bz)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
out, ok = tx.(T)
|
||||
if !ok {
|
||||
return out, errors.New("unexpected Tx type")
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// DecodeJSON implements transaction.Codec.
|
||||
func (t *temporaryTxDecoder) DecodeJSON(bz []byte) (transaction.Tx, error) {
|
||||
return t.txConfig.TxJSONDecoder()(bz)
|
||||
func (t *temporaryTxDecoder[T]) DecodeJSON(bz []byte) (T, error) {
|
||||
var out T
|
||||
tx, err := t.txConfig.TxJSONDecoder()(bz)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
out, ok = tx.(T)
|
||||
if !ok {
|
||||
return out, errors.New("unexpected Tx type")
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func newApp(logger log.Logger, viper *viper.Viper) serverv2.AppI[transaction.Tx] {
|
||||
return simapp.NewSimApp(logger, viper)
|
||||
func newApp[AppT serverv2.AppI[T], T transaction.Tx](
|
||||
logger log.Logger, viper *viper.Viper,
|
||||
) AppT {
|
||||
return serverv2.AppI[T](simapp.NewSimApp[T](logger, viper)).(AppT)
|
||||
}
|
||||
|
||||
func initRootCmd(
|
||||
func initRootCmd[AppT serverv2.AppI[T], T transaction.Tx](
|
||||
rootCmd *cobra.Command,
|
||||
txConfig client.TxConfig,
|
||||
moduleManager *runtimev2.MM,
|
||||
moduleManager *runtimev2.MM[T],
|
||||
) {
|
||||
cfg := sdk.GetConfig()
|
||||
cfg.Seal()
|
||||
@ -78,8 +104,8 @@ func initRootCmd(
|
||||
rootCmd,
|
||||
newApp,
|
||||
logger,
|
||||
cometbft.New(&temporaryTxDecoder{txConfig}),
|
||||
grpc.New(),
|
||||
cometbft.New[AppT, T](&temporaryTxDecoder[T]{txConfig}),
|
||||
grpc.New[AppT, T](),
|
||||
); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -87,7 +113,7 @@ func initRootCmd(
|
||||
// add keybase, auxiliary RPC, query, genesis, and tx child commands
|
||||
rootCmd.AddCommand(
|
||||
server.StatusCommand(),
|
||||
genesisCommand(txConfig, moduleManager, appExport),
|
||||
genesisCommand[T](txConfig, moduleManager, appExport[T]),
|
||||
queryCommand(),
|
||||
txCommand(),
|
||||
keys.Commands(),
|
||||
@ -96,9 +122,9 @@ func initRootCmd(
|
||||
}
|
||||
|
||||
// genesisCommand builds genesis-related `simd genesis` command. Users may provide application specific commands as a parameter
|
||||
func genesisCommand(
|
||||
func genesisCommand[T transaction.Tx](
|
||||
txConfig client.TxConfig,
|
||||
moduleManager *runtimev2.MM,
|
||||
moduleManager *runtimev2.MM[T],
|
||||
appExport func(logger log.Logger,
|
||||
height int64,
|
||||
forZeroHeight bool,
|
||||
@ -171,7 +197,7 @@ func txCommand() *cobra.Command {
|
||||
}
|
||||
|
||||
// appExport creates a new simapp (optionally at a given height) and exports state.
|
||||
func appExport(
|
||||
func appExport[T transaction.Tx](
|
||||
logger log.Logger,
|
||||
height int64,
|
||||
forZeroHeight bool,
|
||||
@ -182,15 +208,15 @@ func appExport(
|
||||
// overwrite the FlagInvCheckPeriod
|
||||
viper.Set(server.FlagInvCheckPeriod, 1)
|
||||
|
||||
var simApp *simapp.SimApp
|
||||
var simApp *simapp.SimApp[T]
|
||||
if height != -1 {
|
||||
simApp = simapp.NewSimApp(logger, viper)
|
||||
simApp = simapp.NewSimApp[T](logger, viper)
|
||||
|
||||
if err := simApp.LoadHeight(uint64(height)); err != nil {
|
||||
return servertypes.ExportedApp{}, err
|
||||
}
|
||||
} else {
|
||||
simApp = simapp.NewSimApp(logger, viper)
|
||||
simApp = simapp.NewSimApp[T](logger, viper)
|
||||
}
|
||||
|
||||
return simApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs, modulesToExport)
|
||||
|
||||
@ -8,9 +8,11 @@ import (
|
||||
"cosmossdk.io/client/v2/autocli"
|
||||
"cosmossdk.io/core/address"
|
||||
"cosmossdk.io/core/legacy"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/runtime/v2"
|
||||
serverv2 "cosmossdk.io/server/v2"
|
||||
"cosmossdk.io/simapp/v2"
|
||||
"cosmossdk.io/x/auth/tx"
|
||||
authtxconfig "cosmossdk.io/x/auth/tx/config"
|
||||
@ -24,10 +26,10 @@ import (
|
||||
)
|
||||
|
||||
// NewRootCmd creates a new root command for simd. It is called once in the main function.
|
||||
func NewRootCmd() *cobra.Command {
|
||||
func NewRootCmd[AppT serverv2.AppI[T], T transaction.Tx]() *cobra.Command {
|
||||
var (
|
||||
autoCliOpts autocli.AppOptions
|
||||
moduleManager *runtime.MM
|
||||
moduleManager *runtime.MM[T]
|
||||
clientCtx client.Context
|
||||
)
|
||||
|
||||
@ -83,7 +85,7 @@ func NewRootCmd() *cobra.Command {
|
||||
},
|
||||
}
|
||||
|
||||
initRootCmd(rootCmd, clientCtx.TxConfig, moduleManager)
|
||||
initRootCmd[AppT, T](rootCmd, clientCtx.TxConfig, moduleManager)
|
||||
if err := autoCliOpts.EnhanceRootCommand(rootCmd); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@ -6,6 +6,8 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cosmossdk.io/core/transaction"
|
||||
serverv2 "cosmossdk.io/server/v2"
|
||||
"cosmossdk.io/simapp/v2"
|
||||
"cosmossdk.io/simapp/v2/simdv2/cmd"
|
||||
|
||||
@ -15,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
func TestInitCmd(t *testing.T) {
|
||||
rootCmd := cmd.NewRootCmd()
|
||||
rootCmd := cmd.NewRootCmd[serverv2.AppI[transaction.Tx], transaction.Tx]()
|
||||
rootCmd.SetArgs([]string{
|
||||
"init", // Test the init cmd
|
||||
"simapp-test", // Moniker
|
||||
@ -28,7 +30,7 @@ func TestInitCmd(t *testing.T) {
|
||||
func TestHomeFlagRegistration(t *testing.T) {
|
||||
homeDir := "/tmp/foo"
|
||||
|
||||
rootCmd := cmd.NewRootCmd()
|
||||
rootCmd := cmd.NewRootCmd[serverv2.AppI[transaction.Tx], transaction.Tx]()
|
||||
rootCmd.SetArgs([]string{
|
||||
"query",
|
||||
fmt.Sprintf("--%s", flags.FlagHome),
|
||||
|
||||
@ -4,13 +4,14 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"cosmossdk.io/core/transaction"
|
||||
serverv2 "cosmossdk.io/server/v2"
|
||||
"cosmossdk.io/simapp/v2"
|
||||
"cosmossdk.io/simapp/v2/simdv2/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
rootCmd := cmd.NewRootCmd()
|
||||
rootCmd := cmd.NewRootCmd[serverv2.AppI[transaction.Tx], transaction.Tx]()
|
||||
if err := serverv2.Execute(rootCmd, "", simapp.DefaultNodeHome); err != nil {
|
||||
fmt.Fprintln(rootCmd.OutOrStderr(), err)
|
||||
os.Exit(1)
|
||||
|
||||
@ -20,7 +20,7 @@ import (
|
||||
// v0.50.x to v0.51.x.
|
||||
const UpgradeName = "v050-to-v051"
|
||||
|
||||
func (app *SimApp) RegisterUpgradeHandlers() {
|
||||
func (app *SimApp[T]) RegisterUpgradeHandlers() {
|
||||
app.UpgradeKeeper.SetUpgradeHandler(
|
||||
UpgradeName,
|
||||
func(ctx context.Context, _ upgradetypes.Plan, fromVM appmodule.VersionMap) (appmodule.VersionMap, error) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user