github.com/cosmos/cosmos-sdk@v0.50.10/types/module/configurator.go (about) 1 package module 2 3 import ( 4 "fmt" 5 6 "github.com/cosmos/gogoproto/grpc" 7 googlegrpc "google.golang.org/grpc" 8 protobuf "google.golang.org/protobuf/proto" 9 "google.golang.org/protobuf/reflect/protoreflect" 10 11 cosmosmsg "cosmossdk.io/api/cosmos/msg/v1" 12 errorsmod "cosmossdk.io/errors" 13 14 "github.com/cosmos/cosmos-sdk/codec" 15 sdk "github.com/cosmos/cosmos-sdk/types" 16 sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 17 ) 18 19 // Configurator provides the hooks to allow modules to configure and register 20 // their services in the RegisterServices method. It is designed to eventually 21 // support module object capabilities isolation as described in 22 // https://github.com/cosmos/cosmos-sdk/issues/7093 23 type Configurator interface { 24 grpc.Server 25 26 // Error returns the last error encountered during RegisterService. 27 Error() error 28 29 // MsgServer returns a grpc.Server instance which allows registering services 30 // that will handle TxBody.messages in transactions. These Msg's WILL NOT 31 // be exposed as gRPC services. 32 MsgServer() grpc.Server 33 34 // QueryServer returns a grpc.Server instance which allows registering services 35 // that will be exposed as gRPC services as well as ABCI query handlers. 36 QueryServer() grpc.Server 37 38 // RegisterMigration registers an in-place store migration for a module. The 39 // handler is a migration script to perform in-place migrations from version 40 // `fromVersion` to version `fromVersion+1`. 41 // 42 // EACH TIME a module's ConsensusVersion increments, a new migration MUST 43 // be registered using this function. If a migration handler is missing for 44 // a particular function, the upgrade logic (see RunMigrations function) 45 // will panic. If the ConsensusVersion bump does not introduce any store 46 // changes, then a no-op function must be registered here. 47 RegisterMigration(moduleName string, fromVersion uint64, handler MigrationHandler) error 48 } 49 50 type configurator struct { 51 cdc codec.Codec 52 msgServer grpc.Server 53 queryServer grpc.Server 54 55 // migrations is a map of moduleName -> fromVersion -> migration script handler 56 migrations map[string]map[uint64]MigrationHandler 57 58 err error 59 } 60 61 // RegisterService implements the grpc.Server interface. 62 func (c *configurator) RegisterService(sd *googlegrpc.ServiceDesc, ss interface{}) { 63 desc, err := c.cdc.InterfaceRegistry().FindDescriptorByName(protoreflect.FullName(sd.ServiceName)) 64 if err != nil { 65 c.err = err 66 return 67 } 68 69 if protobuf.HasExtension(desc.Options(), cosmosmsg.E_Service) { 70 c.msgServer.RegisterService(sd, ss) 71 } else { 72 c.queryServer.RegisterService(sd, ss) 73 } 74 } 75 76 // Error returns the last error encountered during RegisterService. 77 func (c *configurator) Error() error { 78 return c.err 79 } 80 81 // NewConfigurator returns a new Configurator instance 82 func NewConfigurator(cdc codec.Codec, msgServer, queryServer grpc.Server) Configurator { 83 return &configurator{ 84 cdc: cdc, 85 msgServer: msgServer, 86 queryServer: queryServer, 87 migrations: map[string]map[uint64]MigrationHandler{}, 88 } 89 } 90 91 var _ Configurator = &configurator{} 92 93 // MsgServer implements the Configurator.MsgServer method 94 func (c *configurator) MsgServer() grpc.Server { 95 return c.msgServer 96 } 97 98 // QueryServer implements the Configurator.QueryServer method 99 func (c *configurator) QueryServer() grpc.Server { 100 return c.queryServer 101 } 102 103 // RegisterMigration implements the Configurator.RegisterMigration method 104 func (c *configurator) RegisterMigration(moduleName string, fromVersion uint64, handler MigrationHandler) error { 105 if fromVersion == 0 { 106 return errorsmod.Wrap(sdkerrors.ErrInvalidVersion, "module migration versions should start at 1") 107 } 108 109 if c.migrations[moduleName] == nil { 110 c.migrations[moduleName] = map[uint64]MigrationHandler{} 111 } 112 113 if c.migrations[moduleName][fromVersion] != nil { 114 return errorsmod.Wrapf(sdkerrors.ErrLogic, "another migration for module %s and version %d already exists", moduleName, fromVersion) 115 } 116 117 c.migrations[moduleName][fromVersion] = handler 118 119 return nil 120 } 121 122 // runModuleMigrations runs all in-place store migrations for one given module from a 123 // version to another version. 124 func (c *configurator) runModuleMigrations(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error { 125 // No-op if toVersion is the initial version or if the version is unchanged. 126 if toVersion <= 1 || fromVersion == toVersion { 127 return nil 128 } 129 130 moduleMigrationsMap, found := c.migrations[moduleName] 131 if !found { 132 return errorsmod.Wrapf(sdkerrors.ErrNotFound, "no migrations found for module %s", moduleName) 133 } 134 135 // Run in-place migrations for the module sequentially until toVersion. 136 for i := fromVersion; i < toVersion; i++ { 137 migrateFn, found := moduleMigrationsMap[i] 138 if !found { 139 return errorsmod.Wrapf(sdkerrors.ErrNotFound, "no migration found for module %s from version %d to version %d", moduleName, i, i+1) 140 } 141 ctx.Logger().Info(fmt.Sprintf("migrating module %s from version %d to version %d", moduleName, i, i+1)) 142 143 err := migrateFn(ctx) 144 if err != nil { 145 return err 146 } 147 } 148 149 return nil 150 }