From 7d4f2bf454910dff8e5d499d5225f5137e616a73 Mon Sep 17 00:00:00 2001 From: KonradStaniec Date: Tue, 29 Oct 2024 08:14:08 +0100 Subject: [PATCH 1/4] more logs --- staker/babylontypes.go | 6 +++++- staker/types.go | 30 +++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/staker/babylontypes.go b/staker/babylontypes.go index f2ad7ae..477cd42 100644 --- a/staker/babylontypes.go +++ b/staker/babylontypes.go @@ -46,7 +46,11 @@ func (app *StakerApp) buildOwnedDelegation( slashingFee := app.getSlashingFee(externalData.babylonParams.MinSlashingTxFeeSat) - stakingSlashingTx, stakingSlashingSpendInfo, err := slashingTxForStakingTx( + app.logger.WithFields(logrus.Fields{ + "slashingFee": slashingFee, + }).Info("Before buidling of the slashing transaction") + + stakingSlashingTx, stakingSlashingSpendInfo, err := app.slashingTxForStakingTx( slashingFee, externalData, storedTx, diff --git a/staker/types.go b/staker/types.go index d0e22b4..641554b 100644 --- a/staker/types.go +++ b/staker/types.go @@ -9,6 +9,7 @@ import ( sdkmath "cosmossdk.io/math" "github.com/babylonlabs-io/babylon/btcstaking" staking "github.com/babylonlabs-io/babylon/btcstaking" + "github.com/sirupsen/logrus" bbn "github.com/babylonlabs-io/babylon/types" cl "github.com/babylonlabs-io/btc-staker/babylonclient" @@ -110,7 +111,7 @@ func createWitnessSignaturesForPubKeys( return signatures, nil } -func slashingTxForStakingTx( +func (app *StakerApp) slashingTxForStakingTx( slashingFee btcutil.Amount, delegationData *externalDelegationData, storedTx *stakerdb.StoredTransaction, @@ -119,6 +120,33 @@ func slashingTxForStakingTx( stakerPubKey := delegationData.stakerPublicKey lockSlashTxLockTime := delegationData.babylonParams.MinUnbondingTime + 1 + slashingRateFloat64, err := delegationData.babylonParams.SlashingRate.Float64() + if err != nil { + return nil, nil, fmt.Errorf("error converting slashing rate to float64: %w", err) + } + + stakingOutput := storedTx.StakingTx.TxOut[storedTx.StakingOutputIndex] + stakingAmount := stakingOutput.Value + + slashingAmount := btcutil.Amount(stakingAmount).MulF64(slashingRateFloat64) + if slashingAmount <= 0 { + return nil, nil, fmt.Errorf("fooo ") + } + + // Calculate the change amount + changeAmount := btcutil.Amount(stakingAmount) - slashingAmount - slashingFee + if changeAmount <= 0 { + return nil, nil, fmt.Errorf("fooo 2") + } + + app.logger.WithFields(logrus.Fields{ + "slashingFee": int64(slashingFee), + "stakingAmount": int64(stakingAmount), + "slashingRate": slashingRateFloat64, + "slashingAmount": int64(slashingAmount), + "changeAmount": int64(changeAmount), + }).Info("Before BuildSlashingTxFromStakingTxStrict") + slashingTx, err := staking.BuildSlashingTxFromStakingTxStrict( storedTx.StakingTx, storedTx.StakingOutputIndex, From c2a894820abfb0e0ea4c358bd08223def53e200e Mon Sep 17 00:00:00 2001 From: Hiep Mai Date: Tue, 29 Oct 2024 11:18:42 +0400 Subject: [PATCH 2/4] add build --- .github/workflows/publish.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 70f9e7b..2347a37 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -4,6 +4,7 @@ on: push: branches: - 'main' + - 'konradstaniec/more-logs-slashing' tags: - '*' From a8f9fb243ea4ff68b6f49d0b4580fc26618074b2 Mon Sep 17 00:00:00 2001 From: KonradStaniec Date: Tue, 29 Oct 2024 11:37:28 +0100 Subject: [PATCH 3/4] more logs --- staker/types.go | 132 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 1 deletion(-) diff --git a/staker/types.go b/staker/types.go index 641554b..3685f3c 100644 --- a/staker/types.go +++ b/staker/types.go @@ -20,6 +20,8 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/mempool" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcwallet/wallet/txrules" "github.com/btcsuite/btcwallet/wallet/txsizes" @@ -111,6 +113,134 @@ func createWitnessSignaturesForPubKeys( return signatures, nil } +func (app *StakerApp) buildSlashingTxFromOutpoint( + stakingOutput wire.OutPoint, + stakingAmount, fee int64, + slashingPkScript []byte, + changeAddress btcutil.Address, + slashingRate sdkmath.LegacyDec, +) (*wire.MsgTx, error) { + // Validate staking amount + if stakingAmount <= 0 { + return nil, fmt.Errorf("staking amount must be larger than 0") + } + + if len(slashingPkScript) == 0 { + return nil, fmt.Errorf("slashing pk script must not be empty") + } + + // Calculate the amount to be slashed + slashingRateFloat64, err := slashingRate.Float64() + if err != nil { + return nil, fmt.Errorf("error converting slashing rate to float64: %w", err) + } + slashingAmount := btcutil.Amount(stakingAmount).MulF64(slashingRateFloat64) + if slashingAmount <= 0 { + return nil, fmt.Errorf("slashing amout low") + } + + // Calculate the change amount + changeAmount := btcutil.Amount(stakingAmount) - slashingAmount - btcutil.Amount(fee) + if changeAmount <= 0 { + return nil, fmt.Errorf("change amount low") + } + // Generate script for change address + changeAddrScript, err := txscript.PayToAddrScript(changeAddress) + if err != nil { + return nil, err + } + + // Create a new btc transaction + tx := wire.NewMsgTx(wire.TxVersion) + // TODO: this builds input with sequence number equal to MaxTxInSequenceNum, which + // means this tx is not replaceable. + input := wire.NewTxIn(&stakingOutput, nil, nil) + tx.AddTxIn(input) + tx.AddTxOut(wire.NewTxOut(int64(slashingAmount), slashingPkScript)) + tx.AddTxOut(wire.NewTxOut(int64(changeAmount), changeAddrScript)) + + // Verify that the none of the outputs is a dust output. + for i, out := range tx.TxOut { + if mempool.IsDust(out, mempool.DefaultMinRelayTxFee) { + app.logger.WithFields(logrus.Fields{ + "slashingFee": int64(fee), + "stakingAmount": int64(stakingAmount), + "slashingRate": slashingRateFloat64, + "slashingAmount": int64(slashingAmount), + "changeAmount": int64(changeAmount), + "outputIndex": i, + "minimalRelayFee": mempool.DefaultMinRelayTxFee, + "slashPkScript": hex.EncodeToString(slashingPkScript), + "changeAddScript": hex.EncodeToString(changeAddrScript), + }).Info("Returning dust error") + + return nil, fmt.Errorf("dust output found") + } + } + + return tx, nil +} + +func getPossibleStakingOutput( + stakingTx *wire.MsgTx, + stakingOutputIdx uint32, +) (*wire.TxOut, error) { + if stakingTx == nil { + return nil, fmt.Errorf("provided staking transaction must not be nil") + } + + if int(stakingOutputIdx) >= len(stakingTx.TxOut) { + return nil, fmt.Errorf("invalid staking output index %d, tx has %d outputs", stakingOutputIdx, len(stakingTx.TxOut)) + } + + stakingOutput := stakingTx.TxOut[stakingOutputIdx] + + if !txscript.IsPayToTaproot(stakingOutput.PkScript) { + return nil, fmt.Errorf("must be pay to taproot output") + } + + return stakingOutput, nil +} + +func (app *StakerApp) BuildSlashingTxFromStakingTxStrict( + stakingTx *wire.MsgTx, + stakingOutputIdx uint32, + slashingPkScript []byte, + stakerPk *btcec.PublicKey, + slashChangeLockTime uint16, + fee int64, + slashingRate sdkmath.LegacyDec, + net *chaincfg.Params, +) (*wire.MsgTx, error) { + // Get the staking output at the specified index from the staking transaction + stakingOutput, err := getPossibleStakingOutput(stakingTx, stakingOutputIdx) + if err != nil { + return nil, err + } + + // Create an OutPoint for the staking output + stakingTxHash := stakingTx.TxHash() + stakingOutpoint := wire.NewOutPoint(&stakingTxHash, stakingOutputIdx) + + // Create taproot address committing to timelock script + si, err := staking.BuildRelativeTimelockTaprootScript( + stakerPk, + slashChangeLockTime, + net, + ) + + if err != nil { + return nil, err + } + + // Build slashing tx with the staking output information + return app.buildSlashingTxFromOutpoint( + *stakingOutpoint, + stakingOutput.Value, fee, + slashingPkScript, si.TapAddress, + slashingRate) +} + func (app *StakerApp) slashingTxForStakingTx( slashingFee btcutil.Amount, delegationData *externalDelegationData, @@ -147,7 +277,7 @@ func (app *StakerApp) slashingTxForStakingTx( "changeAmount": int64(changeAmount), }).Info("Before BuildSlashingTxFromStakingTxStrict") - slashingTx, err := staking.BuildSlashingTxFromStakingTxStrict( + slashingTx, err := app.BuildSlashingTxFromStakingTxStrict( storedTx.StakingTx, storedTx.StakingOutputIndex, delegationData.babylonParams.SlashingPkScript, From 8e68f329722a0722dcfd684bd3877d0eb9021f72 Mon Sep 17 00:00:00 2001 From: KonradStaniec Date: Tue, 29 Oct 2024 13:09:35 +0100 Subject: [PATCH 4/4] more logs --- babylonclient/babyloncontroller.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/babylonclient/babyloncontroller.go b/babylonclient/babyloncontroller.go index c995597..da609f1 100644 --- a/babylonclient/babyloncontroller.go +++ b/babylonclient/babyloncontroller.go @@ -452,6 +452,10 @@ func (bc *BabylonController) QueryStakingTracker() (*StakingTrackerResponse, err return nil, err } + bc.logger.WithFields(logrus.Fields{ + "slashingPkScript": hex.EncodeToString(response.Params.SlashingPkScript), + }).Info("slashing pk script from babylon") + // check early that the 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