github.com/cosmos/cosmos-sdk@v0.50.10/runtime/app.go (about)

     1  package runtime
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  
     7  	abci "github.com/cometbft/cometbft/abci/types"
     8  	"golang.org/x/exp/slices"
     9  
    10  	runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1"
    11  	appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1"
    12  	"cosmossdk.io/core/appmodule"
    13  	"cosmossdk.io/log"
    14  	storetypes "cosmossdk.io/store/types"
    15  
    16  	"github.com/cosmos/cosmos-sdk/baseapp"
    17  	"github.com/cosmos/cosmos-sdk/client"
    18  	"github.com/cosmos/cosmos-sdk/client/grpc/cmtservice"
    19  	nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
    20  	"github.com/cosmos/cosmos-sdk/codec"
    21  	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
    22  	"github.com/cosmos/cosmos-sdk/server"
    23  	"github.com/cosmos/cosmos-sdk/server/api"
    24  	"github.com/cosmos/cosmos-sdk/server/config"
    25  	servertypes "github.com/cosmos/cosmos-sdk/server/types"
    26  	sdk "github.com/cosmos/cosmos-sdk/types"
    27  	"github.com/cosmos/cosmos-sdk/types/module"
    28  	authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
    29  )
    30  
    31  // App is a wrapper around BaseApp and ModuleManager that can be used in hybrid
    32  // app.go/app config scenarios or directly as a servertypes.Application instance.
    33  // To get an instance of *App, *AppBuilder must be requested as a dependency
    34  // in a container which declares the runtime module and the AppBuilder.Build()
    35  // method must be called.
    36  //
    37  // App can be used to create a hybrid app.go setup where some configuration is
    38  // done declaratively with an app config and the rest of it is done the old way.
    39  // See simapp/app.go for an example of this setup.
    40  type App struct {
    41  	*baseapp.BaseApp
    42  
    43  	ModuleManager     *module.Manager
    44  	configurator      module.Configurator
    45  	config            *runtimev1alpha1.Module
    46  	storeKeys         []storetypes.StoreKey
    47  	interfaceRegistry codectypes.InterfaceRegistry
    48  	cdc               codec.Codec
    49  	amino             *codec.LegacyAmino
    50  	basicManager      module.BasicManager
    51  	baseAppOptions    []BaseAppOption
    52  	msgServiceRouter  *baseapp.MsgServiceRouter
    53  	grpcQueryRouter   *baseapp.GRPCQueryRouter
    54  	appConfig         *appv1alpha1.Config
    55  	logger            log.Logger
    56  	// initChainer is the init chainer function defined by the app config.
    57  	// this is only required if the chain wants to add special InitChainer logic.
    58  	initChainer sdk.InitChainer
    59  }
    60  
    61  // RegisterModules registers the provided modules with the module manager and
    62  // the basic module manager. This is the primary hook for integrating with
    63  // modules which are not registered using the app config.
    64  func (a *App) RegisterModules(modules ...module.AppModule) error {
    65  	for _, appModule := range modules {
    66  		name := appModule.Name()
    67  		if _, ok := a.ModuleManager.Modules[name]; ok {
    68  			return fmt.Errorf("AppModule named %q already exists", name)
    69  		}
    70  
    71  		if _, ok := a.basicManager[name]; ok {
    72  			return fmt.Errorf("AppModuleBasic named %q already exists", name)
    73  		}
    74  
    75  		a.ModuleManager.Modules[name] = appModule
    76  		a.basicManager[name] = appModule
    77  		appModule.RegisterInterfaces(a.interfaceRegistry)
    78  		appModule.RegisterLegacyAminoCodec(a.amino)
    79  
    80  		if module, ok := appModule.(module.HasServices); ok {
    81  			module.RegisterServices(a.configurator)
    82  		} else if module, ok := appModule.(appmodule.HasServices); ok {
    83  			if err := module.RegisterServices(a.configurator); err != nil {
    84  				return err
    85  			}
    86  		}
    87  	}
    88  
    89  	return nil
    90  }
    91  
    92  // RegisterStores registers the provided store keys.
    93  // This method should only be used for registering extra stores
    94  // wiich is necessary for modules that not registered using the app config.
    95  // To be used in combination of RegisterModules.
    96  func (a *App) RegisterStores(keys ...storetypes.StoreKey) error {
    97  	a.storeKeys = append(a.storeKeys, keys...)
    98  	a.MountStores(keys...)
    99  
   100  	return nil
   101  }
   102  
   103  // Load finishes all initialization operations and loads the app.
   104  func (a *App) Load(loadLatest bool) error {
   105  	if len(a.config.InitGenesis) != 0 {
   106  		a.ModuleManager.SetOrderInitGenesis(a.config.InitGenesis...)
   107  		if a.initChainer == nil {
   108  			a.SetInitChainer(a.InitChainer)
   109  		}
   110  	}
   111  
   112  	if len(a.config.ExportGenesis) != 0 {
   113  		a.ModuleManager.SetOrderExportGenesis(a.config.ExportGenesis...)
   114  	} else if len(a.config.InitGenesis) != 0 {
   115  		a.ModuleManager.SetOrderExportGenesis(a.config.InitGenesis...)
   116  	}
   117  
   118  	if len(a.config.PreBlockers) != 0 {
   119  		a.ModuleManager.SetOrderPreBlockers(a.config.PreBlockers...)
   120  		if a.BaseApp.PreBlocker() == nil {
   121  			a.SetPreBlocker(a.PreBlocker)
   122  		}
   123  	}
   124  
   125  	if len(a.config.BeginBlockers) != 0 {
   126  		a.ModuleManager.SetOrderBeginBlockers(a.config.BeginBlockers...)
   127  		a.SetBeginBlocker(a.BeginBlocker)
   128  	}
   129  
   130  	if len(a.config.EndBlockers) != 0 {
   131  		a.ModuleManager.SetOrderEndBlockers(a.config.EndBlockers...)
   132  		a.SetEndBlocker(a.EndBlocker)
   133  	}
   134  
   135  	if len(a.config.Precommiters) != 0 {
   136  		a.ModuleManager.SetOrderPrecommiters(a.config.Precommiters...)
   137  		a.SetPrecommiter(a.Precommiter)
   138  	}
   139  
   140  	if len(a.config.PrepareCheckStaters) != 0 {
   141  		a.ModuleManager.SetOrderPrepareCheckStaters(a.config.PrepareCheckStaters...)
   142  		a.SetPrepareCheckStater(a.PrepareCheckStater)
   143  	}
   144  
   145  	if len(a.config.OrderMigrations) != 0 {
   146  		a.ModuleManager.SetOrderMigrations(a.config.OrderMigrations...)
   147  	}
   148  
   149  	if loadLatest {
   150  		if err := a.LoadLatestVersion(); err != nil {
   151  			return err
   152  		}
   153  	}
   154  
   155  	return nil
   156  }
   157  
   158  // PreBlocker application updates every pre block
   159  func (a *App) PreBlocker(ctx sdk.Context, _ *abci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) {
   160  	return a.ModuleManager.PreBlock(ctx)
   161  }
   162  
   163  // BeginBlocker application updates every begin block
   164  func (a *App) BeginBlocker(ctx sdk.Context) (sdk.BeginBlock, error) {
   165  	return a.ModuleManager.BeginBlock(ctx)
   166  }
   167  
   168  // EndBlocker application updates every end block
   169  func (a *App) EndBlocker(ctx sdk.Context) (sdk.EndBlock, error) {
   170  	return a.ModuleManager.EndBlock(ctx)
   171  }
   172  
   173  // Precommiter application updates every commit
   174  func (a *App) Precommiter(ctx sdk.Context) {
   175  	a.ModuleManager.Precommit(ctx)
   176  }
   177  
   178  // PrepareCheckStater application updates every commit
   179  func (a *App) PrepareCheckStater(ctx sdk.Context) {
   180  	a.ModuleManager.PrepareCheckState(ctx)
   181  }
   182  
   183  // InitChainer initializes the chain.
   184  func (a *App) InitChainer(ctx sdk.Context, req *abci.RequestInitChain) (*abci.ResponseInitChain, error) {
   185  	var genesisState map[string]json.RawMessage
   186  	if err := json.Unmarshal(req.AppStateBytes, &genesisState); err != nil {
   187  		panic(err)
   188  	}
   189  	return a.ModuleManager.InitGenesis(ctx, a.cdc, genesisState)
   190  }
   191  
   192  // RegisterAPIRoutes registers all application module routes with the provided
   193  // API server.
   194  func (a *App) RegisterAPIRoutes(apiSvr *api.Server, _ config.APIConfig) {
   195  	clientCtx := apiSvr.ClientCtx
   196  	// Register new tx routes from grpc-gateway.
   197  	authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
   198  
   199  	// Register new CometBFT queries routes from grpc-gateway.
   200  	cmtservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
   201  
   202  	// Register node gRPC service for grpc-gateway.
   203  	nodeservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
   204  
   205  	// Register grpc-gateway routes for all modules.
   206  	a.basicManager.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
   207  }
   208  
   209  // RegisterTxService implements the Application.RegisterTxService method.
   210  func (a *App) RegisterTxService(clientCtx client.Context) {
   211  	authtx.RegisterTxService(a.GRPCQueryRouter(), clientCtx, a.Simulate, a.interfaceRegistry)
   212  }
   213  
   214  // RegisterTendermintService implements the Application.RegisterTendermintService method.
   215  func (a *App) RegisterTendermintService(clientCtx client.Context) {
   216  	cmtApp := server.NewCometABCIWrapper(a)
   217  	cmtservice.RegisterTendermintService(
   218  		clientCtx,
   219  		a.GRPCQueryRouter(),
   220  		a.interfaceRegistry,
   221  		cmtApp.Query,
   222  	)
   223  }
   224  
   225  // RegisterNodeService registers the node gRPC service on the app gRPC router.
   226  func (a *App) RegisterNodeService(clientCtx client.Context, cfg config.Config) {
   227  	nodeservice.RegisterNodeService(clientCtx, a.GRPCQueryRouter(), cfg)
   228  }
   229  
   230  // Configurator returns the app's configurator.
   231  func (a *App) Configurator() module.Configurator {
   232  	return a.configurator
   233  }
   234  
   235  // LoadHeight loads a particular height
   236  func (a *App) LoadHeight(height int64) error {
   237  	return a.LoadVersion(height)
   238  }
   239  
   240  // DefaultGenesis returns a default genesis from the registered AppModuleBasic's.
   241  func (a *App) DefaultGenesis() map[string]json.RawMessage {
   242  	return a.basicManager.DefaultGenesis(a.cdc)
   243  }
   244  
   245  // GetStoreKeys returns all the stored store keys.
   246  func (a *App) GetStoreKeys() []storetypes.StoreKey {
   247  	return a.storeKeys
   248  }
   249  
   250  // SetInitChainer sets the init chainer function
   251  // It wraps `BaseApp.SetInitChainer` to allow setting a custom init chainer from an app.
   252  func (a *App) SetInitChainer(initChainer sdk.InitChainer) {
   253  	a.initChainer = initChainer
   254  	a.BaseApp.SetInitChainer(initChainer)
   255  }
   256  
   257  // UnsafeFindStoreKey fetches a registered StoreKey from the App in linear time.
   258  //
   259  // NOTE: This should only be used in testing.
   260  func (a *App) UnsafeFindStoreKey(storeKey string) storetypes.StoreKey {
   261  	i := slices.IndexFunc(a.storeKeys, func(s storetypes.StoreKey) bool { return s.Name() == storeKey })
   262  	if i == -1 {
   263  		return nil
   264  	}
   265  
   266  	return a.storeKeys[i]
   267  }
   268  
   269  var _ servertypes.Application = &App{}