Skip to content

Commit

Permalink
allow min unbonding value
Browse files Browse the repository at this point in the history
  • Loading branch information
gitferry committed Nov 19, 2024
1 parent 48978b0 commit 5ff5e3e
Show file tree
Hide file tree
Showing 12 changed files with 57 additions and 90 deletions.
5 changes: 3 additions & 2 deletions testutil/btcstaking-helper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ func (h *Helper) BeginBlocker() {
}

func (h *Helper) GenAndApplyParams(r *rand.Rand) ([]*btcec.PrivateKey, []*btcec.PublicKey) {
return h.GenAndApplyCustomParams(r, 100, 0, 0)
// ensure that minUnbondingTime is larger than finalizationTimeout
return h.GenAndApplyCustomParams(r, 100, 200, 0)
}

func (h *Helper) SetCtxHeight(height uint64) {
Expand Down Expand Up @@ -228,7 +229,7 @@ func (h *Helper) CreateDelegation(
if unbondingValue == 0 {
unbondingValue = defaultUnbondingValue
}
defaultUnbondingTime := types.MinimumUnbondingTime(&bsParams, &bcParams) + 1
defaultUnbondingTime := bsParams.MinUnbondingTimeBlocks
if unbondingTime == 0 {
unbondingTime = uint16(defaultUnbondingTime)
}
Expand Down
7 changes: 6 additions & 1 deletion x/btccheckpoint/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import (
"context"

errorsmod "cosmossdk.io/errors"
"github.com/babylonlabs-io/babylon/x/btccheckpoint/types"
sdk "github.com/cosmos/cosmos-sdk/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"

"github.com/babylonlabs-io/babylon/x/btccheckpoint/types"
)

var _ types.MsgServer = msgServer{}
Expand Down Expand Up @@ -110,6 +111,10 @@ func (ms msgServer) UpdateParams(goCtx context.Context, req *types.MsgUpdatePara
}

ctx := sdk.UnwrapSDKContext(goCtx)
if req.Params.CheckpointFinalizationTimeout != ms.k.GetParams(ctx).CheckpointFinalizationTimeout {
return nil, govtypes.ErrInvalidProposalMsg.Wrapf("the checkpoint finalization timeout cannot be changed")
}

if err := ms.k.SetParams(ctx, req.Params); err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion x/btcstaking/keeper/btc_delegations.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func (k Keeper) AddBTCDelegation(
NewState: types.BTCDelegationStatus_UNBONDED,
})

// NOTE: we should have verified that EndHeight > btcTip.Height + max(w, min_unbonding_time)
// NOTE: we should have verified that EndHeight > btcTip.Height + min_unbonding_time
k.addPowerDistUpdateEvent(ctx, btcDel.EndHeight-minUnbondingTime, unbondedEvent)
}

Expand Down
8 changes: 4 additions & 4 deletions x/btcstaking/keeper/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@ import (
"strings"
"testing"

"github.com/stretchr/testify/require"

"github.com/babylonlabs-io/babylon/testutil/datagen"
"github.com/babylonlabs-io/babylon/testutil/helper"
btclightclientt "github.com/babylonlabs-io/babylon/x/btclightclient/types"
"github.com/babylonlabs-io/babylon/x/btcstaking/types"
"github.com/stretchr/testify/require"
)

func TestExportGenesis(t *testing.T) {
r, h := rand.New(rand.NewSource(11)), helper.NewHelper(t)
k, btclcK, btcCheckK, ctx := h.App.BTCStakingKeeper, h.App.BTCLightClientKeeper, h.App.BtcCheckpointKeeper, h.Ctx
k, btclcK, ctx := h.App.BTCStakingKeeper, h.App.BTCLightClientKeeper, h.Ctx
numFps := 3

fps := datagen.CreateNFinalityProviders(r, t, numFps)
params := k.GetParams(ctx)
btcckptParams := btcCheckK.GetParams(ctx)

minUnbondingTime := types.MinimumUnbondingTime(&params, &btcckptParams)
minUnbondingTime := params.MinUnbondingTimeBlocks

chainsHeight := make([]*types.BlockHeightBbnToBtc, 0)
// creates the first as it starts already with an chain height from the helper.
Expand Down
18 changes: 13 additions & 5 deletions x/btcstaking/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,16 @@ func (ms msgServer) UpdateParams(goCtx context.Context, req *types.MsgUpdatePara
return nil, govtypes.ErrInvalidProposalMsg.Wrapf("invalid parameter: %v", err)
}

// ensure the min unbonding time is always larger than the checkpoint finalization timeout
ctx := sdk.UnwrapSDKContext(goCtx)
ckptFinalizationTime := ms.btccKeeper.GetParams(ctx).CheckpointFinalizationTimeout
minUnbondingTime := req.Params.MinUnbondingTimeBlocks
if minUnbondingTime <= ckptFinalizationTime {
return nil, govtypes.ErrInvalidProposalMsg.
Wrapf("the min unbonding time %d must be larger than the checkpoint finalization timeout %d",
minUnbondingTime, ckptFinalizationTime)
}

if err := ms.SetParams(ctx, req.Params); err != nil {
return nil, err
}
Expand Down Expand Up @@ -190,16 +199,15 @@ func (ms msgServer) CreateBTCDelegation(goCtx context.Context, req *types.MsgCre
}

// 6. Validate parsed message against parameters
btccParams := ms.btccKeeper.GetParams(ctx)

paramsValidationResult, err := types.ValidateParsedMessageAgainstTheParams(parsedMsg, &vp.Params, &btccParams, ms.btcNet)
paramsValidationResult, err := types.ValidateParsedMessageAgainstTheParams(parsedMsg, &vp.Params, ms.btcNet)

if err != nil {
return nil, err
}

// 7. If the delegation contains the inclusion proof, we need to verify the proof
// and set start height and end height
btccParams := ms.btccKeeper.GetParams(ctx)
var startHeight, endHeight uint32
if parsedMsg.StakingTxProofOfInclusion != nil {
timeInfo, err := ms.VerifyInclusionProofAndGetHeight(
Expand Down Expand Up @@ -300,7 +308,7 @@ func (ms msgServer) AddBTCDelegationInclusionProof(

btccParams := ms.btccKeeper.GetParams(ctx)

minUnbondingTime := types.MinimumUnbondingTime(params, &btccParams)
minUnbondingTime := params.MinUnbondingTimeBlocks

timeInfo, err := ms.VerifyInclusionProofAndGetHeight(
ctx,
Expand Down Expand Up @@ -349,7 +357,7 @@ func (ms msgServer) AddBTCDelegationInclusionProof(
NewState: types.BTCDelegationStatus_UNBONDED,
})

// NOTE: we should have verified that EndHeight > btcTip.Height + max(w, min_unbonding_time)
// NOTE: we should have verified that EndHeight > btcTip.Height + min_unbonding_time
ms.addPowerDistUpdateEvent(ctx, btcDel.EndHeight-minUnbondingTime, unbondedEvent)

// at this point, the BTC delegation inclusion proof is verified and is not duplicated
Expand Down
22 changes: 5 additions & 17 deletions x/btcstaking/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -690,14 +690,10 @@ func TestDoNotAllowDelegationWithoutFinalityProvider(t *testing.T) {
// set covenant PK to params
_, covenantPKs := h.GenAndApplyParams(r)
bsParams := h.BTCStakingKeeper.GetParams(h.Ctx)
bcParams := h.BTCCheckpointKeeper.GetParams(h.Ctx)

minUnbondingTime := types.MinimumUnbondingTime(
&bsParams,
&bcParams,
)
minUnbondingTime := bsParams.MinUnbondingTimeBlocks

slashingChangeLockTime := uint16(minUnbondingTime) + 1
slashingChangeLockTime := uint16(minUnbondingTime)

// We only generate a finality provider, but not insert it into KVStore. So later
// insertion of delegation should fail.
Expand Down Expand Up @@ -820,13 +816,6 @@ func TestCorrectUnbondingTimeInDelegation(t *testing.T) {
finalizationTimeout: 100,
err: nil,
},
{
name: "failed delegation when ubonding time in delegation is not larger than finalization time when min unbonding time is lower than finalization timeout",
unbondingTimeInDelegation: 100,
minUnbondingTime: 99,
finalizationTimeout: 100,
err: types.ErrInvalidUnbondingTx,
},
{
name: "successful delegation when ubonding time ubonding time in delegation is larger than min unbonding time when min unbonding time is larger than finalization timeout",
unbondingTimeInDelegation: 151,
Expand All @@ -835,11 +824,11 @@ func TestCorrectUnbondingTimeInDelegation(t *testing.T) {
err: nil,
},
{
name: "failed delegation when ubonding time in delegation is not larger than minUnbondingTime when min unbonding time is larger than finalization timeout",
name: "successful delegation when ubonding time in delegation is equal to minUnbondingTime when min unbonding time is larger than finalization timeout",
unbondingTimeInDelegation: 150,
minUnbondingTime: 150,
finalizationTimeout: 100,
err: types.ErrInvalidUnbondingTx,
err: nil,
},
}

Expand Down Expand Up @@ -1063,9 +1052,8 @@ func FuzzDeterminismBtcstakingBeginBlocker(f *testing.F) {
stakingParams := h.App.BTCStakingKeeper.GetParams(h.Ctx)
covQuorum := stakingParams.CovenantQuorum
maxFinalityProviders := int32(h.App.FinalityKeeper.GetParams(h.Ctx).MaxActiveFinalityProviders)
btcckptParams := h.App.BtcCheckpointKeeper.GetParams(h.Ctx)

minUnbondingTime := types.MinimumUnbondingTime(&stakingParams, &btcckptParams)
minUnbondingTime := stakingParams.MinUnbondingTimeBlocks
// Number of finality providers from 10 to maxFinalityProviders + 10
numFinalityProviders := int(r.Int31n(maxFinalityProviders) + 10)

Expand Down
3 changes: 2 additions & 1 deletion x/btcstaking/keeper/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import (

"cosmossdk.io/math"
"cosmossdk.io/store/prefix"
"github.com/babylonlabs-io/babylon/x/btcstaking/types"
"github.com/cosmos/cosmos-sdk/runtime"

"github.com/babylonlabs-io/babylon/x/btcstaking/types"
)

// cosmos-sdk does not have utils for uint32
Expand Down
15 changes: 0 additions & 15 deletions x/btcstaking/types/btcstaking.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@ package types
import (
"fmt"

"cosmossdk.io/math"

sdk "github.com/cosmos/cosmos-sdk/types"

asig "github.com/babylonlabs-io/babylon/crypto/schnorr-adaptor-signature"
bbn "github.com/babylonlabs-io/babylon/types"
btcctypes "github.com/babylonlabs-io/babylon/x/btccheckpoint/types"
)

func (fp *FinalityProvider) IsSlashed() bool {
Expand Down Expand Up @@ -105,15 +102,3 @@ func GetOrderedCovenantSignatures(fpIdx int, covSigsList []*CovenantAdaptorSigna

return orderedCovSigs, nil
}

// MinimumUnbondingTime returns the minimum unbonding time. It is the bigger value from:
// - MinUnbondingTime
// - CheckpointFinalizationTimeout
func MinimumUnbondingTime(
stakingParams *Params,
checkpointingParams *btcctypes.Params) uint32 {
return math.Max[uint32](
stakingParams.MinUnbondingTimeBlocks,
checkpointingParams.CheckpointFinalizationTimeout,
)
}
5 changes: 2 additions & 3 deletions x/btcstaking/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,8 @@ func DefaultParams() Params {
MinCommissionRate: sdkmath.LegacyZeroDec(),
// The Default slashing rate is 0.1 i.e., 10% of the total staked BTC will be burned.
SlashingRate: sdkmath.LegacyNewDecWithPrec(1, 1), // 1 * 10^{-1} = 0.1
// The default minimum unbonding time is 0, which effectively defaults to checkpoint
// finalization timeout.
MinUnbondingTimeBlocks: 0,
// min unbonding time should be always larger than the checkpoint finalization timeout
MinUnbondingTimeBlocks: 200,
UnbondingFeeSat: 1000,
DelegationCreationBaseGasFee: defaultDelegationCreationBaseGasFee,
// The default allow list expiration height is 0, which effectively disables the allow list.
Expand Down
15 changes: 5 additions & 10 deletions x/btcstaking/types/validate_parsed_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

"github.com/babylonlabs-io/babylon/btcstaking"
bbn "github.com/babylonlabs-io/babylon/types"
btcckpttypes "github.com/babylonlabs-io/babylon/x/btccheckpoint/types"
)

type ParamsValidationResult struct {
Expand All @@ -21,17 +20,13 @@ type ParamsValidationResult struct {
func ValidateParsedMessageAgainstTheParams(
pm *ParsedCreateDelegationMessage,
parameters *Params,
btcheckpointParameters *btcckpttypes.Params,
net *chaincfg.Params,
) (*ParamsValidationResult, error) {
// 1. Validate unbonding time first as it will be used in other checks
minUnbondingTime := MinimumUnbondingTime(parameters, btcheckpointParameters)
// Check unbonding time (staking time from unbonding tx) is larger than min unbonding time
// which is larger value from:
// - MinUnbondingTime
// - CheckpointFinalizationTimeout
if uint32(pm.UnbondingTime) <= minUnbondingTime {
return nil, ErrInvalidUnbondingTx.Wrapf("unbonding time %d must be larger than %d", pm.UnbondingTime, minUnbondingTime)
// Check unbonding time (staking time from unbonding tx) is not less than min unbonding time
if uint32(pm.UnbondingTime) < parameters.MinUnbondingTimeBlocks {
return nil, ErrInvalidUnbondingTx.Wrapf("unbonding time %d must not be less than %d",
pm.UnbondingTime, parameters.MinUnbondingTimeBlocks)
}

stakingTxHash := pm.StakingTx.Transaction.TxHash()
Expand Down Expand Up @@ -206,6 +201,6 @@ func ValidateParsedMessageAgainstTheParams(
return &ParamsValidationResult{
StakingOutputIdx: stakingOutputIdx,
UnbondingOutputIdx: 0, // unbonding output always has only 1 output
MinUnbondingTime: minUnbondingTime,
MinUnbondingTime: parameters.MinUnbondingTimeBlocks,
}, nil
}
13 changes: 5 additions & 8 deletions x/btcstaking/types/validate_parsed_message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ func createMsgDelegationForParams(
stakingValue := int64(randRange(r, int(p.MinStakingValueSat), int(p.MaxStakingValueSat)))

// always chose minimum unbonding time possible
unbondingTime := uint16(types.MinimumUnbondingTime(p, cp)) + 1
unbondingTime := p.MinUnbondingTimeBlocks

testStakingInfo := datagen.GenBTCStakingSlashingInfo(
r,
Expand All @@ -167,7 +167,7 @@ func createMsgDelegationForParams(
stakingValue,
p.SlashingPkScript,
p.SlashingRate,
unbondingTime,
uint16(unbondingTime),
)

slashingSpendInfo, err := testStakingInfo.StakingInfo.SlashingPathSpendInfo()
Expand Down Expand Up @@ -205,7 +205,7 @@ func createMsgDelegationForParams(
fpPk,
stkTxHash,
stkOutputIdx,
unbondingTime,
uint16(unbondingTime),
unbondingValue,
p,
)
Expand Down Expand Up @@ -871,7 +871,7 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
r := rand.New(rand.NewSource(time.Now().Unix()))

msg, params, checkpointParams := tt.fn(r, t)
msg, params, _ := tt.fn(r, t)

parsed, err := types.ParseCreateDelegationMessage(msg)

Expand All @@ -885,7 +885,6 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {
got, err := types.ValidateParsedMessageAgainstTheParams(
parsed,
params,
checkpointParams,
&chaincfg.MainNetParams,
)

Expand All @@ -895,9 +894,7 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {
} else {
require.NoError(t, err)
require.NotNil(t, got)

minUnbondingTime := types.MinimumUnbondingTime(params, checkpointParams)
require.Equal(t, minUnbondingTime, got.MinUnbondingTime)
require.Equal(t, params.MinUnbondingTimeBlocks, got.MinUnbondingTime)
}

})
Expand Down
Loading

0 comments on commit 5ff5e3e

Please sign in to comment.