Skip to content

Commit

Permalink
fix jailed fp get voting power in next delegation
Browse files Browse the repository at this point in the history
  • Loading branch information
gitferry committed Sep 12, 2024
1 parent 10f04f3 commit a1b253d
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 46 deletions.
3 changes: 3 additions & 0 deletions proto/babylon/btcstaking/v1/incentive.proto
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ message FinalityProviderDistInfo {
// is_timestamped indicates whether the finality provider
// has timestamped public randomness committed
bool is_timestamped = 6;
// is_jailed indicates whether the finality provider
// is jailed, if so, it should not be assigned voting power
bool is_jailed = 7;
}

// BTCDelDistInfo contains the information related to reward distribution for a BTC delegation
Expand Down
12 changes: 9 additions & 3 deletions x/btcstaking/keeper/power_dist_change.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,17 @@ func (k Keeper) recordVotingPowerAndCache(ctx context.Context, prevDc, newDc *ty

// label fps with whether it has timestamped pub rand so that these fps
// will not be assigned voting power
for _, fp := range newDc.FinalityProviders {
for _, fpDistInfo := range newDc.FinalityProviders {
// TODO calling HasTimestampedPubRand potentially iterates
// all the pub rand committed by the fp, which might slow down
// all the pub rand committed by the fpDistInfo, which might slow down
// the process, need optimization
fp.IsTimestamped = k.FinalityKeeper.HasTimestampedPubRand(ctx, fp.BtcPk, babylonTipHeight)
fpDistInfo.IsTimestamped = k.FinalityKeeper.HasTimestampedPubRand(ctx, fpDistInfo.BtcPk, babylonTipHeight)

fp, err := k.GetFinalityProvider(ctx, fpDistInfo.BtcPk.MustMarshal())
if err != nil {
panic(fmt.Errorf("the finality provider %s does not exist: %w", fp.BtcPk.MarshalHex(), err))
}
fpDistInfo.IsJailed = fp.IsJailed()
}

// apply the finality provider voting power dist info to the new cache
Expand Down
37 changes: 35 additions & 2 deletions x/btcstaking/keeper/power_dist_change_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,9 @@ func FuzzJailFinalityProviderEvents(f *testing.F) {
require.ErrorIs(t, err, types.ErrFpAlreadyJailed)

// ensure the jailed label is set
fpAfter, err := h.BTCStakingKeeper.GetFinalityProvider(h.Ctx, fp.BtcPk.MustMarshal())
fpAfterJailing, err := h.BTCStakingKeeper.GetFinalityProvider(h.Ctx, fp.BtcPk.MustMarshal())
h.NoError(err)
require.True(t, fpAfter.IsJailed())
require.True(t, fpAfterJailing.IsJailed())

// at this point, there should be only 1 event that the finality provider is jailed
btcTipHeight := btclcKeeper.GetTipInfo(h.Ctx).Height
Expand All @@ -239,6 +239,39 @@ func FuzzJailFinalityProviderEvents(f *testing.F) {
h.NoError(err)
// ensure the finality provider does not have voting power anymore
require.Zero(t, h.BTCStakingKeeper.GetVotingPower(h.Ctx, *fp.BtcPk, babylonHeight))

/*
insert another active BTC delegation and check whether the jailed
fp has voting power
*/
stakingValue = int64(2 * 10e8)
_, _, _, msgCreateBTCDel, actualDel = h.CreateDelegation(
r,
fpPK,
changeAddress.EncodeAddress(),
stakingValue,
1000,
)
// give it a quorum number of covenant signatures
msgs = h.GenerateCovenantSignaturesMessages(r, covenantSKs, msgCreateBTCDel, actualDel)
for i := 0; i < int(h.BTCStakingKeeper.GetParams(h.Ctx).CovenantQuorum); i++ {
_, err = h.MsgServer.AddCovenantSigs(h.Ctx, msgs[i])
h.NoError(err)
}

// execute BeginBlock
btcTip = btclcKeeper.GetTipInfo(h.Ctx)
babylonHeight += 1
h.SetCtxHeight(babylonHeight)
h.BTCLightClientKeeper.EXPECT().GetTipInfo(gomock.Eq(h.Ctx)).Return(btcTip).AnyTimes()
err = h.BTCStakingKeeper.BeginBlocker(h.Ctx)
h.NoError(err)
// ensure the finality provider is not jailed and has voting power at this height

fpAfterJailing, err = h.BTCStakingKeeper.GetFinalityProvider(h.Ctx, fp.BtcPk.MustMarshal())
h.NoError(err)
require.True(t, fpAfterJailing.IsJailed())
require.Equal(t, uint64(0), h.BTCStakingKeeper.GetVotingPower(h.Ctx, *fp.BtcPk, babylonHeight))
})
}

Expand Down
2 changes: 1 addition & 1 deletion x/btcstaking/keeper/voting_power_table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ func FuzzVotingPowerTable_ActiveFinalityProviders(f *testing.F) {

maxActiveFpsParam := h.BTCStakingKeeper.GetParams(h.Ctx).MaxActiveFinalityProviders
// get a map of expected active finality providers
types.SortFinalityProvidersWithTimestamping(fpsWithMeta)
types.SortFinalityProvidersWithTimestampingAndJailing(fpsWithMeta)
expectedActiveFps := fpsWithMeta[:min(uint32(len(fpsWithMeta)-len(noTimestampedFps)), maxActiveFpsParam)]
expectedActiveFpsMap := map[string]uint64{}
for _, fp := range expectedActiveFps {
Expand Down
10 changes: 8 additions & 2 deletions x/btcstaking/types/btcstaking.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,24 @@ func (fp *FinalityProvider) ValidateBasic() error {
return nil
}

// SortFinalityProvidersWithTimestamping sorts the finality providers slice,
// SortFinalityProvidersWithTimestampingAndJailing sorts the finality providers slice,
// from higher to lower voting power
// finality providers that are timestamped come higher than
// those are not
func SortFinalityProvidersWithTimestamping(fps []*FinalityProviderDistInfo) {
func SortFinalityProvidersWithTimestampingAndJailing(fps []*FinalityProviderDistInfo) {
sort.SliceStable(fps, func(i, j int) bool {
if fps[i].IsTimestamped && !fps[j].IsTimestamped {
return true
}
if !fps[i].IsTimestamped && fps[j].IsTimestamped {
return false
}
if !fps[i].IsJailed && fps[j].IsJailed {
return true
}
if fps[i].IsJailed && !fps[j].IsJailed {
return false
}
return fps[i].TotalVotingPower > fps[j].TotalVotingPower
})
}
Expand Down
5 changes: 4 additions & 1 deletion x/btcstaking/types/incentive.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (dc *VotingPowerDistCache) FindNewActiveFinalityProviders(prevDc *VotingPow
// and records them in cache
func (dc *VotingPowerDistCache) ApplyActiveFinalityProviders(maxActiveFPs uint32) {
// sort finality providers with timestamping considered
SortFinalityProvidersWithTimestamping(dc.FinalityProviders)
SortFinalityProvidersWithTimestampingAndJailing(dc.FinalityProviders)

numActiveFPs := uint32(0)

Expand All @@ -56,6 +56,9 @@ func (dc *VotingPowerDistCache) ApplyActiveFinalityProviders(maxActiveFPs uint32
if !fp.IsTimestamped {
break
}
if fp.IsJailed {
break
}
numActiveFPs++
}

Expand Down
118 changes: 81 additions & 37 deletions x/btcstaking/types/incentive.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit a1b253d

Please sign in to comment.