github.com/cosmos/cosmos-sdk@v0.50.10/types/module/module.go (about) 1 /* 2 Package module contains application module patterns and associated "manager" functionality. 3 The module pattern has been broken down by: 4 - independent module functionality (AppModuleBasic) 5 - inter-dependent module simulation functionality (AppModuleSimulation) 6 - inter-dependent module full functionality (AppModule) 7 8 inter-dependent module functionality is module functionality which somehow 9 depends on other modules, typically through the module keeper. Many of the 10 module keepers are dependent on each other, thus in order to access the full 11 set of module functionality we need to define all the keepers/params-store/keys 12 etc. This full set of advanced functionality is defined by the AppModule interface. 13 14 Independent module functions are separated to allow for the construction of the 15 basic application structures required early on in the application definition 16 and used to enable the definition of full module functionality later in the 17 process. This separation is necessary, however we still want to allow for a 18 high level pattern for modules to follow - for instance, such that we don't 19 have to manually register all of the codecs for all the modules. This basic 20 procedure as well as other basic patterns are handled through the use of 21 BasicManager. 22 23 Lastly the interface for genesis functionality (HasGenesis & HasABCIGenesis) has been 24 separated out from full module functionality (AppModule) so that modules which 25 are only used for genesis can take advantage of the Module patterns without 26 needlessly defining many placeholder functions 27 */ 28 package module 29 30 import ( 31 "context" 32 "encoding/json" 33 "errors" 34 "fmt" 35 "sort" 36 37 abci "github.com/cometbft/cometbft/abci/types" 38 "github.com/grpc-ecosystem/grpc-gateway/runtime" 39 "github.com/spf13/cobra" 40 "golang.org/x/exp/maps" 41 42 "cosmossdk.io/core/appmodule" 43 "cosmossdk.io/core/genesis" 44 errorsmod "cosmossdk.io/errors" 45 storetypes "cosmossdk.io/store/types" 46 47 "github.com/cosmos/cosmos-sdk/client" 48 "github.com/cosmos/cosmos-sdk/codec" 49 "github.com/cosmos/cosmos-sdk/codec/types" 50 sdk "github.com/cosmos/cosmos-sdk/types" 51 sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 52 ) 53 54 // AppModuleBasic is the standard form for basic non-dependant elements of an application module. 55 type AppModuleBasic interface { 56 HasName 57 RegisterLegacyAminoCodec(*codec.LegacyAmino) 58 RegisterInterfaces(types.InterfaceRegistry) 59 RegisterGRPCGatewayRoutes(client.Context, *runtime.ServeMux) 60 } 61 62 // HasName allows the module to provide its own name for legacy purposes. 63 // Newer apps should specify the name for their modules using a map 64 // using NewManagerFromMap. 65 type HasName interface { 66 Name() string 67 } 68 69 // HasGenesisBasics is the legacy interface for stateless genesis methods. 70 type HasGenesisBasics interface { 71 DefaultGenesis(codec.JSONCodec) json.RawMessage 72 ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage) error 73 } 74 75 // BasicManager is a collection of AppModuleBasic 76 type BasicManager map[string]AppModuleBasic 77 78 // NewBasicManager creates a new BasicManager object 79 func NewBasicManager(modules ...AppModuleBasic) BasicManager { 80 moduleMap := make(map[string]AppModuleBasic) 81 for _, module := range modules { 82 moduleMap[module.Name()] = module 83 } 84 return moduleMap 85 } 86 87 // NewBasicManagerFromManager creates a new BasicManager from a Manager 88 // The BasicManager will contain all AppModuleBasic from the AppModule Manager 89 // Module's AppModuleBasic can be overridden by passing a custom AppModuleBasic map 90 func NewBasicManagerFromManager(manager *Manager, customModuleBasics map[string]AppModuleBasic) BasicManager { 91 moduleMap := make(map[string]AppModuleBasic) 92 for name, module := range manager.Modules { 93 if customBasicMod, ok := customModuleBasics[name]; ok { 94 moduleMap[name] = customBasicMod 95 continue 96 } 97 98 if appModule, ok := module.(appmodule.AppModule); ok { 99 moduleMap[name] = CoreAppModuleBasicAdaptor(name, appModule) 100 continue 101 } 102 103 if basicMod, ok := module.(AppModuleBasic); ok { 104 moduleMap[name] = basicMod 105 } 106 } 107 108 return moduleMap 109 } 110 111 // RegisterLegacyAminoCodec registers all module codecs 112 func (bm BasicManager) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 113 for _, b := range bm { 114 b.RegisterLegacyAminoCodec(cdc) 115 } 116 } 117 118 // RegisterInterfaces registers all module interface types 119 func (bm BasicManager) RegisterInterfaces(registry types.InterfaceRegistry) { 120 for _, m := range bm { 121 m.RegisterInterfaces(registry) 122 } 123 } 124 125 // DefaultGenesis provides default genesis information for all modules 126 func (bm BasicManager) DefaultGenesis(cdc codec.JSONCodec) map[string]json.RawMessage { 127 genesisData := make(map[string]json.RawMessage) 128 for _, b := range bm { 129 if mod, ok := b.(HasGenesisBasics); ok { 130 genesisData[b.Name()] = mod.DefaultGenesis(cdc) 131 } 132 } 133 134 return genesisData 135 } 136 137 // ValidateGenesis performs genesis state validation for all modules 138 func (bm BasicManager) ValidateGenesis(cdc codec.JSONCodec, txEncCfg client.TxEncodingConfig, genesisData map[string]json.RawMessage) error { 139 for _, b := range bm { 140 // first check if the module is an adapted Core API Module 141 if mod, ok := b.(HasGenesisBasics); ok { 142 if err := mod.ValidateGenesis(cdc, txEncCfg, genesisData[b.Name()]); err != nil { 143 return err 144 } 145 } 146 } 147 148 return nil 149 } 150 151 // RegisterGRPCGatewayRoutes registers all module rest routes 152 func (bm BasicManager) RegisterGRPCGatewayRoutes(clientCtx client.Context, rtr *runtime.ServeMux) { 153 for _, b := range bm { 154 b.RegisterGRPCGatewayRoutes(clientCtx, rtr) 155 } 156 } 157 158 // AddTxCommands adds all tx commands to the rootTxCmd. 159 func (bm BasicManager) AddTxCommands(rootTxCmd *cobra.Command) { 160 for _, b := range bm { 161 if mod, ok := b.(interface { 162 GetTxCmd() *cobra.Command 163 }); ok { 164 if cmd := mod.GetTxCmd(); cmd != nil { 165 rootTxCmd.AddCommand(cmd) 166 } 167 } 168 } 169 } 170 171 // AddQueryCommands adds all query commands to the rootQueryCmd. 172 func (bm BasicManager) AddQueryCommands(rootQueryCmd *cobra.Command) { 173 for _, b := range bm { 174 if mod, ok := b.(interface { 175 GetQueryCmd() *cobra.Command 176 }); ok { 177 if cmd := mod.GetQueryCmd(); cmd != nil { 178 rootQueryCmd.AddCommand(cmd) 179 } 180 } 181 } 182 } 183 184 // HasGenesis is the extension interface for stateful genesis methods. 185 type HasGenesis interface { 186 HasGenesisBasics 187 InitGenesis(sdk.Context, codec.JSONCodec, json.RawMessage) 188 ExportGenesis(sdk.Context, codec.JSONCodec) json.RawMessage 189 } 190 191 // HasABCIGenesis is the extension interface for stateful genesis methods which returns validator updates. 192 type HasABCIGenesis interface { 193 HasGenesisBasics 194 InitGenesis(sdk.Context, codec.JSONCodec, json.RawMessage) []abci.ValidatorUpdate 195 ExportGenesis(sdk.Context, codec.JSONCodec) json.RawMessage 196 } 197 198 // AppModule is the form for an application module. Most of 199 // its functionality has been moved to extension interfaces. 200 // Deprecated: use appmodule.AppModule with a combination of extension interfaes interfaces instead. 201 type AppModule interface { 202 appmodule.AppModule 203 204 AppModuleBasic 205 } 206 207 // HasInvariants is the interface for registering invariants. 208 type HasInvariants interface { 209 // RegisterInvariants registers module invariants. 210 RegisterInvariants(sdk.InvariantRegistry) 211 } 212 213 // HasServices is the interface for modules to register services. 214 type HasServices interface { 215 // RegisterServices allows a module to register services. 216 RegisterServices(Configurator) 217 } 218 219 // HasConsensusVersion is the interface for declaring a module consensus version. 220 type HasConsensusVersion interface { 221 // ConsensusVersion is a sequence number for state-breaking change of the 222 // module. It should be incremented on each consensus-breaking change 223 // introduced by the module. To avoid wrong/empty versions, the initial version 224 // should be set to 1. 225 ConsensusVersion() uint64 226 } 227 228 // HasABCIEndblock is a released typo of HasABCIEndBlock. 229 // Deprecated: use HasABCIEndBlock instead. 230 type HasABCIEndblock HasABCIEndBlock 231 232 // HasABCIEndBlock is the interface for modules that need to run code at the end of the block. 233 type HasABCIEndBlock interface { 234 AppModule 235 EndBlock(context.Context) ([]abci.ValidatorUpdate, error) 236 } 237 238 var ( 239 _ appmodule.AppModule = (*GenesisOnlyAppModule)(nil) 240 _ AppModuleBasic = (*GenesisOnlyAppModule)(nil) 241 ) 242 243 // AppModuleGenesis is the standard form for an application module genesis functions 244 type AppModuleGenesis interface { 245 AppModuleBasic 246 HasABCIGenesis 247 } 248 249 // GenesisOnlyAppModule is an AppModule that only has import/export functionality 250 type GenesisOnlyAppModule struct { 251 AppModuleGenesis 252 } 253 254 // NewGenesisOnlyAppModule creates a new GenesisOnlyAppModule object 255 func NewGenesisOnlyAppModule(amg AppModuleGenesis) GenesisOnlyAppModule { 256 return GenesisOnlyAppModule{ 257 AppModuleGenesis: amg, 258 } 259 } 260 261 // IsOnePerModuleType implements the depinject.OnePerModuleType interface. 262 func (GenesisOnlyAppModule) IsOnePerModuleType() {} 263 264 // IsAppModule implements the appmodule.AppModule interface. 265 func (GenesisOnlyAppModule) IsAppModule() {} 266 267 // RegisterInvariants is a placeholder function register no invariants 268 func (GenesisOnlyAppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} 269 270 // ConsensusVersion implements AppModule/ConsensusVersion. 271 func (gam GenesisOnlyAppModule) ConsensusVersion() uint64 { return 1 } 272 273 // Manager defines a module manager that provides the high level utility for managing and executing 274 // operations for a group of modules 275 type Manager struct { 276 Modules map[string]interface{} // interface{} is used now to support the legacy AppModule as well as new core appmodule.AppModule. 277 OrderInitGenesis []string 278 OrderExportGenesis []string 279 OrderPreBlockers []string 280 OrderBeginBlockers []string 281 OrderEndBlockers []string 282 OrderPrepareCheckStaters []string 283 OrderPrecommiters []string 284 OrderMigrations []string 285 } 286 287 // NewManager creates a new Manager object. 288 func NewManager(modules ...AppModule) *Manager { 289 moduleMap := make(map[string]interface{}) 290 modulesStr := make([]string, 0, len(modules)) 291 preBlockModulesStr := make([]string, 0) 292 for _, module := range modules { 293 if _, ok := module.(appmodule.AppModule); !ok { 294 panic(fmt.Sprintf("module %s does not implement appmodule.AppModule", module.Name())) 295 } 296 297 moduleMap[module.Name()] = module 298 modulesStr = append(modulesStr, module.Name()) 299 if _, ok := module.(appmodule.HasPreBlocker); ok { 300 preBlockModulesStr = append(preBlockModulesStr, module.Name()) 301 } 302 } 303 304 return &Manager{ 305 Modules: moduleMap, 306 OrderInitGenesis: modulesStr, 307 OrderExportGenesis: modulesStr, 308 OrderPreBlockers: preBlockModulesStr, 309 OrderBeginBlockers: modulesStr, 310 OrderPrepareCheckStaters: modulesStr, 311 OrderPrecommiters: modulesStr, 312 OrderEndBlockers: modulesStr, 313 } 314 } 315 316 // NewManagerFromMap creates a new Manager object from a map of module names to module implementations. 317 // This method should be used for apps and modules which have migrated to the cosmossdk.io/core.appmodule.AppModule API. 318 func NewManagerFromMap(moduleMap map[string]appmodule.AppModule) *Manager { 319 simpleModuleMap := make(map[string]interface{}) 320 modulesStr := make([]string, 0, len(simpleModuleMap)) 321 preBlockModulesStr := make([]string, 0) 322 for name, module := range moduleMap { 323 simpleModuleMap[name] = module 324 modulesStr = append(modulesStr, name) 325 if _, ok := module.(appmodule.HasPreBlocker); ok { 326 preBlockModulesStr = append(preBlockModulesStr, name) 327 } 328 } 329 330 // Sort the modules by name. Given that we are using a map above we can't guarantee the order. 331 sort.Strings(modulesStr) 332 333 return &Manager{ 334 Modules: simpleModuleMap, 335 OrderInitGenesis: modulesStr, 336 OrderExportGenesis: modulesStr, 337 OrderPreBlockers: preBlockModulesStr, 338 OrderBeginBlockers: modulesStr, 339 OrderEndBlockers: modulesStr, 340 OrderPrecommiters: modulesStr, 341 OrderPrepareCheckStaters: modulesStr, 342 } 343 } 344 345 // SetOrderInitGenesis sets the order of init genesis calls 346 func (m *Manager) SetOrderInitGenesis(moduleNames ...string) { 347 m.assertNoForgottenModules("SetOrderInitGenesis", moduleNames, func(moduleName string) bool { 348 module := m.Modules[moduleName] 349 if _, hasGenesis := module.(appmodule.HasGenesis); hasGenesis { 350 return !hasGenesis 351 } 352 353 if _, hasABCIGenesis := module.(HasABCIGenesis); hasABCIGenesis { 354 return !hasABCIGenesis 355 } 356 357 _, hasGenesis := module.(HasGenesis) 358 return !hasGenesis 359 }) 360 m.OrderInitGenesis = moduleNames 361 } 362 363 // SetOrderExportGenesis sets the order of export genesis calls 364 func (m *Manager) SetOrderExportGenesis(moduleNames ...string) { 365 m.assertNoForgottenModules("SetOrderExportGenesis", moduleNames, func(moduleName string) bool { 366 module := m.Modules[moduleName] 367 if _, hasGenesis := module.(appmodule.HasGenesis); hasGenesis { 368 return !hasGenesis 369 } 370 371 if _, hasABCIGenesis := module.(HasABCIGenesis); hasABCIGenesis { 372 return !hasABCIGenesis 373 } 374 375 _, hasGenesis := module.(HasGenesis) 376 return !hasGenesis 377 }) 378 m.OrderExportGenesis = moduleNames 379 } 380 381 // SetOrderPreBlockers sets the order of set pre-blocker calls 382 func (m *Manager) SetOrderPreBlockers(moduleNames ...string) { 383 m.assertNoForgottenModules("SetOrderPreBlockers", moduleNames, 384 func(moduleName string) bool { 385 module := m.Modules[moduleName] 386 _, hasBlock := module.(appmodule.HasPreBlocker) 387 return !hasBlock 388 }) 389 m.OrderPreBlockers = moduleNames 390 } 391 392 // SetOrderBeginBlockers sets the order of set begin-blocker calls 393 func (m *Manager) SetOrderBeginBlockers(moduleNames ...string) { 394 m.assertNoForgottenModules("SetOrderBeginBlockers", moduleNames, 395 func(moduleName string) bool { 396 module := m.Modules[moduleName] 397 _, hasBeginBlock := module.(appmodule.HasBeginBlocker) 398 return !hasBeginBlock 399 }) 400 m.OrderBeginBlockers = moduleNames 401 } 402 403 // SetOrderEndBlockers sets the order of set end-blocker calls 404 func (m *Manager) SetOrderEndBlockers(moduleNames ...string) { 405 m.assertNoForgottenModules("SetOrderEndBlockers", moduleNames, 406 func(moduleName string) bool { 407 module := m.Modules[moduleName] 408 if _, hasEndBlock := module.(appmodule.HasEndBlocker); hasEndBlock { 409 return !hasEndBlock 410 } 411 412 _, hasABCIEndBlock := module.(HasABCIEndBlock) 413 return !hasABCIEndBlock 414 }) 415 m.OrderEndBlockers = moduleNames 416 } 417 418 // SetOrderPrepareCheckStaters sets the order of set prepare-check-stater calls 419 func (m *Manager) SetOrderPrepareCheckStaters(moduleNames ...string) { 420 m.assertNoForgottenModules("SetOrderPrepareCheckStaters", moduleNames, 421 func(moduleName string) bool { 422 module := m.Modules[moduleName] 423 _, hasPrepareCheckState := module.(appmodule.HasPrepareCheckState) 424 return !hasPrepareCheckState 425 }) 426 m.OrderPrepareCheckStaters = moduleNames 427 } 428 429 // SetOrderPrecommiters sets the order of set precommiter calls 430 func (m *Manager) SetOrderPrecommiters(moduleNames ...string) { 431 m.assertNoForgottenModules("SetOrderPrecommiters", moduleNames, 432 func(moduleName string) bool { 433 module := m.Modules[moduleName] 434 _, hasPrecommit := module.(appmodule.HasPrecommit) 435 return !hasPrecommit 436 }) 437 m.OrderPrecommiters = moduleNames 438 } 439 440 // SetOrderMigrations sets the order of migrations to be run. If not set 441 // then migrations will be run with an order defined in `DefaultMigrationsOrder`. 442 func (m *Manager) SetOrderMigrations(moduleNames ...string) { 443 m.assertNoForgottenModules("SetOrderMigrations", moduleNames, nil) 444 m.OrderMigrations = moduleNames 445 } 446 447 // RegisterInvariants registers all module invariants 448 func (m *Manager) RegisterInvariants(ir sdk.InvariantRegistry) { 449 for _, module := range m.Modules { 450 if module, ok := module.(HasInvariants); ok { 451 module.RegisterInvariants(ir) 452 } 453 } 454 } 455 456 // RegisterServices registers all module services 457 func (m *Manager) RegisterServices(cfg Configurator) error { 458 for _, module := range m.Modules { 459 if module, ok := module.(HasServices); ok { 460 module.RegisterServices(cfg) 461 } 462 463 if module, ok := module.(appmodule.HasServices); ok { 464 err := module.RegisterServices(cfg) 465 if err != nil { 466 return err 467 } 468 } 469 470 if cfg.Error() != nil { 471 return cfg.Error() 472 } 473 } 474 475 return nil 476 } 477 478 // InitGenesis performs init genesis functionality for modules. Exactly one 479 // module must return a non-empty validator set update to correctly initialize 480 // the chain. 481 func (m *Manager) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData map[string]json.RawMessage) (*abci.ResponseInitChain, error) { 482 var validatorUpdates []abci.ValidatorUpdate 483 ctx.Logger().Info("initializing blockchain state from genesis.json") 484 for _, moduleName := range m.OrderInitGenesis { 485 if genesisData[moduleName] == nil { 486 continue 487 } 488 489 mod := m.Modules[moduleName] 490 // we might get an adapted module, a native core API module or a legacy module 491 if module, ok := mod.(appmodule.HasGenesis); ok { 492 ctx.Logger().Debug("running initialization for module", "module", moduleName) 493 // core API genesis 494 source, err := genesis.SourceFromRawJSON(genesisData[moduleName]) 495 if err != nil { 496 return &abci.ResponseInitChain{}, err 497 } 498 499 err = module.InitGenesis(ctx, source) 500 if err != nil { 501 return &abci.ResponseInitChain{}, err 502 } 503 } else if module, ok := mod.(HasGenesis); ok { 504 ctx.Logger().Debug("running initialization for module", "module", moduleName) 505 module.InitGenesis(ctx, cdc, genesisData[moduleName]) 506 } else if module, ok := mod.(HasABCIGenesis); ok { 507 ctx.Logger().Debug("running initialization for module", "module", moduleName) 508 moduleValUpdates := module.InitGenesis(ctx, cdc, genesisData[moduleName]) 509 510 // use these validator updates if provided, the module manager assumes 511 // only one module will update the validator set 512 if len(moduleValUpdates) > 0 { 513 if len(validatorUpdates) > 0 { 514 return &abci.ResponseInitChain{}, errors.New("validator InitGenesis updates already set by a previous module") 515 } 516 validatorUpdates = moduleValUpdates 517 } 518 } 519 } 520 521 // a chain must initialize with a non-empty validator set 522 if len(validatorUpdates) == 0 { 523 return &abci.ResponseInitChain{}, fmt.Errorf("validator set is empty after InitGenesis, please ensure at least one validator is initialized with a delegation greater than or equal to the DefaultPowerReduction (%d)", sdk.DefaultPowerReduction) 524 } 525 526 return &abci.ResponseInitChain{ 527 Validators: validatorUpdates, 528 }, nil 529 } 530 531 // ExportGenesis performs export genesis functionality for modules 532 func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) (map[string]json.RawMessage, error) { 533 return m.ExportGenesisForModules(ctx, cdc, []string{}) 534 } 535 536 // ExportGenesisForModules performs export genesis functionality for modules 537 func (m *Manager) ExportGenesisForModules(ctx sdk.Context, cdc codec.JSONCodec, modulesToExport []string) (map[string]json.RawMessage, error) { 538 if len(modulesToExport) == 0 { 539 modulesToExport = m.OrderExportGenesis 540 } 541 // verify modules exists in app, so that we don't panic in the middle of an export 542 if err := m.checkModulesExists(modulesToExport); err != nil { 543 return nil, err 544 } 545 546 type genesisResult struct { 547 bz json.RawMessage 548 err error 549 } 550 551 channels := make(map[string]chan genesisResult) 552 for _, moduleName := range modulesToExport { 553 mod := m.Modules[moduleName] 554 if module, ok := mod.(appmodule.HasGenesis); ok { 555 // core API genesis 556 channels[moduleName] = make(chan genesisResult) 557 go func(module appmodule.HasGenesis, ch chan genesisResult) { 558 ctx := ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) // avoid race conditions 559 target := genesis.RawJSONTarget{} 560 err := module.ExportGenesis(ctx, target.Target()) 561 if err != nil { 562 ch <- genesisResult{nil, err} 563 return 564 } 565 566 rawJSON, err := target.JSON() 567 if err != nil { 568 ch <- genesisResult{nil, err} 569 return 570 } 571 572 ch <- genesisResult{rawJSON, nil} 573 }(module, channels[moduleName]) 574 } else if module, ok := mod.(HasGenesis); ok { 575 channels[moduleName] = make(chan genesisResult) 576 go func(module HasGenesis, ch chan genesisResult) { 577 ctx := ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) // avoid race conditions 578 ch <- genesisResult{module.ExportGenesis(ctx, cdc), nil} 579 }(module, channels[moduleName]) 580 } else if module, ok := mod.(HasABCIGenesis); ok { 581 channels[moduleName] = make(chan genesisResult) 582 go func(module HasABCIGenesis, ch chan genesisResult) { 583 ctx := ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) // avoid race conditions 584 ch <- genesisResult{module.ExportGenesis(ctx, cdc), nil} 585 }(module, channels[moduleName]) 586 } 587 } 588 589 genesisData := make(map[string]json.RawMessage) 590 for moduleName := range channels { 591 res := <-channels[moduleName] 592 if res.err != nil { 593 return nil, fmt.Errorf("genesis export error in %s: %w", moduleName, res.err) 594 } 595 596 genesisData[moduleName] = res.bz 597 } 598 599 return genesisData, nil 600 } 601 602 // checkModulesExists verifies that all modules in the list exist in the app 603 func (m *Manager) checkModulesExists(moduleName []string) error { 604 for _, name := range moduleName { 605 if _, ok := m.Modules[name]; !ok { 606 return fmt.Errorf("module %s does not exist", name) 607 } 608 } 609 610 return nil 611 } 612 613 // assertNoForgottenModules checks that we didn't forget any modules in the SetOrder* functions. 614 // `pass` is a closure which allows one to omit modules from `moduleNames`. 615 // If you provide non-nil `pass` and it returns true, the module would not be subject of the assertion. 616 func (m *Manager) assertNoForgottenModules(setOrderFnName string, moduleNames []string, pass func(moduleName string) bool) { 617 ms := make(map[string]bool) 618 for _, m := range moduleNames { 619 ms[m] = true 620 } 621 var missing []string 622 for m := range m.Modules { 623 m := m 624 if pass != nil && pass(m) { 625 continue 626 } 627 628 if !ms[m] { 629 missing = append(missing, m) 630 } 631 } 632 if len(missing) != 0 { 633 sort.Strings(missing) 634 panic(fmt.Sprintf( 635 "all modules must be defined when setting %s, missing: %v", setOrderFnName, missing)) 636 } 637 } 638 639 // MigrationHandler is the migration function that each module registers. 640 type MigrationHandler func(sdk.Context) error 641 642 // VersionMap is a map of moduleName -> version 643 type VersionMap map[string]uint64 644 645 // RunMigrations performs in-place store migrations for all modules. This 646 // function MUST be called insde an x/upgrade UpgradeHandler. 647 // 648 // Recall that in an upgrade handler, the `fromVM` VersionMap is retrieved from 649 // x/upgrade's store, and the function needs to return the target VersionMap 650 // that will in turn be persisted to the x/upgrade's store. In general, 651 // returning RunMigrations should be enough: 652 // 653 // Example: 654 // 655 // cfg := module.NewConfigurator(...) 656 // app.UpgradeKeeper.SetUpgradeHandler("my-plan", func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { 657 // return app.mm.RunMigrations(ctx, cfg, fromVM) 658 // }) 659 // 660 // Internally, RunMigrations will perform the following steps: 661 // - create an `updatedVM` VersionMap of module with their latest ConsensusVersion 662 // - make a diff of `fromVM` and `udpatedVM`, and for each module: 663 // - if the module's `fromVM` version is less than its `updatedVM` version, 664 // then run in-place store migrations for that module between those versions. 665 // - if the module does not exist in the `fromVM` (which means that it's a new module, 666 // because it was not in the previous x/upgrade's store), then run 667 // `InitGenesis` on that module. 668 // 669 // - return the `updatedVM` to be persisted in the x/upgrade's store. 670 // 671 // Migrations are run in an order defined by `Manager.OrderMigrations` or (if not set) defined by 672 // `DefaultMigrationsOrder` function. 673 // 674 // As an app developer, if you wish to skip running InitGenesis for your new 675 // module "foo", you need to manually pass a `fromVM` argument to this function 676 // foo's module version set to its latest ConsensusVersion. That way, the diff 677 // between the function's `fromVM` and `udpatedVM` will be empty, hence not 678 // running anything for foo. 679 // 680 // Example: 681 // 682 // cfg := module.NewConfigurator(...) 683 // app.UpgradeKeeper.SetUpgradeHandler("my-plan", func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { 684 // // Assume "foo" is a new module. 685 // // `fromVM` is fetched from existing x/upgrade store. Since foo didn't exist 686 // // before this upgrade, `v, exists := fromVM["foo"]; exists == false`, and RunMigration will by default 687 // // run InitGenesis on foo. 688 // // To skip running foo's InitGenesis, you need set `fromVM`'s foo to its latest 689 // // consensus version: 690 // fromVM["foo"] = foo.AppModule{}.ConsensusVersion() 691 // 692 // return app.mm.RunMigrations(ctx, cfg, fromVM) 693 // }) 694 // 695 // Please also refer to https://docs.cosmos.network/main/core/upgrade for more information. 696 func (m Manager) RunMigrations(ctx context.Context, cfg Configurator, fromVM VersionMap) (VersionMap, error) { 697 c, ok := cfg.(*configurator) 698 if !ok { 699 return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidType, "expected %T, got %T", &configurator{}, cfg) 700 } 701 modules := m.OrderMigrations 702 if modules == nil { 703 modules = DefaultMigrationsOrder(m.ModuleNames()) 704 } 705 706 sdkCtx := sdk.UnwrapSDKContext(ctx) 707 updatedVM := VersionMap{} 708 for _, moduleName := range modules { 709 module := m.Modules[moduleName] 710 fromVersion, exists := fromVM[moduleName] 711 toVersion := uint64(0) 712 if module, ok := module.(HasConsensusVersion); ok { 713 toVersion = module.ConsensusVersion() 714 } 715 716 // We run migration if the module is specified in `fromVM`. 717 // Otherwise we run InitGenesis. 718 // 719 // The module won't exist in the fromVM in two cases: 720 // 1. A new module is added. In this case we run InitGenesis with an 721 // empty genesis state. 722 // 2. An existing chain is upgrading from version < 0.43 to v0.43+ for the first time. 723 // In this case, all modules have yet to be added to x/upgrade's VersionMap store. 724 if exists { 725 err := c.runModuleMigrations(sdkCtx, moduleName, fromVersion, toVersion) 726 if err != nil { 727 return nil, err 728 } 729 } else { 730 sdkCtx.Logger().Info(fmt.Sprintf("adding a new module: %s", moduleName)) 731 if module, ok := m.Modules[moduleName].(HasGenesis); ok { 732 module.InitGenesis(sdkCtx, c.cdc, module.DefaultGenesis(c.cdc)) 733 } 734 if module, ok := m.Modules[moduleName].(HasABCIGenesis); ok { 735 moduleValUpdates := module.InitGenesis(sdkCtx, c.cdc, module.DefaultGenesis(c.cdc)) 736 // The module manager assumes only one module will update the 737 // validator set, and it can't be a new module. 738 if len(moduleValUpdates) > 0 { 739 return nil, errorsmod.Wrapf(sdkerrors.ErrLogic, "validator InitGenesis update is already set by another module") 740 } 741 } 742 } 743 744 updatedVM[moduleName] = toVersion 745 } 746 747 return updatedVM, nil 748 } 749 750 // PreBlock performs begin block functionality for upgrade module. 751 // It takes the current context as a parameter and returns a boolean value 752 // indicating whether the migration was successfully executed or not. 753 func (m *Manager) PreBlock(ctx sdk.Context) (*sdk.ResponsePreBlock, error) { 754 paramsChanged := false 755 for _, moduleName := range m.OrderPreBlockers { 756 if module, ok := m.Modules[moduleName].(appmodule.HasPreBlocker); ok { 757 rsp, err := module.PreBlock(ctx) 758 if err != nil { 759 return nil, err 760 } 761 if rsp.IsConsensusParamsChanged() { 762 paramsChanged = true 763 } 764 } 765 } 766 return &sdk.ResponsePreBlock{ 767 ConsensusParamsChanged: paramsChanged, 768 }, nil 769 } 770 771 // BeginBlock performs begin block functionality for all modules. It creates a 772 // child context with an event manager to aggregate events emitted from all 773 // modules. 774 func (m *Manager) BeginBlock(ctx sdk.Context) (sdk.BeginBlock, error) { 775 ctx = ctx.WithEventManager(sdk.NewEventManager()) 776 for _, moduleName := range m.OrderBeginBlockers { 777 if module, ok := m.Modules[moduleName].(appmodule.HasBeginBlocker); ok { 778 if err := module.BeginBlock(ctx); err != nil { 779 return sdk.BeginBlock{}, err 780 } 781 } 782 } 783 784 return sdk.BeginBlock{ 785 Events: ctx.EventManager().ABCIEvents(), 786 }, nil 787 } 788 789 // EndBlock performs end block functionality for all modules. It creates a 790 // child context with an event manager to aggregate events emitted from all 791 // modules. 792 func (m *Manager) EndBlock(ctx sdk.Context) (sdk.EndBlock, error) { 793 ctx = ctx.WithEventManager(sdk.NewEventManager()) 794 validatorUpdates := []abci.ValidatorUpdate{} 795 796 for _, moduleName := range m.OrderEndBlockers { 797 if module, ok := m.Modules[moduleName].(appmodule.HasEndBlocker); ok { 798 err := module.EndBlock(ctx) 799 if err != nil { 800 return sdk.EndBlock{}, err 801 } 802 } else if module, ok := m.Modules[moduleName].(HasABCIEndBlock); ok { 803 moduleValUpdates, err := module.EndBlock(ctx) 804 if err != nil { 805 return sdk.EndBlock{}, err 806 } 807 // use these validator updates if provided, the module manager assumes 808 // only one module will update the validator set 809 if len(moduleValUpdates) > 0 { 810 if len(validatorUpdates) > 0 { 811 return sdk.EndBlock{}, errors.New("validator EndBlock updates already set by a previous module") 812 } 813 814 for _, updates := range moduleValUpdates { 815 validatorUpdates = append(validatorUpdates, abci.ValidatorUpdate{PubKey: updates.PubKey, Power: updates.Power}) 816 } 817 } 818 } else { 819 continue 820 } 821 } 822 823 return sdk.EndBlock{ 824 ValidatorUpdates: validatorUpdates, 825 Events: ctx.EventManager().ABCIEvents(), 826 }, nil 827 } 828 829 // Precommit performs precommit functionality for all modules. 830 func (m *Manager) Precommit(ctx sdk.Context) error { 831 for _, moduleName := range m.OrderPrecommiters { 832 module, ok := m.Modules[moduleName].(appmodule.HasPrecommit) 833 if !ok { 834 continue 835 } 836 if err := module.Precommit(ctx); err != nil { 837 return err 838 } 839 } 840 return nil 841 } 842 843 // PrepareCheckState performs functionality for preparing the check state for all modules. 844 func (m *Manager) PrepareCheckState(ctx sdk.Context) error { 845 for _, moduleName := range m.OrderPrepareCheckStaters { 846 module, ok := m.Modules[moduleName].(appmodule.HasPrepareCheckState) 847 if !ok { 848 continue 849 } 850 if err := module.PrepareCheckState(ctx); err != nil { 851 return err 852 } 853 } 854 return nil 855 } 856 857 // GetVersionMap gets consensus version from all modules 858 func (m *Manager) GetVersionMap() VersionMap { 859 vermap := make(VersionMap) 860 for name, v := range m.Modules { 861 version := uint64(0) 862 if v, ok := v.(HasConsensusVersion); ok { 863 version = v.ConsensusVersion() 864 } 865 name := name 866 vermap[name] = version 867 } 868 869 return vermap 870 } 871 872 // ModuleNames returns list of all module names, without any particular order. 873 func (m *Manager) ModuleNames() []string { 874 return maps.Keys(m.Modules) 875 } 876 877 // DefaultMigrationsOrder returns a default migrations order: ascending alphabetical by module name, 878 // except x/auth which will run last, see: 879 // https://github.com/cosmos/cosmos-sdk/issues/10591 880 func DefaultMigrationsOrder(modules []string) []string { 881 const authName = "auth" 882 out := make([]string, 0, len(modules)) 883 hasAuth := false 884 for _, m := range modules { 885 if m == authName { 886 hasAuth = true 887 } else { 888 out = append(out, m) 889 } 890 } 891 sort.Strings(out) 892 if hasAuth { 893 out = append(out, authName) 894 } 895 return out 896 }