Skip to content

Commit

Permalink
fix: unbound sidechain delegation directly after FirstSunsetFork
Browse files Browse the repository at this point in the history
  • Loading branch information
j75689 committed Jan 3, 2024
1 parent a5baa68 commit 1b21736
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 20 deletions.
25 changes: 22 additions & 3 deletions x/stake/cross_stake/cross_stake.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,28 @@ func (app *CrossStakeApp) handleUndelegate(ctx sdk.Context, pack *types.CrossSta
}, errCode, nil
}

_, err := app.stakeKeeper.BeginUnbonding(ctx.WithCrossStake(true), delAddr, pack.Validator, shares)
if err != nil {
return sdk.ExecuteResult{}, errCode, err
validator, found := app.stakeKeeper.GetValidator(ctx, pack.Validator)
if !found {
errCode = CrossStakeErrBadDelegation
return sdk.ExecuteResult{
Err: types.ErrNoValidatorFound(app.stakeKeeper.Codespace()),
}, errCode, nil
}

if sdk.IsUpgrade(sdk.FirstSunsetFork) && !validator.IsSelfDelegator(delAddr) {
// unbound the delegation directly, do not wait for the breathe block
// this is to prevent too many user get the coins back in the breathe block
// but self delegation still needs to wait until the unbonding period

_, _, err := app.stakeKeeper.UnboundDelegation(ctx.WithCrossStake(true), delAddr, pack.Validator, shares)
if err != nil {
return sdk.ExecuteResult{}, errCode, err
}
} else {
_, err := app.stakeKeeper.BeginUnbonding(ctx.WithCrossStake(true), delAddr, pack.Validator, shares, false)
if err != nil {
return sdk.ExecuteResult{}, errCode, err
}
}

// publish undelegate event
Expand Down
2 changes: 1 addition & 1 deletion x/stake/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ func handleMsgUndelegate(ctx sdk.Context, msg types.MsgUndelegate, k keeper.Keep
}

func handleMsgBeginUnbonding(ctx sdk.Context, msg types.MsgBeginUnbonding, k keeper.Keeper) sdk.Result {
ubd, err := k.BeginUnbonding(ctx, msg.DelegatorAddr, msg.ValidatorAddr, msg.SharesAmount)
ubd, err := k.BeginUnbonding(ctx, msg.DelegatorAddr, msg.ValidatorAddr, msg.SharesAmount, true)
if err != nil {
return err.Result()
}
Expand Down
29 changes: 25 additions & 4 deletions x/stake/handler_sidechain.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,9 +437,30 @@ func handleMsgSideChainUndelegate(ctx sdk.Context, msg MsgSideChainUndelegate, k
return err.Result()
}

ubd, err := k.BeginUnbonding(ctx, msg.DelegatorAddr, msg.ValidatorAddr, shares)
if err != nil {
return err.Result()
var (
ubd types.UnbondingDelegation
events sdk.Events
)

validator, found := k.GetValidator(ctx, msg.ValidatorAddr)
if !found {
return types.ErrNoValidatorFound(k.Codespace()).Result()
}

if sdk.IsUpgrade(sdk.FirstSunsetFork) && !validator.IsSelfDelegator(msg.DelegatorAddr) {
// unbound the delegation directly, do not wait for the breathe block
// this is to prevent too many user get the coins back in the breathe block
// but self delegation still needs to wait until the unbonding period

ubd, events, err = k.UnboundDelegation(ctx, msg.DelegatorAddr, msg.ValidatorAddr, shares)
if err != nil {
return err.Result()
}
} else {
ubd, err = k.BeginUnbonding(ctx, msg.DelegatorAddr, msg.ValidatorAddr, shares, true)
if err != nil {
return err.Result()
}
}

finishTime := types.MsgCdc.MustMarshalBinaryLengthPrefixed(ubd.MinTime)
Expand Down Expand Up @@ -468,7 +489,7 @@ func handleMsgSideChainUndelegate(ctx sdk.Context, msg MsgSideChainUndelegate, k
k.PbsbServer.Publish(event)
}

return sdk.Result{Data: finishTime, Tags: tags}
return sdk.Result{Data: finishTime, Tags: tags, Events: events}
}

// we allow the self-delegator delegating/redelegating to its validator.
Expand Down
25 changes: 23 additions & 2 deletions x/stake/keeper/delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -658,9 +658,25 @@ func (k Keeper) getBeginInfo(ctx sdk.Context, valSrcAddr sdk.ValAddress) (
}
}

func (k Keeper) UnboundDelegation(ctx sdk.Context,
delAddr sdk.AccAddress, valAddr sdk.ValAddress, sharesAmount sdk.Dec,
) (types.UnbondingDelegation, sdk.Events, sdk.Error) {
ubd, err := k.BeginUnbonding(ctx, delAddr, valAddr, sharesAmount, false)
if err != nil {
return ubd, nil, err
}
ubd, events, err := k.CompleteUnbonding(ctx, ubd.DelegatorAddr, ubd.ValidatorAddr)
if err != nil {
return ubd, events, err
}

return ubd, events, nil
}

// begin unbonding an unbonding record
func (k Keeper) BeginUnbonding(ctx sdk.Context,
delAddr sdk.AccAddress, valAddr sdk.ValAddress, sharesAmount sdk.Dec) (types.UnbondingDelegation, sdk.Error) {
delAddr sdk.AccAddress, valAddr sdk.ValAddress, sharesAmount sdk.Dec,
enqueue bool) (types.UnbondingDelegation, sdk.Error) {

// TODO quick fix, instead we should use an index, see https://github.com/cosmos/cosmos-sdk/issues/1402
_, found := k.GetUnbondingDelegation(ctx, delAddr, valAddr)
Expand All @@ -677,6 +693,9 @@ func (k Keeper) BeginUnbonding(ctx sdk.Context,
balance := sdk.NewCoin(k.BondDenom(ctx), returnAmount.RawInt())

completionTime := ctx.BlockHeader().Time.Add(k.UnbondingTime(ctx))
if !enqueue {
completionTime = ctx.BlockHeader().Time
}
ubd := types.UnbondingDelegation{
DelegatorAddr: delAddr,
ValidatorAddr: valAddr,
Expand All @@ -687,7 +706,9 @@ func (k Keeper) BeginUnbonding(ctx sdk.Context,
CrossStake: ctx.CrossStake(),
}
k.SetUnbondingDelegation(ctx, ubd)
k.InsertUnbondingQueue(ctx, ubd)
if enqueue {
k.InsertUnbondingQueue(ctx, ubd)
}

return ubd, nil
}
Expand Down
18 changes: 9 additions & 9 deletions x/stake/keeper/delegation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ func TestUndelegateSelfDelegation(t *testing.T) {
keeper.SetDelegation(ctx, delegation)

val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDecWithoutFra(10))
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDecWithoutFra(10), true)
require.NoError(t, err)

// end block
Expand Down Expand Up @@ -337,7 +337,7 @@ func TestUndelegateFromUnbondingValidator(t *testing.T) {

// unbond the all self-delegation to put validator in unbonding state
val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDecWithoutFra(10))
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDecWithoutFra(10), true)
require.NoError(t, err)

// end block
Expand All @@ -357,7 +357,7 @@ func TestUndelegateFromUnbondingValidator(t *testing.T) {
ctx = ctx.WithBlockTime(blockTime2)

// unbond some of the other delegation's shares
_, err = keeper.BeginUnbonding(ctx, addrDels[0], addrVals[0], sdk.NewDecWithoutFra(6))
_, err = keeper.BeginUnbonding(ctx, addrDels[0], addrVals[0], sdk.NewDecWithoutFra(6), true)
require.NoError(t, err)

// retrieve the unbonding delegation
Expand Down Expand Up @@ -409,7 +409,7 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) {
ctx = ctx.WithBlockTime(time.Unix(333, 0))

// unbond the all self-delegation to put validator in unbonding state
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDecWithoutFra(10))
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDecWithoutFra(10), true)
require.NoError(t, err)

// end block
Expand Down Expand Up @@ -439,7 +439,7 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) {
require.Equal(t, 1, len(matureUbds))

// unbond all the other delegation's shares
_, err = keeper.BeginUnbonding(ctx, addrDels[0], addrVals[0], sdk.NewDecWithoutFra(10))
_, err = keeper.BeginUnbonding(ctx, addrDels[0], addrVals[0], sdk.NewDecWithoutFra(10), true)
require.NoError(t, err)
ubd, found := keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
require.True(t, found)
Expand Down Expand Up @@ -491,15 +491,15 @@ func TestUnbondingAllDelegationFromValidator(t *testing.T) {
ctx = ctx.WithBlockTime(time.Unix(333, 0))

// unbond the all self-delegation to put validator in unbonding state
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDecWithoutFra(10))
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDecWithoutFra(10), true)
require.NoError(t, err)

// end block
_, updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
require.Equal(t, 1, len(updates))

// unbond all the remaining delegation
_, err = keeper.BeginUnbonding(ctx, addrDels[0], addrVals[0], sdk.NewDecWithoutFra(10))
_, err = keeper.BeginUnbonding(ctx, addrDels[0], addrVals[0], sdk.NewDecWithoutFra(10), true)
require.NoError(t, err)

// validator should still be in state and still be in unbonding state
Expand Down Expand Up @@ -713,7 +713,7 @@ func TestRedelegateFromUnbondingValidator(t *testing.T) {
ctx = ctx.WithBlockHeader(header)

// unbond the all self-delegation to put validator in unbonding state
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDecWithoutFra(10))
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDecWithoutFra(10), true)
require.NoError(t, err)

// end block
Expand Down Expand Up @@ -795,7 +795,7 @@ func TestRedelegateFromUnbondedValidator(t *testing.T) {
ctx = ctx.WithBlockTime(time.Unix(333, 0))

// unbond the all self-delegation to put validator in unbonding state
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDecWithoutFra(10))
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDecWithoutFra(10), true)
require.NoError(t, err)

// end block
Expand Down
2 changes: 1 addition & 1 deletion x/stake/querier/queryable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ func TestQueryDelegation(t *testing.T) {
require.NotNil(t, err)

// Query unbonging delegation
keeper.BeginUnbonding(ctx, addrAcc2, val1.OperatorAddr, sdk.NewDec(sdk.NewDecWithoutFra(10).RawInt()))
keeper.BeginUnbonding(ctx, addrAcc2, val1.OperatorAddr, sdk.NewDec(sdk.NewDecWithoutFra(10).RawInt()), true)

query = abci.RequestQuery{
Path: "/custom/stake/unbondingDelegation",
Expand Down

0 comments on commit 1b21736

Please sign in to comment.