Merge #2500: Block conflicting redelegations
* Block conflicting redelegations * Update PENDING.md * Add conflicting redelegation testcase
This commit is contained in:
parent
6164640ffd
commit
c0ce451003
|
@ -70,6 +70,7 @@ BREAKING CHANGES
|
||||||
* [x/staking] \#2236 more distribution hooks for distribution
|
* [x/staking] \#2236 more distribution hooks for distribution
|
||||||
* [x/stake] \#2394 Split up UpdateValidator into distinct state transitions applied only in EndBlock
|
* [x/stake] \#2394 Split up UpdateValidator into distinct state transitions applied only in EndBlock
|
||||||
* [x/stake] \#2412 Added an unbonding validator queue to EndBlock to automatically update validator.Status when finished Unbonding
|
* [x/stake] \#2412 Added an unbonding validator queue to EndBlock to automatically update validator.Status when finished Unbonding
|
||||||
|
* [x/stake] \#2500 Block conflicting redelegations until we add an index
|
||||||
* [x/params] Global Paramstore refactored
|
* [x/params] Global Paramstore refactored
|
||||||
|
|
||||||
* Tendermint
|
* Tendermint
|
||||||
|
|
|
@ -863,6 +863,48 @@ func TestTransitiveRedelegation(t *testing.T) {
|
||||||
require.True(t, got.IsOK(), "expected no error")
|
require.True(t, got.IsOK(), "expected no error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConflictingRedelegation(t *testing.T) {
|
||||||
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
||||||
|
validatorAddr := sdk.ValAddress(keep.Addrs[0])
|
||||||
|
validatorAddr2 := sdk.ValAddress(keep.Addrs[1])
|
||||||
|
|
||||||
|
// set the unbonding time
|
||||||
|
params := keeper.GetParams(ctx)
|
||||||
|
params.UnbondingTime = 1
|
||||||
|
keeper.SetParams(ctx, params)
|
||||||
|
|
||||||
|
// create the validators
|
||||||
|
msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||||
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||||
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||||
|
|
||||||
|
msgCreateValidator = newTestMsgCreateValidator(validatorAddr2, keep.PKs[1], 10)
|
||||||
|
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||||
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||||
|
|
||||||
|
// end block to bond them
|
||||||
|
EndBlocker(ctx, keeper)
|
||||||
|
|
||||||
|
// begin redelegate
|
||||||
|
msgBeginRedelegate := NewMsgBeginRedelegate(sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2, sdk.NewDec(5))
|
||||||
|
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
||||||
|
require.True(t, got.IsOK(), "expected no error, %v", got)
|
||||||
|
|
||||||
|
// cannot redelegate again while first redelegation still exists
|
||||||
|
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
||||||
|
require.True(t, !got.IsOK(), "expected an error, msg: %v", msgBeginRedelegate)
|
||||||
|
|
||||||
|
// progress forward in time
|
||||||
|
ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(10 * time.Second))
|
||||||
|
|
||||||
|
// complete first redelegation
|
||||||
|
EndBlocker(ctx, keeper)
|
||||||
|
|
||||||
|
// now should be able to redelegate again
|
||||||
|
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
||||||
|
require.True(t, got.IsOK(), "expected no error")
|
||||||
|
}
|
||||||
|
|
||||||
func TestUnbondingWhenExcessValidators(t *testing.T) {
|
func TestUnbondingWhenExcessValidators(t *testing.T) {
|
||||||
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
||||||
validatorAddr1 := sdk.ValAddress(keep.Addrs[0])
|
validatorAddr1 := sdk.ValAddress(keep.Addrs[0])
|
||||||
|
|
|
@ -526,6 +526,13 @@ func (k Keeper) CompleteUnbonding(ctx sdk.Context, delAddr sdk.AccAddress, valAd
|
||||||
func (k Keeper) BeginRedelegation(ctx sdk.Context, delAddr sdk.AccAddress,
|
func (k Keeper) BeginRedelegation(ctx sdk.Context, delAddr sdk.AccAddress,
|
||||||
valSrcAddr, valDstAddr sdk.ValAddress, sharesAmount sdk.Dec) (types.Redelegation, sdk.Error) {
|
valSrcAddr, valDstAddr sdk.ValAddress, sharesAmount sdk.Dec) (types.Redelegation, sdk.Error) {
|
||||||
|
|
||||||
|
// check if there is already a redelgation in progress from src to dst
|
||||||
|
// TODO quick fix, instead we should use an index, see https://github.com/cosmos/cosmos-sdk/issues/1402
|
||||||
|
_, found := k.GetRedelegation(ctx, delAddr, valSrcAddr, valDstAddr)
|
||||||
|
if found {
|
||||||
|
return types.Redelegation{}, types.ErrConflictingRedelegation(k.Codespace())
|
||||||
|
}
|
||||||
|
|
||||||
// check if this is a transitive redelegation
|
// check if this is a transitive redelegation
|
||||||
if k.HasReceivingRedelegation(ctx, delAddr, valSrcAddr) {
|
if k.HasReceivingRedelegation(ctx, delAddr, valSrcAddr) {
|
||||||
return types.Redelegation{}, types.ErrTransitiveRedelegation(k.Codespace())
|
return types.Redelegation{}, types.ErrTransitiveRedelegation(k.Codespace())
|
||||||
|
|
|
@ -164,6 +164,11 @@ func ErrTransitiveRedelegation(codespace sdk.CodespaceType) sdk.Error {
|
||||||
"redelegation to this validator already in progress, first redelegation to this validator must complete before next redelegation")
|
"redelegation to this validator already in progress, first redelegation to this validator must complete before next redelegation")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ErrConflictingRedelegation(codespace sdk.CodespaceType) sdk.Error {
|
||||||
|
return sdk.NewError(codespace, CodeInvalidDelegation,
|
||||||
|
"conflicting redelegation from this source validator to this dest validator already exists, you must wait for it to finish")
|
||||||
|
}
|
||||||
|
|
||||||
func ErrBothShareMsgsGiven(codespace sdk.CodespaceType) sdk.Error {
|
func ErrBothShareMsgsGiven(codespace sdk.CodespaceType) sdk.Error {
|
||||||
return sdk.NewError(codespace, CodeInvalidInput, "both shares amount and shares percent provided")
|
return sdk.NewError(codespace, CodeInvalidInput, "both shares amount and shares percent provided")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue