Slow Misty Iguana
Medium
The voting power table of the historical block is not updated, and the voting power of jailed fp will be counted in the totalPower
.
The voting power table of the historical block is not updated
It may result in votes that cannot pass and blocks cannot enter Finalize state.
HandleLiveness
is used to add sluggish fp to the jail and send event updates voting power table:
x/finality/abci.go/EndBlocker -> HandleLiveness -> HandleFinalityProviderLiveness
func (k Keeper) HandleFinalityProviderLiveness(ctx context.Context, fpPk *types.BIP340PubKey, missed bool, height int64) error {
......
// if the number of missed block reaches the threshold within the sliding window
// jail the finality provider
if height > minHeight && signInfo.MissedBlocksCounter > maxMissed {
updated = true
-> if err := k.jailSluggishFinalityProvider(ctx, fpPk); err != nil {
return fmt.Errorf("failed to jail sluggish finality provider %s: %w", fpPk.MarshalHex(), err)
}
-> signInfo.JailedUntil = sdkCtx.HeaderInfo().Time.Add(params.JailDuration)
// we need to reset the counter & bitmap so that the finality provider won't be
// immediately jailed after unjailing.
signInfo.MissedBlocksCounter = 0
if err := k.DeleteMissedBlockBitmap(ctx, fpPk); err != nil {
return fmt.Errorf("failed to remove the missed block bit map: %w", err)
}
k.Logger(sdkCtx).Info(
"finality provider is jailed",
"height", height,
"public_key", fpPk.MarshalHex(),
)
}
// Set the updated signing info
if updated {
-> return k.FinalityProviderSigningTracker.Set(ctx, fpPk.MustMarshal(), *signInfo)
}
return nil
}
But the problem is that the jailed event is sent based on the btcHight height corresponding to the current block, so only the voting power table(VotingPowerDistCache) of the current block is updated after the jailed event:
func (k Keeper) JailFinalityProvider(ctx context.Context, fpBTCPK []byte) error {
// ensure finality provider exists
fp, err := k.GetFinalityProvider(ctx, fpBTCPK)
if err != nil {
return err
}
// ensure finality provider is not slashed yet
if fp.IsSlashed() {
return types.ErrFpAlreadySlashed
}
// ensure finality provider is not jailed yet
if fp.IsJailed() {
return types.ErrFpAlreadyJailed
}
// set finality provider to be jailed
fp.Jailed = true
k.setFinalityProvider(ctx, fp)
btcTip := k.btclcKeeper.GetTipInfo(ctx)
if btcTip == nil {
return fmt.Errorf("failed to get current BTC tip")
}
// record jailed event. The next `BeginBlock` will consume this
// event for updating the finality provider set
powerUpdateEvent := types.NewEventPowerDistUpdateWithJailedFP(fp.BtcPk)
-> k.addPowerDistUpdateEvent(ctx, btcTip.Height, powerUpdateEvent)
return nil
}
After being jailed, fp cannot vote, not only for the current block, but also for the historical block:
// AddFinalitySig adds a new vote to a given block
func (ms msgServer) AddFinalitySig(goCtx context.Context, req *types.MsgAddFinalitySig) (*types.MsgAddFinalitySigResponse, error) {
......
-> if fp.IsJailed() {
return nil, bstypes.ErrFpAlreadyJailed.Wrapf("finality provider public key: %s", fpPK.MarshalHex())
}
......
However, the problem is that the voting power of jailed fp is still retained in the voting power table of the historical block, which may cause that the voting cannot reach the quorum of 2/3. In particular, some fp with more voting power have been jailed or a lot of fp have been jailed.
Assume that block 1, 2, and 3 are all in UNFinalize state, and fp is required to vote:
The current block height is that fp0 is jailed in block 4, the jailed event is sent and processed, and the voting power table of block 4 is updated with a new value and no longer contains the voting power of fp0.
But the voting power table in blocks 1, 2, 3 is still the old value,
At this time, fp0 can no longer vote, but the value of fp0 is protected when calculating totalPower
.
UpdatePowerDist
updates only the events between currentHeight-1 and the btcHeight associated before currentHeight, and does not process the events in the old block:
The totalPower
in the historical block needs to be subtracted from the voting power of jailed fp.