From 232a23a422c9ec1737038884f906f62ed8bd945e Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Thu, 17 Oct 2024 11:42:13 +0200 Subject: [PATCH 1/4] refactor(runtime/v2): simplify app manager --- runtime/v2/app.go | 102 +++++++++++++++++---- runtime/v2/builder.go | 90 ++++-------------- runtime/v2/manager.go | 4 +- runtime/v2/module.go | 2 +- server/v2/api/grpc/server.go | 4 +- server/v2/api/rest/server.go | 2 +- server/v2/appmanager/appmanager.go | 28 +++++- server/v2/appmanager/appmanager_builder.go | 40 -------- server/v2/appmanager/config.go | 1 - server/v2/appmanager/genesis.go | 6 +- server/v2/store/server.go | 2 +- server/v2/types.go | 8 +- simapp/v2/app_di.go | 4 +- 13 files changed, 138 insertions(+), 155 deletions(-) delete mode 100644 server/v2/appmanager/appmanager_builder.go diff --git a/runtime/v2/app.go b/runtime/v2/app.go index e52ea26c6e9f..401ccbb8d25a 100644 --- a/runtime/v2/app.go +++ b/runtime/v2/app.go @@ -1,13 +1,19 @@ package runtime import ( + "context" "encoding/json" + "errors" + "fmt" + "io" runtimev2 "cosmossdk.io/api/cosmos/app/runtime/v2" appmodulev2 "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/registry" + "cosmossdk.io/core/store" "cosmossdk.io/core/transaction" "cosmossdk.io/log" + "cosmossdk.io/runtime/v2/services" "cosmossdk.io/schema/decoding" "cosmossdk.io/server/v2/appmanager" "cosmossdk.io/server/v2/stf" @@ -23,26 +29,80 @@ import ( // 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[T transaction.Tx] struct { - *appmanager.AppManager[T] + // app configuration + logger log.Logger + config *runtimev2.Module - // app manager dependencies + // state stf *stf.STF[T] msgRouterBuilder *stf.MsgRouterBuilder queryRouterBuilder *stf.MsgRouterBuilder + appm *appmanager.AppManager[T] + branch func(state store.ReaderMap) store.WriterMap db Store + storeLoader StoreLoader - // app configuration - logger log.Logger - config *runtimev2.Module - + // modules interfaceRegistrar registry.InterfaceRegistrar amino registry.AminoRegistrar moduleManager *MM[T] + queryHandlers map[string]appmodulev2.Handler // queryHandlers defines the query handlers +} + +// initGenesis initializes the genesis state of the application. +func (a *App[T]) initGenesis(ctx context.Context, src io.Reader, txHandler func(json.RawMessage) error) (store.WriterMap, error) { + // this implementation assumes that the state is a JSON object + bz, err := io.ReadAll(src) + if err != nil { + return nil, fmt.Errorf("failed to read import state: %w", err) + } + var genesisJSON map[string]json.RawMessage + if err = json.Unmarshal(bz, &genesisJSON); err != nil { + return nil, err + } + + v, zeroState, err := a.db.StateLatest() + if err != nil { + return nil, fmt.Errorf("unable to get latest state: %w", err) + } + if v != 0 { // TODO: genesis state may be > 0, we need to set version on store + return nil, errors.New("cannot init genesis on non-zero state") + } + genesisCtx := services.NewGenesisContext(a.branch(zeroState)) + genesisState, err := genesisCtx.Mutate(ctx, func(ctx context.Context) error { + err = a.moduleManager.InitGenesisJSON(ctx, genesisJSON, txHandler) + if err != nil { + return fmt.Errorf("failed to init genesis: %w", err) + } + return nil + }) + + return genesisState, err +} - // QueryHandlers defines the query handlers - QueryHandlers map[string]appmodulev2.Handler +// exportGenesis exports the genesis state of the application. +func (a *App[T]) exportGenesis(ctx context.Context, version uint64) ([]byte, error) { + state, err := a.db.StateAt(version) + if err != nil { + return nil, fmt.Errorf("unable to get state at given version: %w", err) + } + + genesisJson, err := a.moduleManager.ExportGenesisForModules( + ctx, + func() store.WriterMap { + return a.branch(state) + }, + ) + if err != nil { + return nil, fmt.Errorf("failed to export genesis: %w", err) + } + + bz, err := json.Marshal(genesisJson) + if err != nil { + return nil, fmt.Errorf("failed to marshal genesis: %w", err) + } - storeLoader StoreLoader + return bz, nil } // Name returns the app name. @@ -85,24 +145,26 @@ func (a *App[T]) LoadLatestHeight() (uint64, error) { return a.db.GetLatestVersion() } -// Close is called in start cmd to gracefully cleanup resources. -func (a *App[T]) Close() error { - return nil +// AppManager returns the app's appamanger +func (a *App[T]) AppManager() *appmanager.AppManager[T] { + return a.appm } -func (a *App[T]) GetAppManager() *appmanager.AppManager[T] { - return a.AppManager +// GetQueryHandlers returns the query handlers. +func (a *App[T]) QueryHandlers() map[string]appmodulev2.Handler { + return a.queryHandlers } -func (a *App[T]) GetQueryHandlers() map[string]appmodulev2.Handler { - return a.QueryHandlers -} - -// GetSchemaDecoderResolver returns the module schema resolver. -func (a *App[T]) GetSchemaDecoderResolver() decoding.DecoderResolver { +// SchemaDecoderResolver returns the module schema resolver. +func (a *App[T]) SchemaDecoderResolver() decoding.DecoderResolver { moduleSet := map[string]any{} for moduleName, module := range a.moduleManager.Modules() { moduleSet[moduleName] = module } return decoding.ModuleSetDecoderResolver(moduleSet) } + +// Close is called in start cmd to gracefully cleanup resources. +func (a *App[T]) Close() error { + return nil +} diff --git a/runtime/v2/builder.go b/runtime/v2/builder.go index adb177d41eb0..06e881a212a7 100644 --- a/runtime/v2/builder.go +++ b/runtime/v2/builder.go @@ -3,15 +3,12 @@ package runtime import ( "context" "encoding/json" - "errors" "fmt" - "io" "cosmossdk.io/core/appmodule" appmodulev2 "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/store" "cosmossdk.io/core/transaction" - "cosmossdk.io/runtime/v2/services" "cosmossdk.io/server/v2/appmanager" "cosmossdk.io/server/v2/stf" "cosmossdk.io/server/v2/stf/branch" @@ -26,7 +23,6 @@ type AppBuilder[T transaction.Tx] struct { storeBuilder root.Builder // the following fields are used to overwrite the default - branch func(state store.ReaderMap) store.WriterMap txValidator func(ctx context.Context, tx T) error postTxExec func(ctx context.Context, tx T, success bool) error } @@ -71,8 +67,8 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) { } // default branch - if a.branch == nil { - a.branch = branch.DefaultNewWriterMap + if a.app.branch == nil { + a.app.branch = branch.DefaultNewWriterMap } // default tx validator @@ -108,82 +104,28 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) { a.txValidator, valUpdate, a.postTxExec, - a.branch, + a.app.branch, ) if err != nil { return nil, fmt.Errorf("failed to create STF: %w", err) } a.app.stf = stf - appManagerBuilder := appmanager.Builder[T]{ - STF: a.app.stf, - DB: a.app.db, - ValidateTxGasLimit: a.app.config.GasConfig.ValidateTxGasLimit, - QueryGasLimit: a.app.config.GasConfig.QueryGasLimit, - SimulationGasLimit: a.app.config.GasConfig.SimulationGasLimit, - InitGenesis: func( - ctx context.Context, - src io.Reader, - txHandler func(json.RawMessage) error, - ) (store.WriterMap, error) { - // this implementation assumes that the state is a JSON object - bz, err := io.ReadAll(src) - if err != nil { - return nil, fmt.Errorf("failed to read import state: %w", err) - } - var genesisJSON map[string]json.RawMessage - if err = json.Unmarshal(bz, &genesisJSON); err != nil { - return nil, err - } - - v, zeroState, err := a.app.db.StateLatest() - if err != nil { - return nil, fmt.Errorf("unable to get latest state: %w", err) - } - if v != 0 { // TODO: genesis state may be > 0, we need to set version on store - return nil, errors.New("cannot init genesis on non-zero state") - } - genesisCtx := services.NewGenesisContext(a.branch(zeroState)) - genesisState, err := genesisCtx.Mutate(ctx, func(ctx context.Context) error { - err = a.app.moduleManager.InitGenesisJSON(ctx, genesisJSON, txHandler) - if err != nil { - return fmt.Errorf("failed to init genesis: %w", err) - } - return nil - }) - - return genesisState, err + appManager, err := appmanager.NewAppManager[T]( + appmanager.Config{ + ValidateTxGasLimit: a.app.config.GasConfig.ValidateTxGasLimit, + QueryGasLimit: a.app.config.GasConfig.QueryGasLimit, + SimulationGasLimit: a.app.config.GasConfig.SimulationGasLimit, }, - ExportGenesis: func(ctx context.Context, version uint64) ([]byte, error) { - state, err := a.app.db.StateAt(version) - if err != nil { - return nil, fmt.Errorf("unable to get state at given version: %w", err) - } - - genesisJson, err := a.app.moduleManager.ExportGenesisForModules( - ctx, - func() store.WriterMap { - return a.branch(state) - }, - ) - if err != nil { - return nil, fmt.Errorf("failed to export genesis: %w", err) - } - - bz, err := json.Marshal(genesisJson) - if err != nil { - return nil, fmt.Errorf("failed to marshal genesis: %w", err) - } - - return bz, nil - }, - } - - appManager, err := appManagerBuilder.Build() + a.app.db, + a.app.stf, + a.app.initGenesis, + a.app.exportGenesis, + ) if err != nil { - return nil, fmt.Errorf("failed to build app manager: %w", err) + return nil, fmt.Errorf("failed to create AppManager: %w", err) } - a.app.AppManager = appManager + a.app.appm = appManager return a.app, nil } @@ -194,7 +136,7 @@ type AppBuilderOption[T transaction.Tx] func(*AppBuilder[T]) // AppBuilderWithBranch sets a custom branch implementation for the app. func AppBuilderWithBranch[T transaction.Tx](branch func(state store.ReaderMap) store.WriterMap) AppBuilderOption[T] { return func(a *AppBuilder[T]) { - a.branch = branch + a.app.branch = branch } } diff --git a/runtime/v2/manager.go b/runtime/v2/manager.go index 2d6515b81225..e2e90c27f808 100644 --- a/runtime/v2/manager.go +++ b/runtime/v2/manager.go @@ -636,7 +636,7 @@ func registerServices[T transaction.Tx](s appmodulev2.AppModule, app *App[T], re // merge maps for path, decoder := range c.queryHandlers { - app.QueryHandlers[path] = decoder + app.queryHandlers[path] = decoder } } @@ -655,7 +655,7 @@ func registerServices[T transaction.Tx](s appmodulev2.AppModule, app *App[T], re module.RegisterQueryHandlers(&wrapper) for path, handler := range wrapper.handlers { - app.QueryHandlers[path] = handler + app.queryHandlers[path] = handler } } diff --git a/runtime/v2/module.go b/runtime/v2/module.go index dcde5ae48772..54d77dc2742f 100644 --- a/runtime/v2/module.go +++ b/runtime/v2/module.go @@ -131,7 +131,7 @@ func ProvideAppBuilder[T transaction.Tx]( amino: amino, msgRouterBuilder: msgRouterBuilder, queryRouterBuilder: stf.NewMsgRouterBuilder(), // TODO dedicated query router - QueryHandlers: map[string]appmodulev2.Handler{}, + queryHandlers: map[string]appmodulev2.Handler{}, storeLoader: DefaultStoreLoader, } appBuilder := &AppBuilder[T]{app: app, storeBuilder: storeBuilder} diff --git a/server/v2/api/grpc/server.go b/server/v2/api/grpc/server.go index 7b70363f6f16..6b596df18e03 100644 --- a/server/v2/api/grpc/server.go +++ b/server/v2/api/grpc/server.go @@ -57,14 +57,14 @@ func (s *Server[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logger log.L return fmt.Errorf("failed to unmarshal config: %w", err) } } - methodsMap := appI.GetQueryHandlers() + methodsMap := appI.QueryHandlers() grpcSrv := grpc.NewServer( grpc.ForceServerCodec(newProtoCodec(appI.InterfaceRegistry()).GRPCCodec()), grpc.MaxSendMsgSize(serverCfg.MaxSendMsgSize), grpc.MaxRecvMsgSize(serverCfg.MaxRecvMsgSize), grpc.UnknownServiceHandler( - makeUnknownServiceHandler(methodsMap, appI.GetAppManager()), + makeUnknownServiceHandler(methodsMap, appI.AppManager()), ), ) diff --git a/server/v2/api/rest/server.go b/server/v2/api/rest/server.go index 993501c710eb..87c3b7bc5016 100644 --- a/server/v2/api/rest/server.go +++ b/server/v2/api/rest/server.go @@ -45,7 +45,7 @@ func (s *Server[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logger log.L } s.router = http.NewServeMux() - s.router.Handle("/", NewDefaultHandler(appI.GetAppManager())) + s.router.Handle("/", NewDefaultHandler(appI.AppManager())) s.config = serverCfg return nil diff --git a/server/v2/appmanager/appmanager.go b/server/v2/appmanager/appmanager.go index 6a5f96ec5fa9..7e1b703ec390 100644 --- a/server/v2/appmanager/appmanager.go +++ b/server/v2/appmanager/appmanager.go @@ -26,14 +26,34 @@ type Store interface { // AppManager is a coordinator for all things related to an application type AppManager[T transaction.Tx] struct { + // Gas limits for validating, querying, and simulating transactions. config Config - + // InitGenesis is a function that initializes the application state from a genesis file. + // It takes a context, a source reader for the genesis file, and a transaction handler function. + initGenesis InitGenesis + // ExportGenesis is a function that exports the application state to a genesis file. + // It takes a context and a version number for the genesis file. + exportGenesis ExportGenesis + // The database for storing application data. db Store + // The state transition function for processing transactions. + stf StateTransitionFunction[T] +} - initGenesis InitGenesis - exportGenesis ExportGenesis +func NewAppManager[T transaction.Tx]( + config Config, + db Store, + stf StateTransitionFunction[T], + initGenesisImpl InitGenesis, + exportGenesisImpl ExportGenesis, +) (*AppManager[T], error) { + appManager := &AppManager[T]{ + config: config, + db: db, + stf: stf, + } - stf StateTransitionFunction[T] + return appManager, nil } // InitGenesis initializes the genesis state of the application. diff --git a/server/v2/appmanager/appmanager_builder.go b/server/v2/appmanager/appmanager_builder.go deleted file mode 100644 index b3671706c7f2..000000000000 --- a/server/v2/appmanager/appmanager_builder.go +++ /dev/null @@ -1,40 +0,0 @@ -package appmanager - -import ( - "cosmossdk.io/core/transaction" -) - -// Builder is a struct that represents the application builder for managing transactions. -// It contains various fields and methods for initializing the application and handling transactions. -type Builder[T transaction.Tx] struct { - STF StateTransitionFunction[T] // The state transition function for processing transactions. - DB Store // The database for storing application data. - - // Gas limits for validating, querying, and simulating transactions. - ValidateTxGasLimit uint64 - QueryGasLimit uint64 - SimulationGasLimit uint64 - - // InitGenesis is a function that initializes the application state from a genesis file. - // It takes a context, a source reader for the genesis file, and a transaction handler function. - InitGenesis InitGenesis - // ExportGenesis is a function that exports the application state to a genesis file. - // It takes a context and a version number for the genesis file. - ExportGenesis ExportGenesis -} - -// Build creates a new instance of AppManager with the provided configuration and returns it. -// It initializes the AppManager with the given database, export state, import state, initGenesis function, and state transition function. -func (b Builder[T]) Build() (*AppManager[T], error) { - return &AppManager[T]{ - config: Config{ - ValidateTxGasLimit: b.ValidateTxGasLimit, - QueryGasLimit: b.QueryGasLimit, - SimulationGasLimit: b.SimulationGasLimit, - }, - db: b.DB, - initGenesis: b.InitGenesis, - exportGenesis: b.ExportGenesis, - stf: b.STF, - }, nil -} diff --git a/server/v2/appmanager/config.go b/server/v2/appmanager/config.go index ae52849bf297..fb3c20341f35 100644 --- a/server/v2/appmanager/config.go +++ b/server/v2/appmanager/config.go @@ -1,7 +1,6 @@ package appmanager // Config represents the configuration options for the app manager. -// TODO: implement comments for toml type Config struct { ValidateTxGasLimit uint64 `mapstructure:"validate-tx-gas-limit"` // TODO: check how this works on app mempool QueryGasLimit uint64 `mapstructure:"query-gas-limit"` diff --git a/server/v2/appmanager/genesis.go b/server/v2/appmanager/genesis.go index 989ae442a9b9..347d0f30e07b 100644 --- a/server/v2/appmanager/genesis.go +++ b/server/v2/appmanager/genesis.go @@ -9,9 +9,6 @@ import ( ) type ( - // ExportGenesis is a function type that represents the export of the genesis state. - ExportGenesis func(ctx context.Context, version uint64) ([]byte, error) - // InitGenesis is a function that will run at application genesis, it will be called with // the following arguments: // - ctx: the context of the genesis operation @@ -25,4 +22,7 @@ type ( src io.Reader, txHandler func(json.RawMessage) error, ) (store.WriterMap, error) + + // ExportGenesis is a function type that represents the export of the genesis state. + ExportGenesis func(ctx context.Context, version uint64) ([]byte, error) ) diff --git a/server/v2/store/server.go b/server/v2/store/server.go index 20ed3b15b0ea..1fafe4e25d53 100644 --- a/server/v2/store/server.go +++ b/server/v2/store/server.go @@ -32,7 +32,7 @@ func New[T transaction.Tx]() *Server[T] { } func (s *Server[T]) Init(app serverv2.AppI[T], v map[string]any, _ log.Logger) (err error) { - s.backend = app.GetStore() + s.backend = app.Store() s.config, err = UnmarshalConfig(v) return err } diff --git a/server/v2/types.go b/server/v2/types.go index 5406313b080e..30ad21d8d7df 100644 --- a/server/v2/types.go +++ b/server/v2/types.go @@ -17,9 +17,9 @@ type AppCreator[T transaction.Tx] func(log.Logger, *viper.Viper) AppI[T] type AppI[T transaction.Tx] interface { Name() string InterfaceRegistry() server.InterfaceRegistry - GetAppManager() *appmanager.AppManager[T] - GetQueryHandlers() map[string]appmodulev2.Handler - GetStore() store.RootStore - GetSchemaDecoderResolver() decoding.DecoderResolver + AppManager() *appmanager.AppManager[T] + QueryHandlers() map[string]appmodulev2.Handler + Store() store.RootStore + SchemaDecoderResolver() decoding.DecoderResolver Close() error } diff --git a/simapp/v2/app_di.go b/simapp/v2/app_di.go index 3c9933721f12..593c8d0c275f 100644 --- a/simapp/v2/app_di.go +++ b/simapp/v2/app_di.go @@ -218,8 +218,8 @@ func (app *SimApp[T]) TxConfig() client.TxConfig { return app.txConfig } -// GetStore returns the root store. -func (app *SimApp[T]) GetStore() store.RootStore { +// Store returns the root store. +func (app *SimApp[T]) Store() store.RootStore { return app.store } From c7ddc39299c2234e671f839c9d24c4d3430a8309 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Thu, 17 Oct 2024 11:53:11 +0200 Subject: [PATCH 2/4] updates --- runtime/v2/app.go | 71 +------------------------ runtime/v2/builder.go | 83 +++++++++++++++++++++++++----- server/v2/appmanager/appmanager.go | 2 +- server/v2/cometbft/abci_test.go | 17 +++--- server/v2/cometbft/server.go | 8 +-- server/v2/stf/stf.go | 4 +- simapp/v2/app_test.go | 4 +- simapp/v2/export.go | 2 +- 8 files changed, 89 insertions(+), 102 deletions(-) diff --git a/runtime/v2/app.go b/runtime/v2/app.go index 401ccbb8d25a..854e0efc90fa 100644 --- a/runtime/v2/app.go +++ b/runtime/v2/app.go @@ -1,19 +1,13 @@ package runtime import ( - "context" "encoding/json" - "errors" - "fmt" - "io" runtimev2 "cosmossdk.io/api/cosmos/app/runtime/v2" appmodulev2 "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/registry" - "cosmossdk.io/core/store" "cosmossdk.io/core/transaction" "cosmossdk.io/log" - "cosmossdk.io/runtime/v2/services" "cosmossdk.io/schema/decoding" "cosmossdk.io/server/v2/appmanager" "cosmossdk.io/server/v2/stf" @@ -29,6 +23,8 @@ import ( // 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[T transaction.Tx] struct { + *appmanager.AppManager[T] + // app configuration logger log.Logger config *runtimev2.Module @@ -37,8 +33,6 @@ type App[T transaction.Tx] struct { stf *stf.STF[T] msgRouterBuilder *stf.MsgRouterBuilder queryRouterBuilder *stf.MsgRouterBuilder - appm *appmanager.AppManager[T] - branch func(state store.ReaderMap) store.WriterMap db Store storeLoader StoreLoader @@ -49,62 +43,6 @@ type App[T transaction.Tx] struct { queryHandlers map[string]appmodulev2.Handler // queryHandlers defines the query handlers } -// initGenesis initializes the genesis state of the application. -func (a *App[T]) initGenesis(ctx context.Context, src io.Reader, txHandler func(json.RawMessage) error) (store.WriterMap, error) { - // this implementation assumes that the state is a JSON object - bz, err := io.ReadAll(src) - if err != nil { - return nil, fmt.Errorf("failed to read import state: %w", err) - } - var genesisJSON map[string]json.RawMessage - if err = json.Unmarshal(bz, &genesisJSON); err != nil { - return nil, err - } - - v, zeroState, err := a.db.StateLatest() - if err != nil { - return nil, fmt.Errorf("unable to get latest state: %w", err) - } - if v != 0 { // TODO: genesis state may be > 0, we need to set version on store - return nil, errors.New("cannot init genesis on non-zero state") - } - genesisCtx := services.NewGenesisContext(a.branch(zeroState)) - genesisState, err := genesisCtx.Mutate(ctx, func(ctx context.Context) error { - err = a.moduleManager.InitGenesisJSON(ctx, genesisJSON, txHandler) - if err != nil { - return fmt.Errorf("failed to init genesis: %w", err) - } - return nil - }) - - return genesisState, err -} - -// exportGenesis exports the genesis state of the application. -func (a *App[T]) exportGenesis(ctx context.Context, version uint64) ([]byte, error) { - state, err := a.db.StateAt(version) - if err != nil { - return nil, fmt.Errorf("unable to get state at given version: %w", err) - } - - genesisJson, err := a.moduleManager.ExportGenesisForModules( - ctx, - func() store.WriterMap { - return a.branch(state) - }, - ) - if err != nil { - return nil, fmt.Errorf("failed to export genesis: %w", err) - } - - bz, err := json.Marshal(genesisJson) - if err != nil { - return nil, fmt.Errorf("failed to marshal genesis: %w", err) - } - - return bz, nil -} - // Name returns the app name. func (a *App[T]) Name() string { return a.config.AppName @@ -145,11 +83,6 @@ func (a *App[T]) LoadLatestHeight() (uint64, error) { return a.db.GetLatestVersion() } -// AppManager returns the app's appamanger -func (a *App[T]) AppManager() *appmanager.AppManager[T] { - return a.appm -} - // GetQueryHandlers returns the query handlers. func (a *App[T]) QueryHandlers() map[string]appmodulev2.Handler { return a.queryHandlers diff --git a/runtime/v2/builder.go b/runtime/v2/builder.go index 06e881a212a7..9931b9cf7d74 100644 --- a/runtime/v2/builder.go +++ b/runtime/v2/builder.go @@ -3,12 +3,15 @@ package runtime import ( "context" "encoding/json" + "errors" "fmt" + "io" "cosmossdk.io/core/appmodule" appmodulev2 "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/store" "cosmossdk.io/core/transaction" + "cosmossdk.io/runtime/v2/services" "cosmossdk.io/server/v2/appmanager" "cosmossdk.io/server/v2/stf" "cosmossdk.io/server/v2/stf/branch" @@ -23,15 +26,11 @@ type AppBuilder[T transaction.Tx] struct { storeBuilder root.Builder // the following fields are used to overwrite the default + branch func(state store.ReaderMap) store.WriterMap 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[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[T]) RegisterModules(modules map[string]appmodulev2.AppModule) error { @@ -67,8 +66,8 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) { } // default branch - if a.app.branch == nil { - a.app.branch = branch.DefaultNewWriterMap + if a.branch == nil { + a.branch = branch.DefaultNewWriterMap } // default tx validator @@ -94,7 +93,7 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) { endBlocker, valUpdate := a.app.moduleManager.EndBlock() - stf, err := stf.NewSTF[T]( + stf, err := stf.New[T]( a.app.logger.With("module", "stf"), a.app.msgRouterBuilder, a.app.queryRouterBuilder, @@ -104,14 +103,14 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) { a.txValidator, valUpdate, a.postTxExec, - a.app.branch, + a.branch, ) if err != nil { return nil, fmt.Errorf("failed to create STF: %w", err) } a.app.stf = stf - appManager, err := appmanager.NewAppManager[T]( + appManager, err := appmanager.New[T]( appmanager.Config{ ValidateTxGasLimit: a.app.config.GasConfig.ValidateTxGasLimit, QueryGasLimit: a.app.config.GasConfig.QueryGasLimit, @@ -119,24 +118,80 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) { }, a.app.db, a.app.stf, - a.app.initGenesis, - a.app.exportGenesis, + a.initGenesis, + a.exportGenesis, ) if err != nil { return nil, fmt.Errorf("failed to create AppManager: %w", err) } - a.app.appm = appManager + a.app.AppManager = appManager return a.app, nil } +// initGenesis returns the app initialization genesis for modules +func (a *AppBuilder[T]) initGenesis(ctx context.Context, src io.Reader, txHandler func(json.RawMessage) error) (store.WriterMap, error) { + // this implementation assumes that the state is a JSON object + bz, err := io.ReadAll(src) + if err != nil { + return nil, fmt.Errorf("failed to read import state: %w", err) + } + var genesisJSON map[string]json.RawMessage + if err = json.Unmarshal(bz, &genesisJSON); err != nil { + return nil, err + } + + v, zeroState, err := a.app.db.StateLatest() + if err != nil { + return nil, fmt.Errorf("unable to get latest state: %w", err) + } + if v != 0 { // TODO: genesis state may be > 0, we need to set version on store + return nil, errors.New("cannot init genesis on non-zero state") + } + genesisCtx := services.NewGenesisContext(a.branch(zeroState)) + genesisState, err := genesisCtx.Mutate(ctx, func(ctx context.Context) error { + err = a.app.moduleManager.InitGenesisJSON(ctx, genesisJSON, txHandler) + if err != nil { + return fmt.Errorf("failed to init genesis: %w", err) + } + return nil + }) + + return genesisState, err +} + +// exportGenesis returns the app export genesis logic for modules +func (a *AppBuilder[T]) exportGenesis(ctx context.Context, version uint64) ([]byte, error) { + state, err := a.app.db.StateAt(version) + if err != nil { + return nil, fmt.Errorf("unable to get state at given version: %w", err) + } + + genesisJson, err := a.app.moduleManager.ExportGenesisForModules( + ctx, + func() store.WriterMap { + return a.branch(state) + }, + ) + if err != nil { + return nil, fmt.Errorf("failed to export genesis: %w", err) + } + + bz, err := json.Marshal(genesisJson) + if err != nil { + return nil, fmt.Errorf("failed to marshal genesis: %w", err) + } + + return bz, nil +} + // AppBuilderOption is a function that can be passed to AppBuilder.Build to customize the resulting app. type AppBuilderOption[T transaction.Tx] func(*AppBuilder[T]) // AppBuilderWithBranch sets a custom branch implementation for the app. func AppBuilderWithBranch[T transaction.Tx](branch func(state store.ReaderMap) store.WriterMap) AppBuilderOption[T] { return func(a *AppBuilder[T]) { - a.app.branch = branch + a.branch = branch } } diff --git a/server/v2/appmanager/appmanager.go b/server/v2/appmanager/appmanager.go index 7e1b703ec390..58ebd614d47c 100644 --- a/server/v2/appmanager/appmanager.go +++ b/server/v2/appmanager/appmanager.go @@ -40,7 +40,7 @@ type AppManager[T transaction.Tx] struct { stf StateTransitionFunction[T] } -func NewAppManager[T transaction.Tx]( +func New[T transaction.Tx]( config Config, db Store, stf StateTransitionFunction[T], diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index 9a42948c6c61..ab4149ad7427 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -646,7 +646,7 @@ func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock. }, nil }) - s, err := stf.NewSTF( + s, err := stf.New( log.NewNopLogger().With("module", "stf"), msgRouterBuilder, queryRouterBuilder, @@ -672,20 +672,19 @@ func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock. sc := cometmock.NewMockCommiter(log.NewNopLogger(), string(actorName), "stf") mockStore := cometmock.NewMockStore(ss, sc) - b := appmanager.Builder[mock.Tx]{ - STF: s, - DB: mockStore, + am, err := appmanager.New(appmanager.Config{ ValidateTxGasLimit: gasLimit, QueryGasLimit: gasLimit, - SimulationGasLimit: gasLimit, - InitGenesis: func(ctx context.Context, src io.Reader, txHandler func(json.RawMessage) error) (store.WriterMap, error) { + SimulationGasLimit: gasLimit}, + mockStore, + s, + func(ctx context.Context, src io.Reader, txHandler func(json.RawMessage) error) (store.WriterMap, error) { _, st, err := mockStore.StateLatest() require.NoError(t, err) return branch.DefaultNewWriterMap(st), nil }, - } - - am, err := b.Build() + nil, + ) require.NoError(t, err) return NewConsensus[mock.Tx](log.NewNopLogger(), "testing-app", am, func() error { return nil }, mempool, map[string]struct{}{}, nil, mockStore, Config{AppTomlConfig: DefaultAppTomlConfig()}, mock.TxCodec{}, "test") diff --git a/server/v2/cometbft/server.go b/server/v2/cometbft/server.go index 20cd63d07ca4..8b289a7cdbe0 100644 --- a/server/v2/cometbft/server.go +++ b/server/v2/cometbft/server.go @@ -102,15 +102,15 @@ func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logg } s.logger = logger.With(log.ModuleKey, s.Name()) - rs := appI.GetStore() + rs := appI.Store() consensus := NewConsensus( s.logger, appI.Name(), - appI.GetAppManager(), + appI.AppManager(), appI.Close, s.serverOptions.Mempool(cfg), indexEvents, - appI.GetQueryHandlers(), + appI.QueryHandlers(), rs, s.config, s.initTxCodec, @@ -137,7 +137,7 @@ func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logg if indexerCfg := s.config.AppTomlConfig.Indexer; len(indexerCfg.Target) > 0 { listener, err := indexer.StartIndexing(indexer.IndexingOptions{ Config: indexerCfg, - Resolver: appI.GetSchemaDecoderResolver(), + Resolver: appI.SchemaDecoderResolver(), Logger: s.logger.With(log.ModuleKey, "indexer"), }) if err != nil { diff --git a/server/v2/stf/stf.go b/server/v2/stf/stf.go index f665aaf3c6e9..6b6f6b2c53da 100644 --- a/server/v2/stf/stf.go +++ b/server/v2/stf/stf.go @@ -44,8 +44,8 @@ type STF[T transaction.Tx] struct { makeGasMeteredState makeGasMeteredStateFn } -// NewSTF returns a new STF instance. -func NewSTF[T transaction.Tx]( +// New returns a new STF instance. +func New[T transaction.Tx]( logger log.Logger, msgRouterBuilder *MsgRouterBuilder, queryRouterBuilder *MsgRouterBuilder, diff --git a/simapp/v2/app_test.go b/simapp/v2/app_test.go index a5d7f352b4d9..61ace5e4ef29 100644 --- a/simapp/v2/app_test.go +++ b/simapp/v2/app_test.go @@ -72,7 +72,7 @@ func NewTestApp(t *testing.T) (*SimApp[transaction.Tx], context.Context) { genesisBytes, err := json.Marshal(genesis) require.NoError(t, err) - st := app.GetStore() + st := app.Store() ci, err := st.LastCommitID() require.NoError(t, err) @@ -108,7 +108,7 @@ func MoveNextBlock(t *testing.T, app *SimApp[transaction.Tx], ctx context.Contex bz := sha256.Sum256([]byte{}) - st := app.GetStore() + st := app.Store() ci, err := st.LastCommitID() require.NoError(t, err) diff --git a/simapp/v2/export.go b/simapp/v2/export.go index 50f4a898bb37..61175f41607f 100644 --- a/simapp/v2/export.go +++ b/simapp/v2/export.go @@ -29,7 +29,7 @@ func (app *SimApp[T]) ExportAppStateAndValidators( return exportedApp, err } - readerMap, err := app.GetStore().StateAt(latestHeight) + readerMap, err := app.Store().StateAt(latestHeight) if err != nil { return exportedApp, err } From 61f7539a7bafa6b3207d7c955dc2da93f1242f90 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Thu, 17 Oct 2024 12:09:46 +0200 Subject: [PATCH 3/4] simplify --- runtime/v2/app.go | 2 +- runtime/v2/builder.go | 6 +- server/v2/api/grpc/server.go | 2 +- server/v2/api/rest/handler.go | 4 +- server/v2/api/rest/server.go | 2 +- server/v2/appmanager/appmanager.go | 72 ++++++++++++++++++----- server/v2/appmanager/{types.go => stf.go} | 0 server/v2/cometbft/abci.go | 4 +- server/v2/cometbft/abci_test.go | 3 +- server/v2/cometbft/server.go | 2 +- server/v2/server_test.go | 13 +--- server/v2/types.go | 3 +- 12 files changed, 69 insertions(+), 44 deletions(-) rename server/v2/appmanager/{types.go => stf.go} (100%) diff --git a/runtime/v2/app.go b/runtime/v2/app.go index 854e0efc90fa..b7887ab77f54 100644 --- a/runtime/v2/app.go +++ b/runtime/v2/app.go @@ -23,7 +23,7 @@ import ( // 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[T transaction.Tx] struct { - *appmanager.AppManager[T] + appmanager.AppManager[T] // app configuration logger log.Logger diff --git a/runtime/v2/builder.go b/runtime/v2/builder.go index 9931b9cf7d74..8556e35745a8 100644 --- a/runtime/v2/builder.go +++ b/runtime/v2/builder.go @@ -110,7 +110,7 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) { } a.app.stf = stf - appManager, err := appmanager.New[T]( + a.app.AppManager = appmanager.New[T]( appmanager.Config{ ValidateTxGasLimit: a.app.config.GasConfig.ValidateTxGasLimit, QueryGasLimit: a.app.config.GasConfig.QueryGasLimit, @@ -121,10 +121,6 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) { a.initGenesis, a.exportGenesis, ) - if err != nil { - return nil, fmt.Errorf("failed to create AppManager: %w", err) - } - a.app.AppManager = appManager return a.app, nil } diff --git a/server/v2/api/grpc/server.go b/server/v2/api/grpc/server.go index 6b596df18e03..c8959c06d491 100644 --- a/server/v2/api/grpc/server.go +++ b/server/v2/api/grpc/server.go @@ -64,7 +64,7 @@ func (s *Server[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logger log.L grpc.MaxSendMsgSize(serverCfg.MaxSendMsgSize), grpc.MaxRecvMsgSize(serverCfg.MaxRecvMsgSize), grpc.UnknownServiceHandler( - makeUnknownServiceHandler(methodsMap, appI.AppManager()), + makeUnknownServiceHandler(methodsMap, appI), ), ) diff --git a/server/v2/api/rest/handler.go b/server/v2/api/rest/handler.go index a5338f35cf31..8159e23ba3bb 100644 --- a/server/v2/api/rest/handler.go +++ b/server/v2/api/rest/handler.go @@ -20,12 +20,12 @@ const ( MaxBodySize = 1 << 20 // 1 MB ) -func NewDefaultHandler[T transaction.Tx](appManager *appmanager.AppManager[T]) http.Handler { +func NewDefaultHandler[T transaction.Tx](appManager appmanager.AppManager[T]) http.Handler { return &DefaultHandler[T]{appManager: appManager} } type DefaultHandler[T transaction.Tx] struct { - appManager *appmanager.AppManager[T] + appManager appmanager.AppManager[T] } func (h *DefaultHandler[T]) ServeHTTP(w http.ResponseWriter, r *http.Request) { diff --git a/server/v2/api/rest/server.go b/server/v2/api/rest/server.go index 87c3b7bc5016..0f2b1777973a 100644 --- a/server/v2/api/rest/server.go +++ b/server/v2/api/rest/server.go @@ -45,7 +45,7 @@ func (s *Server[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logger log.L } s.router = http.NewServeMux() - s.router.Handle("/", NewDefaultHandler(appI.AppManager())) + s.router.Handle("/", NewDefaultHandler(appI)) s.config = serverCfg return nil diff --git a/server/v2/appmanager/appmanager.go b/server/v2/appmanager/appmanager.go index 58ebd614d47c..af54936ebf03 100644 --- a/server/v2/appmanager/appmanager.go +++ b/server/v2/appmanager/appmanager.go @@ -12,6 +12,45 @@ import ( "cosmossdk.io/core/transaction" ) +// AppManager is a coordinator for all things related to an application +// It is responsible for interacting with stf and store. +// Runtime/v2 is an extension of this interface. +type AppManager[T transaction.Tx] interface { + // InitGenesis initializes the genesis state of the application. + InitGenesis( + ctx context.Context, + blockRequest *server.BlockRequest[T], + initGenesisJSON []byte, + txDecoder transaction.Codec[T], + ) (*server.BlockResponse, corestore.WriterMap, error) + + // ExportGenesis exports the genesis state of the application. + ExportGenesis(ctx context.Context, version uint64) ([]byte, error) + + // DeliverBlock executes a block of transactions. + DeliverBlock( + ctx context.Context, + block *server.BlockRequest[T], + ) (*server.BlockResponse, corestore.WriterMap, error) + + // ValidateTx will validate the tx against the latest storage state. This means that + // only the stateful validation will be run, not the execution portion of the tx. + // If full execution is needed, Simulate must be used. + ValidateTx(ctx context.Context, tx T) (server.TxResult, error) + + // Simulate runs validation and execution flow of a Tx. + Simulate(ctx context.Context, tx T) (server.TxResult, corestore.WriterMap, error) + + // Query queries the application at the provided version. + // CONTRACT: Version must always be provided, if 0, get latest + Query(ctx context.Context, version uint64, request transaction.Msg) (transaction.Msg, error) + + // QueryWithState executes a query with the provided state. This allows to process a query + // independently of the db state. For example, it can be used to process a query with temporary + // and uncommitted state + QueryWithState(ctx context.Context, state corestore.ReaderMap, request transaction.Msg) (transaction.Msg, error) +} + // Store defines the underlying storage behavior needed by AppManager. type Store interface { // StateLatest returns a readonly view over the latest @@ -24,8 +63,8 @@ type Store interface { StateAt(version uint64) (corestore.ReaderMap, error) } -// AppManager is a coordinator for all things related to an application -type AppManager[T transaction.Tx] struct { +// appManager is a coordinator for all things related to an application +type appManager[T transaction.Tx] struct { // Gas limits for validating, querying, and simulating transactions. config Config // InitGenesis is a function that initializes the application state from a genesis file. @@ -46,18 +85,18 @@ func New[T transaction.Tx]( stf StateTransitionFunction[T], initGenesisImpl InitGenesis, exportGenesisImpl ExportGenesis, -) (*AppManager[T], error) { - appManager := &AppManager[T]{ - config: config, - db: db, - stf: stf, +) AppManager[T] { + return &appManager[T]{ + config: config, + db: db, + stf: stf, + initGenesis: initGenesisImpl, + exportGenesis: exportGenesisImpl, } - - return appManager, nil } // InitGenesis initializes the genesis state of the application. -func (a AppManager[T]) InitGenesis( +func (a appManager[T]) InitGenesis( ctx context.Context, blockRequest *server.BlockRequest[T], initGenesisJSON []byte, @@ -102,7 +141,7 @@ func (a AppManager[T]) InitGenesis( } // ExportGenesis exports the genesis state of the application. -func (a AppManager[T]) ExportGenesis(ctx context.Context, version uint64) ([]byte, error) { +func (a appManager[T]) ExportGenesis(ctx context.Context, version uint64) ([]byte, error) { if a.exportGenesis == nil { return nil, errors.New("export genesis function not set") } @@ -110,7 +149,8 @@ func (a AppManager[T]) ExportGenesis(ctx context.Context, version uint64) ([]byt return a.exportGenesis(ctx, version) } -func (a AppManager[T]) DeliverBlock( +// DeliverBlock executes a block of transactions. +func (a appManager[T]) DeliverBlock( ctx context.Context, block *server.BlockRequest[T], ) (*server.BlockResponse, corestore.WriterMap, error) { @@ -134,7 +174,7 @@ func (a AppManager[T]) DeliverBlock( // ValidateTx will validate the tx against the latest storage state. This means that // only the stateful validation will be run, not the execution portion of the tx. // If full execution is needed, Simulate must be used. -func (a AppManager[T]) ValidateTx(ctx context.Context, tx T) (server.TxResult, error) { +func (a appManager[T]) ValidateTx(ctx context.Context, tx T) (server.TxResult, error) { _, latestState, err := a.db.StateLatest() if err != nil { return server.TxResult{}, err @@ -144,7 +184,7 @@ func (a AppManager[T]) ValidateTx(ctx context.Context, tx T) (server.TxResult, e } // Simulate runs validation and execution flow of a Tx. -func (a AppManager[T]) Simulate(ctx context.Context, tx T) (server.TxResult, corestore.WriterMap, error) { +func (a appManager[T]) Simulate(ctx context.Context, tx T) (server.TxResult, corestore.WriterMap, error) { _, state, err := a.db.StateLatest() if err != nil { return server.TxResult{}, nil, err @@ -155,7 +195,7 @@ func (a AppManager[T]) Simulate(ctx context.Context, tx T) (server.TxResult, cor // Query queries the application at the provided version. // CONTRACT: Version must always be provided, if 0, get latest -func (a AppManager[T]) Query(ctx context.Context, version uint64, request transaction.Msg) (transaction.Msg, error) { +func (a appManager[T]) Query(ctx context.Context, version uint64, request transaction.Msg) (transaction.Msg, error) { // if version is provided attempt to do a height query. if version != 0 { queryState, err := a.db.StateAt(version) @@ -176,6 +216,6 @@ func (a AppManager[T]) Query(ctx context.Context, version uint64, request transa // QueryWithState executes a query with the provided state. This allows to process a query // independently of the db state. For example, it can be used to process a query with temporary // and uncommitted state -func (a AppManager[T]) QueryWithState(ctx context.Context, state corestore.ReaderMap, request transaction.Msg) (transaction.Msg, error) { +func (a appManager[T]) QueryWithState(ctx context.Context, state corestore.ReaderMap, request transaction.Msg) (transaction.Msg, error) { return a.stf.Query(ctx, state, a.config.QueryGasLimit, request) } diff --git a/server/v2/appmanager/types.go b/server/v2/appmanager/stf.go similarity index 100% rename from server/v2/appmanager/types.go rename to server/v2/appmanager/stf.go diff --git a/server/v2/cometbft/abci.go b/server/v2/cometbft/abci.go index d9e20a8ebe65..5daf0c103038 100644 --- a/server/v2/cometbft/abci.go +++ b/server/v2/cometbft/abci.go @@ -42,7 +42,7 @@ var _ abci.Application = (*Consensus[transaction.Tx])(nil) type Consensus[T transaction.Tx] struct { logger log.Logger appName, version string - app *appmanager.AppManager[T] + app appmanager.AppManager[T] appCloser func() error txCodec transaction.Codec[T] store types.Store @@ -77,7 +77,7 @@ type Consensus[T transaction.Tx] struct { func NewConsensus[T transaction.Tx]( logger log.Logger, appName string, - app *appmanager.AppManager[T], + app appmanager.AppManager[T], appCloser func() error, mp mempool.Mempool[T], indexedEvents map[string]struct{}, diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index ab4149ad7427..9ee4562ee351 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -672,7 +672,7 @@ func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock. sc := cometmock.NewMockCommiter(log.NewNopLogger(), string(actorName), "stf") mockStore := cometmock.NewMockStore(ss, sc) - am, err := appmanager.New(appmanager.Config{ + am := appmanager.New(appmanager.Config{ ValidateTxGasLimit: gasLimit, QueryGasLimit: gasLimit, SimulationGasLimit: gasLimit}, @@ -685,7 +685,6 @@ func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock. }, nil, ) - require.NoError(t, err) return NewConsensus[mock.Tx](log.NewNopLogger(), "testing-app", am, func() error { return nil }, mempool, map[string]struct{}{}, nil, mockStore, Config{AppTomlConfig: DefaultAppTomlConfig()}, mock.TxCodec{}, "test") } diff --git a/server/v2/cometbft/server.go b/server/v2/cometbft/server.go index 8b289a7cdbe0..1ad285bb99e7 100644 --- a/server/v2/cometbft/server.go +++ b/server/v2/cometbft/server.go @@ -106,7 +106,7 @@ func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logg consensus := NewConsensus( s.logger, appI.Name(), - appI.AppManager(), + appI, appI.Close, s.serverOptions.Mempool(cfg), indexEvents, diff --git a/server/v2/server_test.go b/server/v2/server_test.go index c35dea1fc627..f65c6569a5b0 100644 --- a/server/v2/server_test.go +++ b/server/v2/server_test.go @@ -17,9 +17,7 @@ import ( "cosmossdk.io/log" serverv2 "cosmossdk.io/server/v2" grpc "cosmossdk.io/server/v2/api/grpc" - "cosmossdk.io/server/v2/appmanager" "cosmossdk.io/server/v2/store" - storev2 "cosmossdk.io/store/v2" ) type mockInterfaceRegistry struct{} @@ -37,22 +35,13 @@ type mockApp[T transaction.Tx] struct { serverv2.AppI[T] } -func (*mockApp[T]) GetQueryHandlers() map[string]appmodulev2.Handler { +func (*mockApp[T]) QueryHandlers() map[string]appmodulev2.Handler { return map[string]appmodulev2.Handler{} } - -func (*mockApp[T]) GetAppManager() *appmanager.AppManager[T] { - return nil -} - func (*mockApp[T]) InterfaceRegistry() coreserver.InterfaceRegistry { return &mockInterfaceRegistry{} } -func (*mockApp[T]) GetStore() storev2.RootStore { - return nil -} - func TestServer(t *testing.T) { currentDir, err := os.Getwd() require.NoError(t, err) diff --git a/server/v2/types.go b/server/v2/types.go index 30ad21d8d7df..40d51e42375c 100644 --- a/server/v2/types.go +++ b/server/v2/types.go @@ -15,9 +15,10 @@ import ( type AppCreator[T transaction.Tx] func(log.Logger, *viper.Viper) AppI[T] type AppI[T transaction.Tx] interface { + appmanager.AppManager[T] + Name() string InterfaceRegistry() server.InterfaceRegistry - AppManager() *appmanager.AppManager[T] QueryHandlers() map[string]appmodulev2.Handler Store() store.RootStore SchemaDecoderResolver() decoding.DecoderResolver From d6cd4146f6601b6b87615e103270e961131c9eac Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Thu, 17 Oct 2024 12:31:59 +0200 Subject: [PATCH 4/4] fixes --- server/v2/api/grpc/server.go | 2 +- server/v2/cometbft/abci_test.go | 3 ++- server/v2/server_test.go | 6 ++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/server/v2/api/grpc/server.go b/server/v2/api/grpc/server.go index c8959c06d491..10e22a514a1e 100644 --- a/server/v2/api/grpc/server.go +++ b/server/v2/api/grpc/server.go @@ -85,7 +85,7 @@ func (s *Server[T]) StartCmdFlags() *pflag.FlagSet { } func makeUnknownServiceHandler(handlers map[string]appmodulev2.Handler, querier interface { - Query(ctx context.Context, version uint64, msg gogoproto.Message) (gogoproto.Message, error) + Query(ctx context.Context, version uint64, msg transaction.Msg) (transaction.Msg, error) }, ) grpc.StreamHandler { getRegistry := sync.OnceValues(gogoproto.MergedRegistry) diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index 9ee4562ee351..d58e87aa9ef9 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -675,7 +675,8 @@ func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock. am := appmanager.New(appmanager.Config{ ValidateTxGasLimit: gasLimit, QueryGasLimit: gasLimit, - SimulationGasLimit: gasLimit}, + SimulationGasLimit: gasLimit, + }, mockStore, s, func(ctx context.Context, src io.Reader, txHandler func(json.RawMessage) error) (store.WriterMap, error) { diff --git a/server/v2/server_test.go b/server/v2/server_test.go index f65c6569a5b0..a53b71fc35b9 100644 --- a/server/v2/server_test.go +++ b/server/v2/server_test.go @@ -18,6 +18,7 @@ import ( serverv2 "cosmossdk.io/server/v2" grpc "cosmossdk.io/server/v2/api/grpc" "cosmossdk.io/server/v2/store" + storev2 "cosmossdk.io/store/v2" ) type mockInterfaceRegistry struct{} @@ -38,10 +39,15 @@ type mockApp[T transaction.Tx] struct { func (*mockApp[T]) QueryHandlers() map[string]appmodulev2.Handler { return map[string]appmodulev2.Handler{} } + func (*mockApp[T]) InterfaceRegistry() coreserver.InterfaceRegistry { return &mockInterfaceRegistry{} } +func (*mockApp[T]) Store() storev2.RootStore { + return nil +} + func TestServer(t *testing.T) { currentDir, err := os.Getwd() require.NoError(t, err)