github.com/cosmos/cosmos-sdk@v0.50.10/x/staking/module.go (about) 1 package staking 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "sort" 8 9 abci "github.com/cometbft/cometbft/abci/types" 10 gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime" 11 "github.com/spf13/cobra" 12 "golang.org/x/exp/maps" 13 14 modulev1 "cosmossdk.io/api/cosmos/staking/module/v1" 15 "cosmossdk.io/core/appmodule" 16 "cosmossdk.io/core/store" 17 "cosmossdk.io/depinject" 18 19 "github.com/cosmos/cosmos-sdk/client" 20 "github.com/cosmos/cosmos-sdk/codec" 21 cdctypes "github.com/cosmos/cosmos-sdk/codec/types" 22 "github.com/cosmos/cosmos-sdk/runtime" 23 sdk "github.com/cosmos/cosmos-sdk/types" 24 "github.com/cosmos/cosmos-sdk/types/module" 25 simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 26 authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 27 govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" 28 "github.com/cosmos/cosmos-sdk/x/staking/client/cli" 29 "github.com/cosmos/cosmos-sdk/x/staking/exported" 30 "github.com/cosmos/cosmos-sdk/x/staking/keeper" 31 "github.com/cosmos/cosmos-sdk/x/staking/simulation" 32 "github.com/cosmos/cosmos-sdk/x/staking/types" 33 ) 34 35 const ( 36 consensusVersion uint64 = 5 37 ) 38 39 var ( 40 _ module.AppModuleBasic = AppModuleBasic{} 41 _ module.AppModuleSimulation = AppModule{} 42 _ module.HasServices = AppModule{} 43 _ module.HasInvariants = AppModule{} 44 _ module.HasABCIGenesis = AppModule{} 45 _ module.HasABCIEndBlock = AppModule{} 46 47 _ appmodule.AppModule = AppModule{} 48 _ appmodule.HasBeginBlocker = AppModule{} 49 ) 50 51 // AppModuleBasic defines the basic application module used by the staking module. 52 type AppModuleBasic struct { 53 cdc codec.Codec 54 ak types.AccountKeeper 55 } 56 57 // Name returns the staking module's name. 58 func (AppModuleBasic) Name() string { 59 return types.ModuleName 60 } 61 62 // RegisterLegacyAminoCodec registers the staking module's types on the given LegacyAmino codec. 63 func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 64 types.RegisterLegacyAminoCodec(cdc) 65 } 66 67 // RegisterInterfaces registers the module's interface types 68 func (AppModuleBasic) RegisterInterfaces(registry cdctypes.InterfaceRegistry) { 69 types.RegisterInterfaces(registry) 70 } 71 72 // DefaultGenesis returns default genesis state as raw bytes for the staking 73 // module. 74 func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { 75 return cdc.MustMarshalJSON(types.DefaultGenesisState()) 76 } 77 78 // ValidateGenesis performs genesis state validation for the staking module. 79 func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { 80 var data types.GenesisState 81 if err := cdc.UnmarshalJSON(bz, &data); err != nil { 82 return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) 83 } 84 85 return ValidateGenesis(&data) 86 } 87 88 // RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the staking module. 89 func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *gwruntime.ServeMux) { 90 if err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)); err != nil { 91 panic(err) 92 } 93 } 94 95 // GetTxCmd returns the root tx command for the staking module. 96 func (amb AppModuleBasic) GetTxCmd() *cobra.Command { 97 return cli.NewTxCmd(amb.cdc.InterfaceRegistry().SigningContext().ValidatorAddressCodec(), amb.cdc.InterfaceRegistry().SigningContext().AddressCodec()) 98 } 99 100 // AppModule implements an application module for the staking module. 101 type AppModule struct { 102 AppModuleBasic 103 104 keeper *keeper.Keeper 105 accountKeeper types.AccountKeeper 106 bankKeeper types.BankKeeper 107 108 // legacySubspace is used solely for migration of x/params managed parameters 109 legacySubspace exported.Subspace 110 } 111 112 // NewAppModule creates a new AppModule object 113 func NewAppModule( 114 cdc codec.Codec, 115 keeper *keeper.Keeper, 116 ak types.AccountKeeper, 117 bk types.BankKeeper, 118 ls exported.Subspace, 119 ) AppModule { 120 return AppModule{ 121 AppModuleBasic: AppModuleBasic{cdc: cdc, ak: ak}, 122 keeper: keeper, 123 accountKeeper: ak, 124 bankKeeper: bk, 125 legacySubspace: ls, 126 } 127 } 128 129 // IsOnePerModuleType implements the depinject.OnePerModuleType interface. 130 func (am AppModule) IsOnePerModuleType() {} 131 132 // IsAppModule implements the appmodule.AppModule interface. 133 func (am AppModule) IsAppModule() {} 134 135 // RegisterInvariants registers the staking module invariants. 136 func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { 137 keeper.RegisterInvariants(ir, am.keeper) 138 } 139 140 // RegisterServices registers module services. 141 func (am AppModule) RegisterServices(cfg module.Configurator) { 142 types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) 143 querier := keeper.Querier{Keeper: am.keeper} 144 types.RegisterQueryServer(cfg.QueryServer(), querier) 145 146 m := keeper.NewMigrator(am.keeper, am.legacySubspace) 147 if err := cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2); err != nil { 148 panic(fmt.Sprintf("failed to migrate x/%s from version 1 to 2: %v", types.ModuleName, err)) 149 } 150 if err := cfg.RegisterMigration(types.ModuleName, 2, m.Migrate2to3); err != nil { 151 panic(fmt.Sprintf("failed to migrate x/%s from version 2 to 3: %v", types.ModuleName, err)) 152 } 153 if err := cfg.RegisterMigration(types.ModuleName, 3, m.Migrate3to4); err != nil { 154 panic(fmt.Sprintf("failed to migrate x/%s from version 3 to 4: %v", types.ModuleName, err)) 155 } 156 if err := cfg.RegisterMigration(types.ModuleName, 4, m.Migrate4to5); err != nil { 157 panic(fmt.Sprintf("failed to migrate x/%s from version 4 to 5: %v", types.ModuleName, err)) 158 } 159 } 160 161 // InitGenesis performs genesis initialization for the staking module. 162 func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate { 163 var genesisState types.GenesisState 164 165 cdc.MustUnmarshalJSON(data, &genesisState) 166 167 return am.keeper.InitGenesis(ctx, &genesisState) 168 } 169 170 // ExportGenesis returns the exported genesis state as raw bytes for the staking 171 // module. 172 func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { 173 return cdc.MustMarshalJSON(am.keeper.ExportGenesis(ctx)) 174 } 175 176 // ConsensusVersion implements AppModule/ConsensusVersion. 177 func (AppModule) ConsensusVersion() uint64 { return consensusVersion } 178 179 // BeginBlock returns the begin blocker for the staking module. 180 func (am AppModule) BeginBlock(ctx context.Context) error { 181 return am.keeper.BeginBlocker(ctx) 182 } 183 184 // EndBlock returns the end blocker for the staking module. It returns no validator 185 // updates. 186 func (am AppModule) EndBlock(ctx context.Context) ([]abci.ValidatorUpdate, error) { 187 return am.keeper.EndBlocker(ctx) 188 } 189 190 func init() { 191 appmodule.Register( 192 &modulev1.Module{}, 193 appmodule.Provide(ProvideModule), 194 appmodule.Invoke(InvokeSetStakingHooks), 195 ) 196 } 197 198 type ModuleInputs struct { 199 depinject.In 200 201 Config *modulev1.Module 202 ValidatorAddressCodec runtime.ValidatorAddressCodec 203 ConsensusAddressCodec runtime.ConsensusAddressCodec 204 AccountKeeper types.AccountKeeper 205 BankKeeper types.BankKeeper 206 Cdc codec.Codec 207 StoreService store.KVStoreService 208 209 // LegacySubspace is used solely for migration of x/params managed parameters 210 LegacySubspace exported.Subspace `optional:"true"` 211 } 212 213 // Dependency Injection Outputs 214 type ModuleOutputs struct { 215 depinject.Out 216 217 StakingKeeper *keeper.Keeper 218 Module appmodule.AppModule 219 } 220 221 func ProvideModule(in ModuleInputs) ModuleOutputs { 222 // default to governance authority if not provided 223 authority := authtypes.NewModuleAddress(govtypes.ModuleName) 224 if in.Config.Authority != "" { 225 authority = authtypes.NewModuleAddressOrBech32Address(in.Config.Authority) 226 } 227 228 k := keeper.NewKeeper( 229 in.Cdc, 230 in.StoreService, 231 in.AccountKeeper, 232 in.BankKeeper, 233 authority.String(), 234 in.ValidatorAddressCodec, 235 in.ConsensusAddressCodec, 236 ) 237 m := NewAppModule(in.Cdc, k, in.AccountKeeper, in.BankKeeper, in.LegacySubspace) 238 return ModuleOutputs{StakingKeeper: k, Module: m} 239 } 240 241 func InvokeSetStakingHooks( 242 config *modulev1.Module, 243 keeper *keeper.Keeper, 244 stakingHooks map[string]types.StakingHooksWrapper, 245 ) error { 246 // all arguments to invokers are optional 247 if keeper == nil || config == nil { 248 return nil 249 } 250 251 modNames := maps.Keys(stakingHooks) 252 order := config.HooksOrder 253 if len(order) == 0 { 254 order = modNames 255 sort.Strings(order) 256 } 257 258 if len(order) != len(modNames) { 259 return fmt.Errorf("len(hooks_order: %v) != len(hooks modules: %v)", order, modNames) 260 } 261 262 if len(modNames) == 0 { 263 return nil 264 } 265 266 var multiHooks types.MultiStakingHooks 267 for _, modName := range order { 268 hook, ok := stakingHooks[modName] 269 if !ok { 270 return fmt.Errorf("can't find staking hooks for module %s", modName) 271 } 272 273 multiHooks = append(multiHooks, hook) 274 } 275 276 keeper.SetHooks(multiHooks) 277 return nil 278 } 279 280 // AppModuleSimulation functions 281 282 // GenerateGenesisState creates a randomized GenState of the staking module. 283 func (AppModule) GenerateGenesisState(simState *module.SimulationState) { 284 simulation.RandomizedGenState(simState) 285 } 286 287 // ProposalMsgs returns msgs used for governance proposals for simulations. 288 func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { 289 return simulation.ProposalMsgs() 290 } 291 292 // RegisterStoreDecoder registers a decoder for staking module's types 293 func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { 294 sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) 295 } 296 297 // WeightedOperations returns the all the staking module operations with their respective weights. 298 func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { 299 return simulation.WeightedOperations( 300 simState.AppParams, simState.Cdc, simState.TxConfig, 301 am.accountKeeper, am.bankKeeper, am.keeper, 302 ) 303 }