Skip to content

Commit

Permalink
fix: update StartHeight signing info in AfterValidatorBonded hook…
Browse files Browse the repository at this point in the history
… when validator re-bonds (#11973)
  • Loading branch information
julienrbrt authored May 18, 2022
1 parent 23baecf commit 0fa90ad
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 30 deletions.
25 changes: 19 additions & 6 deletions x/slashing/keeper/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,22 @@ import (

func (k Keeper) AfterValidatorBonded(ctx sdk.Context, address sdk.ConsAddress, _ sdk.ValAddress) error {
// Update the signing info start height or create a new signing info
_, found := k.GetValidatorSigningInfo(ctx, address)
if !found {
signingInfo := types.NewValidatorSigningInfo(
signingInfo, found := k.GetValidatorSigningInfo(ctx, address)
if found {
signingInfo.StartHeight = ctx.BlockHeight()
} else {
signingInfo = types.NewValidatorSigningInfo(
address,
ctx.BlockHeight(),
0,
time.Unix(0, 0),
false,
0,
)
k.SetValidatorSigningInfo(ctx, address, signingInfo)
}

k.SetValidatorSigningInfo(ctx, address, signingInfo)

return nil
}

Expand Down Expand Up @@ -74,17 +77,27 @@ func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) er
func (h Hooks) AfterValidatorBeginUnbonding(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) BeforeValidatorModified(_ sdk.Context, _ sdk.ValAddress) error { return nil }

func (h Hooks) BeforeValidatorModified(_ sdk.Context, _ sdk.ValAddress) error {
return nil
}

func (h Hooks) BeforeDelegationCreated(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
return nil
}

func (h Hooks) BeforeDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
return nil
}

func (h Hooks) BeforeDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
return nil
}

func (h Hooks) AfterDelegationModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) error {
return nil
}
func (h Hooks) BeforeValidatorSlashed(_ sdk.Context, _ sdk.ValAddress, _ sdk.Dec) error { return nil }

func (h Hooks) BeforeValidatorSlashed(_ sdk.Context, _ sdk.ValAddress, _ sdk.Dec) error {
return nil
}
44 changes: 24 additions & 20 deletions x/slashing/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,9 @@ func TestValidatorDippingInAndOut(t *testing.T) {
valAddr := sdk.ValAddress(addr)

tstaking.CreateValidatorWithValPower(valAddr, val, power, true)
staking.EndBlocker(ctx, app.StakingKeeper)
validatorUpdates := staking.EndBlocker(ctx, app.StakingKeeper)
require.Equal(t, 2, len(validatorUpdates))
tstaking.CheckValidator(valAddr, stakingtypes.Bonded, false)

// 100 first blocks OK
height := int64(0)
Expand All @@ -210,22 +212,23 @@ func TestValidatorDippingInAndOut(t *testing.T) {
}

// kick first validator out of validator set
tstaking.CreateValidatorWithValPower(sdk.ValAddress(pks[1].Address()), pks[1], 101, true)
validatorUpdates := staking.EndBlocker(ctx, app.StakingKeeper)
tstaking.CreateValidatorWithValPower(sdk.ValAddress(pks[1].Address()), pks[1], power+1, true)
validatorUpdates = staking.EndBlocker(ctx, app.StakingKeeper)
require.Equal(t, 2, len(validatorUpdates))
tstaking.CheckValidator(sdk.ValAddress(pks[1].Address()), stakingtypes.Bonded, false)
tstaking.CheckValidator(valAddr, stakingtypes.Unbonding, false)

// 600 more blocks happened
height = 700
height = height + 600
ctx = ctx.WithBlockHeight(height)

// validator added back in
tstaking.DelegateWithPower(sdk.AccAddress(pks[2].Address()), sdk.ValAddress(pks[0].Address()), 50)
tstaking.DelegateWithPower(sdk.AccAddress(pks[2].Address()), valAddr, 50)

validatorUpdates = staking.EndBlocker(ctx, app.StakingKeeper)
require.Equal(t, 2, len(validatorUpdates))
tstaking.CheckValidator(valAddr, stakingtypes.Bonded, false)
newPower := int64(150)
newPower := power + 50

// validator misses a block
app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), newPower, false)
Expand All @@ -234,9 +237,9 @@ func TestValidatorDippingInAndOut(t *testing.T) {
// shouldn't be jailed/kicked yet
tstaking.CheckValidator(valAddr, stakingtypes.Bonded, false)

// validator misses 500 more blocks, 501 total
latest := height
for ; height < latest+500; height++ {
// validator misses an additional 500 more blocks, after the cooling off period of SignedBlockWindow (here 1000 blocks).
latest := app.SlashingKeeper.SignedBlocksWindow(ctx) + height
for ; height < latest+app.SlashingKeeper.MinSignedPerWindow(ctx); height++ {
ctx = ctx.WithBlockHeight(height)
app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), newPower, false)
}
Expand All @@ -248,30 +251,31 @@ func TestValidatorDippingInAndOut(t *testing.T) {
// check all the signing information
signInfo, found := app.SlashingKeeper.GetValidatorSigningInfo(ctx, consAddr)
require.True(t, found)
require.Equal(t, int64(0), signInfo.MissedBlocksCounter)
require.Equal(t, int64(0), signInfo.IndexOffset)
// array should be cleared
for offset := int64(0); offset < app.SlashingKeeper.SignedBlocksWindow(ctx); offset++ {
missed := app.SlashingKeeper.GetValidatorMissedBlockBitArray(ctx, consAddr, offset)
require.False(t, missed)
}
require.Equal(t, int64(700), signInfo.StartHeight)
require.Equal(t, int64(499), signInfo.MissedBlocksCounter)
require.Equal(t, int64(499), signInfo.IndexOffset)

// some blocks pass
height = int64(5000)
ctx = ctx.WithBlockHeight(height)

// validator rejoins and starts signing again
app.StakingKeeper.Unjail(ctx, consAddr)

app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), newPower, true)
height++

// validator should not be kicked since we reset counter/array when it was jailed
staking.EndBlocker(ctx, app.StakingKeeper)
tstaking.CheckValidator(valAddr, stakingtypes.Bonded, false)

// validator misses 501 blocks
latest = height
for ; height < latest+501; height++ {
// check start height is correctly set
signInfo, found = app.SlashingKeeper.GetValidatorSigningInfo(ctx, consAddr)
require.True(t, found)
require.Equal(t, height, signInfo.StartHeight)

// validator misses 501 blocks after SignedBlockWindow period (1000 blocks)
latest = app.SlashingKeeper.SignedBlocksWindow(ctx) + height
for ; height < latest+app.SlashingKeeper.MinSignedPerWindow(ctx); height++ {
ctx = ctx.WithBlockHeight(height)
app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), newPower, false)
}
Expand Down
6 changes: 2 additions & 4 deletions x/slashing/spec/01_concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,14 @@ _V<sub>u</sub>_ : validator unbonded

### Single Double Sign Infraction

<----------------->
[----------C<sub>1</sub>----D<sub>1</sub>,V<sub>u</sub>-----]
\[----------C<sub>1</sub>----D<sub>1</sub>,V<sub>u</sub>-----\]

A single infraction is committed then later discovered, at which point the
validator is unbonded and slashed at the full amount for the infraction.

### Multiple Double Sign Infractions

<--------------------------->
[----------C<sub>1</sub>--C<sub>2</sub>---C<sub>3</sub>---D<sub>1</sub>,D<sub>2</sub>,D<sub>3</sub>V<sub>u</sub>-----]
\[----------C<sub>1</sub>--C<sub>2</sub>---C<sub>3</sub>---D<sub>1</sub>,D<sub>2</sub>,D<sub>3</sub>V<sub>u</sub>-----\]

Multiple infractions are committed and then later discovered, at which point the
validator is jailed and slashed for only one infraction. Because the validator
Expand Down
5 changes: 5 additions & 0 deletions x/slashing/spec/05_hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ The following hooks impact the slashing state:
Upon successful first-time bonding of a new validator, we create a new `ValidatorSigningInfo` structure for the
now-bonded validator, which `StartHeight` of the current block.

If the validator was out of the validator set and gets bonded again, its new bonded height is set.

```go
onValidatorBonded(address sdk.ValAddress)

Expand All @@ -32,7 +34,10 @@ onValidatorBonded(address sdk.ValAddress)
JailedUntil : time.Unix(0, 0),
Tombstone : false,
MissedBloskCounter : 0
} else {
signingInfo.StartHeight = CurrentHeight
}

setValidatorSigningInfo(signingInfo)
}

Expand Down

0 comments on commit 0fa90ad

Please sign in to comment.