Skip to content

Commit 8f5df61

Browse files
authored
feat(slashing): disable slashing during the singularity (#17)
1 parent bb2d11d commit 8f5df61

File tree

9 files changed

+215
-64
lines changed

9 files changed

+215
-64
lines changed

api/cosmos/slashing/v1beta1/slashing.pulsar.go

Lines changed: 79 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

proto/cosmos/slashing/v1beta1/slashing.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,6 @@ message Params {
5959
(gogoproto.nullable) = false,
6060
(amino.dont_omitempty) = true
6161
];
62+
// the block height until singularity is activated
63+
uint64 singularity_height = 6;
6264
}

x/slashing/abci_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ func TestBeginBlocker(t *testing.T) {
4545

4646
ctx := app.BaseApp.NewContext(false)
4747

48+
params, err := slashingKeeper.GetParams(ctx)
49+
require.NoError(t, err)
50+
51+
params.SingularityHeight = 1
52+
require.NoError(t, slashingKeeper.SetParams(ctx, params))
53+
4854
pks := simtestutil.CreateTestPubKeys(1)
4955
simtestutil.AddTestAddrsFromPubKeys(bankKeeper, stakingKeeper, ctx, pks, stakingKeeper.TokensFromConsensusPower(ctx, 200))
5056
addr, pk := sdk.ValAddress(pks[0].Address()), pks[0]
@@ -84,7 +90,7 @@ func TestBeginBlocker(t *testing.T) {
8490
require.Equal(t, time.Unix(0, 0).UTC(), info.JailedUntil)
8591
require.Equal(t, int64(0), info.MissedBlocksCounter)
8692

87-
height := int64(0)
93+
height := int64(2)
8894

8995
signedBlocksWindow, err := slashingKeeper.SignedBlocksWindow(ctx)
9096
require.NoError(t, err)

x/slashing/keeper/infractions.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,13 @@ func (k Keeper) HandleValidatorSignature(ctx context.Context, addr cryptotypes.A
109109
minHeight := signInfo.StartHeight + signedBlocksWindow
110110
maxMissed := signedBlocksWindow - minSignedPerWindow
111111

112+
params, err := k.GetParams(ctx)
113+
if err != nil {
114+
return errors.Wrap(err, "failed to get params")
115+
}
116+
112117
// if we are past the minimum height and the validator has missed too many blocks, punish them
113-
if height > minHeight && signInfo.MissedBlocksCounter > maxMissed {
118+
if height > int64(params.SingularityHeight) && height > minHeight && signInfo.MissedBlocksCounter > maxMissed {
114119
validator, err := k.sk.ValidatorByConsAddr(ctx, consAddr)
115120
if err != nil {
116121
return err
@@ -170,6 +175,11 @@ func (k Keeper) HandleValidatorSignature(ctx context.Context, addr cryptotypes.A
170175
"slashed", slashFractionDowntime.String(),
171176
"jailed_until", signInfo.JailedUntil,
172177
)
178+
} else if height == int64(params.SingularityHeight) {
179+
// reset the counter & bitmap so that the validator won't be
180+
// immediately slashed after singularity.
181+
signInfo.MissedBlocksCounter = 0
182+
signInfo.IndexOffset = 0
173183
} else {
174184
// validator was (a) not found or (b) already jailed so we do not slash
175185
logger.Info(

x/slashing/keeper/msg_server_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ func (s *KeeperTestSuite) TestUpdateParams() {
125125
DowntimeJailDuration: time.Duration(34800000000000),
126126
SlashFractionDoubleSign: slashFractionDoubleSign,
127127
SlashFractionDowntime: slashFractionDowntime,
128+
SingularityHeight: uint64(1),
128129
},
129130
},
130131
expectErr: false,

x/slashing/simulation/genesis.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const (
2020
DowntimeJailDuration = "downtime_jail_duration"
2121
SlashFractionDoubleSign = "slash_fraction_double_sign"
2222
SlashFractionDowntime = "slash_fraction_downtime"
23+
SingularityHeight = "singularity_height"
2324
)
2425

2526
// GenSignedBlocksWindow randomized SignedBlocksWindow
@@ -47,6 +48,10 @@ func GenSlashFractionDowntime(r *rand.Rand) math.LegacyDec {
4748
return math.LegacyNewDec(1).Quo(math.LegacyNewDec(int64(r.Intn(200) + 1)))
4849
}
4950

51+
func GenSingularityHeight(r *rand.Rand) uint64 {
52+
return uint64(simulation.RandIntBetween(r, 10, 1000))
53+
}
54+
5055
// RandomizedGenState generates a random GenesisState for slashing
5156
func RandomizedGenState(simState *module.SimulationState) {
5257
var signedBlocksWindow int64
@@ -64,9 +69,12 @@ func RandomizedGenState(simState *module.SimulationState) {
6469
var slashFractionDowntime math.LegacyDec
6570
simState.AppParams.GetOrGenerate(SlashFractionDowntime, &slashFractionDowntime, simState.Rand, func(r *rand.Rand) { slashFractionDowntime = GenSlashFractionDowntime(r) })
6671

72+
var singularityHeight uint64
73+
simState.AppParams.GetOrGenerate(SingularityHeight, &singularityHeight, simState.Rand, func(r *rand.Rand) { singularityHeight = GenSingularityHeight(r) })
74+
6775
params := types.NewParams(
6876
signedBlocksWindow, minSignedPerWindow, downtimeJailDuration,
69-
slashFractionDoubleSign, slashFractionDowntime,
77+
slashFractionDoubleSign, slashFractionDowntime, singularityHeight,
7078
)
7179

7280
slashingGenesis := types.NewGenesisState(params, []types.SigningInfo{}, []types.ValidatorMissedBlocks{})

x/slashing/types/genesis.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,10 @@ func ValidateGenesis(data GenesisState) error {
6262
return fmt.Errorf("signed blocks window must be at least 10, is %d", signedWindow)
6363
}
6464

65+
singularityHeight := data.Params.SingularityHeight
66+
if singularityHeight == 0 {
67+
return fmt.Errorf("singularity height must be positive, is %d", singularityHeight)
68+
}
69+
6570
return nil
6671
}

x/slashing/types/params.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
const (
1212
DefaultSignedBlocksWindow = int64(100)
1313
DefaultDowntimeJailDuration = 60 * 10 * time.Second
14+
DefaultSingularityHeight = 1209600 // 42 days with 3 seconds block time
1415
)
1516

1617
var (
@@ -22,14 +23,15 @@ var (
2223
// NewParams creates a new Params object
2324
func NewParams(
2425
signedBlocksWindow int64, minSignedPerWindow math.LegacyDec, downtimeJailDuration time.Duration,
25-
slashFractionDoubleSign, slashFractionDowntime math.LegacyDec,
26+
slashFractionDoubleSign, slashFractionDowntime math.LegacyDec, singularityHeight uint64,
2627
) Params {
2728
return Params{
2829
SignedBlocksWindow: signedBlocksWindow,
2930
MinSignedPerWindow: minSignedPerWindow,
3031
DowntimeJailDuration: downtimeJailDuration,
3132
SlashFractionDoubleSign: slashFractionDoubleSign,
3233
SlashFractionDowntime: slashFractionDowntime,
34+
SingularityHeight: singularityHeight,
3335
}
3436
}
3537

@@ -41,6 +43,7 @@ func DefaultParams() Params {
4143
DefaultDowntimeJailDuration,
4244
DefaultSlashFractionDoubleSign,
4345
DefaultSlashFractionDowntime,
46+
DefaultSingularityHeight,
4447
)
4548
}
4649

@@ -61,6 +64,9 @@ func (p Params) Validate() error {
6164
if err := validateSlashFractionDowntime(p.SlashFractionDowntime); err != nil {
6265
return err
6366
}
67+
if err := validateSingularityHeight(p.SingularityHeight); err != nil {
68+
return err
69+
}
6470
return nil
6571
}
6672

@@ -146,3 +152,16 @@ func validateSlashFractionDowntime(i interface{}) error {
146152

147153
return nil
148154
}
155+
156+
func validateSingularityHeight(i interface{}) error {
157+
v, ok := i.(uint64)
158+
if !ok {
159+
return fmt.Errorf("invalid parameter type: %T", i)
160+
}
161+
162+
if v == 0 {
163+
return fmt.Errorf("singularity height must be positive: %d", v)
164+
}
165+
166+
return nil
167+
}

0 commit comments

Comments
 (0)