Skip to content

Commit

Permalink
Merge pull request #230 from Fairblock/fix/idle-validator-slashing-logic
Browse files Browse the repository at this point in the history
Fix idle validator slashing logic
  • Loading branch information
p0p3yee authored Oct 25, 2024
2 parents 7dfb39e + 35d19c0 commit 949c6c8
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 8 deletions.
1 change: 1 addition & 0 deletions x/keyshare/keeper/msg_override_pubkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func (k msgServer) OverrideLatestPubkey(
encSharesExistsValidators[encShare.Validator] = true
}

// Remove all validators in the set that not in the current epoch
for _, v := range allValidatorSet {
if _, exists := encSharesExistsValidators[v.Validator]; !exists {
k.RemoveValidatorSet(ctx, v.Validator)
Expand Down
4 changes: 3 additions & 1 deletion x/keyshare/keeper/msg_send_keyshare.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,9 @@ func (k msgServer) SendKeyshare(goCtx context.Context, msg *types.MsgSendKeyshar
// Save the new keyshare to state
k.SetKeyshare(ctx, keyshare)

k.SetLastSubmittedHeight(ctx, msg.Creator, strconv.FormatUint(msg.BlockHeight, 10))
// It should set the validator last submitted height instead of the `msg.creator`,
// which might be the authorized address
k.SetLastSubmittedHeight(ctx, validatorInfo.Validator, strconv.FormatUint(msg.BlockHeight, 10))

validatorList := k.GetAllValidatorSet(ctx)

Expand Down
7 changes: 4 additions & 3 deletions x/keyshare/keeper/msg_submit_encrypted_keyshare.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,19 @@ func (k msgServer) SubmitEncryptedKeyshare(goCtx context.Context, msg *types.Msg
ctx := sdk.UnwrapSDKContext(goCtx)

// check if validator is registered
_, found := k.GetValidatorSet(ctx, msg.Creator)
validatorInfo, found := k.GetValidatorSet(ctx, msg.Creator)

if !found {
authorizedAddrInfo, found := k.GetAuthorizedAddress(ctx, msg.Creator)
if !found || !authorizedAddrInfo.IsAuthorized {
return nil, types.ErrAddrIsNotValidatorOrAuthorized.Wrap(msg.Creator)
}

_, found = k.GetValidatorSet(ctx, authorizedAddrInfo.AuthorizedBy)
authorizedByValInfo, found := k.GetValidatorSet(ctx, authorizedAddrInfo.AuthorizedBy)
if !found {
return nil, types.ErrAuthorizerIsNotValidator.Wrap(authorizedAddrInfo.AuthorizedBy)
}
validatorInfo = authorizedByValInfo

// If the sender is in the validator set & authorized another address to submit key share
} else if count := k.GetAuthorizedCount(ctx, msg.Creator); count != 0 {
Expand Down Expand Up @@ -62,7 +63,7 @@ func (k msgServer) SubmitEncryptedKeyshare(goCtx context.Context, msg *types.Msg

// Save the new private keyshare to state
k.SetPrivateKeyshare(ctx, valEncKeyshare)
k.SetLastSubmittedHeight(ctx, msg.Creator, strconv.FormatInt(ctx.BlockHeight(), 10))
k.SetLastSubmittedHeight(ctx, validatorInfo.Validator, strconv.FormatInt(ctx.BlockHeight(), 10))

validatorList := k.GetAllValidatorSet(ctx)

Expand Down
2 changes: 1 addition & 1 deletion x/keyshare/keeper/msg_submit_general_keyshare.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func (k msgServer) SubmitGeneralKeyshare(

// Save the new general key share to state
k.SetGeneralKeyshare(ctx, generalKeyshare)
k.SetLastSubmittedHeight(ctx, msg.Creator, strconv.FormatInt(ctx.BlockHeight(), 10))
k.SetLastSubmittedHeight(ctx, validatorInfo.Validator, strconv.FormatInt(ctx.BlockHeight(), 10))

validatorList := k.GetAllValidatorSet(ctx)

Expand Down
31 changes: 28 additions & 3 deletions x/keyshare/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,15 @@ func (am AppModule) BeginBlock(cctx context.Context) error {
if foundQc {
am.keeper.SetActiveCommitments(ctx, qc)
}
// When switching the active public key,
// Reset all validators last submitted height,
// So they won't get slashed if they miss the first block of the new active pubkey keyshare.
for _, v := range qk.EncryptedKeyshares {
am.keeper.SetLastSubmittedHeight(ctx, v.Validator, strconv.FormatInt(ctx.BlockHeight(), 10))
}

// We don't need to remove the validators that not in the new round from the set
// They won't be slashed because of the new slashing idle validators logic
}
am.keeper.DeleteQueuedPubkey(ctx)
am.pepKeeper.DeleteQueuedPubkey(ctx)
Expand All @@ -256,6 +265,13 @@ func (am AppModule) EndBlock(cctx context.Context) error {
validators := am.keeper.GetAllValidatorSet(ctx)
params := am.keeper.GetParams(ctx)

pubKey, found := am.keeper.GetActivePubkey(ctx)
// If no active public key / no validator in the current public key
// Then no Idling check needed
if !found || len(pubKey.PublicKey) == 0 || len(pubKey.EncryptedKeyshares) == 0 {
return nil
}

for _, eachValidator := range validators {
lastSubmittedHeight := am.keeper.GetLastSubmittedHeight(ctx, eachValidator.Validator)
am.keeper.Logger().Info(fmt.Sprintf("Last submitted: %s: %d", eachValidator.Validator, lastSubmittedHeight))
Expand All @@ -279,10 +295,19 @@ func (am AppModule) EndBlock(cctx context.Context) error {
continue
}

if val, found := am.keeper.GetActivePubkey(ctx); !found || len(val.PublicKey) == 0 {
// Not slashing validator if there is no active public key
inCurrentEpoch := false

for _, k := range pubKey.EncryptedKeyshares {
if k.Validator == eachValidator.Validator {
inCurrentEpoch = true
break
}
}

if !inCurrentEpoch {
am.keeper.Logger().Info(fmt.Sprintf("Validator: %s not in the current epoch, updating last submitted height to current block height.", eachValidator.Validator))
am.keeper.SetLastSubmittedHeight(ctx, eachValidator.Validator, strconv.FormatInt(ctx.BlockHeight(), 10))
continue
return nil
}

am.keeper.SlashingKeeper().Slash(
Expand Down

0 comments on commit 949c6c8

Please sign in to comment.