diff --git a/babylonclient/babyloncontroller.go b/babylonclient/babyloncontroller.go index 61659ab..9c802c5 100644 --- a/babylonclient/babyloncontroller.go +++ b/babylonclient/babyloncontroller.go @@ -100,13 +100,18 @@ func NewBabylonController( } type StakingTrackerResponse struct { - SlashingAddress btcutil.Address + SlashingPkScript []byte SlashingRate sdkmath.LegacyDec MinComissionRate sdkmath.LegacyDec CovenantPks []*btcec.PublicKey CovenantQuruomThreshold uint32 MinSlashingFee btcutil.Amount - MinUnbodningTime uint16 + MinUnbondingTime uint16 + UnbondingFee btcutil.Amount + MinStakingTime uint16 + MaxStakingTime uint16 + MinStakingValue btcutil.Amount + MaxStakingValue btcutil.Amount } type FinalityProviderInfo struct { @@ -175,18 +180,23 @@ func (bc *BabylonController) Params() (*StakingParams, error) { minUnbondingTime := sdkmath.Max[uint16]( uint16(bccParams.CheckpointFinalizationTimeout), - stakingTrackerParams.MinUnbodningTime, + stakingTrackerParams.MinUnbondingTime, ) return &StakingParams{ ConfirmationTimeBlocks: uint32(bccParams.BtcConfirmationDepth), FinalizationTimeoutBlocks: uint32(bccParams.CheckpointFinalizationTimeout), - SlashingAddress: stakingTrackerParams.SlashingAddress, + SlashingPkScript: stakingTrackerParams.SlashingPkScript, CovenantPks: stakingTrackerParams.CovenantPks, MinSlashingTxFeeSat: stakingTrackerParams.MinSlashingFee, SlashingRate: stakingTrackerParams.SlashingRate, CovenantQuruomThreshold: stakingTrackerParams.CovenantQuruomThreshold, MinUnbondingTime: minUnbondingTime, + UnbondingFee: stakingTrackerParams.UnbondingFee, + MinStakingTime: stakingTrackerParams.MinStakingTime, + MaxStakingTime: stakingTrackerParams.MaxStakingTime, + MinStakingValue: stakingTrackerParams.MinStakingValue, + MaxStakingValue: stakingTrackerParams.MaxStakingValue, }, nil } @@ -446,11 +456,6 @@ func (bc *BabylonController) QueryStakingTracker() (*StakingTrackerResponse, err return nil, err } - slashingAddress, err := btcutil.DecodeAddress(response.Params.SlashingAddress, bc.btcParams) - if err != nil { - return nil, err - } - // check this early than covenant config makes sense, so that rest of the // code can assume that: // 1. covenant quorum is less or equal to number of covenant pks @@ -473,18 +478,43 @@ func (bc *BabylonController) QueryStakingTracker() (*StakingTrackerResponse, err covenantPks = append(covenantPks, covenantBtcPk) } - if response.Params.MinUnbondingTime > math.MaxUint16 { + if response.Params.MinUnbondingTimeBlocks > math.MaxUint16 { return nil, fmt.Errorf("min unbonding time is bigger than uint16: %w", ErrInvalidValueReceivedFromBabylonNode) } + if response.Params.MinStakingTimeBlocks > math.MaxUint16 { + return nil, fmt.Errorf("min staking time is bigger than uint16: %w", ErrInvalidValueReceivedFromBabylonNode) + } + + if response.Params.MaxStakingTimeBlocks > math.MaxUint16 { + return nil, fmt.Errorf("max staking time is bigger than uint16: %w", ErrInvalidValueReceivedFromBabylonNode) + } + + if response.Params.MinStakingValueSat < 0 { + return nil, fmt.Errorf("min staking value is negative: %w", ErrInvalidValueReceivedFromBabylonNode) + } + + if response.Params.MaxStakingValueSat < 0 { + return nil, fmt.Errorf("max staking value is negative: %w", ErrInvalidValueReceivedFromBabylonNode) + } + + if response.Params.UnbondingFeeSat < 0 { + return nil, fmt.Errorf("unbonding fee is negative: %w", ErrInvalidValueReceivedFromBabylonNode) + } + return &StakingTrackerResponse{ - SlashingAddress: slashingAddress, + SlashingPkScript: response.Params.SlashingPkScript, SlashingRate: response.Params.SlashingRate, MinComissionRate: response.Params.MinCommissionRate, CovenantPks: covenantPks, MinSlashingFee: btcutil.Amount(response.Params.MinSlashingTxFeeSat), CovenantQuruomThreshold: response.Params.CovenantQuorum, - MinUnbodningTime: uint16(response.Params.MinUnbondingTime), + MinUnbondingTime: uint16(response.Params.MinUnbondingTimeBlocks), + UnbondingFee: btcutil.Amount(response.Params.UnbondingFeeSat), + MinStakingTime: uint16(response.Params.MinStakingTimeBlocks), + MaxStakingTime: uint16(response.Params.MaxStakingTimeBlocks), + MinStakingValue: btcutil.Amount(response.Params.MinStakingValueSat), + MaxStakingValue: btcutil.Amount(response.Params.MaxStakingValueSat), }, nil } diff --git a/babylonclient/interface.go b/babylonclient/interface.go index a1783a6..77e33a0 100644 --- a/babylonclient/interface.go +++ b/babylonclient/interface.go @@ -10,6 +10,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" pv "github.com/cosmos/relayer/v2/relayer/provider" @@ -27,8 +28,8 @@ type StakingParams struct { // Bitcoin public key of the current covenant CovenantPks []*btcec.PublicKey - // Address to which slashing transactions are sent - SlashingAddress btcutil.Address + // PkScript that must be inserted in the slashing output of the slashing transaction + SlashingPkScript []byte // The rate at which the staked funds will be slashed, expressed as a decimal. SlashingRate sdkmath.LegacyDec @@ -38,6 +39,21 @@ type StakingParams struct { // Minimum unbonding time required by bayblon MinUnbondingTime uint16 + + // Fee required by unbonding transaction + UnbondingFee btcutil.Amount + + // Minimum staking time required by bayblon + MinStakingTime uint16 + + // Maximum staking time required by bayblon + MaxStakingTime uint16 + + // Minimum staking value required by bayblon + MinStakingValue btcutil.Amount + + // Maximum staking value required by bayblon + MaxStakingValue btcutil.Amount } // SingleKeyCosmosKeyring represents a keyring that supports only one pritvate/public key pair @@ -154,6 +170,12 @@ func GetMockClient() *MockBabylonClient { slashingAddress, _ := btcutil.NewAddressPubKey(covenantPk.PubKey().SerializeCompressed(), &chaincfg.SimNetParams) + slashingPkScript, err := txscript.PayToAddrScript(slashingAddress) + + if err != nil { + panic(err) + } + fpBtcPrivKey, err := btcec.NewPrivateKey() if err != nil { panic(err) @@ -170,7 +192,7 @@ func GetMockClient() *MockBabylonClient { FinalizationTimeoutBlocks: 5, MinSlashingTxFeeSat: btcutil.Amount(1000), CovenantPks: []*btcec.PublicKey{covenantPk.PubKey()}, - SlashingAddress: slashingAddress, + SlashingPkScript: slashingPkScript, SlashingRate: sdkmath.LegacyNewDecWithPrec(1, 1), // 1 * 10^{-1} = 0.1 }, babylonKey: priv, diff --git a/go.mod b/go.mod index 270b170..a2b87b6 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( cosmossdk.io/errors v1.0.1 cosmossdk.io/math v1.3.0 github.com/avast/retry-go/v4 v4.5.1 - github.com/babylonlabs-io/babylon v0.9.0 + github.com/babylonlabs-io/babylon v0.9.3-0.20240904123958-b1e255a85e76 github.com/babylonlabs-io/networks/parameters v0.2.2 github.com/btcsuite/btcd v0.24.2 github.com/btcsuite/btcd/btcec/v2 v2.3.2 diff --git a/go.sum b/go.sum index 180bccc..f7777d5 100644 --- a/go.sum +++ b/go.sum @@ -285,8 +285,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX github.com/aws/aws-sdk-go v1.44.312 h1:llrElfzeqG/YOLFFKjg1xNpZCFJ2xraIi3PqSuP+95k= github.com/aws/aws-sdk-go v1.44.312/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonlabs-io/babylon v0.9.0 h1:dHZ9wUrI5XLaO4UIwJRgiCdnzFdi5yv7dpibbu6TDv0= -github.com/babylonlabs-io/babylon v0.9.0/go.mod h1:t7B4e+ooD2oYvAxkegtNKDL9bXe+vU29a8xnCQh+UKo= +github.com/babylonlabs-io/babylon v0.9.3-0.20240904123958-b1e255a85e76 h1:JOdd2H+bOYPyKYNyCcjT2lW7H76A4Pbfstk7n/Vo2Vc= +github.com/babylonlabs-io/babylon v0.9.3-0.20240904123958-b1e255a85e76/go.mod h1:9VUUAwVaalXiDdPZT65SPoawKWpp6ple6tBr8Vw0NI8= github.com/babylonlabs-io/networks/parameters v0.2.2 h1:TCu39fZvjX5f6ZZrjhYe54M6wWxglNewuKu56yE+zrc= github.com/babylonlabs-io/networks/parameters v0.2.2/go.mod h1:iEJVOzaLsE33vpP7J4u+CRGfkSIfErUAwRmgCFCBpyI= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= diff --git a/itest/babylon_node_handler.go b/itest/babylon_node_handler.go index 52f9cef..364fc54 100644 --- a/itest/babylon_node_handler.go +++ b/itest/babylon_node_handler.go @@ -107,7 +107,7 @@ func NewBabylonNodeHandler( covenantPk1 *btcec.PublicKey, covenantPk2 *btcec.PublicKey, covenantPk3 *btcec.PublicKey, - slashingAddress string, + slashingPkScript string, baseHeaderHex string, ) (*BabylonNodeHandler, error) { testDir, err := baseDirBabylondir() @@ -132,7 +132,9 @@ func NewBabylonNodeHandler( "--btc-finalization-timeout=4", "--btc-confirmation-depth=2", "--btc-network=regtest", - fmt.Sprintf("--slashing-address=%s", slashingAddress), + "--min-staking-time-blocks=200", + "--min-staking-amount-sat=10000", + fmt.Sprintf("--slashing-pk-script=%s", slashingPkScript), fmt.Sprintf("--btc-base-header=%s", baseHeaderHex), "--additional-sender-account", fmt.Sprintf("--covenant-quorum=%s", quorumString), diff --git a/itest/e2e_test.go b/itest/e2e_test.go index 4de26b5..d9ca01e 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -246,13 +246,16 @@ func StartManager( require.NoError(t, err) baseHeaderHex := hex.EncodeToString(buff.Bytes()) + pkScript, err := txscript.PayToAddrScript(minerAddressDecoded) + require.NoError(t, err) + bh, err := NewBabylonNodeHandler( quorum, coventantPrivKeys[0].PubKey(), coventantPrivKeys[1].PubKey(), coventantPrivKeys[2].PubKey(), // all slashings will be sent back to wallet - minerAddressDecoded.EncodeAddress(), + hex.EncodeToString(pkScript), baseHeaderHex, ) require.NoError(t, err) @@ -806,7 +809,7 @@ func (tm *TestManager) sendWatchedStakingTx( slashingTx, err := staking.BuildSlashingTxFromStakingTxStrict( tx, uint32(stakingOutputIdx), - params.SlashingAddress, + params.SlashingPkScript, testStakingData.StakerKey, unbondingTme, int64(params.MinSlashingTxFeeSat)+10, @@ -838,7 +841,7 @@ func (tm *TestManager) sendWatchedStakingTx( serializedSlashingTx, err := utils.SerializeBtcTransaction(slashingTx) require.NoError(t, err) // Build unbonding related data - unbondingFee := btcutil.Amount(1000) + unbondingFee := params.UnbondingFee unbondingAmount := btcutil.Amount(testStakingData.StakingAmount) - unbondingFee unbondingInfo, err := staking.BuildUnbondingInfo( @@ -862,7 +865,7 @@ func (tm *TestManager) sendWatchedStakingTx( slashUnbondingTx, err := staking.BuildSlashingTxFromStakingTxStrict( unbondingTx, 0, - params.SlashingAddress, + params.SlashingPkScript, testStakingData.StakerKey, unbondingTme, int64(params.MinSlashingTxFeeSat)+10, @@ -1103,9 +1106,8 @@ func TestStakingFailures(t *testing.T) { cl := tm.Sa.BabylonController() params, err := cl.Params() require.NoError(t, err) - stakingTime := uint16(staker.GetMinStakingTime(params)) - testStakingData := tm.getTestStakingData(t, tm.WalletPubKey, stakingTime, 10000, 1) + testStakingData := tm.getTestStakingData(t, tm.WalletPubKey, params.MinStakingTime, 10000, 1) fpKey := hex.EncodeToString(schnorr.SerializePubKey(testStakingData.FinalityProviderBtcKeys[0])) tm.createAndRegisterFinalityProviders(t, testStakingData) @@ -1143,9 +1145,8 @@ func TestSendingStakingTransaction(t *testing.T) { cl := tm.Sa.BabylonController() params, err := cl.Params() require.NoError(t, err) - stakingTime := uint16(staker.GetMinStakingTime(params)) - testStakingData := tm.getTestStakingData(t, tm.WalletPubKey, stakingTime, 10000, 1) + testStakingData := tm.getTestStakingData(t, tm.WalletPubKey, params.MinStakingTime, 10000, 1) hashed, err := chainhash.NewHash(datagen.GenRandomByteArray(r, 32)) require.NoError(t, err) @@ -1218,7 +1219,7 @@ func TestMultipleWithdrawableStakingTransactions(t *testing.T) { cl := tm.Sa.BabylonController() params, err := cl.Params() require.NoError(t, err) - minStakingTime := uint16(staker.GetMinStakingTime(params)) + minStakingTime := params.MinStakingTime stakingTime1 := minStakingTime stakingTime2 := minStakingTime + 4 stakingTime3 := minStakingTime + 1 @@ -1284,8 +1285,8 @@ func TestSendingWatchedStakingTransaction(t *testing.T) { cl := tm.Sa.BabylonController() params, err := cl.Params() require.NoError(t, err) - stakingTime := uint16(staker.GetMinStakingTime(params)) - testStakingData := tm.getTestStakingData(t, tm.WalletPubKey, stakingTime, 10000, 1) + + testStakingData := tm.getTestStakingData(t, tm.WalletPubKey, params.MinStakingTime, 10000, 1) tm.createAndRegisterFinalityProviders(t, testStakingData) @@ -1306,8 +1307,8 @@ func TestRestartingTxNotDeepEnough(t *testing.T) { cl := tm.Sa.BabylonController() params, err := cl.Params() require.NoError(t, err) - stakingTime := uint16(staker.GetMinStakingTime(params)) - testStakingData := tm.getTestStakingData(t, tm.WalletPubKey, stakingTime, 10000, 1) + + testStakingData := tm.getTestStakingData(t, tm.WalletPubKey, params.MinStakingTime, 10000, 1) tm.createAndRegisterFinalityProviders(t, testStakingData) txHash := tm.sendStakingTxBTC(t, testStakingData) @@ -1331,9 +1332,8 @@ func TestRestartingTxNotOnBabylon(t *testing.T) { cl := tm.Sa.BabylonController() params, err := cl.Params() require.NoError(t, err) - stakingTime := uint16(staker.GetMinStakingTime(params)) - testStakingData1 := tm.getTestStakingData(t, tm.WalletPubKey, stakingTime, 10000, 1) + testStakingData1 := tm.getTestStakingData(t, tm.WalletPubKey, params.MinStakingTime, 10000, 1) testStakingData2 := testStakingData1.withStakingAmout(11000) tm.createAndRegisterFinalityProviders(t, testStakingData1) @@ -1615,10 +1615,9 @@ func TestSendingStakingTransaction_Restaking(t *testing.T) { cl := tm.Sa.BabylonController() params, err := cl.Params() require.NoError(t, err) - stakingTime := uint16(staker.GetMinStakingTime(params)) // restaked to 5 finality providers - testStakingData := tm.getTestStakingData(t, tm.WalletPubKey, stakingTime, 10000, 5) + testStakingData := tm.getTestStakingData(t, tm.WalletPubKey, params.MinStakingTime, 10000, 5) hashed, err := chainhash.NewHash(datagen.GenRandomByteArray(r, 32)) require.NoError(t, err) @@ -1656,9 +1655,8 @@ func TestRecoverAfterRestartDuringWithdrawal(t *testing.T) { cl := tm.Sa.BabylonController() params, err := cl.Params() require.NoError(t, err) - stakingTime := uint16(staker.GetMinStakingTime(params)) - testStakingData := tm.getTestStakingData(t, tm.WalletPubKey, stakingTime, 10000, 1) + testStakingData := tm.getTestStakingData(t, tm.WalletPubKey, params.MinStakingTime, 10000, 1) hashed, err := chainhash.NewHash(datagen.GenRandomByteArray(r, 32)) require.NoError(t, err) diff --git a/staker/babylontypes.go b/staker/babylontypes.go index 4178050..e63a177 100644 --- a/staker/babylontypes.go +++ b/staker/babylontypes.go @@ -56,17 +56,13 @@ func (app *StakerApp) buildOwnedDelegation( }).Fatalf("Failed to build delegation data for already confirmed staking transaction") } - // TODO: Option to use custom fee rate, as estimator uses pretty big value for fee - // in case of estimation failure (25 sat/byte) - unbondingTxFeeRatePerKb := btcutil.Amount(app.feeEstimator.EstimateFeePerKb()) - undelegationDesc, err := createUndelegationData( storedTx, externalData.stakerPublicKey, externalData.babylonParams.CovenantPks, externalData.babylonParams.CovenantQuruomThreshold, - externalData.babylonParams.SlashingAddress, - unbondingTxFeeRatePerKb, + externalData.babylonParams.SlashingPkScript, + externalData.babylonParams.UnbondingFee, // TODO: Possiblity to customize finalization time uint16(externalData.babylonParams.MinUnbondingTime)+1, app.getSlashingFee(externalData.babylonParams.MinSlashingTxFeeSat), diff --git a/staker/stakerapp.go b/staker/stakerapp.go index b36880e..4300622 100644 --- a/staker/stakerapp.go +++ b/staker/stakerapp.go @@ -98,21 +98,6 @@ const ( defaultWalletUnlockTimeout = 15 - // Actual virtual size of transaction which spends staking transaction through slashing - // path. In reality it highly depends on slashingAddress size: - // for p2pk - 222vb - // for p2wpkh - 177vb - // for p2tr - 189vb - // We are chosing 180vb as we expect slashing address will be one of the more recent - // address types. - // Transaction is quite big as witness to spend is composed of: - // 1. StakerSig - // 2. CovenantSig - // 3. FinalityProviderSig - // 4. StakingScript - // 5. Taproot control block - slashingPathSpendTxVSize = 180 - // Set minimum fee to 1 sat/byte, as in standard rules policy MinFeePerKb = txrules.DefaultRelayFeePerKb @@ -1401,15 +1386,6 @@ func (app *StakerApp) BabylonController() cl.BabylonClient { return app.babylonClient } -func GetMinStakingTime(p *cl.StakingParams) uint32 { - // Actual minimum staking time in babylon is k+w, but setting it to that would - // result in delegation which have voting power for 0 btc blocks. - // therefore setting it to 2*w + k, will result in delegation with voting power - // for at least w blocks. Therefore this conditions enforces min staking time i.e time - // when stake is active of w blocks - return 2*p.FinalizationTimeoutBlocks + p.ConfirmationTimeBlocks -} - func (app *StakerApp) WatchStaking( stakingTx *wire.MsgTx, stakingTime uint16, @@ -1538,11 +1514,14 @@ func (app *StakerApp) StakeFunds( return nil, fmt.Errorf("staking amount %d is less than minimum slashing fee %d", stakingAmount, slashingFee) } + if stakingTimeBlocks < params.MinStakingTime || stakingTimeBlocks > params.MaxStakingTime { + return nil, fmt.Errorf("staking time %d is not in range [%d, %d]", + stakingTimeBlocks, params.MinStakingTime, params.MaxStakingTime) + } - minStakingTime := GetMinStakingTime(params) - if uint32(stakingTimeBlocks) < minStakingTime { - return nil, fmt.Errorf("staking time %d is less than minimum staking time %d", - stakingTimeBlocks, minStakingTime) + if stakingAmount < params.MinStakingValue || stakingAmount > params.MaxStakingValue { + return nil, fmt.Errorf("staking amount %d is not in range [%d, %d]", + stakingAmount, params.MinStakingValue, params.MaxStakingValue) } // unlock wallet for the rest of the operations diff --git a/staker/types.go b/staker/types.go index c454d52..a8e4172 100644 --- a/staker/types.go +++ b/staker/types.go @@ -111,7 +111,7 @@ func slashingTxForStakingTx( slashingTx, err := staking.BuildSlashingTxFromStakingTxStrict( storedTx.StakingTx, storedTx.StakingOutputIndex, - delegationData.babylonParams.SlashingAddress, + delegationData.babylonParams.SlashingPkScript, stakerPubKey, lockSlashTxLockTime, int64(slashingFee), @@ -328,8 +328,8 @@ func createUndelegationData( stakerPubKey *btcec.PublicKey, covenantPubKeys []*btcec.PublicKey, covenantThreshold uint32, - slashingAddress btcutil.Address, - feeRatePerKb btcutil.Amount, + slashingPkScript []byte, + unbondingTxFee btcutil.Amount, unbondingTime uint16, slashingFee btcutil.Amount, slashingRate sdkmath.LegacyDec, @@ -339,19 +339,17 @@ func createUndelegationData( stakingOutpout := storedTx.StakingTx.TxOut[storedTx.StakingOutputIndex] - unbondingTxFee := txrules.FeeForSerializeSize(feeRatePerKb, slashingPathSpendTxVSize) - unbondingOutputValue := stakingOutpout.Value - int64(unbondingTxFee) if unbondingOutputValue <= 0 { return nil, fmt.Errorf( - "too large fee rate %d sats/kb. Staking output value:%d sats. Unbonding tx fee:%d sats", int64(feeRatePerKb), stakingOutpout.Value, int64(unbondingTxFee), + "staking output value:%d sats. Unbonding tx fee:%d sats", stakingOutpout.Value, int64(unbondingTxFee), ) } if unbondingOutputValue <= int64(slashingFee) { return nil, fmt.Errorf( - "too large fee rate %d sats/kb. Unbonding output value %d sats. Slashing tx fee: %d sats", int64(feeRatePerKb), unbondingOutputValue, int64(slashingFee), + "unbonding output value %d sats. Slashing tx fee: %d sats", unbondingOutputValue, int64(slashingFee), ) } @@ -376,7 +374,7 @@ func createUndelegationData( slashUnbondingTx, err := staking.BuildSlashingTxFromStakingTxStrict( unbondingTx, 0, - slashingAddress, + slashingPkScript, stakerPubKey, unbondingTime, int64(slashingFee), @@ -464,6 +462,19 @@ func parseWatchStakingRequest( currentParams *cl.StakingParams, network *chaincfg.Params, ) (*stakingRequestedEvent, error) { + // TODO(https://github.com/babylonlabs-io/btc-staker/issues/32): + // This check re-implements whole babylon validation logic. We should + // refactor this to use babylon validation utilities. + if stakingTime < currentParams.MinStakingTime || stakingTime > currentParams.MaxStakingTime { + return nil, fmt.Errorf("staking time %d is not in range [%d, %d]", + stakingTime, currentParams.MinStakingTime, currentParams.MaxStakingTime) + } + + if stakingValue < currentParams.MinStakingValue || stakingValue > currentParams.MaxStakingValue { + return nil, fmt.Errorf("staking amount %d is not in range [%d, %d]", + stakingValue, currentParams.MinStakingValue, currentParams.MaxStakingValue) + } + stakingInfo, err := staking.BuildStakingInfo( stakerBtcPk, fpBtcPks, @@ -494,7 +505,7 @@ func parseWatchStakingRequest( stakingOutputIdx, int64(currentParams.MinSlashingTxFeeSat), currentParams.SlashingRate, - currentParams.SlashingAddress, + currentParams.SlashingPkScript, stakerBtcPk, unbondingTime, network, @@ -561,7 +572,7 @@ func parseWatchStakingRequest( 0, int64(currentParams.MinSlashingTxFeeSat), currentParams.SlashingRate, - currentParams.SlashingAddress, + currentParams.SlashingPkScript, stakerBtcPk, unbondingTime, network, @@ -591,6 +602,12 @@ func parseWatchStakingRequest( return nil, fmt.Errorf("failed to watch staking tx. Unbonding tx value must be less than staking output value") } + if stakingTx.TxOut[stakingOutputIdx].Value-unbondingTx.TxOut[0].Value != int64(currentParams.UnbondingFee) { + return nil, fmt.Errorf("failed to watch staking tx. unbonding tx fee must be equal to %d, and it is equal to %d", + currentParams.UnbondingFee, + unbondingTx.TxOut[0].Value-stakingTx.TxOut[stakingOutputIdx].Value) + } + stakingTxHash := stakingTx.TxHash() unbondingTxPointsToStakingTxHash := unbondingTx.TxIn[0].PreviousOutPoint.Hash.IsEqual(&stakingTxHash) unbondingTxPointsToStakingOutputIdx := unbondingTx.TxIn[0].PreviousOutPoint.Index == stakingOutputIdx diff --git a/tools/go.mod b/tools/go.mod index 64d036a..335b2b0 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -2,7 +2,7 @@ module github.com/babylonlabs-io/btc-staker/tools go 1.22.3 -require github.com/babylonlabs-io/babylon v0.9.0 +require github.com/babylonlabs-io/babylon v0.9.3-0.20240904123958-b1e255a85e76 require ( cloud.google.com/go v0.112.0 // indirect diff --git a/tools/go.sum b/tools/go.sum index 8c9db55..e00eec2 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -270,8 +270,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX github.com/aws/aws-sdk-go v1.44.312 h1:llrElfzeqG/YOLFFKjg1xNpZCFJ2xraIi3PqSuP+95k= github.com/aws/aws-sdk-go v1.44.312/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonlabs-io/babylon v0.9.0 h1:dHZ9wUrI5XLaO4UIwJRgiCdnzFdi5yv7dpibbu6TDv0= -github.com/babylonlabs-io/babylon v0.9.0/go.mod h1:t7B4e+ooD2oYvAxkegtNKDL9bXe+vU29a8xnCQh+UKo= +github.com/babylonlabs-io/babylon v0.9.3-0.20240904123958-b1e255a85e76 h1:JOdd2H+bOYPyKYNyCcjT2lW7H76A4Pbfstk7n/Vo2Vc= +github.com/babylonlabs-io/babylon v0.9.3-0.20240904123958-b1e255a85e76/go.mod h1:9VUUAwVaalXiDdPZT65SPoawKWpp6ple6tBr8Vw0NI8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=