diff --git a/CHANGELOG.md b/CHANGELOG.md index 7458ff7c5..6ab0b6188 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,17 +39,34 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Improvements +- [#316](https://github.com/babylonlabs-io/babylon/pull/316) Add testnet upgrade data + +### Bug fixes + +- [#324](https://github.com/babylonlabs-io/babylon/pull/324) Fix decrementing +jailed fp counter + +## v0.18.0 + +### Improvements + - [#309](https://github.com/babylonlabs-io/babylon/pull/309) feat(adr-036): custom withdrawal address - [#305](https://github.com/babylonlabs-io/babylon/pull/305) chore: add more error logs to `VerifyInclusionProofAndGetHeight` - [#304](https://github.com/babylonlabs-io/babylon/pull/304) Add highest voted height to finality provider - [#314](https://github.com/babylonlabs-io/babylon/pull/314) Require exact unbonding time in delegation -- [#316](https://github.com/babylonlabs-io/babylon/pull/316) Add testnet upgrade data +- [#317](https://github.com/babylonlabs-io/babylon/pull/317) Enforce that EOI +delegations using correct parameters version ### State Machine Breaking - [#310](https://github.com/babylonlabs-io/babylon/pull/310) implement adr-37 - making params valid for btc light client ranges +### Bug fixes + +- [#318](https://github.com/babylonlabs-io/babylon/pull/318) Fix BTC delegation status check +to relay on UnbondingTime in delegation + ## v0.17.2 ### Improvements diff --git a/testutil/btcstaking-helper/keeper.go b/testutil/btcstaking-helper/keeper.go index 8c86a5616..5c39fc655 100644 --- a/testutil/btcstaking-helper/keeper.go +++ b/testutil/btcstaking-helper/keeper.go @@ -241,7 +241,6 @@ func (h *Helper) CreateDelegationWithBtcBlockHeight( ) (string, *types.MsgCreateBTCDelegation, *types.BTCDelegation, *btclctypes.BTCHeaderInfo, *types.InclusionProof, *UnbondingTxInfo, error) { stakingTimeBlocks := stakingTime bsParams := h.BTCStakingKeeper.GetParams(h.Ctx) - bcParams := h.BTCCheckpointKeeper.GetParams(h.Ctx) covPKs, err := bbn.NewBTCPKsFromBIP340PKs(bsParams.CovenantPks) h.NoError(err) @@ -384,7 +383,7 @@ func (h *Helper) CreateDelegationWithBtcBlockHeight( h.NoError(err) // ensure the delegation is still pending - require.Equal(h.t, btcDel.GetStatus(btcTipHeight, bcParams.CheckpointFinalizationTimeout, bsParams.CovenantQuorum), types.BTCDelegationStatus_PENDING) + require.Equal(h.t, btcDel.GetStatus(btcTipHeight, bsParams.CovenantQuorum), types.BTCDelegationStatus_PENDING) if usePreApproval { // the BTC delegation does not have inclusion proof @@ -481,7 +480,6 @@ func (h *Helper) CreateCovenantSigs( msgCreateBTCDel *types.MsgCreateBTCDelegation, del *types.BTCDelegation, ) { - bcParams := h.BTCCheckpointKeeper.GetParams(h.Ctx) bsParams := h.BTCStakingKeeper.GetParams(h.Ctx) stakingTx, err := bbn.NewBTCTxFromBytes(del.StakingTx) @@ -510,7 +508,7 @@ func (h *Helper) CreateCovenantSigs( require.Len(h.t, actualDelWithCovenantSigs.BtcUndelegation.CovenantSlashingSigs[0].AdaptorSigs, 1) // ensure the BTC delegation is verified (if using pre-approval flow) or active - status := actualDelWithCovenantSigs.GetStatus(btcTipHeight, bcParams.CheckpointFinalizationTimeout, bsParams.CovenantQuorum) + status := actualDelWithCovenantSigs.GetStatus(btcTipHeight, bsParams.CovenantQuorum) if msgCreateBTCDel.StakingTxInclusionProof != nil { // not pre-approval flow, the BTC delegation should be active require.Equal(h.t, status, types.BTCDelegationStatus_ACTIVE) @@ -525,13 +523,12 @@ func (h *Helper) AddInclusionProof( btcHeader *btclctypes.BTCHeaderInfo, proof *types.InclusionProof, ) { - bcParams := h.BTCCheckpointKeeper.GetParams(h.Ctx) bsParams := h.BTCStakingKeeper.GetParams(h.Ctx) // Get the BTC delegation and ensure it's verified del, err := h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) h.NoError(err) - status := del.GetStatus(btcTipHeight, bcParams.CheckpointFinalizationTimeout, bsParams.CovenantQuorum) + status := del.GetStatus(btcTipHeight, bsParams.CovenantQuorum) require.Equal(h.t, status, types.BTCDelegationStatus_VERIFIED, "the BTC delegation shall be verified") // Create the MsgAddBTCDelegationInclusionProof message @@ -551,7 +548,7 @@ func (h *Helper) AddInclusionProof( // has been activated updatedDel, err := h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) h.NoError(err) - status = updatedDel.GetStatus(btcTipHeight, bcParams.CheckpointFinalizationTimeout, bsParams.CovenantQuorum) + status = updatedDel.GetStatus(btcTipHeight, bsParams.CovenantQuorum) require.Equal(h.t, status, types.BTCDelegationStatus_ACTIVE, "the BTC delegation shall be active") } diff --git a/x/btcstaking/keeper/grpc_query.go b/x/btcstaking/keeper/grpc_query.go index 1f3f45f3d..414bfc259 100644 --- a/x/btcstaking/keeper/grpc_query.go +++ b/x/btcstaking/keeper/grpc_query.go @@ -87,8 +87,6 @@ func (k Keeper) BTCDelegations(ctx context.Context, req *types.QueryBTCDelegatio // get current BTC height btcTipHeight := k.btclcKeeper.GetTipInfo(ctx).Height - // get value of w - wValue := k.btccKeeper.GetParams(ctx).CheckpointFinalizationTimeout store := k.btcDelegationStore(ctx) var btcDels []*types.BTCDelegationResponse @@ -97,7 +95,7 @@ func (k Keeper) BTCDelegations(ctx context.Context, req *types.QueryBTCDelegatio k.cdc.MustUnmarshal(value, &btcDel) // hit if the queried status is ANY or matches the BTC delegation status - status := btcDel.GetStatus(btcTipHeight, wValue, covenantQuorum) + status := btcDel.GetStatus(btcTipHeight, covenantQuorum) if req.Status == types.BTCDelegationStatus_ANY || status == req.Status { if accumulate { resp := types.NewBTCDelegationResponse(&btcDel, status) @@ -137,7 +135,6 @@ func (k Keeper) FinalityProviderDelegations(ctx context.Context, req *types.Quer sdkCtx := sdk.UnwrapSDKContext(ctx) btcDelStore := k.btcDelegatorFpStore(sdkCtx, fpPK) - currentWValue := k.btccKeeper.GetParams(ctx).CheckpointFinalizationTimeout btcHeight := k.btclcKeeper.GetTipInfo(ctx).Height covenantQuorum := k.GetParams(ctx).CovenantQuorum @@ -154,7 +151,6 @@ func (k Keeper) FinalityProviderDelegations(ctx context.Context, req *types.Quer for i, btcDel := range curBTCDels.Dels { status := btcDel.GetStatus( btcHeight, - currentWValue, covenantQuorum, ) btcDelsResp[i] = types.NewBTCDelegationResponse(btcDel, status) @@ -190,10 +186,8 @@ func (k Keeper) BTCDelegation(ctx context.Context, req *types.QueryBTCDelegation return nil, types.ErrBTCDelegationNotFound } - currentWValue := k.btccKeeper.GetParams(ctx).CheckpointFinalizationTimeout status := btcDel.GetStatus( k.btclcKeeper.GetTipInfo(ctx).Height, - currentWValue, k.GetParams(ctx).CovenantQuorum, ) diff --git a/x/btcstaking/keeper/msg_server.go b/x/btcstaking/keeper/msg_server.go index e2ffa041e..1f5de40f4 100644 --- a/x/btcstaking/keeper/msg_server.go +++ b/x/btcstaking/keeper/msg_server.go @@ -345,12 +345,28 @@ func (ms msgServer) AddBTCDelegationInclusionProof( return nil, fmt.Errorf("invalid inclusion proof: %w", err) } - // 6. set start height and end height and save it to db + // 6. Check if parameters used the validate /create the delegation are the same + // as the one in the BTC light client + _, version, err := ms.GetParamsForBtcHeight(ctx, uint64(timeInfo.StartHeight)) + if err != nil { + return nil, err + } + + if btcDel.ParamsVersion != version { + return nil, types.ErrParamsVersionMismatch.Wrapf( + "params version in BTC delegation: %d, params version at height %d: %d", + btcDel.ParamsVersion, + timeInfo.StartHeight, + version, + ) + } + + // 7. set start height and end height and save it to db btcDel.StartHeight = timeInfo.StartHeight btcDel.EndHeight = timeInfo.EndHeight ms.setBTCDelegation(ctx, btcDel) - // 7. emit events + // 8. emit events stakingTxHash := btcDel.MustGetStakingTxHash() newInclusionProofEvent := types.NewInclusionProofEvent( @@ -436,8 +452,7 @@ func (ms msgServer) AddCovenantSigs(goCtx context.Context, req *types.MsgAddCove // ensure BTC delegation is still pending, i.e., not unbonded btcTipHeight := ms.btclcKeeper.GetTipInfo(ctx).Height - wValue := ms.btccKeeper.GetParams(ctx).CheckpointFinalizationTimeout - status := btcDel.GetStatus(btcTipHeight, wValue, params.CovenantQuorum) + status := btcDel.GetStatus(btcTipHeight, params.CovenantQuorum) if status == types.BTCDelegationStatus_UNBONDED { ms.Logger(ctx).Debug("Received covenant signature after the BTC delegation is already unbonded", "covenant pk", req.Pk.MarshalHex()) return nil, types.ErrInvalidCovenantSig.Wrap("the BTC delegation is already unbonded") @@ -583,9 +598,11 @@ func (ms msgServer) BTCUndelegate(goCtx context.Context, req *types.MsgBTCUndele // ensure the BTC delegation with the given staking tx hash is active btcTip := ms.btclcKeeper.GetTipInfo(ctx) - wValue := ms.btccKeeper.GetParams(ctx).CheckpointFinalizationTimeout - btcDelStatus := btcDel.GetStatus(btcTip.Height, wValue, bsParams.CovenantQuorum) + btcDelStatus := btcDel.GetStatus( + btcTip.Height, + bsParams.CovenantQuorum, + ) if btcDelStatus == types.BTCDelegationStatus_UNBONDED { return nil, types.ErrInvalidBTCUndelegateReq.Wrap("cannot unbond an unbonded BTC delegation") @@ -690,9 +707,8 @@ func (ms msgServer) SelectiveSlashingEvidence(goCtx context.Context, req *types. // ensure the BTC delegation is active, or its BTC undelegation receives an // unbonding signature from the staker btcTip := ms.btclcKeeper.GetTipInfo(ctx) - wValue := ms.btccKeeper.GetParams(ctx).CheckpointFinalizationTimeout covQuorum := bsParams.CovenantQuorum - if btcDel.GetStatus(btcTip.Height, wValue, covQuorum) != types.BTCDelegationStatus_ACTIVE && !btcDel.IsUnbondedEarly() { + if btcDel.GetStatus(btcTip.Height, covQuorum) != types.BTCDelegationStatus_ACTIVE && !btcDel.IsUnbondedEarly() { return nil, types.ErrBTCDelegationNotFound.Wrap("a BTC delegation that is not active or unbonding early cannot be slashed") } diff --git a/x/btcstaking/keeper/msg_server_test.go b/x/btcstaking/keeper/msg_server_test.go index 29cbebf89..1e53260f7 100644 --- a/x/btcstaking/keeper/msg_server_test.go +++ b/x/btcstaking/keeper/msg_server_test.go @@ -387,6 +387,92 @@ func TestProperVersionInDelegation(t *testing.T) { require.Equal(t, uint32(2), actualDel1.ParamsVersion) } +func TestRejectActivationOfTheDelegationCreatedWithOldParams(t *testing.T) { + r := rand.New(rand.NewSource(time.Now().Unix())) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + // mock BTC light client and BTC checkpoint modules + btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) + btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) + h := testutil.NewHelper(t, btclcKeeper, btccKeeper) + + // set all parameters + covenantSKs, _ := h.GenAndApplyParams(r) + + changeAddress, err := datagen.GenRandomBTCAddress(r, h.Net) + require.NoError(t, err) + + // generate and insert new finality provider + _, fpPK, _ := h.CreateFinalityProvider(r) + + // create fresh version of params + currentParams := h.BTCStakingKeeper.GetParams(h.Ctx) + // params will be activate at block height 2 + currentParams.BtcActivationHeight = currentParams.BtcActivationHeight + 1 + // Update new params + err = h.BTCStakingKeeper.SetParams(h.Ctx, currentParams) + require.NoError(t, err) + + // generate and insert new BTC delegation + stakingValue := int64(2 * 10e8) + delSK, _, err := datagen.GenRandomBTCKeyPair(r) + h.NoError(err) + stakingTxHash, msgCreateBTCDel, _, headerInfo, inclusionProof, _, err := h.CreateDelegationWithBtcBlockHeight( + r, + delSK, + fpPK, + changeAddress.EncodeAddress(), + stakingValue, + 1000, + 0, + 0, + // use the pre-approval flow + true, + false, + // staking tx will be included in BTC block height 1, which is before the activation of the new params + 1, + ) + h.NoError(err) + require.NotNil(t, headerInfo) + require.NotNil(t, inclusionProof) + + // ensure consistency between the msg and the BTC delegation in DB + actualDel, err := h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) + h.NoError(err) + require.NotNil(t, actualDel) + + msgs := h.GenerateCovenantSignaturesMessages(r, covenantSKs, msgCreateBTCDel, actualDel) + for _, msg := range msgs { + _, err = h.MsgServer.AddCovenantSigs(h.Ctx, msg) + h.NoError(err) + } + + // get updated delegation + actualDel, err = h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) + h.NoError(err) + require.NotNil(t, actualDel) + + tipHeight := h.BTCLightClientKeeper.GetTipInfo(h.Ctx).Height + covenantQuorum := h.BTCStakingKeeper.GetParams(h.Ctx).CovenantQuorum + + status := actualDel.GetStatus(tipHeight, covenantQuorum) + require.Equal(t, types.BTCDelegationStatus_VERIFIED, status) + + msg := &types.MsgAddBTCDelegationInclusionProof{ + StakingTxHash: stakingTxHash, + StakingTxInclusionProof: inclusionProof, + } + + // mock BTC header that includes the staking tx + h.BTCLightClientKeeper.EXPECT().GetHeaderByHash(gomock.Eq(h.Ctx), gomock.Eq(headerInfo.Header.Hash())).Return(headerInfo, nil).AnyTimes() + + // Call the AddBTCDelegationInclusionProof handler + _, err = h.MsgServer.AddBTCDelegationInclusionProof(h.Ctx, msg) + h.Error(err) + require.ErrorAs(t, err, &types.ErrBTCDelegationNotFound) +} + func FuzzAddCovenantSigs(f *testing.F) { datagen.AddRandomSeedsToFuzzer(f, 10) @@ -458,10 +544,9 @@ func FuzzAddCovenantSigs(f *testing.F) { require.True(h.T(), actualDel.BtcUndelegation.HasCovenantQuorums(h.BTCStakingKeeper.GetParams(h.Ctx).CovenantQuorum)) tipHeight := h.BTCLightClientKeeper.GetTipInfo(h.Ctx).Height - checkpointTimeout := h.BTCCheckpointKeeper.GetParams(h.Ctx).CheckpointFinalizationTimeout covenantQuorum := h.BTCStakingKeeper.GetParams(h.Ctx).CovenantQuorum - status := actualDel.GetStatus(tipHeight, checkpointTimeout, covenantQuorum) - votingPower := actualDel.VotingPower(tipHeight, checkpointTimeout, covenantQuorum) + status := actualDel.GetStatus(tipHeight, covenantQuorum) + votingPower := actualDel.VotingPower(tipHeight, covenantQuorum) if usePreApproval { require.Equal(t, status, types.BTCDelegationStatus_VERIFIED) @@ -520,10 +605,9 @@ func FuzzAddBTCDelegationInclusionProof(f *testing.F) { // ensure the BTC delegation is now verified and does not have voting power tipHeight := h.BTCLightClientKeeper.GetTipInfo(h.Ctx).Height - checkpointTimeout := h.BTCCheckpointKeeper.GetParams(h.Ctx).CheckpointFinalizationTimeout covenantQuorum := h.BTCStakingKeeper.GetParams(h.Ctx).CovenantQuorum - status := actualDel.GetStatus(tipHeight, checkpointTimeout, covenantQuorum) - votingPower := actualDel.VotingPower(tipHeight, checkpointTimeout, covenantQuorum) + status := actualDel.GetStatus(tipHeight, covenantQuorum) + votingPower := actualDel.VotingPower(tipHeight, covenantQuorum) require.Equal(t, status, types.BTCDelegationStatus_VERIFIED) require.Zero(t, votingPower) @@ -534,8 +618,8 @@ func FuzzAddBTCDelegationInclusionProof(f *testing.F) { actualDel, err = h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) h.NoError(err) - status = actualDel.GetStatus(tipHeight, checkpointTimeout, covenantQuorum) - votingPower = actualDel.VotingPower(tipHeight, checkpointTimeout, covenantQuorum) + status = actualDel.GetStatus(tipHeight, covenantQuorum) + votingPower = actualDel.VotingPower(tipHeight, covenantQuorum) require.Equal(t, status, types.BTCDelegationStatus_ACTIVE) require.Equal(t, uint64(stakingValue), votingPower) @@ -559,7 +643,6 @@ func FuzzBTCUndelegate(f *testing.F) { covenantSKs, _ := h.GenAndApplyParams(r) bsParams := h.BTCStakingKeeper.GetParams(h.Ctx) - wValue := h.BTCCheckpointKeeper.GetParams(h.Ctx).CheckpointFinalizationTimeout changeAddress, err := datagen.GenRandomBTCAddress(r, h.Net) require.NoError(t, err) @@ -594,7 +677,7 @@ func FuzzBTCUndelegate(f *testing.F) { actualDel, err = h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) h.NoError(err) btcTip := h.BTCLightClientKeeper.GetTipInfo(h.Ctx).Height - status := actualDel.GetStatus(btcTip, wValue, bsParams.CovenantQuorum) + status := actualDel.GetStatus(btcTip, bsParams.CovenantQuorum) require.Equal(t, types.BTCDelegationStatus_ACTIVE, status) msg := &types.MsgBTCUndelegate{ @@ -617,7 +700,7 @@ func FuzzBTCUndelegate(f *testing.F) { // ensure the BTC delegation is unbonded actualDel, err = h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) h.NoError(err) - status = actualDel.GetStatus(btcTip, wValue, bsParams.CovenantQuorum) + status = actualDel.GetStatus(btcTip, bsParams.CovenantQuorum) require.Equal(t, types.BTCDelegationStatus_UNBONDED, status) }) } diff --git a/x/btcstaking/types/btc_delegation.go b/x/btcstaking/types/btc_delegation.go index e9a877a26..aba0e8c87 100644 --- a/x/btcstaking/types/btc_delegation.go +++ b/x/btcstaking/types/btc_delegation.go @@ -97,11 +97,19 @@ func (d *BTCDelegation) FinalityProviderKeys() []string { return fpPks } -// GetStatus returns the status of the BTC Delegation based on BTC height, w value, and covenant quorum -// Pending: the BTC height is in the range of d's [startHeight, endHeight-w] and the delegation does not have covenant signatures -// Active: the BTC height is in the range of d's [startHeight, endHeight-w] and the delegation has quorum number of signatures over slashing tx, unbonding tx, and slashing unbonding tx from covenant committee -// Unbonded: the BTC height is larger than `endHeight-w` or the BTC delegation has received a signature on unbonding tx from the delegator -func (d *BTCDelegation) GetStatus(btcHeight uint32, w uint32, covenantQuorum uint32) BTCDelegationStatus { +// GetStatus returns the status of the BTC Delegation based on BTC height, +// unbonding time, and covenant quorum +// Pending: the BTC height is in the range of d's [startHeight, endHeight-unbondingTime] +// and the delegation does not have covenant signatures +// Active: the BTC height is in the range of d's [startHeight, endHeight-unbondingTime] +// and the delegation has quorum number of signatures over slashing tx, +// unbonding tx, and slashing unbonding tx from covenant committee +// Unbonded: the BTC height is larger than `endHeight-unbondingTime` or the +// BTC delegation has received a signature on unbonding tx from the delegator +func (d *BTCDelegation) GetStatus( + btcHeight uint32, + covenantQuorum uint32, +) BTCDelegationStatus { if d.IsUnbondedEarly() { return BTCDelegationStatus_UNBONDED } @@ -119,8 +127,8 @@ func (d *BTCDelegation) GetStatus(btcHeight uint32, w uint32, covenantQuorum uin // At this point we already have covenant quorum and inclusion proof, // we can check the status based on the BTC height - if btcHeight < d.StartHeight || btcHeight+w > d.EndHeight { - // staking tx's timelock has not begun, or is less than w BTC + if btcHeight < d.StartHeight || btcHeight+d.UnbondingTime > d.EndHeight { + // staking tx's timelock has not begun, or is less than unbonding time BTC // blocks left, or is expired return BTCDelegationStatus_UNBONDED } @@ -133,10 +141,9 @@ func (d *BTCDelegation) GetStatus(btcHeight uint32, w uint32, covenantQuorum uin } // VotingPower returns the voting power of the BTC delegation at a given BTC height -// and a given w value. // The BTC delegation d has voting power iff it is active. -func (d *BTCDelegation) VotingPower(btcHeight uint32, w uint32, covenantQuorum uint32) uint64 { - if d.GetStatus(btcHeight, w, covenantQuorum) != BTCDelegationStatus_ACTIVE { +func (d *BTCDelegation) VotingPower(btcHeight uint32, covenantQuorum uint32) uint64 { + if d.GetStatus(btcHeight, covenantQuorum) != BTCDelegationStatus_ACTIVE { return 0 } return d.GetTotalSat() @@ -486,12 +493,3 @@ func (i *BTCDelegatorDelegationIndex) Add(stakingTxHash chainhash.Hash) error { return nil } - -// VotingPower calculates the total voting power of all BTC delegations -func (dels *BTCDelegatorDelegations) VotingPower(btcHeight uint32, w uint32, covenantQuorum uint32) uint64 { - power := uint64(0) - for _, del := range dels.Dels { - power += del.VotingPower(btcHeight, w, covenantQuorum) - } - return power -} diff --git a/x/btcstaking/types/btc_delegation_test.go b/x/btcstaking/types/btc_delegation_test.go index b15788dfa..b4fafc6e5 100644 --- a/x/btcstaking/types/btc_delegation_test.go +++ b/x/btcstaking/types/btc_delegation_test.go @@ -23,12 +23,12 @@ func FuzzBTCDelegation(f *testing.F) { f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) - + unbondingTime := uint32(datagen.RandomInt(r, 50)) btcDel := &types.BTCDelegation{} // randomise voting power btcDel.TotalSat = datagen.RandomInt(r, 100000) btcDel.BtcUndelegation = &types.BTCUndelegation{} - + btcDel.UnbondingTime = unbondingTime // randomise covenant sig hasCovenantSig := datagen.RandomInt(r, 2) == 0 if hasCovenantSig { @@ -56,11 +56,10 @@ func FuzzBTCDelegation(f *testing.F) { // randomise BTC tip and w btcHeight := btcDel.StartHeight + uint32(datagen.RandomInt(r, 50)) - w := uint32(datagen.RandomInt(r, 50)) // test expected voting power - hasVotingPower := hasCovenantSig && btcDel.StartHeight <= btcHeight && btcHeight+w <= btcDel.EndHeight - actualVotingPower := btcDel.VotingPower(btcHeight, w, 1) + hasVotingPower := hasCovenantSig && btcDel.StartHeight <= btcHeight && btcHeight+unbondingTime <= btcDel.EndHeight + actualVotingPower := btcDel.VotingPower(btcHeight, 1) if hasVotingPower { require.Equal(t, btcDel.TotalSat, actualVotingPower) } else { diff --git a/x/btcstaking/types/errors.go b/x/btcstaking/types/errors.go index a213d28ae..d44a12195 100644 --- a/x/btcstaking/types/errors.go +++ b/x/btcstaking/types/errors.go @@ -30,4 +30,5 @@ var ( ErrFpAlreadyJailed = errorsmod.Register(ModuleName, 1121, "the finality provider has already been jailed") ErrFpNotJailed = errorsmod.Register(ModuleName, 1122, "the finality provider is not jailed") ErrDuplicatedCovenantSig = errorsmod.Register(ModuleName, 1123, "the covenant signature is already submitted") + ErrParamsVersionMismatch = errorsmod.Register(ModuleName, 1124, "the parameters version in the BTC delegation is different from the parameters active at staking transaction inclusion height") ) diff --git a/x/finality/keeper/msg_server.go b/x/finality/keeper/msg_server.go index 4d02c9ba2..6b10ad7d9 100644 --- a/x/finality/keeper/msg_server.go +++ b/x/finality/keeper/msg_server.go @@ -316,7 +316,7 @@ func (ms msgServer) UnjailFinalityProvider(ctx context.Context, req *types.MsgUn return nil, fmt.Errorf("failed to unjail finality provider %s: %w", fpPk.MarshalHex(), err) } - types.DecrementJailedFinalityProviderCounter() + types.IncrementUnjailedFinalityProviderCounter() return &types.MsgUnjailFinalityProviderResponse{}, nil } diff --git a/x/finality/types/metrics.go b/x/finality/types/metrics.go index 6e6dbeee9..49b277ba7 100644 --- a/x/finality/types/metrics.go +++ b/x/finality/types/metrics.go @@ -24,9 +24,14 @@ const ( /* Metrics for monitoring finality provider liveness */ - // MetricsKeyJailedFinalityProviderCounter is the number of finality providers - // that are being labeled as jailed + // MetricsKeyJailedFinalityProviderCounter is the total number of finality providers + // that are labeled as jailed MetricsKeyJailedFinalityProviderCounter = "jailed_finality_provider_counter" + // MetricsKeyUnjailedFinalityProviderCounter is the total number of finality providers + // that are unjailed + // the number of finality providers that are being jailed can be calculated by + // jailed_finality_provider_counter - unjailed_finality_provider_counter + MetricsKeyUnjailedFinalityProviderCounter = "unjailed_finality_provider_counter" ) // RecordLastHeight records the last height. It is triggered upon `IndexBlock` @@ -64,14 +69,14 @@ func IncrementJailedFinalityProviderCounter() { ) } -// DecrementJailedFinalityProviderCounter decrements the counter for the jailed +// IncrementUnjailedFinalityProviderCounter increments the counter for the unjailed // finality providers -func DecrementJailedFinalityProviderCounter() { - keys := []string{MetricsKeyJailedFinalityProviderCounter} +func IncrementUnjailedFinalityProviderCounter() { + keys := []string{MetricsKeyUnjailedFinalityProviderCounter} labels := []metrics.Label{telemetry.NewLabel(telemetry.MetricLabelNameModule, ModuleName)} telemetry.IncrCounterWithLabels( keys, - -1, + 1, labels, ) }