Skip to content

Commit

Permalink
fixme: panic in distribute rewards of expired unbond tx
Browse files Browse the repository at this point in the history
  • Loading branch information
RafilxTenfen committed Feb 28, 2025
1 parent bc0d3a0 commit 1568c74
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 18 deletions.
2 changes: 2 additions & 0 deletions testutil/datagen/btcstaking.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ type CreateDelegationInfo struct {
MsgAddCovenantSigs []*bstypes.MsgAddCovenantSigs
StakingTxHash string
StakingTx *wire.MsgTx
UnbondingTx *wire.MsgTx
}

// GenRandomMsgCreateBtcDelegation generates a random MsgCreateBTCDelegation message
Expand Down Expand Up @@ -427,6 +428,7 @@ func GenRandomMsgCreateBtcDelegationAndMsgAddCovenantSignatures(
MsgAddCovenantSigs: msgs,
StakingTxHash: stkTxHash.String(),
StakingTx: stakingSlashingInfo.StakingTx,
UnbondingTx: unbondingSlashingInfo.UnbondingTx,
}
}

Expand Down
59 changes: 41 additions & 18 deletions x/finality/keeper/power_dist_change_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
testutil "github.com/babylonlabs-io/babylon/testutil/btcstaking-helper"
"github.com/babylonlabs-io/babylon/testutil/datagen"
bbn "github.com/babylonlabs-io/babylon/types"
btcckeeper "github.com/babylonlabs-io/babylon/x/btccheckpoint/keeper"
btcctypes "github.com/babylonlabs-io/babylon/x/btccheckpoint/types"
btclckeeper "github.com/babylonlabs-io/babylon/x/btclightclient/keeper"
btclightclientkeeper "github.com/babylonlabs-io/babylon/x/btclightclient/keeper"
Expand Down Expand Up @@ -50,21 +49,22 @@ func FuzzDistributionCache_BtcUndelegateSameBlockAsExpiration(f *testing.F) {
ctx = ctx.WithHeaderInfo(initHeader)

btcStkK, finalityK, checkPointK, btcCheckK, btcLightK := app.BTCStakingKeeper, app.FinalityKeeper, app.CheckpointingKeeper, app.BtcCheckpointKeeper, app.BTCLightClientKeeper
msgSrvrBtcStk, msgSrvrBtcCheck := btcstakingkeeper.NewMsgServerImpl(btcStkK), btcckeeper.NewMsgServerImpl(btcCheckK)
msgSrvrBtcStk := btcstakingkeeper.NewMsgServerImpl(btcStkK)
btcNet := app.BTCLightClientKeeper.GetBTCNet()
btcStkParams, btcCheckParams := btcStkK.GetParams(ctx), btcCheckK.GetParams(ctx)

covenantSKs, _, _ := bstypes.DefaultCovenantCommittee()
btcCheckParams.BtcConfirmationDepth = 2
btcCheckParams.CheckpointFinalizationTimeout = 5

_, err := msgSrvrBtcCheck.UpdateParams(ctx, &btcctypes.MsgUpdateParams{
Authority: appparams.AccGov.String(),
Params: btcCheckParams,
})
err := btcCheckK.SetParams(ctx, btcCheckParams)
require.NoError(t, err)

btcCheckParams = btcCheckK.GetParams(ctx)
btcStkParams.UnbondingTimeBlocks = btcCheckParams.BtcConfirmationDepth + btcCheckParams.CheckpointFinalizationTimeout
btcStkParams.BtcActivationHeight = 1
btcStkParams.MinStakingTimeBlocks = 25
btcStkParams.MaxStakingTimeBlocks = 26

_, err = msgSrvrBtcStk.UpdateParams(ctx, &btcstktypes.MsgUpdateParams{
Authority: appparams.AccGov.String(),
Expand All @@ -81,8 +81,9 @@ func FuzzDistributionCache_BtcUndelegateSameBlockAsExpiration(f *testing.F) {
_, err = msgSrvrBtcStk.CreateFinalityProvider(ctx, fpMsg)
require.NoError(t, err)

AddNBtcBlock(t, r, app, ctx, 1)
// creates one BTC block
ctx = ProduceBlock(t, r, app, ctx)
AddNBtcBlock(t, r, app, ctx, 1)

fpBtcPk := []bbn.BIP340PubKey{*fpMsg.BtcPk}
delBtcSK, _, err := datagen.GenRandomBTCKeyPair(r)
Expand Down Expand Up @@ -117,6 +118,7 @@ func FuzzDistributionCache_BtcUndelegateSameBlockAsExpiration(f *testing.F) {

checkPointK.SetLastFinalizedEpoch(ctx, 1)

ctx = ProduceBlock(t, r, app, ctx)
block, stakingTransactions := AddBtcBlockWithDelegations(t, r, app, ctx, delCreationInfo)
ctx = ProduceBlock(t, r, app, ctx)

Expand All @@ -133,7 +135,9 @@ func FuzzDistributionCache_BtcUndelegateSameBlockAsExpiration(f *testing.F) {
})

// produce btc block to update tip height
ctx = ProduceBlock(t, r, app, ctx)
AddNBtcBlock(t, r, app, ctx, 1)

ctx = ProduceBlock(t, r, app, ctx)

// all the fps are in the vp dst cache
Expand All @@ -143,24 +147,39 @@ func FuzzDistributionCache_BtcUndelegateSameBlockAsExpiration(f *testing.F) {
activeFps := vpDstCache.GetActiveFinalityProviderSet()
require.Equal(t, len(activeFps), 1)

parsedInclusionProof, err := bstypes.NewParsedProofOfInclusion(inclusionProof)
btcDel, err := btcStkK.GetBTCDelegation(ctx, delCreationInfo.StakingTxHash)
require.NoError(t, err)
tip := btcLightK.GetTipInfo(ctx)
btcBlocksUntilBtcDelExpire := btcDel.EndHeight - (tip.Height + btcStkParams.UnbondingTimeBlocks)

stakingTxHeader, err := btcLightK.GetHeaderByHash(ctx, parsedInclusionProof.HeaderHash)
require.NoError(t, err)
endHeight := stakingTxHeader.Height + delCreationInfo.MsgCreateBTCDelegation.StakingTime
btcBlocksUntilBtcDelExpire := endHeight - btcStkParams.UnbondingTimeBlocks
ctx = ProduceBlock(t, r, app, ctx)
AddNBtcBlock(t, r, app, ctx, uint(btcBlocksUntilBtcDelExpire-1)) // it will miss one block to reach expired
ctx = ProduceBlock(t, r, app, ctx) // updates tip header

// reaches expired btc block
AddNBtcBlock(t, r, app, ctx, uint(btcBlocksUntilBtcDelExpire))
block = AddBtcBlockWithTxs(t, r, app, ctx, delCreationInfo.UnbondingTx)
inclusionProof = bstypes.NewInclusionProofFromSpvProof(block.Proofs[1])

_, err = app.BeginBlocker(ctx)
_, err = app.BeginBlocker(ctx) // process voting power dis change events, setting to expired
require.NoError(t, err)

// sends unbond del
msgUndelegate := &bstypes.MsgBTCUndelegate{
Signer: datagen.GenRandomAccount().Address,
StakingTxHash: delCreationInfo.StakingTxHash,
StakeSpendingTx: delCreationInfo.MsgCreateBTCDelegation.UnbondingTx,
StakeSpendingTxInclusionProof: inclusionProof,
}
_, err = msgSrvrBtcStk.BTCUndelegate(ctx, msgUndelegate) // fails to unbond, since the BTC was expired
require.EqualError(t, err, bstypes.ErrInvalidBTCUndelegateReq.Wrap("cannot unbond an unbonded BTC delegation").Error(), "should error out")

// produce block
_, err = app.EndBlocker(ctx)
require.NoError(t, err)

// produces one more block to process the unbonding and it should not halt the chain
require.NotPanics(t, func() {
ProduceBlock(t, r, app, ctx)
})
})
}

Expand Down Expand Up @@ -1275,20 +1294,24 @@ func TestDoNotGenerateDuplicateEventsAfterHavingCovenantQuorum(t *testing.T) {
}

func AddBtcBlockWithDelegations(t *testing.T, r *rand.Rand, app *babylonApp.BabylonApp, ctx sdk.Context, delInfos ...*datagen.CreateDelegationInfo) (*datagen.BlockWithProofs, []*wire.MsgTx) {
stkTxs := replay.DelegationInfosToBTCTx(delInfos)
return AddBtcBlockWithTxs(t, r, app, ctx, stkTxs...), stkTxs
}

func AddBtcBlockWithTxs(t *testing.T, r *rand.Rand, app *babylonApp.BabylonApp, ctx sdk.Context, txs ...*wire.MsgTx) *datagen.BlockWithProofs {
btcLightK := app.BTCLightClientKeeper
msgSrvrBtcLight := btclightclientkeeper.NewMsgServerImpl(btcLightK)

stkTxs := replay.DelegationInfosToBTCTx(delInfos)
tip := btcLightK.GetTipInfo(ctx)
block := datagen.GenRandomBtcdBlockWithTransactions(r, stkTxs, tip.Header.ToBlockHeader())
block := datagen.GenRandomBtcdBlockWithTransactions(r, txs, tip.Header.ToBlockHeader())
headers := replay.BlocksWithProofsToHeaderBytes([]*datagen.BlockWithProofs{block})
_, err := msgSrvrBtcLight.InsertHeaders(ctx, &btclctypes.MsgInsertHeaders{
Signer: datagen.GenRandomAccount().Address,
Headers: headers,
})
require.NoError(t, err)

return block, stkTxs
return block
}

func MaybeProduceBlock(t *testing.T, r *rand.Rand, app *babylonApp.BabylonApp, ctx sdk.Context) sdk.Context {
Expand Down

0 comments on commit 1568c74

Please sign in to comment.