github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/gov/keeper/keeper.go (about) 1 package keeper 2 3 import ( 4 "fmt" 5 "time" 6 7 supplyexported "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/supply/exported" 8 "github.com/fibonacci-chain/fbc/x/common" 9 "github.com/fibonacci-chain/fbc/x/gov/types" 10 "github.com/fibonacci-chain/fbc/x/staking/exported" 11 12 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 13 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 14 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/log" 15 "github.com/fibonacci-chain/fbc/x/params" 16 ) 17 18 // Keeper defines governance keeper 19 type Keeper struct { 20 // The reference to the Param Keeper to get and set Global Params 21 paramsKeeper params.Keeper 22 23 // The reference to the Paramstore to get and set gov specific params 24 paramSpace params.Subspace 25 26 // The SupplyKeeper to reduce the supply of the network 27 supplyKeeper SupplyKeeper 28 29 // The reference to the DelegationSet and ValidatorSet to get information about validators and delegators 30 sk StakingKeeper 31 32 // The (unexposed) keys used to access the stores from the Context. 33 storeKey sdk.StoreKey 34 35 // The codec codec for binary encoding/decoding. 36 cdc *codec.Codec 37 38 // Reserved codespace 39 codespace string 40 41 // Proposal router 42 router Router 43 44 // name of the FeeCollector ModuleAccount 45 feeCollectorName string 46 47 // The reference to the CoinKeeper to modify balances 48 bankKeeper BankKeeper 49 50 // Proposal module parameter router 51 proposalHandlerRouter ProposalHandlerRouter 52 } 53 54 // NewKeeper returns a governance keeper. It handles: 55 // - submitting governance proposals 56 // - depositing funds into proposals, and activating upon sufficient funds being deposited 57 // - users voting on proposals, with weight proportional to stake in the system 58 // - and tallying the result of the vote. 59 func NewKeeper( 60 cdc *codec.Codec, key sdk.StoreKey, paramsKeeper params.Keeper, paramSpace params.Subspace, 61 supplyKeeper SupplyKeeper, sk StakingKeeper, codespace string, rtr Router, 62 ck BankKeeper, phr ProposalHandlerRouter, feeCollectorName string, 63 ) Keeper { 64 // ensure governance module account is set 65 if addr := supplyKeeper.GetModuleAddress(types.ModuleName); addr == nil { 66 panic(fmt.Sprintf("%s module account has not been set", types.ModuleName)) 67 } 68 69 // It is vital to seal the governance proposal router here as to not allow 70 // further handlers to be registered after the keeper is created since this 71 // could create invalid or non-deterministic behavior. 72 rtr.Seal() 73 74 keeper := Keeper{ 75 storeKey: key, 76 paramsKeeper: paramsKeeper, 77 paramSpace: paramSpace.WithKeyTable(types.ParamKeyTable()), 78 supplyKeeper: supplyKeeper, 79 sk: sk, 80 cdc: cdc, 81 codespace: codespace, 82 router: rtr, 83 feeCollectorName: feeCollectorName, 84 bankKeeper: ck, 85 proposalHandlerRouter: phr, 86 } 87 keeper.proposalHandlerRouter = keeper.proposalHandlerRouter.AddRoute(types.RouterKey, keeper) 88 return keeper 89 } 90 91 // BankKeeper returns bank keeper in gov keeper 92 func (keeper Keeper) BankKeeper() BankKeeper { 93 return keeper.bankKeeper 94 } 95 96 // ProposalHandlerRouter returns proposal handler router in gov keeper 97 func (keeper Keeper) ProposalHandlerRouter() ProposalHandlerRouter { 98 return keeper.proposalHandlerRouter 99 } 100 101 // Params 102 103 // GetDepositParams returns the current DepositParams from the global param store 104 func (keeper Keeper) GetDepositParams(ctx sdk.Context) types.DepositParams { 105 var depositParams types.DepositParams 106 keeper.paramSpace.Get(ctx, types.ParamStoreKeyDepositParams, &depositParams) 107 return depositParams 108 } 109 110 // GetVotingParams returns the current VotingParams from the global param store 111 func (keeper Keeper) GetVotingParams(ctx sdk.Context) types.VotingParams { 112 var votingParams types.VotingParams 113 keeper.paramSpace.Get(ctx, types.ParamStoreKeyVotingParams, &votingParams) 114 return votingParams 115 } 116 117 // GetTallyParams returns the current TallyParams from the global param store 118 func (keeper Keeper) GetTallyParams(ctx sdk.Context) types.TallyParams { 119 var tallyParams types.TallyParams 120 keeper.paramSpace.Get(ctx, types.ParamStoreKeyTallyParams, &tallyParams) 121 return tallyParams 122 } 123 124 // SetDepositParams sets the current DepositParams to the global param store 125 func (keeper Keeper) SetDepositParams(ctx sdk.Context, depositParams types.DepositParams) { 126 keeper.paramSpace.Set(ctx, types.ParamStoreKeyDepositParams, &depositParams) 127 } 128 129 // SetVotingParams sets the current VotingParams to the global param store 130 func (keeper Keeper) SetVotingParams(ctx sdk.Context, votingParams types.VotingParams) { 131 keeper.paramSpace.Set(ctx, types.ParamStoreKeyVotingParams, &votingParams) 132 } 133 134 // SetTallyParams sets the current TallyParams to the global param store 135 func (keeper Keeper) SetTallyParams(ctx sdk.Context, tallyParams types.TallyParams) { 136 keeper.paramSpace.Set(ctx, types.ParamStoreKeyTallyParams, &tallyParams) 137 } 138 139 // ProposalQueues 140 141 // WaitingProposalQueueIterator returns an iterator for all the proposals in the Waiting Queue that expire by endTime 142 func (keeper Keeper) WaitingProposalQueueIterator(ctx sdk.Context, blockHeight uint64) sdk.Iterator { 143 store := ctx.KVStore(keeper.storeKey) 144 return store.Iterator(types.PrefixWaitingProposalQueue, 145 sdk.PrefixEndBytes(types.WaitingProposalByBlockHeightKey(blockHeight))) 146 } 147 148 // InsertWaitingProposalQueue inserts a ProposalID into the waiting proposal queue at endTime 149 func (keeper Keeper) InsertWaitingProposalQueue(ctx sdk.Context, blockHeight, proposalID uint64) { 150 store := ctx.KVStore(keeper.storeKey) 151 bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalID) 152 store.Set(types.WaitingProposalQueueKey(proposalID, blockHeight), bz) 153 } 154 155 // RemoveFromWaitingProposalQueue removes a proposalID from the waiting Proposal Queue 156 func (keeper Keeper) RemoveFromWaitingProposalQueue(ctx sdk.Context, blockHeight, proposalID uint64) { 157 store := ctx.KVStore(keeper.storeKey) 158 store.Delete(types.WaitingProposalQueueKey(proposalID, blockHeight)) 159 } 160 161 // Iterators 162 163 // IterateProposals iterates over the all the proposals and performs a callback function 164 func (keeper Keeper) IterateProposals(ctx sdk.Context, cb func(proposal types.Proposal) (stop bool)) { 165 store := ctx.KVStore(keeper.storeKey) 166 iterator := sdk.KVStorePrefixIterator(store, types.ProposalsKeyPrefix) 167 168 defer iterator.Close() 169 for ; iterator.Valid(); iterator.Next() { 170 var proposal types.Proposal 171 keeper.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &proposal) 172 173 if cb(proposal) { 174 break 175 } 176 } 177 } 178 179 // IterateActiveProposalsQueue iterates over the proposals in the active proposal queue 180 // and performs a callback function 181 func (keeper Keeper) IterateActiveProposalsQueue( 182 ctx sdk.Context, endTime time.Time, cb func(proposal types.Proposal, 183 ) (stop bool)) { 184 iterator := keeper.ActiveProposalQueueIterator(ctx, endTime) 185 186 defer iterator.Close() 187 for ; iterator.Valid(); iterator.Next() { 188 proposalID, _ := types.SplitActiveProposalQueueKey(iterator.Key()) 189 proposal, found := keeper.GetProposal(ctx, proposalID) 190 if !found { 191 panic(fmt.Sprintf("proposal %d does not exist", proposalID)) 192 } 193 194 if cb(proposal) { 195 break 196 } 197 } 198 } 199 200 // IterateInactiveProposalsQueue iterates over the proposals in the inactive proposal queue 201 // and performs a callback function 202 func (keeper Keeper) IterateInactiveProposalsQueue( 203 ctx sdk.Context, endTime time.Time, cb func(proposal types.Proposal, 204 ) (stop bool)) { 205 iterator := keeper.InactiveProposalQueueIterator(ctx, endTime) 206 207 defer iterator.Close() 208 for ; iterator.Valid(); iterator.Next() { 209 proposalID, _ := types.SplitInactiveProposalQueueKey(iterator.Key()) 210 proposal, found := keeper.GetProposal(ctx, proposalID) 211 if !found { 212 panic(fmt.Sprintf("proposal %d does not exist", proposalID)) 213 } 214 215 if cb(proposal) { 216 break 217 } 218 } 219 } 220 221 // IterateWaitingProposalsQueue iterates over the proposals in the waiting proposal queue 222 // and performs a callback function 223 func (keeper Keeper) IterateWaitingProposalsQueue( 224 ctx sdk.Context, height uint64, cb func(proposal types.Proposal, 225 ) (stop bool)) { 226 iterator := keeper.WaitingProposalQueueIterator(ctx, height) 227 228 defer iterator.Close() 229 for ; iterator.Valid(); iterator.Next() { 230 proposalID, _ := types.SplitWaitingProposalQueueKey(iterator.Key()) 231 proposal, found := keeper.GetProposal(ctx, proposalID) 232 if !found { 233 panic(fmt.Sprintf("proposal %d does not exist", proposalID)) 234 } 235 236 if cb(proposal) { 237 break 238 } 239 } 240 } 241 242 // IterateAllWaitingProposals iterates over the all proposals in the waiting proposal queue 243 // and performs a callback function 244 func (keeper Keeper) IterateAllWaitingProposals(ctx sdk.Context, 245 cb func(proposal types.Proposal, proposalID, height uint64) (stop bool)) { 246 store := ctx.KVStore(keeper.storeKey) 247 iterator := store.Iterator(types.PrefixWaitingProposalQueue, 248 sdk.PrefixEndBytes(types.PrefixWaitingProposalQueue)) 249 250 defer iterator.Close() 251 for ; iterator.Valid(); iterator.Next() { 252 proposalID, height := types.SplitWaitingProposalQueueKey(iterator.Key()) 253 proposal, found := keeper.GetProposal(ctx, proposalID) 254 if !found { 255 panic(fmt.Sprintf("proposal %d does not exist", proposalID)) 256 } 257 258 if cb(proposal, proposalID, height) { 259 break 260 } 261 } 262 } 263 264 // IterateAllDeposits iterates over the all the stored deposits and performs a callback function 265 func (keeper Keeper) IterateAllDeposits(ctx sdk.Context, cb func(deposit types.Deposit) (stop bool)) { 266 store := ctx.KVStore(keeper.storeKey) 267 iterator := sdk.KVStorePrefixIterator(store, types.DepositsKeyPrefix) 268 269 defer iterator.Close() 270 for ; iterator.Valid(); iterator.Next() { 271 var deposit types.Deposit 272 keeper.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &deposit) 273 274 if cb(deposit) { 275 break 276 } 277 } 278 } 279 280 // IterateDeposits iterates over the all the proposals deposits and performs a callback function 281 func (keeper Keeper) IterateDeposits(ctx sdk.Context, proposalID uint64, cb func(deposit types.Deposit) (stop bool)) { 282 iterator := keeper.GetDepositsIterator(ctx, proposalID) 283 284 defer iterator.Close() 285 for ; iterator.Valid(); iterator.Next() { 286 var deposit types.Deposit 287 keeper.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &deposit) 288 289 if cb(deposit) { 290 break 291 } 292 } 293 } 294 295 // IterateVotes iterates over the all the proposals votes and performs a callback function 296 func (keeper Keeper) IterateVotes(ctx sdk.Context, proposalID uint64, cb func(vote types.Vote) (stop bool)) { 297 iterator := keeper.GetVotesIterator(ctx, proposalID) 298 299 defer iterator.Close() 300 for ; iterator.Valid(); iterator.Next() { 301 var vote types.Vote 302 keeper.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &vote) 303 304 if cb(vote) { 305 break 306 } 307 } 308 } 309 310 // GetMinDeposit implement ProposalHandler 311 // nolint 312 func (keeper Keeper) GetMinDeposit(ctx sdk.Context, content types.Content) sdk.SysCoins { 313 return keeper.GetDepositParams(ctx).MinDeposit 314 } 315 316 // nolint 317 func (keeper Keeper) GetMaxDepositPeriod(ctx sdk.Context, content types.Content) time.Duration { 318 return keeper.GetDepositParams(ctx).MaxDepositPeriod 319 } 320 321 // nolint 322 func (keeper Keeper) GetVotingPeriod(ctx sdk.Context, content types.Content) time.Duration { 323 return keeper.GetVotingParams(ctx).VotingPeriod 324 } 325 326 // nolint 327 func (keeper Keeper) CheckMsgSubmitProposal(ctx sdk.Context, msg types.MsgSubmitProposal) sdk.Error { 328 // check initial deposit more than or equal to ratio of MinDeposit 329 initDeposit := keeper.GetDepositParams(ctx).MinDeposit.MulDec(sdk.NewDecWithPrec(1, 1)) 330 err := common.HasSufficientCoins(msg.Proposer, msg.InitialDeposit, 331 initDeposit) 332 if err != nil { 333 return types.ErrInitialDepositNotEnough(initDeposit.String()) 334 } 335 // check proposer has sufficient coins 336 err = common.HasSufficientCoins(msg.Proposer, keeper.bankKeeper.GetCoins(ctx, msg.Proposer), 337 msg.InitialDeposit) 338 if err != nil { 339 return common.ErrInsufficientCoins(types.DefaultCodespace, err.Error()) 340 } 341 return nil 342 } 343 344 // nolint 345 func (keeper Keeper) AfterSubmitProposalHandler(ctx sdk.Context, proposal types.Proposal) {} 346 347 // nolint 348 func (keeper Keeper) VoteHandler(ctx sdk.Context, proposal types.Proposal, vote types.Vote) (string, sdk.Error) { 349 return "", nil 350 } 351 352 // nolint 353 func (keeper Keeper) AfterDepositPeriodPassed(ctx sdk.Context, proposal types.Proposal) {} 354 355 // nolint 356 func (keeper Keeper) RejectedHandler(ctx sdk.Context, content types.Content) {} 357 358 // get all current validators except candidate votes 359 func (keeper Keeper) totalPower(ctx sdk.Context) sdk.Dec { 360 totalVoting := sdk.ZeroDec() 361 keeper.sk.IterateBondedValidatorsByPower(ctx, func(index int64, validator exported.ValidatorI) (stop bool) { 362 totalVoting = totalVoting.Add(validator.GetDelegatorShares()) 363 return false 364 }) 365 return totalVoting 366 } 367 368 // Logger returns a module-specific logger. 369 func (keeper Keeper) Logger(ctx sdk.Context) log.Logger { 370 return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) 371 } 372 373 // GetGovernanceAccount returns the governance ModuleAccount 374 func (keeper Keeper) GetGovernanceAccount(ctx sdk.Context) supplyexported.ModuleAccountI { 375 return keeper.supplyKeeper.GetModuleAccount(ctx, types.ModuleName) 376 } 377 378 // Params 379 380 // ProposalQueues 381 382 // InsertActiveProposalQueue inserts a ProposalID into the active proposal queue at endTime 383 func (keeper Keeper) InsertActiveProposalQueue(ctx sdk.Context, proposalID uint64, endTime time.Time) { 384 store := ctx.KVStore(keeper.storeKey) 385 bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalID) 386 store.Set(types.ActiveProposalQueueKey(proposalID, endTime), bz) 387 } 388 389 // RemoveFromActiveProposalQueue removes a proposalID from the Active Proposal Queue 390 func (keeper Keeper) RemoveFromActiveProposalQueue(ctx sdk.Context, proposalID uint64, endTime time.Time) { 391 store := ctx.KVStore(keeper.storeKey) 392 store.Delete(types.ActiveProposalQueueKey(proposalID, endTime)) 393 } 394 395 // InsertInactiveProposalQueue Inserts a ProposalID into the inactive proposal queue at endTime 396 func (keeper Keeper) InsertInactiveProposalQueue(ctx sdk.Context, proposalID uint64, endTime time.Time) { 397 store := ctx.KVStore(keeper.storeKey) 398 bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalID) 399 store.Set(types.InactiveProposalQueueKey(proposalID, endTime), bz) 400 } 401 402 // RemoveFromInactiveProposalQueue removes a proposalID from the Inactive Proposal Queue 403 func (keeper Keeper) RemoveFromInactiveProposalQueue(ctx sdk.Context, proposalID uint64, endTime time.Time) { 404 store := ctx.KVStore(keeper.storeKey) 405 store.Delete(types.InactiveProposalQueueKey(proposalID, endTime)) 406 } 407 408 // IterateAllVotes iterates over the all the stored votes and performs a callback function 409 func (keeper Keeper) IterateAllVotes(ctx sdk.Context, cb func(vote types.Vote) (stop bool)) { 410 store := ctx.KVStore(keeper.storeKey) 411 iterator := sdk.KVStorePrefixIterator(store, types.VotesKeyPrefix) 412 413 defer iterator.Close() 414 for ; iterator.Valid(); iterator.Next() { 415 var vote types.Vote 416 keeper.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &vote) 417 418 if cb(vote) { 419 break 420 } 421 } 422 } 423 424 // ActiveProposalQueueIterator returns an sdk.Iterator for all the proposals in the Active Queue that expire by endTime 425 func (keeper Keeper) ActiveProposalQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator { 426 store := ctx.KVStore(keeper.storeKey) 427 return store.Iterator(types.ActiveProposalQueuePrefix, sdk.PrefixEndBytes(types.ActiveProposalByTimeKey(endTime))) 428 } 429 430 // InactiveProposalQueueIterator returns an sdk.Iterator for all the proposals in the Inactive Queue that expire by endTime 431 func (keeper Keeper) InactiveProposalQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator { 432 store := ctx.KVStore(keeper.storeKey) 433 return store.Iterator(types.InactiveProposalQueuePrefix, sdk.PrefixEndBytes(types.InactiveProposalByTimeKey(endTime))) 434 } 435 436 func (keeper Keeper) Cdc() *codec.Codec { 437 return keeper.cdc 438 } 439 440 func (keeper Keeper) Router() Router { 441 return keeper.router 442 } 443 444 func (keeper Keeper) SupplyKeeper() SupplyKeeper { 445 return keeper.supplyKeeper 446 }