diff --git a/x/slashing/keeper.go b/x/slashing/keeper.go index dc316b2b6..473a5f5f6 100644 --- a/x/slashing/keeper.go +++ b/x/slashing/keeper.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/params" + stake "github.com/cosmos/cosmos-sdk/x/stake/types" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" ) @@ -60,7 +61,7 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio // Note that this *can* result in a "distributionHeight" of -1, // i.e. at the end of the pre-genesis block (none) = at the beginning of the genesis block. // That's fine since this is just used to filter unbonding delegations & redelegations. - distributionHeight := infractionHeight - ValidatorUpdateDelay + distributionHeight := infractionHeight - stake.ValidatorUpdateDelay // Cap the amount slashed to the penalty for the worst infraction // within the slashing period when this infraction was committed @@ -137,7 +138,7 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p // Note that this *can* result in a "distributionHeight" of -1 or -2, // i.e. at the end of the pre-genesis block (none) = at the beginning of the genesis block. // That's fine since this is just used to filter unbonding delegations & redelegations. - distributionHeight := height - ValidatorUpdateDelay - 1 + distributionHeight := height - stake.ValidatorUpdateDelay - 1 k.validatorSet.Slash(ctx, consAddr, distributionHeight, power, k.SlashFractionDowntime(ctx)) k.validatorSet.Jail(ctx, consAddr) signInfo.JailedUntil = ctx.BlockHeader().Time.Add(k.DowntimeUnbondDuration(ctx)) diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index 43c8e2a20..cf67af192 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -250,6 +250,7 @@ func TestHandleAbsentValidator(t *testing.T) { info, found = keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.True(t, found) require.Equal(t, height, info.StartHeight) + // we've missed 2 blocks more than the maximum require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)-2, info.SignedBlocksCounter) // validator should not be immediately jailed again diff --git a/x/slashing/keys.go b/x/slashing/keys.go index 4303f4635..ec453cedc 100644 --- a/x/slashing/keys.go +++ b/x/slashing/keys.go @@ -4,6 +4,7 @@ import ( "encoding/binary" sdk "github.com/cosmos/cosmos-sdk/types" + stake "github.com/cosmos/cosmos-sdk/x/stake/types" ) // key prefix bytes @@ -34,8 +35,8 @@ func GetValidatorSlashingPeriodPrefix(v sdk.ConsAddress) []byte { // stored by *Tendermint* address (not operator address) followed by start height func GetValidatorSlashingPeriodKey(v sdk.ConsAddress, startHeight int64) []byte { b := make([]byte, 8) - // this needs to be height + 1 because the slashing period for genesis validators starts at height -1 - binary.BigEndian.PutUint64(b, uint64(startHeight+1)) + // this needs to be height + ValidatorUpdateDelay because the slashing period for genesis validators starts at height -ValidatorUpdateDelay + binary.BigEndian.PutUint64(b, uint64(startHeight+stake.ValidatorUpdateDelay)) return append(GetValidatorSlashingPeriodPrefix(v), b...) } diff --git a/x/slashing/params.go b/x/slashing/params.go index 467af3c11..6e18e5f48 100644 --- a/x/slashing/params.go +++ b/x/slashing/params.go @@ -15,12 +15,6 @@ const ( DowntimeUnbondDurationKey = "slashing/DowntimeUnbondDuration" SlashFractionDoubleSignKey = "slashing/SlashFractionDoubleSign" SlashFractionDowntimeKey = "slashing/SlashFractionDowntime" - - // Delay, in blocks, between when validator updates are returned to Tendermint and when they are applied - // For example, if this is 0, the validator set at the end of a block will sign the next block, or - // if this is 1, the validator set at the end of a block will sign the block after the next. - // Constant as this should not change without a hard fork. - ValidatorUpdateDelay int64 = 1 ) // MaxEvidenceAge - Max age for evidence - 21 days (3 weeks) diff --git a/x/slashing/slashing_period.go b/x/slashing/slashing_period.go index 1d94aa559..0595d5eeb 100644 --- a/x/slashing/slashing_period.go +++ b/x/slashing/slashing_period.go @@ -5,6 +5,7 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + stake "github.com/cosmos/cosmos-sdk/x/stake/types" ) // Cap an infraction's slash amount by the slashing period in which it was committed @@ -68,7 +69,7 @@ func (k Keeper) unmarshalSlashingPeriodKeyValue(key []byte, value []byte) Valida var slashingPeriodValue ValidatorSlashingPeriodValue k.cdc.MustUnmarshalBinary(value, &slashingPeriodValue) address := sdk.ConsAddress(key[1 : 1+sdk.AddrLen]) - startHeight := int64(binary.BigEndian.Uint64(key[1+sdk.AddrLen:1+sdk.AddrLen+8]) - 1) + startHeight := int64(binary.BigEndian.Uint64(key[1+sdk.AddrLen:1+sdk.AddrLen+8]) - uint64(stake.ValidatorUpdateDelay)) return ValidatorSlashingPeriod{ ValidatorAddr: address, StartHeight: startHeight, diff --git a/x/stake/genesis.go b/x/stake/genesis.go index 336e414fe..1d500bd82 100644 --- a/x/stake/genesis.go +++ b/x/stake/genesis.go @@ -17,10 +17,10 @@ import ( // Returns final validator set after applying all declaration and delegations func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res []abci.ValidatorUpdate, err error) { - // We need to pretend to be "one block before genesis" so that e.g. slashing periods - // are correctly initialized for the validator set one-block offset - the first TM block - // is at height 0, so state updates applied from genesis.json are in block -1. - ctx = ctx.WithBlockHeight(-1) + // We need to pretend to be "n blocks before genesis", where "n" is the validator update delay, + // so that e.g. slashing periods are correctly initialized for the validator set + // e.g. with a one-block offset - the first TM block is at height 0, so state updates applied from genesis.json are in block -1. + ctx = ctx.WithBlockHeight(-types.ValidatorUpdateDelay) keeper.SetPool(ctx, data.Pool) keeper.SetParams(ctx, data.Params) diff --git a/x/stake/types/params.go b/x/stake/types/params.go index 4dcc3782a..c3685f7c3 100644 --- a/x/stake/types/params.go +++ b/x/stake/types/params.go @@ -9,9 +9,17 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// defaultUnbondingTime reflects three weeks in seconds as the default -// unbonding time. -const defaultUnbondingTime time.Duration = 60 * 60 * 24 * 3 * time.Second +const ( + // defaultUnbondingTime reflects three weeks in seconds as the default + // unbonding time. + defaultUnbondingTime time.Duration = 60 * 60 * 24 * 3 * time.Second + + // Delay, in blocks, between when validator updates are returned to Tendermint and when they are applied + // For example, if this is 0, the validator set at the end of a block will sign the next block, or + // if this is 1, the validator set at the end of a block will sign the block after the next. + // Constant as this should not change without a hard fork. + ValidatorUpdateDelay int64 = 1 +) // Params defines the high level settings for staking type Params struct {