Merge #2500: Block conflicting redelegations

* Block conflicting redelegations

* Update PENDING.md

* Add conflicting redelegation testcase
This commit is contained in:
Christopher Goes 2018-10-16 03:06:31 +02:00 committed by Rigel
parent 6164640ffd
commit c0ce451003
4 changed files with 55 additions and 0 deletions

View File

@ -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

View File

@ -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])

View File

@ -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())

View File

@ -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")
} }