Skip to content

Commit

Permalink
fix: slashed fp inclusion proof (#579)
Browse files Browse the repository at this point in the history
- Add a new check if the FP was slashed in
`ProcessAllPowerDistUpdateEvents`
- Func `NewFinalityProviderDistInfo` was also modified to load the
properties `IsJailed` and `IsSlashed` from the FP that was in DB (only
this check was already enough to fix the issue), but to keep consistency
with slashed event processing in the `ProcessAllPowerDistUpdateEvents`
the slashed finality provider should not even be included in the `newDc`

This check was to avoid activating a slashed FP

The slashed FP could be activated if a BTC delegation without inclusion
proof was created before the FP was slashed and having the inclusion
proof sent after the slashing
  • Loading branch information
RafilxTenfen committed Feb 28, 2025
1 parent cbcefdc commit 2df260c
Show file tree
Hide file tree
Showing 8 changed files with 379 additions and 81 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ block bank send and still create BTC delegations

- [#539](https://github.com/babylonlabs-io/babylon/pull/539) fix: add missing `x/checkpointing` hooks
invocation
- [#579](https://github.com/babylonlabs-io/babylon/pull/579) Slashed FP gets activated in voting power distribution
cache if an old BTC delegation receives inclusion proof
- [#592](https://github.com/babylonlabs-io/babylon/pull/592) finality: avoid refunding finality signatures over forks
- [#525](https://github.com/babylonlabs-io/babylon/pull/525) fix: add back `NewIBCHeaderDecorator` post handler
- [#563](https://github.com/babylonlabs-io/babylon/pull/563) reject coinbase staking transactions
Expand Down
6 changes: 3 additions & 3 deletions test/replay/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ func (d *BabylonAppDriver) GetBTCLCTip() (*wire.BlockHeader, uint32) {
return tipInfo.Header.ToBlockHeader(), tipInfo.Height
}

func blocksWithProofsToHeaderBytes(blocks []*datagen.BlockWithProofs) []bbn.BTCHeaderBytes {
func BlocksWithProofsToHeaderBytes(blocks []*datagen.BlockWithProofs) []bbn.BTCHeaderBytes {
headerBytes := []bbn.BTCHeaderBytes{}
for _, block := range blocks {
headerBytes = append(headerBytes, bbn.NewBTCHeaderBytesFromBlockHeader(&block.Block.Header))
Expand All @@ -565,7 +565,7 @@ func (d *BabylonAppDriver) ExtendBTCLcWithNEmptyBlocks(
) (*wire.BlockHeader, uint32) {
tip, _ := d.GetBTCLCTip()
blocks := datagen.GenNEmptyBlocks(r, uint64(n), tip)
headers := blocksWithProofsToHeaderBytes(blocks)
headers := BlocksWithProofsToHeaderBytes(blocks)

d.SendTxWithMsgsFromDriverAccount(t, &btclighttypes.MsgInsertHeaders{
Signer: d.GetDriverAccountAddress().String(),
Expand All @@ -583,7 +583,7 @@ func (d *BabylonAppDriver) GenBlockWithTransactions(
) *datagen.BlockWithProofs {
tip, _ := d.GetBTCLCTip()
block := datagen.GenRandomBtcdBlockWithTransactions(r, txs, tip)
headers := blocksWithProofsToHeaderBytes([]*datagen.BlockWithProofs{block})
headers := BlocksWithProofsToHeaderBytes([]*datagen.BlockWithProofs{block})

d.SendTxWithMsgsFromDriverAccount(t, &btclighttypes.MsgInsertHeaders{
Signer: d.GetDriverAccountAddress().String(),
Expand Down
9 changes: 9 additions & 0 deletions testutil/datagen/btcstaking.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ func GenRandomFinalityProvider(r *rand.Rand) (*bstypes.FinalityProvider, error)
return GenRandomFinalityProviderWithBTCSK(r, btcSK)
}

func GenRandomMsgCreateFinalityProvider(r *rand.Rand) (*bstypes.MsgCreateFinalityProvider, error) {
// BTC key pairs
btcSK, _, err := GenRandomBTCKeyPair(r)
if err != nil {
return nil, err
}
return GenRandomCreateFinalityProviderMsgWithBTCBabylonSKs(r, btcSK, GenRandomAccount().GetAddress())
}

func CreateNFinalityProviders(r *rand.Rand, t *testing.T, n int) []*bstypes.FinalityProvider {
fps := make([]*bstypes.FinalityProvider, n)
for i := 0; i < n; i++ {
Expand Down
2 changes: 1 addition & 1 deletion x/btcstaking/keeper/btc_reorg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ func TestSetLargestBtcReorg(t *testing.T) {
require.NoError(t, err)

actLargestBtcReorg := k.GetLargestBtcReorg(ctx)
require.Equal(t, tc.expectedLargestBtcReorg, actLargestBtcReorg)
require.EqualValues(t, tc.expectedLargestBtcReorg, actLargestBtcReorg)
})
}
}
27 changes: 20 additions & 7 deletions x/finality/keeper/power_dist_change.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ func (k Keeper) ProcessAllPowerDistUpdateEvents(
) *ftypes.VotingPowerDistCache {
// a map where key is finality provider's BTC PK hex and value is a list
// of BTC delegations satoshis amount that newly become active under this provider
activedSatsByFpBtcPk := map[string][]uint64{}
activatedSatsByFpBtcPk := map[string][]uint64{}
// a map where key is finality provider's BTC PK hex and value is a list
// of BTC delegations satoshis that were unbonded or expired without previously
// being unbonded
Expand Down Expand Up @@ -210,9 +210,11 @@ func (k Keeper) ProcessAllPowerDistUpdateEvents(
// add the BTC delegation to each restaked finality provider
for _, fpBTCPK := range btcDel.FpBtcPkList {
fpBTCPKHex := fpBTCPK.MarshalHex()
activedSatsByFpBtcPk[fpBTCPKHex] = append(activedSatsByFpBtcPk[fpBTCPKHex], btcDel.TotalSat)
activatedSatsByFpBtcPk[fpBTCPKHex] = append(activatedSatsByFpBtcPk[fpBTCPKHex], btcDel.TotalSat)
}

// FP could be already slashed when it is being activated, but it is okay
// since slashed finality providers do not earn rewards
k.processRewardTracker(ctx, fpByBtcPkHex, btcDel, func(fp, del sdk.AccAddress, sats uint64) {
k.MustProcessBtcDelegationActivated(ctx, fp, del, sats)
})
Expand Down Expand Up @@ -287,15 +289,15 @@ func (k Keeper) ProcessAllPowerDistUpdateEvents(
}

// process all new BTC delegations under this finality provider
if fpActiveSats, ok := activedSatsByFpBtcPk[fpBTCPKHex]; ok {
if fpActiveSats, ok := activatedSatsByFpBtcPk[fpBTCPKHex]; ok {
// handle new BTC delegations for this finality provider
for _, activatedSats := range fpActiveSats {
fp.AddBondedSats(activatedSats)
}
// remove the finality provider entry in fpActiveSats map, so that
// after the for loop the rest entries in fpActiveSats belongs to new
// finality providers with new BTC delegations
delete(activedSatsByFpBtcPk, fpBTCPKHex)
delete(activatedSatsByFpBtcPk, fpBTCPKHex)
}

// process all new unbonding BTC delegations under this finality provider
Expand All @@ -321,8 +323,8 @@ func (k Keeper) ProcessAllPowerDistUpdateEvents(
process new BTC delegations under new finality providers in activeBTCDels
*/
// sort new finality providers in activeBTCDels to ensure determinism
fpActiveBtcPkHexList := make([]string, 0, len(activedSatsByFpBtcPk))
for fpBTCPKHex := range activedSatsByFpBtcPk {
fpActiveBtcPkHexList := make([]string, 0, len(activatedSatsByFpBtcPk))
for fpBTCPKHex := range activatedSatsByFpBtcPk {
// if the fp was slashed, should not even be added to the list
_, isSlashed := slashedFPs[fpBTCPKHex]
if isSlashed {
Expand All @@ -338,6 +340,17 @@ func (k Keeper) ProcessAllPowerDistUpdateEvents(
for _, fpBTCPKHex := range fpActiveBtcPkHexList {
// get the finality provider and initialise its dist info
newFP := k.loadFP(ctx, fpByBtcPkHex, fpBTCPKHex)
if newFP == nil {
// This is a consumer FP rather than Babylon FP, skip it
continue
}
// if the fp is slashed it shouldn't be included in the newDc
if newFP.IsSlashed() {
// case if a BTC delegation is created without inclusion proof
// the finality provider gets slashed
// inclusion proof gets included and generates an EventPowerDistUpdate_BtcDelStateUpdate
continue
}
fpDistInfo := ftypes.NewFinalityProviderDistInfo(newFP)

// check for jailing cases
Expand All @@ -349,7 +362,7 @@ func (k Keeper) ProcessAllPowerDistUpdateEvents(
}

// add each BTC delegation
fpActiveSats := activedSatsByFpBtcPk[fpBTCPKHex]
fpActiveSats := activatedSatsByFpBtcPk[fpBTCPKHex]
for _, activatedSats := range fpActiveSats {
fpDistInfo.AddBondedSats(activatedSats)
}
Expand Down
Loading

0 comments on commit 2df260c

Please sign in to comment.