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  }