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