Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Cancel unbonding delegation entry #10885

Merged
merged 56 commits into from
Apr 5, 2022
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
b18cbc2
feat(WIP): add msg service for cancel unbonding delegation
Jan 5, 2022
276d33b
WIP: add simulation for canceling unbonding delegation
Jan 5, 2022
5f197f1
Merge the master
Jan 5, 2022
759fff3
WIP: update the initial balance in ubd entry
Jan 5, 2022
bf10855
WIP: update the initial balance and balance in ubd entry
Jan 6, 2022
bcee445
Merge remote-tracking branch 'upstream/master' into sai/577_cancel_un…
Jan 6, 2022
ff8be0f
revert the proto-gen for gov,staking
Jan 6, 2022
ee7079e
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Jan 6, 2022
98a6126
test: add cli test for cancel unbond delegation
Jan 7, 2022
8d3a82b
Merge branch 'sai/577_cancel_unbond' of github.com:gsk967/cosmos-sdk …
Jan 7, 2022
78042e6
test: add simulation test for cancel-unbond
Jan 8, 2022
5147003
chore: check the validator is jailed or not for cancel unbond
Jan 11, 2022
d93705f
chore: try to fix cancel unbond simulation
Jan 11, 2022
389bd1f
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Jan 11, 2022
f909286
chore: update the consensus version and changelog
Jan 19, 2022
07a4822
chore: update the consensus version and changelog
Jan 19, 2022
a8cd5dd
Merge branch 'master' of https://github.com/cosmos/cosmos-sdk into sa…
Jan 20, 2022
31c54a1
test: add more test cases for cancel unbond delegation
Jan 20, 2022
927e3b9
Merge remote-tracking branch 'upstream/master' into sai/577_cancel_un…
Jan 21, 2022
550e27d
fix: fix the issue of docs bug
Jan 27, 2022
65b8527
Merge the upstream/master
Jan 27, 2022
2d26ab3
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Jan 27, 2022
816cb9c
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Jan 28, 2022
e27b990
Merge remote upstream master
Jan 29, 2022
61c4818
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Jan 31, 2022
be0b721
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Feb 1, 2022
ad66dc4
Merge branch 'master' into sai/577_cancel_unbond
Mar 21, 2022
ef9f21e
fix: fix the build issue
Mar 21, 2022
15d215e
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Mar 23, 2022
b21d5a0
chore: address the pr comments
Mar 23, 2022
563db02
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Mar 23, 2022
f288ecd
Update CHANGELOG.md
alexanderbez Mar 23, 2022
70a2b53
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Mar 24, 2022
e9bd4bb
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Mar 24, 2022
971dc0a
chore: remove commented code
Mar 24, 2022
8b9fee6
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Mar 25, 2022
ea69358
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Mar 25, 2022
f7cafe2
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Mar 26, 2022
28243eb
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Mar 28, 2022
6c3aa6f
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Mar 29, 2022
4c67387
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Mar 30, 2022
793ce7f
test: add test cases for cancel unbond
Mar 30, 2022
8c1e20a
chore: covert creation_height from uint64 to int64
Mar 30, 2022
de22757
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Mar 30, 2022
597aa0b
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Mar 30, 2022
5390f78
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Mar 31, 2022
b468491
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Apr 1, 2022
b8b643e
Merge branch 'master' into sai/577_cancel_unbond
anilcse Apr 1, 2022
0bc4085
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Apr 3, 2022
069101a
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Apr 4, 2022
ebaa959
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Apr 4, 2022
78725ee
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Apr 5, 2022
d4bba93
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Apr 5, 2022
376024d
chore: address the review comments
Apr 5, 2022
21ce078
Merge branch 'sai/577_cancel_unbond' of github.com:gsk967/cosmos-sdk …
Apr 5, 2022
bb70c1c
Merge branch 'master' into sai/577_cancel_unbond
gsk967 Apr 5, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions proto/cosmos/staking/v1beta1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ service Msg {
// Undelegate defines a method for performing an undelegation from a
// delegate and a validator.
rpc Undelegate(MsgUndelegate) returns (MsgUndelegateResponse);

// CancelUnbondingDelegation defines a method for performing canceling the unbonding delegation
// and delegate back to previous validator
rpc CancelUnbondingDelegation(MsgCancelUnbondingDelegation) returns (MsgCancelUnbondingDelegationResponse);
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
}

// MsgCreateValidator defines a SDK message for creating a new validator.
Expand Down Expand Up @@ -120,3 +124,18 @@ message MsgUndelegate {
message MsgUndelegateResponse {
google.protobuf.Timestamp completion_time = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
}

// MsgCancelUnbondingDelegation defines the SDK message for performing an cancel unbonding delegation for delegator
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
message MsgCancelUnbondingDelegation{
option (gogoproto.equal) = false;
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
option (gogoproto.goproto_getters) = false;

string delegator_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string validator_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
cosmos.base.v1beta1.Coin amount = 3 [(gogoproto.nullable) = false];
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved
// creation_height is the height which the unbonding took place.
uint64 creation_height = 4;
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
}

// MsgCancelUnbondingDelegationResponse
message MsgCancelUnbondingDelegationResponse{}
1 change: 1 addition & 0 deletions simapp/params/weights.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const (
DefaultWeightMsgDelegate int = 100
DefaultWeightMsgUndelegate int = 100
DefaultWeightMsgBeginRedelegate int = 100
DefaultWeightMsgCancelUnbondingDelegation int = 100

DefaultWeightCommunitySpendProposal int = 5
DefaultWeightTextProposal int = 5
Expand Down
2 changes: 1 addition & 1 deletion x/gov/types/v1beta1/gov.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion x/gov/types/v1beta1/tx.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 49 additions & 0 deletions x/staking/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func NewTxCmd() *cobra.Command {
NewDelegateCmd(),
NewRedelegateCmd(),
NewUnbondCmd(),
NewCancelUnBondDelegation(),
)

return stakingTxCmd
Expand Down Expand Up @@ -277,6 +278,54 @@ $ %s tx staking unbond %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj 100stake --from
return cmd
}

func NewCancelUnBondDelegation() *cobra.Command {
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()

cmd := &cobra.Command{
Use: "cancel-unbond [validator-addr] [amount] [creation-height]",
Short: "Cancel unbonding delegation and delegate back to validator",
Args: cobra.ExactArgs(3),
Long: strings.TrimSpace(
fmt.Sprintf(`Cancel Unbonding Delegation and delegate back to validator.

Example:
$ %s tx staking cancel-unbond %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj 100stake 2 --from mykey
`,
version.AppName, bech32PrefixValAddr,
),
),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
delAddr := clientCtx.GetFromAddress()
valAddr, err := sdk.ValAddressFromBech32(args[0])
if err != nil {
return err
}

amount, err := sdk.ParseCoinNormalized(args[1])
if err != nil {
return err
}

creationHeight, ok := sdk.NewIntFromString(args[2])
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
if !ok {
return sdkerrors.Wrap(fmt.Errorf("invalid height: %d", creationHeight), "invalid height")
}

msg := types.NewMsgCancelUnbondingDelegation(delAddr, valAddr, creationHeight.Uint64(), amount)

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}

func newBuildCreateValidatorMsg(clientCtx client.Context, txf tx.Factory, fs *flag.FlagSet) (tx.Factory, *types.MsgCreateValidator, error) {
fAmount, _ := fs.GetString(FlagAmount)
amount, err := sdk.ParseCoinNormalized(fAmount)
Expand Down
85 changes: 84 additions & 1 deletion x/staking/client/testutil/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,11 @@ func (s *IntegrationTestSuite) SetupSuite() {
_, err = s.network.WaitForHeight(1)
s.Require().NoError(err)
// unbonding
_, err = MsgUnbondExec(val.ClientCtx, val.Address, val.ValAddress, unbond)
out, err = MsgUnbondExec(val.ClientCtx, val.Address, val.ValAddress, unbond)
s.Require().NoError(err)
s.Require().NoError(err)
s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txRes))
s.Require().Equal(uint32(0), txRes.Code)

_, err = s.network.WaitForHeight(1)
s.Require().NoError(err)
Expand Down Expand Up @@ -531,6 +534,7 @@ func (s *IntegrationTestSuite) TestGetCmdQueryUnbondingDelegations() {

s.Require().NoError(err)
s.Require().Len(ubds.UnbondingResponses, 1)
fmt.Println(ubds.UnbondingResponses)
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
s.Require().Equal(ubds.UnbondingResponses[0].DelegatorAddress, val.Address.String())
}
})
Expand Down Expand Up @@ -1297,6 +1301,85 @@ func (s *IntegrationTestSuite) TestNewUnbondCmd() {
}
}

func (s *IntegrationTestSuite) TestNewCancelUnbondingDelegationCmd() {
val := s.network.Validators[0]

testCases := []struct {
name string
args []string
expectErr bool
expectedCode uint32
respType proto.Message
}{
{
"Without validator address",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
},
true, 0, nil,
},
{
"Without canceling unbond delegation amount",
[]string{
val.ValAddress.String(),
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
},
true, 0, nil,
},
{
"Without unbond creation height",
[]string{
val.ValAddress.String(),
sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(),
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
},
true, 0, nil,
},
{
"valid transaction of canceling unbonding delegation",
[]string{
val.ValAddress.String(),
sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)).String(),
sdk.NewInt(3).String(),
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
},
false, 0, &sdk.TxResponse{},
},
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
}

for _, tc := range testCases {
tc := tc

s.Run(tc.name, func() {
cmd := cli.NewCancelUnBondDelegation()
clientCtx := val.ClientCtx

out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expectErr {
s.Require().Error(err)
} else {
s.Require().NoError(err, out.String())
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())

txResp := tc.respType.(*sdk.TxResponse)
s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
}
})
}
}

// TestBlockResults tests that the validator updates correctly show when
// calling the /block_results RPC endpoint.
// ref: https://github.com/cosmos/cosmos-sdk/issues/7401.
Expand Down
2 changes: 1 addition & 1 deletion x/staking/keeper/delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ func (k Keeper) DequeueAllMatureUBDQueue(ctx sdk.Context, currTime time.Time) (m
store := ctx.KVStore(k.storeKey)

// gets an iterator for all timeslices from time 0 until the current Blockheader time
unbondingTimesliceIterator := k.UBDQueueIterator(ctx, ctx.BlockHeader().Time)
unbondingTimesliceIterator := k.UBDQueueIterator(ctx, currTime)
defer unbondingTimesliceIterator.Close()

for ; unbondingTimesliceIterator.Valid(); unbondingTimesliceIterator.Next() {
Expand Down
3 changes: 3 additions & 0 deletions x/staking/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type KeeperTestSuite struct {
addrs []sdk.AccAddress
vals []types.Validator
queryClient types.QueryClient
msgServer types.MsgServer
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
}

func (suite *KeeperTestSuite) SetupTest() {
Expand All @@ -35,6 +36,8 @@ func (suite *KeeperTestSuite) SetupTest() {
types.RegisterQueryServer(queryHelper, querier)
queryClient := types.NewQueryClient(queryHelper)

suite.msgServer = keeper.NewMsgServerImpl(app.StakingKeeper)

addrs, _, validators := createValidators(suite.T(), ctx, app, []int64{9, 8, 7})
header := tmproto.Header{
ChainID: "HelloChain",
Expand Down
112 changes: 111 additions & 1 deletion x/staking/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package keeper

import (
"context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"strconv"
"time"

"github.com/armon/go-metrics"
Expand Down Expand Up @@ -173,7 +176,7 @@ func (k msgServer) EditValidator(goCtx context.Context, msg *types.MsgEditValida
return nil, types.ErrSelfDelegationBelowMinimum
}

validator.MinSelfDelegation = (*msg.MinSelfDelegation)
validator.MinSelfDelegation = *msg.MinSelfDelegation
}

k.SetValidator(ctx, validator)
Expand Down Expand Up @@ -381,3 +384,110 @@ func (k msgServer) Undelegate(goCtx context.Context, msg *types.MsgUndelegate) (
CompletionTime: completionTime,
}, nil
}

// CancelUnbondingDelegation defines a method for canceling the unbonding delegation
// and delegate back to validator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// and delegate back to validator
// and delegate back to validator.

func (k msgServer) CancelUnbondingDelegation(goCtx context.Context, msg *types.MsgCancelUnbondingDelegation) (*types.MsgCancelUnbondingDelegationResponse, error) {
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
ctx := sdk.UnwrapSDKContext(goCtx)
valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
return nil, err
}
delegatorAddress, err := sdk.AccAddressFromBech32(msg.DelegatorAddress)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ctx := sdk.UnwrapSDKContext(goCtx)
valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
return nil, err
}
delegatorAddress, err := sdk.AccAddressFromBech32(msg.DelegatorAddress)
ctx := sdk.UnwrapSDKContext(goCtx)
valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
return nil, err
}
delegatorAddress, err := sdk.AccAddressFromBech32(msg.DelegatorAddress)

if err != nil {
return nil, err
}

bondDenom := k.BondDenom(ctx)
if msg.Amount.Denom != bondDenom {
return nil, sdkerrors.Wrapf(
sdkerrors.ErrInvalidRequest, "invalid coin denomination: got %s, expected %s", msg.Amount.Denom, bondDenom,
)
}

// get validator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// get validator

validator, found := k.GetValidator(ctx, valAddr)
if !found {
return nil, types.ErrNoValidatorFound
}

//// In some situations, the exchange rate becomes invalid, e.g. if
//// Validator loses all tokens due to slashing. In this case,
//// make all future delegations invalid.
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
if validator.InvalidExRate() {
return nil, types.ErrDelegatorShareExRateInvalid
}

if validator.IsJailed(){
return nil, types.ErrValidatorJailed
}

ubd, found := k.GetUnbondingDelegation(ctx, delegatorAddress, valAddr)
if !found {
return nil, status.Errorf(
codes.NotFound,
"unbonding delegation with delegator %s not found for validator %s",
msg.DelegatorAddress, msg.ValidatorAddress)
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
}

var (
foundUnBondingAtHeight = false
unbondEntry types.UnbondingDelegationEntry
unbondEntryIndex int64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we can initialize unbondEntryIndex to -1 we can eliminate foundUnBondingAtHeight and unbondEntryIndex can be used at L447

)

for i, entry := range ubd.Entries {
if entry.CreationHeight == int64(msg.CreationHeight) {
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
foundUnBondingAtHeight = true
unbondEntry = entry
unbondEntryIndex = int64(i)
break
}
}
if !foundUnBondingAtHeight {
return nil, sdkerrors.Wrapf(sdkerrors.ErrNotFound, "unbonding delegation is not found at block height %d", msg.CreationHeight)
}

if unbondEntry.Balance.LT(msg.Amount.Amount) {
return nil, sdkerrors.Wrap(types.ErrNotEnoughDelegationShares, msg.Amount.String())
}

if !ubd.Entries[unbondEntryIndex].CompletionTime.After(ctx.BlockTime()){
return nil, sdkerrors.Wrap(types.ErrNotEnoughDelegationShares, msg.Amount.String())
}

// delegate the unbonding delegation amount to validator back
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
_, err = k.Keeper.Delegate(ctx, delegatorAddress, msg.Amount.Amount, types.Unbonding, validator, false)
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
}

amount := unbondEntry.Balance.Sub(msg.Amount.Amount)
atheeshp marked this conversation as resolved.
Show resolved Hide resolved
if amount.Equal(sdk.NewInt(0)) {
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
// remove from ubd
gsk967 marked this conversation as resolved.
Show resolved Hide resolved
ubd.RemoveEntry(unbondEntryIndex)
} else {
// update the unbondingDelegationEntryBalance and InitialBalance for ubd entry
ubd.Entries[unbondEntryIndex].Balance = amount
ubd.Entries[unbondEntryIndex].InitialBalance = ubd.Entries[unbondEntryIndex].InitialBalance.Sub(msg.Amount.Amount)
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
}

// set the unbonding delegation or remove it if there are no more entries
if len(ubd.Entries) == 0 {
k.RemoveUnbondingDelegation(ctx, ubd)
} else {
k.SetUnbondingDelegation(ctx, ubd)
}

ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeCancelUnbondDelegation,
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.String()),
sdk.NewAttribute(types.AttributeKeyValidator, msg.ValidatorAddress),
sdk.NewAttribute(types.AttributeKeyDelegator, msg.DelegatorAddress),
sdk.NewAttribute(types.AttributeKeyCreationHeight, strconv.FormatUint(msg.CreationHeight, 10)),
),
)

return &types.MsgCancelUnbondingDelegationResponse{}, nil
}
Loading