github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/params/proposal_handler.go (about)

     1  package params
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"time"
     7  
     8  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     9  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
    10  	sdkparams "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/params"
    11  	"github.com/fibonacci-chain/fbc/x/common"
    12  	govtypes "github.com/fibonacci-chain/fbc/x/gov/types"
    13  	"github.com/fibonacci-chain/fbc/x/params/types"
    14  )
    15  
    16  // NewParamChangeProposalHandler returns the rollback function of the param proposal handler
    17  func NewParamChangeProposalHandler(k *Keeper) govtypes.Handler {
    18  	return func(ctx sdk.Context, proposal *govtypes.Proposal) sdk.Error {
    19  		switch c := proposal.Content.(type) {
    20  		case types.ParameterChangeProposal:
    21  			return handleParameterChangeProposal(ctx, k, proposal)
    22  		default:
    23  			return common.ErrUnknownProposalType(DefaultCodespace, fmt.Sprintf("%T", c))
    24  		}
    25  	}
    26  }
    27  
    28  func handleParameterChangeProposal(ctx sdk.Context, k *Keeper, proposal *govtypes.Proposal) sdk.Error {
    29  	logger := ctx.Logger().With("module", ModuleName)
    30  	logger.Info("Execute ParameterProposal begin")
    31  	paramProposal := proposal.Content.(types.ParameterChangeProposal)
    32  	curHeight := uint64(ctx.BlockHeight())
    33  	if paramProposal.Height > curHeight {
    34  		k.gk.InsertWaitingProposalQueue(ctx, paramProposal.Height, proposal.ProposalID)
    35  		return nil
    36  	}
    37  
    38  	defer k.gk.RemoveFromWaitingProposalQueue(ctx, paramProposal.Height, proposal.ProposalID)
    39  	return changeParams(ctx, k, paramProposal)
    40  }
    41  
    42  func changeParams(ctx sdk.Context, k *Keeper, paramProposal types.ParameterChangeProposal) sdk.Error {
    43  	defer k.signalUpdate()
    44  	for _, c := range paramProposal.Changes {
    45  		ss, ok := k.GetSubspace(c.Subspace)
    46  		if !ok {
    47  			return sdkerrors.Wrap(sdkparams.ErrUnknownSubspace, c.Subspace)
    48  		}
    49  
    50  		err := ss.Update(ctx, []byte(c.Key), []byte(c.Value))
    51  		if err != nil {
    52  			return sdkerrors.Wrap(sdkparams.ErrSettingParameter, err.Error())
    53  		}
    54  	}
    55  	return nil
    56  }
    57  
    58  func (k *Keeper) RegisterSignal(handler func()) {
    59  	k.signals = append(k.signals, handler)
    60  }
    61  func (k *Keeper) signalUpdate() {
    62  	for i, _ := range k.signals {
    63  		k.signals[i]()
    64  	}
    65  }
    66  
    67  func checkDenom(paramProposal types.ParameterChangeProposal) sdk.Error {
    68  	for _, c := range paramProposal.Changes {
    69  		if c.Subspace == "evm" && c.Key == "EVMDenom" {
    70  			return sdkerrors.Wrap(sdkparams.ErrSettingParameter, "evm denom can not be reset")
    71  		}
    72  		if c.Subspace == "staking" && c.Key == "BondDenom" {
    73  			return sdkerrors.Wrap(sdkparams.ErrSettingParameter, "staking bond denom can not be reset")
    74  		}
    75  	}
    76  	return nil
    77  }
    78  
    79  // GetMinDeposit implements ProposalHandler interface
    80  func (keeper Keeper) GetMinDeposit(ctx sdk.Context, content govtypes.Content) (minDeposit sdk.SysCoins) {
    81  	switch content.(type) {
    82  	case types.ParameterChangeProposal, types.UpgradeProposal:
    83  		minDeposit = keeper.GetParams(ctx).MinDeposit
    84  	}
    85  
    86  	return
    87  }
    88  
    89  // GetMaxDepositPeriod implements ProposalHandler interface
    90  func (keeper Keeper) GetMaxDepositPeriod(ctx sdk.Context, content govtypes.Content) (maxDepositPeriod time.Duration) {
    91  	switch content.(type) {
    92  	case types.ParameterChangeProposal, types.UpgradeProposal:
    93  		maxDepositPeriod = keeper.GetParams(ctx).MaxDepositPeriod
    94  	}
    95  
    96  	return
    97  }
    98  
    99  // GetVotingPeriod implements ProposalHandler interface
   100  func (keeper Keeper) GetVotingPeriod(ctx sdk.Context, content govtypes.Content) (votingPeriod time.Duration) {
   101  	switch content.(type) {
   102  	case types.ParameterChangeProposal, types.UpgradeProposal:
   103  		votingPeriod = keeper.GetParams(ctx).VotingPeriod
   104  	}
   105  
   106  	return
   107  }
   108  
   109  // CheckMsgSubmitProposal implements ProposalHandler interface
   110  func (keeper Keeper) CheckMsgSubmitProposal(ctx sdk.Context, msg govtypes.MsgSubmitProposal) sdk.Error {
   111  	switch proposal := msg.Content.(type) {
   112  	case types.ParameterChangeProposal:
   113  		return keeper.checkSubmitParamsChangeProposal(ctx, msg.Proposer, msg.InitialDeposit, proposal)
   114  	case types.UpgradeProposal:
   115  		return keeper.checkSubmitUpgradeProposal(ctx, msg.Proposer, msg.InitialDeposit, proposal)
   116  	default:
   117  		return common.ErrUnknownProposalType(DefaultCodespace, fmt.Sprintf("%T", proposal))
   118  	}
   119  
   120  }
   121  
   122  func (keeper Keeper) checkSubmitParamsChangeProposal(ctx sdk.Context, proposer sdk.AccAddress, initialDeposit sdk.SysCoins, paramsChangeProposal types.ParameterChangeProposal) sdk.Error {
   123  	if err := keeper.proposalCommonCheck(ctx, true, proposer, initialDeposit); err != nil {
   124  		return err
   125  	}
   126  
   127  	curHeight := uint64(ctx.BlockHeight())
   128  	maxHeight := keeper.GetParams(ctx).MaxBlockHeight
   129  	if maxHeight == 0 {
   130  		maxHeight = math.MaxInt64 - paramsChangeProposal.Height
   131  	}
   132  	if paramsChangeProposal.Height < curHeight || paramsChangeProposal.Height > curHeight+maxHeight {
   133  		return govtypes.ErrInvalidHeight(paramsChangeProposal.Height, curHeight, maxHeight)
   134  	}
   135  
   136  	// run simulation with cache context
   137  	cacheCtx, _ := ctx.CacheContext()
   138  	return changeParams(cacheCtx, &keeper, paramsChangeProposal)
   139  }
   140  
   141  func (keeper Keeper) checkSubmitUpgradeProposal(ctx sdk.Context, proposer sdk.AccAddress, initialDeposit sdk.SysCoins, proposal types.UpgradeProposal) sdk.Error {
   142  	if err := keeper.proposalCommonCheck(ctx, true, proposer, initialDeposit); err != nil {
   143  		return err
   144  	}
   145  
   146  	if err := checkUpgradeValidEffectiveHeight(ctx, &keeper, proposal.ExpectHeight); err != nil {
   147  		return err
   148  	}
   149  
   150  	if keeper.isUpgradeExist(ctx, proposal.Name) {
   151  		keeper.Logger(ctx).Error("upgrade has been exist", "name", proposal.Name)
   152  		return sdk.ErrInternal(fmt.Sprintf("upgrade proposal name '%s' has been exist", proposal.Name))
   153  	}
   154  	return nil
   155  }
   156  
   157  func (keeper Keeper) proposalCommonCheck(ctx sdk.Context, checkIsValidator bool, proposer sdk.AccAddress, initialDeposit sdk.SysCoins) sdk.Error {
   158  	// check message sender is current validator
   159  	if checkIsValidator && !keeper.sk.IsValidator(ctx, proposer) {
   160  		return govtypes.ErrInvalidProposer()
   161  	}
   162  	// check initial deposit more than or equal to ratio of MinDeposit
   163  	initDeposit := keeper.GetParams(ctx).MinDeposit.MulDec(sdk.NewDecWithPrec(1, 1))
   164  	if err := common.HasSufficientCoins(proposer, initialDeposit, initDeposit); err != nil {
   165  		return sdk.ErrInvalidCoins(fmt.Sprintf("InitialDeposit must not be less than %s", initDeposit.String()))
   166  	}
   167  	// check proposer has sufficient coins
   168  	if err := common.HasSufficientCoins(proposer, keeper.ck.GetCoins(ctx, proposer), initialDeposit); err != nil {
   169  		return sdk.ErrInvalidCoins(err.Error())
   170  	}
   171  
   172  	return nil
   173  }
   174  
   175  // nolint
   176  func (keeper Keeper) AfterSubmitProposalHandler(ctx sdk.Context, proposal govtypes.Proposal) {
   177  	switch content := proposal.Content.(type) {
   178  	case types.UpgradeProposal:
   179  		// must be no error in the normal situation, for the error comes from upgrade name has been exist,
   180  		// which has checked in CheckMsgSubmitProposal.
   181  		_ = storePreparingUpgrade(ctx, &keeper, content)
   182  
   183  	}
   184  }
   185  
   186  func (keeper Keeper) VoteHandler(ctx sdk.Context, proposal govtypes.Proposal, vote govtypes.Vote) (string, sdk.Error) {
   187  	switch content := proposal.Content.(type) {
   188  	case types.UpgradeProposal:
   189  		return checkUpgradeVote(ctx, proposal.ProposalID, content, vote)
   190  	}
   191  	return "", nil
   192  }
   193  func (keeper Keeper) AfterDepositPeriodPassed(ctx sdk.Context, proposal govtypes.Proposal) {}
   194  func (keeper Keeper) RejectedHandler(ctx sdk.Context, content govtypes.Content)            {}