Skip to content

Commit

Permalink
hotfix: StakingOutputIdx is not set in delegation type conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
gitferry authored Apr 2, 2024
2 parents 78bff6d + 6ef9258 commit e2de00e
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 15 deletions.
21 changes: 11 additions & 10 deletions clientcontroller/babylon.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,16 +247,17 @@ func ConvertDelegationType(del *btcstakingtypes.BTCDelegation) *types.Delegation
}

return &types.Delegation{
BtcPk: del.BtcPk.MustToBTCPK(),
FpBtcPks: fpBtcPks,
TotalSat: del.TotalSat,
StartHeight: del.StartHeight,
EndHeight: del.EndHeight,
StakingTxHex: stakingTxHex,
SlashingTxHex: slashingTxHex,
CovenantSigs: covenantSigs,
UnbondingTime: del.UnbondingTime,
BtcUndelegation: undelegation,
BtcPk: del.BtcPk.MustToBTCPK(),
FpBtcPks: fpBtcPks,
TotalSat: del.TotalSat,
StartHeight: del.StartHeight,
EndHeight: del.EndHeight,
StakingTxHex: stakingTxHex,
SlashingTxHex: slashingTxHex,
StakingOutputIdx: del.StakingOutputIdx,
CovenantSigs: covenantSigs,
UnbondingTime: del.UnbondingTime,
BtcUndelegation: undelegation,
}
}

Expand Down
10 changes: 9 additions & 1 deletion covenant/covenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package covenant
import (
"bytes"
"fmt"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"strings"
"sync"
"time"

"github.com/btcsuite/btcd/btcec/v2/schnorr"

"github.com/avast/retry-go/v4"
"github.com/btcsuite/btcd/btcec/v2"

Expand Down Expand Up @@ -169,6 +170,13 @@ func (ce *CovenantEmulator) AddCovenantSignatures(btcDels []*types.Delegation) (
uint16(unbondingTime),
&ce.config.BTCNetParams,
); err != nil {
ce.logger.Error("invalid delegation",
zap.String("staker_pk", bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.BtcPk).MarshalHex()),
zap.String("finality_provider_pk", bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.FpBtcPks[0]).MarshalHex()),
zap.String("staking_tx_hex", btcDel.StakingTxHex),
zap.String("slashing_tx_hex", btcDel.SlashingTxHex),
zap.Error(err),
)
return nil, fmt.Errorf("invalid txs in the delegation: %w", err)
}

Expand Down
4 changes: 3 additions & 1 deletion covenant/covenant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ func FuzzAddCovenantSig(f *testing.F) {
stakingTxBytes, err := bbntypes.SerializeBTCTx(testInfo.StakingTx)
require.NoError(t, err)
startHeight := datagen.RandomInt(r, 1000) + 100
stakingOutputIdx, err := bbntypes.GetOutputIdxInBTCTx(testInfo.StakingTx, testInfo.StakingInfo.StakingOutput)
require.NoError(t, err)
btcDel := &types.Delegation{
BtcPk: delPK,
FpBtcPks: fpPks,
Expand All @@ -91,7 +93,7 @@ func FuzzAddCovenantSig(f *testing.F) {
TotalSat: uint64(stakingValue),
UnbondingTime: uint32(unbondingTime),
StakingTxHex: hex.EncodeToString(stakingTxBytes),
StakingOutputIdx: 0,
StakingOutputIdx: stakingOutputIdx,
SlashingTxHex: testInfo.SlashingTx.ToHexStr(),
}
btcDels = append(btcDels, btcDel)
Expand Down
7 changes: 4 additions & 3 deletions itest/test_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
covcc "github.com/babylonchain/covenant-emulator/clientcontroller"
covcfg "github.com/babylonchain/covenant-emulator/config"
"github.com/babylonchain/covenant-emulator/covenant"
"github.com/babylonchain/covenant-emulator/testutil"
"github.com/babylonchain/covenant-emulator/types"
)

Expand Down Expand Up @@ -238,7 +239,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe
require.NoError(t, err)

unbondingTime := uint16(tm.StakingParams.MinimumUnbondingTime()) + 1
testStakingInfo := datagen.GenBTCStakingSlashingInfo(
testStakingInfo := testutil.GenBTCStakingSlashingInfo(
r,
t,
btcNetworkParams,
Expand Down Expand Up @@ -293,7 +294,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe
// delegator sig
delegatorSig, err := testStakingInfo.SlashingTx.Sign(
testStakingInfo.StakingTx,
0,
1,
slashignSpendInfo.GetPkScriptPath(),
delBtcPrivKey,
)
Expand All @@ -310,7 +311,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe
fpPks,
params.CovenantPks,
params.CovenantQuorum,
wire.NewOutPoint(&stakingTxHash, 0),
wire.NewOutPoint(&stakingTxHash, 1),
unbondingTime,
unbondingValue,
params.SlashingAddress.String(),
Expand Down
138 changes: 138 additions & 0 deletions testutil/datagen.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,31 @@ import (
"time"

sdkmath "cosmossdk.io/math"
"github.com/babylonchain/babylon/btcstaking"
"github.com/babylonchain/babylon/testutil/datagen"
bstypes "github.com/babylonchain/babylon/x/btcstaking/types"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/stretchr/testify/require"

"github.com/babylonchain/covenant-emulator/types"
)

type TestStakingSlashingInfo struct {
StakingTx *wire.MsgTx
SlashingTx *bstypes.BTCSlashingTx
StakingInfo *btcstaking.StakingInfo
}

type spendableOut struct {
prevOut wire.OutPoint
amount btcutil.Amount
}

func GenRandomHexStr(r *rand.Rand, length uint64) string {
randBytes := datagen.GenRandomByteArray(r, length)
return hex.EncodeToString(randBytes)
Expand Down Expand Up @@ -67,3 +84,124 @@ func GenBtcPublicKeys(r *rand.Rand, t *testing.T, num int) []*btcec.PublicKey {

return pks
}

func GenBTCStakingSlashingInfo(
r *rand.Rand,
t testing.TB,
btcNet *chaincfg.Params,
stakerSK *btcec.PrivateKey,
fpPKs []*btcec.PublicKey,
covenantPKs []*btcec.PublicKey,
covenantQuorum uint32,
stakingTimeBlocks uint16,
stakingValue int64,
slashingAddress string,
slashingRate sdkmath.LegacyDec,
slashingChangeLockTime uint16,
) *TestStakingSlashingInfo {
// an arbitrary input
unbondingTxFee := r.Int63n(1000) + 1
spend := makeSpendableOutWithRandOutPoint(r, btcutil.Amount(stakingValue+unbondingTxFee))
outPoint := &spend.prevOut
return GenBTCStakingSlashingInfoWithOutPoint(
r,
t,
btcNet,
outPoint,
stakerSK,
fpPKs,
covenantPKs,
covenantQuorum,
stakingTimeBlocks,
stakingValue,
slashingAddress,
slashingRate,
slashingChangeLockTime,
)
}

func makeSpendableOutWithRandOutPoint(r *rand.Rand, amount btcutil.Amount) spendableOut {
out := randOutPoint(r)

return spendableOut{
prevOut: out,
amount: amount,
}
}

func GenBTCStakingSlashingInfoWithOutPoint(
r *rand.Rand,
t testing.TB,
btcNet *chaincfg.Params,
outPoint *wire.OutPoint,
stakerSK *btcec.PrivateKey,
fpPKs []*btcec.PublicKey,
covenantPKs []*btcec.PublicKey,
covenantQuorum uint32,
stakingTimeBlocks uint16,
stakingValue int64,
slashingAddress string,
slashingRate sdkmath.LegacyDec,
slashingChangeLockTime uint16,
) *TestStakingSlashingInfo {

stakingInfo, err := btcstaking.BuildStakingInfo(
stakerSK.PubKey(),
fpPKs,
covenantPKs,
covenantQuorum,
stakingTimeBlocks,
btcutil.Amount(stakingValue),
btcNet,
)

require.NoError(t, err)
tx := wire.NewMsgTx(2)

// 2 outputs for changes and staking output
changeAddrScript, err := datagen.GenRandomPubKeyHashScript(r, btcNet)
require.NoError(t, err)
require.False(t, txscript.GetScriptClass(changeAddrScript) == txscript.NonStandardTy)

tx.AddTxOut(wire.NewTxOut(10000, changeAddrScript)) // output for change

// add the given tx input
txIn := wire.NewTxIn(outPoint, nil, nil)
tx.AddTxIn(txIn)
tx.AddTxOut(stakingInfo.StakingOutput)

// construct slashing tx
slashingAddrBtc, err := btcutil.DecodeAddress(slashingAddress, btcNet)
require.NoError(t, err)

slashingMsgTx, err := btcstaking.BuildSlashingTxFromStakingTxStrict(
tx,
uint32(1),
slashingAddrBtc,
stakerSK.PubKey(),
slashingChangeLockTime,
2000,
slashingRate,
btcNet)
require.NoError(t, err)
slashingTx, err := bstypes.NewBTCSlashingTxFromMsgTx(slashingMsgTx)
require.NoError(t, err)

return &TestStakingSlashingInfo{
StakingTx: tx,
SlashingTx: slashingTx,
StakingInfo: stakingInfo,
}
}

func randOutPoint(r *rand.Rand) wire.OutPoint {
hash, _ := chainhash.NewHash(datagen.GenRandomByteArray(r, chainhash.HashSize))
// TODO this will be deterministic without seed but for now it is not that
// important
idx := r.Uint32()

return wire.OutPoint{
Hash: *hash,
Index: idx,
}
}

0 comments on commit e2de00e

Please sign in to comment.