From e58c3c1d80bbce138517136a0f3aba3a0e67de84 Mon Sep 17 00:00:00 2001 From: Sishir Giri Date: Tue, 10 Jan 2023 08:27:33 -0800 Subject: [PATCH] [ValSet-Pref] Add Redelegate, Withdraw cli commands and sim_msgs (#3966) * added new cli commands * added cli commands * added withdraw sim function * added simulator functions * working redelegation cli test --- x/valset-pref/client/cli/tx.go | 59 +++++++++++-- x/valset-pref/simulation/sim_msgs.go | 112 +++++++++++++++++++------ x/valset-pref/valpref-module/module.go | 4 +- 3 files changed, 142 insertions(+), 33 deletions(-) diff --git a/x/valset-pref/client/cli/tx.go b/x/valset-pref/client/cli/tx.go index fcc53d67f75..aab073f34f8 100644 --- a/x/valset-pref/client/cli/tx.go +++ b/x/valset-pref/client/cli/tx.go @@ -19,6 +19,8 @@ func GetTxCmd() *cobra.Command { osmocli.AddTxCmd(txCmd, NewSetValSetCmd) osmocli.AddTxCmd(txCmd, NewDelValSetCmd) osmocli.AddTxCmd(txCmd, NewUnDelValSetCmd) + osmocli.AddTxCmd(txCmd, NewReDelValSetCmd) + osmocli.AddTxCmd(txCmd, NewWithRewValSetCmd) return txCmd } @@ -36,7 +38,7 @@ func NewDelValSetCmd() (*osmocli.TxCliDesc, *types.MsgDelegateToValidatorSet) { return &osmocli.TxCliDesc{ Use: "delegate-valset [delegator_addr] [amount]", Short: "Delegate tokens to existing valset using delegatorAddress and tokenAmount.", - Example: "osmosisd tx valset-pref delegate-valset osmo1... 100stake", + Example: "osmosisd tx valset-pref delegate-valset osmo1... 100stake", NumArgs: 2, }, &types.MsgDelegateToValidatorSet{} } @@ -45,17 +47,65 @@ func NewUnDelValSetCmd() (*osmocli.TxCliDesc, *types.MsgUndelegateFromValidatorS return &osmocli.TxCliDesc{ Use: "undelegate-valset [delegator_addr] [amount]", Short: "UnDelegate tokens from existing valset using delegatorAddress and tokenAmount.", - Example: "osmosisd tx valset-pref undelegate-valset osmo1... 100stake", + Example: "osmosisd tx valset-pref undelegate-valset osmo1... 100stake", NumArgs: 2, }, &types.MsgUndelegateFromValidatorSet{} } +func NewReDelValSetCmd() (*osmocli.TxCliDesc, *types.MsgRedelegateValidatorSet) { + return &osmocli.TxCliDesc{ + Use: "redelegate-valset [delegator_addr] [validators] [weights]", + Short: "Redelegate tokens from existing validators to new sets of validators", + Example: "osmosisd tx valset-pref redelegate-valset osmo1... osmovaloper1efg...,osmovaloper1hij... 0.56,0.44", + NumArgs: 3, + ParseAndBuildMsg: NewMsgReDelValidatorSetPreference, + }, &types.MsgRedelegateValidatorSet{} +} + +func NewWithRewValSetCmd() (*osmocli.TxCliDesc, *types.MsgWithdrawDelegationRewards) { + return &osmocli.TxCliDesc{ + Use: "withdraw-reward-valset [delegator_addr]", + Short: "Withdraw delegation reward form the new validator set.", + Example: "osmosisd tx valset-pref withdraw-valset osmo1...", + NumArgs: 1, + }, &types.MsgWithdrawDelegationRewards{} +} + func NewMsgSetValidatorSetPreference(clientCtx client.Context, args []string, fs *pflag.FlagSet) (sdk.Msg, error) { delAddr, err := sdk.AccAddressFromBech32(args[0]) if err != nil { return nil, err } + valset, err := ValidateValAddrAndWeight(args) + if err != nil { + return nil, err + } + + return types.NewMsgSetValidatorSetPreference( + delAddr, + valset, + ), nil +} + +func NewMsgReDelValidatorSetPreference(clientCtx client.Context, args []string, fs *pflag.FlagSet) (sdk.Msg, error) { + delAddr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return nil, err + } + + valset, err := ValidateValAddrAndWeight(args) + if err != nil { + return nil, err + } + + return types.NewMsgRedelegateValidatorSet( + delAddr, + valset, + ), nil +} + +func ValidateValAddrAndWeight(args []string) ([]types.ValidatorPreference, error) { var valAddrs []string valAddrs = append(valAddrs, strings.Split(args[1], ",")...) @@ -80,8 +130,5 @@ func NewMsgSetValidatorSetPreference(clientCtx client.Context, args []string, fs }) } - return types.NewMsgSetValidatorSetPreference( - delAddr, - valset, - ), nil + return valset, nil } diff --git a/x/valset-pref/simulation/sim_msgs.go b/x/valset-pref/simulation/sim_msgs.go index a4d9b55c586..c995ecedcf6 100644 --- a/x/valset-pref/simulation/sim_msgs.go +++ b/x/valset-pref/simulation/sim_msgs.go @@ -14,30 +14,12 @@ import ( ) func RandomMsgSetValSetPreference(k valsetkeeper.Keeper, sim *osmosimtypes.SimCtx, ctx sdk.Context) (*types.MsgSetValidatorSetPreference, error) { - var preferences []types.ValidatorPreference - // Start with a weight of 1 remainingWeight := sdk.NewDec(1) - // Generate random validators with random weights that sums to 1 - for remainingWeight.GT(sdk.ZeroDec()) { - randValidator := RandomValidator(ctx, sim) - if randValidator == nil { - return nil, fmt.Errorf("No validator") - } - - randValue, err := RandomWeight(remainingWeight) - if err != nil { - return nil, fmt.Errorf("Error with random weights") - } - - remainingWeight = remainingWeight.Sub(randValue) - if !randValue.Equal(sdk.ZeroDec()) { - preferences = append(preferences, types.ValidatorPreference{ - ValOperAddress: randValidator.OperatorAddress, - Weight: randValue, - }) - } + preferences, err := GetRandomValAndWeights(ctx, k, sim, remainingWeight) + if err != nil { + return nil, err } return &types.MsgSetValidatorSetPreference{ @@ -62,7 +44,7 @@ func RandomMsgDelegateToValSet(k valsetkeeper.Keeper, sim *osmosimtypes.SimCtx, }, nil } -func RandomMsgUnDelegateToValSet(k valsetkeeper.Keeper, sim *osmosimtypes.SimCtx, ctx sdk.Context) (*types.MsgUndelegateFromValidatorSet, error) { +func RandomMsgUnDelegateFromValSet(k valsetkeeper.Keeper, sim *osmosimtypes.SimCtx, ctx sdk.Context) (*types.MsgUndelegateFromValidatorSet, error) { delegator := sim.RandomSimAccount() // check if the delegator valset created err := GetRandomExistingValSet(ctx, k, sim, delegator.Address) @@ -71,7 +53,7 @@ func RandomMsgUnDelegateToValSet(k valsetkeeper.Keeper, sim *osmosimtypes.SimCtx } // check that the delegator has delegated tokens - err = GetRandomExistingDelegation(ctx, k, sim, delegator.Address) + _, err = GetRandomExistingDelegation(ctx, k, sim, delegator.Address) if err != nil { return nil, err } @@ -83,6 +65,57 @@ func RandomMsgUnDelegateToValSet(k valsetkeeper.Keeper, sim *osmosimtypes.SimCtx }, nil } +func RandomMsgReDelegateToValSet(k valsetkeeper.Keeper, sim *osmosimtypes.SimCtx, ctx sdk.Context) (*types.MsgRedelegateValidatorSet, error) { + delegator := sim.RandomSimAccount() + // check if the delegator valset created + err := GetRandomExistingValSet(ctx, k, sim, delegator.Address) + if err != nil { + return nil, err + } + + // check that the delegator has delegated tokens + _, err = GetRandomExistingDelegation(ctx, k, sim, delegator.Address) + if err != nil { + return nil, err + } + + remainingWeight := sdk.NewDec(1) + preferences, err := GetRandomValAndWeights(ctx, k, sim, remainingWeight) + if err != nil { + return nil, err + } + + return &types.MsgRedelegateValidatorSet{ + Delegator: delegator.Address.String(), + Preferences: preferences, + }, nil +} + +func RandomMsgWithdrawRewardsFromValSet(k valsetkeeper.Keeper, sim *osmosimtypes.SimCtx, ctx sdk.Context) (*types.MsgWithdrawDelegationRewards, error) { + delegator := sim.RandomSimAccount() + + err := GetRandomExistingValSet(ctx, k, sim, delegator.Address) + if err != nil { + return nil, err + } + + // check that the delegator has delegated tokens + delegations, err := GetRandomExistingDelegation(ctx, k, sim, delegator.Address) + if err != nil { + return nil, err + } + + delegation := delegations[rand.Intn(len(delegations))] + validator := sim.StakingKeeper().Validator(ctx, delegation.GetValidatorAddr()) + if validator == nil { + return nil, fmt.Errorf("validator not found") + } + + return &types.MsgWithdrawDelegationRewards{ + Delegator: delegator.Address.String(), + }, nil +} + func RandomValidator(ctx sdk.Context, sim *osmosimtypes.SimCtx) *stakingtypes.Validator { rand.Seed(time.Now().UnixNano()) @@ -94,6 +127,33 @@ func RandomValidator(ctx sdk.Context, sim *osmosimtypes.SimCtx) *stakingtypes.Va return &validators[rand.Intn(len(validators))] } +func GetRandomValAndWeights(ctx sdk.Context, k valsetkeeper.Keeper, sim *osmosimtypes.SimCtx, remainingWeight sdk.Dec) ([]types.ValidatorPreference, error) { + var preferences []types.ValidatorPreference + + // Generate random validators with random weights that sums to 1 + for remainingWeight.GT(sdk.ZeroDec()) { + randValidator := RandomValidator(ctx, sim) + if randValidator == nil { + return nil, fmt.Errorf("No validator") + } + + randValue, err := RandomWeight(remainingWeight) + if err != nil { + return nil, fmt.Errorf("Error with random weights") + } + + remainingWeight = remainingWeight.Sub(randValue) + if !randValue.Equal(sdk.ZeroDec()) { + preferences = append(preferences, types.ValidatorPreference{ + ValOperAddress: randValidator.OperatorAddress, + Weight: randValue, + }) + } + } + + return preferences, nil +} + // TODO: Change this to user GetDelegations() once #3857 gets merged, issue created func GetRandomExistingValSet(ctx sdk.Context, k valsetkeeper.Keeper, sim *osmosimtypes.SimCtx, delegatorAddr sdk.AccAddress) error { // Get Valset delegations @@ -105,14 +165,14 @@ func GetRandomExistingValSet(ctx sdk.Context, k valsetkeeper.Keeper, sim *osmosi return nil } -func GetRandomExistingDelegation(ctx sdk.Context, k valsetkeeper.Keeper, sim *osmosimtypes.SimCtx, delegatorAddr sdk.AccAddress) error { +func GetRandomExistingDelegation(ctx sdk.Context, k valsetkeeper.Keeper, sim *osmosimtypes.SimCtx, delegatorAddr sdk.AccAddress) ([]stakingtypes.Delegation, error) { // gets the existing delegation existingDelegations := sim.StakingKeeper().GetDelegatorDelegations(ctx, delegatorAddr, math.MaxUint16) if len(existingDelegations) == 0 { - return fmt.Errorf("No existing delegation") + return nil, fmt.Errorf("No existing delegation") } - return nil + return existingDelegations, nil } // Random float point from 0-1 diff --git a/x/valset-pref/valpref-module/module.go b/x/valset-pref/valpref-module/module.go index f765a12272b..25c381fe79d 100644 --- a/x/valset-pref/valpref-module/module.go +++ b/x/valset-pref/valpref-module/module.go @@ -175,6 +175,8 @@ func (am AppModule) Actions() []simtypes.Action { return []simtypes.Action{ simtypes.NewMsgBasedAction("SetValidatorSetPreference", am.keeper, simulation.RandomMsgSetValSetPreference), simtypes.NewMsgBasedAction("MsgDelegateToValidatorSet", am.keeper, simulation.RandomMsgDelegateToValSet), - simtypes.NewMsgBasedAction("MsgUndelegateFromValidatorSet", am.keeper, simulation.RandomMsgUnDelegateToValSet), + simtypes.NewMsgBasedAction("MsgUndelegateFromValidatorSet", am.keeper, simulation.RandomMsgUnDelegateFromValSet), + simtypes.NewMsgBasedAction("MsgRedelegateValSet", am.keeper, simulation.RandomMsgReDelegateToValSet), + simtypes.NewMsgBasedAction("MsgWithdrawDelegationRewards", am.keeper, simulation.RandomMsgWithdrawRewardsFromValSet), } }