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) {}