From f73962de7088a36329e55708403cd970a8f56773 Mon Sep 17 00:00:00 2001 From: Vitalis Salis Date: Thu, 14 Dec 2023 16:11:46 +0400 Subject: [PATCH] feat: Covenant handles pre-signed unbonding txs (#180) --- README.md | 1 - clientcontroller/babylon.go | 97 ++++++------------ clientcontroller/interface.go | 15 +-- covenant/covenant.go | 183 +++++++++++----------------------- covenant/covenant_test.go | 27 ++--- go.mod | 3 +- go.sum | 6 +- itest/babylon_node_handler.go | 3 +- itest/e2e_test.go | 62 ------------ itest/test_manager.go | 140 ++++++++++++-------------- testutil/mocks/babylon.go | 76 ++------------ tools/go.mod | 3 +- tools/go.sum | 6 +- types/delegation.go | 5 +- 14 files changed, 184 insertions(+), 443 deletions(-) diff --git a/README.md b/README.md index 2b33473b..9b476acd 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,6 @@ $ make build ``` The above will lead to a build directory having the following structure: - ```bash $ ls build ├── eotsd diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 1ab24866..2708acd5 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -200,7 +200,7 @@ func (bc *BabylonController) CommitPubRandList( ValBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), StartHeight: startHeight, PubRandList: schnorrPubRandList, - Sig: &bip340Sig, + Sig: bip340Sig, } res, err := bc.reliablySendMsg(msg) @@ -216,40 +216,19 @@ func (bc *BabylonController) CommitPubRandList( func (bc *BabylonController) SubmitCovenantSigs( covPk *btcec.PublicKey, stakingTxHash string, - sigs [][]byte, -) (*types.TxResponse, error) { - - msg := &btcstakingtypes.MsgAddCovenantSig{ - Signer: bc.mustGetTxSigner(), - Pk: bbntypes.NewBIP340PubKeyFromBTCPK(covPk), - StakingTxHash: stakingTxHash, - Sigs: sigs, - } - - res, err := bc.reliablySendMsg(msg) - if err != nil { - return nil, err - } - - return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil -} - -// SubmitCovenantUnbondingSigs submits the Covenant signatures via a MsgAddCovenantUnbondingSigs to Babylon if the daemon runs in Covenant mode -// it returns tx hash and error -func (bc *BabylonController) SubmitCovenantUnbondingSigs( - covPk *btcec.PublicKey, - stakingTxHash string, + slashingSigs [][]byte, unbondingSig *schnorr.Signature, - slashUnbondingSigs [][]byte, + unbondingSlashingSigs [][]byte, ) (*types.TxResponse, error) { bip340UnbondingSig := bbntypes.NewBIP340SignatureFromBTCSig(unbondingSig) - msg := &btcstakingtypes.MsgAddCovenantUnbondingSigs{ + msg := &btcstakingtypes.MsgAddCovenantSigs{ Signer: bc.mustGetTxSigner(), Pk: bbntypes.NewBIP340PubKeyFromBTCPK(covPk), StakingTxHash: stakingTxHash, - UnbondingTxSig: &bip340UnbondingSig, - SlashingUnbondingTxSigs: slashUnbondingSigs, + SlashingTxSigs: slashingSigs, + UnbondingTxSig: bip340UnbondingSig, + SlashingUnbondingTxSigs: unbondingSlashingSigs, } res, err := bc.reliablySendMsg(msg) @@ -308,10 +287,6 @@ func (bc *BabylonController) QueryPendingDelegations(limit uint64) ([]*types.Del return bc.queryDelegationsWithStatus(btcstakingtypes.BTCDelegationStatus_PENDING, limit) } -func (bc *BabylonController) QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) { - return bc.queryDelegationsWithStatus(btcstakingtypes.BTCDelegationStatus_UNBONDING, limit) -} - // queryDelegationsWithStatus queries BTC delegations that need a Covenant signature // with the given status (either pending or unbonding) // it is only used when the program is running in Covenant mode @@ -643,6 +618,7 @@ func ConvertUndelegationType(undel *btcstakingtypes.BTCUndelegation) *types.Unde CovenantSlashingSigs: covenantSlashingSigs, CovenantUnbondingSigs: covenantUnbondingSigs, UnbondingTime: undel.UnbondingTime, + DelegatorUnbondingSig: undel.DelegatorUnbondingSig, } } @@ -656,23 +632,33 @@ func (bc *BabylonController) CreateBTCDelegation( stakingValue int64, stakingTxInfo *btcctypes.TransactionInfo, slashingTx *btcstakingtypes.BTCSlashingTx, - delSig *bbntypes.BIP340Signature, + delSlashingSig *bbntypes.BIP340Signature, + unbondingTx []byte, + unbondingTime uint32, + unbondingValue int64, + unbondingSlashingTx *btcstakingtypes.BTCSlashingTx, + delUnbondingSlashingSig *bbntypes.BIP340Signature, ) (*types.TxResponse, error) { valBtcPks := make([]bbntypes.BIP340PubKey, 0, len(valPks)) for _, v := range valPks { valBtcPks = append(valBtcPks, *bbntypes.NewBIP340PubKeyFromBTCPK(v)) } msg := &btcstakingtypes.MsgCreateBTCDelegation{ - Signer: bc.mustGetTxSigner(), - BabylonPk: delBabylonPk, - BtcPk: delBtcPk, - ValBtcPkList: valBtcPks, - Pop: pop, - StakingTime: stakingTime, - StakingValue: stakingValue, - StakingTx: stakingTxInfo, - SlashingTx: slashingTx, - DelegatorSig: delSig, + Signer: bc.mustGetTxSigner(), + BabylonPk: delBabylonPk, + Pop: pop, + BtcPk: delBtcPk, + ValBtcPkList: valBtcPks, + StakingTime: stakingTime, + StakingValue: stakingValue, + StakingTx: stakingTxInfo, + SlashingTx: slashingTx, + DelegatorSlashingSig: delSlashingSig, + UnbondingTx: unbondingTx, + UnbondingTime: unbondingTime, + UnbondingValue: unbondingValue, + UnbondingSlashingTx: unbondingSlashingTx, + DelegatorUnbondingSlashingSig: delUnbondingSlashingSig, } res, err := bc.reliablySendMsg(msg) @@ -683,31 +669,6 @@ func (bc *BabylonController) CreateBTCDelegation( return &types.TxResponse{TxHash: res.TxHash}, nil } -// Currently this is only used for e2e tests, probably does not need to add this into the interface -func (bc *BabylonController) CreateBTCUndelegation( - unbondingTx []byte, - unbondingTime uint32, - unbondingValue int64, - slashingTx *btcstakingtypes.BTCSlashingTx, - delSig *bbntypes.BIP340Signature, -) (*provider.RelayerTxResponse, error) { - msg := &btcstakingtypes.MsgBTCUndelegate{ - Signer: bc.mustGetTxSigner(), - UnbondingTx: unbondingTx, - UnbondingTime: unbondingTime, - UnbondingValue: unbondingValue, - SlashingTx: slashingTx, - DelegatorSlashingSig: delSig, - } - - res, err := bc.reliablySendMsg(msg) - if err != nil { - return nil, err - } - - return res, nil -} - // Insert BTC block header using rpc client // Currently this is only used for e2e tests, probably does not need to add it into the interface func (bc *BabylonController) InsertBtcBlockHeaders(headers []bbntypes.BTCHeaderBytes) (*provider.RelayerTxResponse, error) { diff --git a/clientcontroller/interface.go b/clientcontroller/interface.go index 4347e1c4..a9e3d2b7 100644 --- a/clientcontroller/interface.go +++ b/clientcontroller/interface.go @@ -79,22 +79,11 @@ type CovenantAPIs interface { // SubmitCovenantSigs submits Covenant signatures to the consumer chain, each corresponding to // a validator that the delegation is (re-)staked to // it returns tx hash and error - SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, sigs [][]byte) (*types.TxResponse, error) - - // SubmitCovenantUnbondingSigs submits the Covenant signatures for undelegation to the consumer chain - // it returns tx hash and error - SubmitCovenantUnbondingSigs( - covPk *btcec.PublicKey, - stakingTxHash string, - unbondingSig *schnorr.Signature, - slashUnbondingSigs [][]byte, - ) (*types.TxResponse, error) + SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, + sigs [][]byte, unbondingSig *schnorr.Signature, unbondingSlashingSigs [][]byte) (*types.TxResponse, error) // QueryPendingDelegations queries BTC delegations that are in status of pending QueryPendingDelegations(limit uint64) ([]*types.Delegation, error) - - // QueryUnbondingDelegations queries BTC delegations that are in status of unbonding - QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) } func NewClientController(chainName string, bbnConfig *config.BBNConfig, netParams *chaincfg.Params, logger *zap.Logger) (ClientController, error) { diff --git a/covenant/covenant.go b/covenant/covenant.go index 76881428..c842d589 100644 --- a/covenant/covenant.go +++ b/covenant/covenant.go @@ -107,7 +107,17 @@ func (ce *CovenantEmulator) UpdateParams() error { } // AddCovenantSignature adds a Covenant signature on the given Bitcoin delegation and submits it to Babylon +// TODO: break this function into smaller components func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*AddCovenantSigResponse, error) { + // 0. nil checks + if btcDel == nil { + return nil, fmt.Errorf("empty delegation") + } + + if btcDel.BtcUndelegation == nil { + return nil, fmt.Errorf("empty undelegation") + } + // 1. the quorum is already achieved, skip sending more sigs if btcDel.HasCovenantQuorum(ce.params.CovenantQuorum) { return nil, nil @@ -141,91 +151,23 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*Add return nil, fmt.Errorf("invalid txs in the delegation: %w", err) } - // 3. sign covenant sigs - covenantPrivKey, err := ce.getPrivKey() - if err != nil { - return nil, fmt.Errorf("failed to get Covenant private key: %w", err) - } - - stakingInfo, err := btcstaking.BuildStakingInfo( - btcDel.BtcPk, - btcDel.ValBtcPks, - ce.params.CovenantPks, - ce.params.CovenantQuorum, - btcDel.GetStakingTime(), - btcutil.Amount(btcDel.TotalSat), - &ce.config.BTCNetParams, - ) - if err != nil { - return nil, err - } - - slashingPathInfo, err := stakingInfo.SlashingPathSpendInfo() - if err != nil { - return nil, err - } - - covSigs := make([][]byte, 0, len(btcDel.ValBtcPks)) - for _, valPk := range btcDel.ValBtcPks { - encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) - if err != nil { - return nil, err - } - covenantSig, err := slashingTx.EncSign( - stakingMsgTx, - btcDel.StakingOutputIdx, - slashingPathInfo.GetPkScriptPath(), - covenantPrivKey, - encKey, - ) - if err != nil { - return nil, err - } - covSigs = append(covSigs, covenantSig.MustMarshal()) - } - - // 4. submit covenant sigs - res, err := ce.cc.SubmitCovenantSigs(ce.pk, stakingMsgTx.TxHash().String(), covSigs) - - if err != nil { - return nil, err - } - - return &AddCovenantSigResponse{TxHash: res.TxHash}, nil -} - -// AddCovenantUnbondingSignatures adds Covenant signature on the given Bitcoin delegation and submits it to Babylon -func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation) (*AddCovenantSigResponse, error) { - if del == nil { - return nil, fmt.Errorf("btc delegation is nil") - } - - if del.BtcUndelegation == nil { - return nil, fmt.Errorf("delegation does not have an unbonding transaction") - } - - // 1. skip sending sigs if the quorum has already been reached - if del.BtcUndelegation.HasAllSignatures(ce.params.CovenantQuorum) { - return nil, fmt.Errorf("undelegation of the delegation already has required signature from covenant") - } - - // 2. ensure that the unbonding tx and the slashing tx are valid - slashingMsgTx, _, err := bbntypes.NewBTCTxFromHex(del.BtcUndelegation.SlashingTxHex) + // 3. Check unbonding transaction + unbondingSlashingMsgTx, _, err := bbntypes.NewBTCTxFromHex(btcDel.BtcUndelegation.SlashingTxHex) if err != nil { return nil, err } - unbondingMsgTx, _, err := bbntypes.NewBTCTxFromHex(del.BtcUndelegation.UnbondingTxHex) + unbondingMsgTx, _, err := bbntypes.NewBTCTxFromHex(btcDel.BtcUndelegation.UnbondingTxHex) if err != nil { return nil, err } unbondingInfo, err := btcstaking.BuildUnbondingInfo( - del.BtcPk, - del.ValBtcPks, + btcDel.BtcPk, + btcDel.ValBtcPks, ce.params.CovenantPks, ce.params.CovenantQuorum, - uint16(del.BtcUndelegation.UnbondingTime), + uint16(btcDel.BtcUndelegation.UnbondingTime), btcutil.Amount(unbondingMsgTx.TxOut[0].Value), &ce.config.BTCNetParams, ) @@ -234,7 +176,7 @@ func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation } err = btcstaking.CheckTransactions( - slashingMsgTx, + unbondingSlashingMsgTx, unbondingMsgTx, 0, int64(ce.params.MinSlashingTxFeeSat), @@ -246,37 +188,58 @@ func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation return nil, fmt.Errorf("invalid txs in the undelegation: %w", err) } - // 3. Sign unbonding transaction + // 4. sign covenant staking sigs + covenantPrivKey, err := ce.getPrivKey() + if err != nil { + return nil, fmt.Errorf("failed to get Covenant private key: %w", err) + } + stakingInfo, err := btcstaking.BuildStakingInfo( - del.BtcPk, - del.ValBtcPks, + btcDel.BtcPk, + btcDel.ValBtcPks, ce.params.CovenantPks, ce.params.CovenantQuorum, - del.GetStakingTime(), - btcutil.Amount(del.TotalSat), + btcDel.GetStakingTime(), + btcutil.Amount(btcDel.TotalSat), &ce.config.BTCNetParams, ) if err != nil { return nil, err } - stakingTxUnbondingPathInfo, err := stakingInfo.UnbondingPathSpendInfo() + slashingPathInfo, err := stakingInfo.SlashingPathSpendInfo() if err != nil { return nil, err } - covenantPrivKey, err := ce.getPrivKey() - if err != nil { - return nil, fmt.Errorf("failed to get Covenant private key: %w", err) + + covSigs := make([][]byte, 0, len(btcDel.ValBtcPks)) + for _, valPk := range btcDel.ValBtcPks { + encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) + if err != nil { + return nil, err + } + covenantSig, err := slashingTx.EncSign( + stakingMsgTx, + btcDel.StakingOutputIdx, + slashingPathInfo.GetPkScriptPath(), + covenantPrivKey, + encKey, + ) + if err != nil { + return nil, err + } + covSigs = append(covSigs, covenantSig.MustMarshal()) } - stakingMsgTx, _, err := bbntypes.NewBTCTxFromHex(del.StakingTxHex) + + // 5. sign covenant unbonding sig + stakingTxUnbondingPathInfo, err := stakingInfo.UnbondingPathSpendInfo() if err != nil { return nil, err } - covenantUnbondingSignature, err := btcstaking.SignTxWithOneScriptSpendInputStrict( unbondingMsgTx, stakingMsgTx, - del.StakingOutputIdx, + btcDel.StakingOutputIdx, stakingTxUnbondingPathInfo.GetPkScriptPath(), covenantPrivKey, ) @@ -284,8 +247,8 @@ func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation return nil, fmt.Errorf("failed to sign unbonding tx: %w", err) } - // 4. Sign slash unbonding transaction - slashUnbondingTx, err := bstypes.NewBTCSlashingTxFromHex(del.BtcUndelegation.SlashingTxHex) + // 6. sign covenant unbonding slashing sig + slashUnbondingTx, err := bstypes.NewBTCSlashingTxFromHex(btcDel.BtcUndelegation.SlashingTxHex) if err != nil { return nil, err } @@ -295,8 +258,8 @@ func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation return nil, err } - covSlashingSigs := make([][]byte, 0, len(del.ValBtcPks)) - for _, valPk := range del.ValBtcPks { + covSlashingSigs := make([][]byte, 0, len(btcDel.ValBtcPks)) + for _, valPk := range btcDel.ValBtcPks { encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) if err != nil { return nil, err @@ -314,21 +277,14 @@ func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation covSlashingSigs = append(covSlashingSigs, covenantSig.MustMarshal()) } - // 5. submit covenant sigs - res, err := ce.cc.SubmitCovenantUnbondingSigs( - ce.pk, - stakingMsgTx.TxHash().String(), - covenantUnbondingSignature, - covSlashingSigs, - ) + // 7. submit covenant sigs + res, err := ce.cc.SubmitCovenantSigs(ce.pk, stakingMsgTx.TxHash().String(), covSigs, covenantUnbondingSignature, covSlashingSigs) if err != nil { return nil, err } - return &AddCovenantSigResponse{ - TxHash: res.TxHash, - }, nil + return &AddCovenantSigResponse{TxHash: res.TxHash}, nil } func (ce *CovenantEmulator) getPrivKey() (*btcec.PrivateKey, error) { @@ -359,7 +315,7 @@ func (ce *CovenantEmulator) covenantSigSubmissionLoop() { continue } - // 1. Get all pending delegations first, these are more important than the unbonding ones + // 1. Get all pending delegations dels, err := ce.cc.QueryPendingDelegations(limit) if err != nil { ce.logger.Debug("failed to get pending delegations", zap.Error(err)) @@ -381,29 +337,6 @@ func (ce *CovenantEmulator) covenantSigSubmissionLoop() { } } - // 2. Get all unbonding delegations - unbondingDels, err := ce.cc.QueryUnbondingDelegations(limit) - if err != nil { - ce.logger.Debug("failed to get unbonding delegations", zap.Error(err)) - continue - } - - if len(unbondingDels) == 0 { - ce.logger.Debug("no unbonding delegations are found") - } - - for _, d := range unbondingDels { - _, err := ce.AddCovenantUnbondingSignatures(d) - if err != nil { - delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(d.BtcPk).MarshalHex() - ce.logger.Error( - "failed to submit covenant signatures to the BTC undelegation", - zap.String("del_btc_pk", delPkHex), - zap.Error(err), - ) - } - } - case <-ce.quit: ce.logger.Debug("exiting covenant signature submission loop") return diff --git a/covenant/covenant_test.go b/covenant/covenant_test.go index 2899c87a..88b78816 100644 --- a/covenant/covenant_test.go +++ b/covenant/covenant_test.go @@ -11,7 +11,6 @@ import ( bbntypes "github.com/babylonchain/babylon/types" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" - "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" "go.uber.org/zap" @@ -94,8 +93,7 @@ func FuzzAddCovenantSig(f *testing.F) { StakingOutputIdx: 0, SlashingTxHex: testInfo.SlashingTx.ToHexStr(), } - - // generate covenant sigs + // generate covenant staking sigs slashingSpendInfo, err := testInfo.StakingInfo.SlashingPathSpendInfo() require.NoError(t, err) covSigs := make([][]byte, 0, len(valPks)) @@ -112,18 +110,6 @@ func FuzzAddCovenantSig(f *testing.F) { covSigs = append(covSigs, covenantSig.MustMarshal()) } - // check the sigs are expected - expectedTxHash := testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT().SubmitCovenantSigs( - covKeyPair.PublicKey, - testInfo.StakingTx.TxHash().String(), - covSigs, - ). - Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - res, err := ce.AddCovenantSignature(btcDel) - require.NoError(t, err) - require.Equal(t, expectedTxHash, res.TxHash) - // generate undelegation unbondingTime := uint16(params.FinalizationTimeoutBlocks) + 1 unbondingValue := int64(btcDel.TotalSat) - 1000 @@ -160,6 +146,7 @@ func FuzzAddCovenantSig(f *testing.F) { btcDel.BtcUndelegation = undel stakingTxUnbondingPathInfo, err := testInfo.StakingInfo.UnbondingPathSpendInfo() require.NoError(t, err) + // generate covenant unbonding sigs unbondingCovSig, err := btcstaking.SignTxWithOneScriptSpendInputStrict( unbondingTxMsg, testInfo.StakingTx, @@ -168,6 +155,7 @@ func FuzzAddCovenantSig(f *testing.F) { covKeyPair.PrivateKey, ) require.NoError(t, err) + // generate covenant unbonding slashing sigs unbondingCovSlashingSigs := make([][]byte, 0, len(valPks)) for _, valPk := range valPks { encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) @@ -184,17 +172,16 @@ func FuzzAddCovenantSig(f *testing.F) { } // check the sigs are expected - expectedTxHash = testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT().QueryUnbondingDelegations(gomock.Any()). - Return([]*types.Delegation{btcDel}, nil).AnyTimes() - mockClientController.EXPECT().SubmitCovenantUnbondingSigs( + expectedTxHash := testutil.GenRandomHexStr(r, 32) + mockClientController.EXPECT().SubmitCovenantSigs( covKeyPair.PublicKey, testInfo.StakingTx.TxHash().String(), + covSigs, unbondingCovSig, unbondingCovSlashingSigs, ). Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - res, err = ce.AddCovenantUnbondingSignatures(btcDel) + res, err := ce.AddCovenantSignature(btcDel) require.NoError(t, err) require.Equal(t, expectedTxHash, res.TxHash) }) diff --git a/go.mod b/go.mod index d22cdd7c..13bfb2bc 100644 --- a/go.mod +++ b/go.mod @@ -100,6 +100,7 @@ require ( github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/distribution/reference v0.5.0 // indirect + github.com/docker/docker v23.0.1+incompatible // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/emicklei/dot v1.6.0 // indirect @@ -237,7 +238,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b github.com/babylonchain/rpc-client => github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231128092309-ad2ef0696dc1 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/go.sum b/go.sum index 09710a9e..6b5dd0af 100644 --- a/go.sum +++ b/go.sum @@ -279,8 +279,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/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959 h1:DbDrHk6UXI9Og0tnQscfJriTSseyD81DYTALQ9bnO1M= -github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959/go.mod h1:hUJ0eyIpD9p9S+weU48es4P0FYDgIo2Nfg39AFiKj8Q= +github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b h1:FAadQ5l5ORQa/P8IRRtHXibK7g7MHOzhKxmvObY42OI= +github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b/go.mod h1:6wqL7SJBWltXMNXgFsvavB1bR5Fft0yChfRLamBtrAY= github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231128092309-ad2ef0696dc1 h1:Cf1aNeXcSfZczocNxZZ1mM+KU4NDopzaIyi1fSoezxo= github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231128092309-ad2ef0696dc1/go.mod h1:M/tRKH7cc0gpAqCEpHTiaYob/6xoTD4v3A4FZQ3Y3ks= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -460,6 +460,8 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WA github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v23.0.1+incompatible h1:vjgvJZxprTTE1A37nm+CLNAdwu6xZekyoiVlUZEINcY= +github.com/docker/docker v23.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/itest/babylon_node_handler.go b/itest/babylon_node_handler.go index 52d21905..9b1362d4 100644 --- a/itest/babylon_node_handler.go +++ b/itest/babylon_node_handler.go @@ -131,7 +131,8 @@ func NewBabylonNodeHandler(t *testing.T, covenantPk *types.BIP340PubKey) *Babylo "--chain-id=chain-test", "--additional-sender-account", fmt.Sprintf("--slashing-address=%s", slashingAddr), - fmt.Sprintf("--covenant-pk=%s", covenantPk.MarshalHex()), + fmt.Sprintf("--covenant-pks=%s", covenantPk.MarshalHex()), + "--covenant-quorum=1", ) var stderr bytes.Buffer diff --git a/itest/e2e_test.go b/itest/e2e_test.go index 6f928e34..fc08cf60 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -178,65 +178,3 @@ func TestFastSync(t *testing.T) { require.NoError(t, err) require.True(t, currentHeight < finalizedHeight+uint64(n)) } - -func TestCovenantLifeCycle(t *testing.T) { - tm, valInsList := StartManagerWithValidator(t, 1) - defer tm.Stop(t) - - valIns := valInsList[0] - - params := tm.GetParams(t) - - valPk := valIns.MustGetBtcPk() - valBtcPk := valIns.GetBtcPkBIP340() - // send BTC delegation and make sure it's deep enough in btclightclient module - delData := tm.InsertBTCDelegation(t, []*btcec.PublicKey{valPk}, stakingTime, stakingAmount, params) - dels := tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) - del := dels[0] - err := tm.Va.Stop() - require.NoError(t, err) - - tm.InsertBTCUnbonding( - t, - del, - delData.DelegatorPrivKey, - delData.ChangeAddr, - params, - ) - - require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valBtcPk, 1000) - if err != nil { - return false - } - return len(dels) == 1 && dels[0].BtcUndelegation != nil - }, eventuallyWaitTimeOut, eventuallyPollTime) - - t.Log("undelegation is found, waiting for covenant sigs") - - // after providing validator unbonding signature, we should wait for covenant to provide both valid signatures - require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valBtcPk, 1000) - if err != nil { - return false - } - - if len(dels) != 1 { - return false - } - - del := dels[0] - - if del.BtcUndelegation == nil { - return false - } - - if len(del.BtcUndelegation.CovenantSlashingSigs) != 0 && len(del.BtcUndelegation.CovenantUnbondingSigs) != 0 { - return true - } - - return false - }, 1*time.Minute, eventuallyPollTime) - - t.Log("covenant signatures for undelegation are submitted") -} diff --git a/itest/test_manager.go b/itest/test_manager.go index a7a934a3..7c1aaa58 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -267,7 +267,8 @@ func (tm *TestManager) WaitForValNActiveDels(t *testing.T, btcPk *bbntypes.BIP34 if err != nil { return false } - return len(dels) == n && CheckDelsStatus(dels, currentBtcTip.Height, params.FinalizationTimeoutBlocks, bstypes.BTCDelegationStatus_ACTIVE) + return len(dels) == n && CheckDelsStatus(dels, currentBtcTip.Height, params.FinalizationTimeoutBlocks, + params.CovenantQuorum, bstypes.BTCDelegationStatus_ACTIVE) }, eventuallyWaitTimeOut, eventuallyPollTime) t.Logf("the delegation is active, validators should start voting") @@ -275,10 +276,10 @@ func (tm *TestManager) WaitForValNActiveDels(t *testing.T, btcPk *bbntypes.BIP34 return dels } -func CheckDelsStatus(dels []*types.Delegation, btcHeight uint64, w uint64, status bstypes.BTCDelegationStatus) bool { +func CheckDelsStatus(dels []*types.Delegation, btcHeight uint64, w uint64, covenantQuorum uint32, status bstypes.BTCDelegationStatus) bool { allChecked := true for _, d := range dels { - s := getDelStatus(d, btcHeight, w) + s := getDelStatus(d, btcHeight, w, covenantQuorum) if s != status { allChecked = false } @@ -287,30 +288,27 @@ func CheckDelsStatus(dels []*types.Delegation, btcHeight uint64, w uint64, statu return allChecked } -func getDelStatus(del *types.Delegation, btcHeight uint64, w uint64) bstypes.BTCDelegationStatus { - if del.BtcUndelegation != nil { - if del.BtcUndelegation.CovenantSlashingSigs != nil && - del.BtcUndelegation.CovenantUnbondingSigs != nil { - return bstypes.BTCDelegationStatus_UNBONDED - } - // If we received an undelegation but is still does not have all required signature, - // delegation receives UNBONING status. - // Voting power from this delegation is removed from the total voting power and now we - // are waiting for signatures from validator and covenant for delegation to become expired. - // For now we do not have any unbonding time on the consumer chain, only time lock on BTC chain - // we may consider adding unbonding time on the consumer chain later to avoid situation where - // we can lose to much voting power in to short time. - return bstypes.BTCDelegationStatus_UNBONDING +func getDelStatus(del *types.Delegation, btcHeight uint64, w uint64, covenantQuorum uint32) bstypes.BTCDelegationStatus { + if del.BtcUndelegation.DelegatorUnbondingSig != nil { + // this means the delegator has signed unbonding signature, and Babylon will consider + // this BTC delegation unbonded directly + return bstypes.BTCDelegationStatus_UNBONDED } - if del.StartHeight <= btcHeight && btcHeight+w <= del.EndHeight { - if del.CovenantSigs != nil { - return bstypes.BTCDelegationStatus_ACTIVE - } else { - return bstypes.BTCDelegationStatus_PENDING - } + if btcHeight < del.StartHeight || btcHeight+w > del.EndHeight { + // staking tx's timelock has not begun, or is less than w BTC + // blocks left, or is expired + return bstypes.BTCDelegationStatus_UNBONDED + } + + // at this point, BTC delegation has an active timelock, and Babylon is not + // aware of unbonding tx with delegator's signature + if del.HasCovenantQuorum(covenantQuorum) { + return bstypes.BTCDelegationStatus_ACTIVE } - return bstypes.BTCDelegationStatus_UNBONDED + + // no covenant quorum yet, pending + return bstypes.BTCDelegationStatus_PENDING } func (tm *TestManager) CheckBlockFinalization(t *testing.T, height uint64, num int) { @@ -466,66 +464,23 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, validatorPks []*btcec.P ) require.NoError(t, err) - // submit the BTC delegation to Babylon - _, err = tm.BabylonClient.CreateBTCDelegation( - delBabylonPubKey.(*secp256k1.PubKey), - bbntypes.NewBIP340PubKeyFromBTCPK(delBtcPubKey), - validatorPks, - pop, - uint32(stakingTime), - stakingAmount, - txInfo, - testStakingInfo.SlashingTx, - delegatorSig) - require.NoError(t, err) - - t.Log("successfully submitted a BTC delegation") - - return &TestDelegationData{ - DelegatorPrivKey: delBtcPrivKey, - DelegatorKey: delBtcPubKey, - DelegatorBabylonPrivKey: delBabylonPrivKey.(*secp256k1.PrivKey), - DelegatorBabylonKey: delBabylonPubKey.(*secp256k1.PubKey), - ValidatorPks: validatorPks, - StakingTx: testStakingInfo.StakingTx, - SlashingTx: testStakingInfo.SlashingTx, - StakingTxInfo: txInfo, - DelegatorSig: delegatorSig, - SlashingAddr: params.SlashingAddress.String(), - ChangeAddr: changeAddress.String(), - StakingTime: stakingTime, - StakingAmount: stakingAmount, - } -} - -func (tm *TestManager) InsertBTCUnbonding( - t *testing.T, - actualDel *types.Delegation, - delSK *btcec.PrivateKey, - changeAddress string, - params *types.StakingParams, -) { - stakingMsgTx, _, err := bbntypes.NewBTCTxFromHex(actualDel.StakingTxHex) - require.NoError(t, err) - stakingTxHash := stakingMsgTx.TxHash() - unbondingTime := uint16(params.FinalizationTimeoutBlocks) + 1 - unbondingValue := int64(actualDel.TotalSat - 1000) - - r := rand.New(rand.NewSource(time.Now().UnixNano())) + unbondingValue := stakingAmount - 1000 + stakingTxHash := testStakingInfo.StakingTx.TxHash() testUnbondingInfo := datagen.GenBTCUnbondingSlashingInfo( r, t, btcNetworkParams, - delSK, - actualDel.ValBtcPks, + delBtcPrivKey, + validatorPks, params.CovenantPks, params.CovenantQuorum, wire.NewOutPoint(&stakingTxHash, 0), unbondingTime, unbondingValue, - params.SlashingAddress.String(), changeAddress, + params.SlashingAddress.String(), + changeAddress.String(), params.SlashingRate, ) @@ -538,19 +493,48 @@ func (tm *TestManager) InsertBTCUnbonding( unbondingTxMsg, 0, unbondingSlashingPathInfo.GetPkScriptPath(), - delSK, + delBtcPrivKey, ) require.NoError(t, err) serializedUnbondingTx, err := bbntypes.SerializeBTCTx(testUnbondingInfo.UnbondingTx) require.NoError(t, err) - _, err = tm.BabylonClient.CreateBTCUndelegation( - serializedUnbondingTx, uint32(unbondingTime), unbondingValue, testUnbondingInfo.SlashingTx, unbondingSig, - ) + // submit the BTC delegation to Babylon + _, err = tm.BabylonClient.CreateBTCDelegation( + delBabylonPubKey.(*secp256k1.PubKey), + bbntypes.NewBIP340PubKeyFromBTCPK(delBtcPubKey), + validatorPks, + pop, + uint32(stakingTime), + stakingAmount, + txInfo, + testStakingInfo.SlashingTx, + delegatorSig, + serializedUnbondingTx, + uint32(unbondingTime), + unbondingValue, + testUnbondingInfo.SlashingTx, + unbondingSig) require.NoError(t, err) - t.Log("successfully submitted a BTC undelegation") + t.Log("successfully submitted a BTC delegation") + + return &TestDelegationData{ + DelegatorPrivKey: delBtcPrivKey, + DelegatorKey: delBtcPubKey, + DelegatorBabylonPrivKey: delBabylonPrivKey.(*secp256k1.PrivKey), + DelegatorBabylonKey: delBabylonPubKey.(*secp256k1.PubKey), + ValidatorPks: validatorPks, + StakingTx: testStakingInfo.StakingTx, + SlashingTx: testStakingInfo.SlashingTx, + StakingTxInfo: txInfo, + DelegatorSig: delegatorSig, + SlashingAddr: params.SlashingAddress.String(), + ChangeAddr: changeAddress.String(), + StakingTime: stakingTime, + StakingAmount: stakingAmount, + } } func (tm *TestManager) GetParams(t *testing.T) *types.StakingParams { diff --git a/testutil/mocks/babylon.go b/testutil/mocks/babylon.go index 7aee9cc3..c98901fe 100644 --- a/testutil/mocks/babylon.go +++ b/testutil/mocks/babylon.go @@ -171,21 +171,6 @@ func (mr *MockClientControllerMockRecorder) QueryStakingParams() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryStakingParams", reflect.TypeOf((*MockClientController)(nil).QueryStakingParams)) } -// QueryUnbondingDelegations mocks base method. -func (m *MockClientController) QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryUnbondingDelegations", limit) - ret0, _ := ret[0].([]*types.Delegation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryUnbondingDelegations indicates an expected call of QueryUnbondingDelegations. -func (mr *MockClientControllerMockRecorder) QueryUnbondingDelegations(limit interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryUnbondingDelegations", reflect.TypeOf((*MockClientController)(nil).QueryUnbondingDelegations), limit) -} - // QueryValidatorSlashed mocks base method. func (m *MockClientController) QueryValidatorSlashed(valPk *btcec.PublicKey) (bool, error) { m.ctrl.T.Helper() @@ -247,33 +232,18 @@ func (mr *MockClientControllerMockRecorder) SubmitBatchFinalitySigs(valPk, block } // SubmitCovenantSigs mocks base method. -func (m *MockClientController) SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, sigs [][]byte) (*types.TxResponse, error) { +func (m *MockClientController) SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, sigs [][]byte, unbondingSig *schnorr.Signature, unbondingSlashingSigs [][]byte) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitCovenantSigs", covPk, stakingTxHash, sigs) + ret := m.ctrl.Call(m, "SubmitCovenantSigs", covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // SubmitCovenantSigs indicates an expected call of SubmitCovenantSigs. -func (mr *MockClientControllerMockRecorder) SubmitCovenantSigs(covPk, stakingTxHash, sigs interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantSigs", reflect.TypeOf((*MockClientController)(nil).SubmitCovenantSigs), covPk, stakingTxHash, sigs) -} - -// SubmitCovenantUnbondingSigs mocks base method. -func (m *MockClientController) SubmitCovenantUnbondingSigs(covPk *btcec.PublicKey, stakingTxHash string, unbondingSig *schnorr.Signature, slashUnbondingSigs [][]byte) (*types.TxResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitCovenantUnbondingSigs", covPk, stakingTxHash, unbondingSig, slashUnbondingSigs) - ret0, _ := ret[0].(*types.TxResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SubmitCovenantUnbondingSigs indicates an expected call of SubmitCovenantUnbondingSigs. -func (mr *MockClientControllerMockRecorder) SubmitCovenantUnbondingSigs(covPk, stakingTxHash, unbondingSig, slashUnbondingSigs interface{}) *gomock.Call { +func (mr *MockClientControllerMockRecorder) SubmitCovenantSigs(covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantUnbondingSigs", reflect.TypeOf((*MockClientController)(nil).SubmitCovenantUnbondingSigs), covPk, stakingTxHash, unbondingSig, slashUnbondingSigs) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantSigs", reflect.TypeOf((*MockClientController)(nil).SubmitCovenantSigs), covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs) } // SubmitFinalitySig mocks base method. @@ -517,47 +487,17 @@ func (mr *MockCovenantAPIsMockRecorder) QueryPendingDelegations(limit interface{ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryPendingDelegations", reflect.TypeOf((*MockCovenantAPIs)(nil).QueryPendingDelegations), limit) } -// QueryUnbondingDelegations mocks base method. -func (m *MockCovenantAPIs) QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryUnbondingDelegations", limit) - ret0, _ := ret[0].([]*types.Delegation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryUnbondingDelegations indicates an expected call of QueryUnbondingDelegations. -func (mr *MockCovenantAPIsMockRecorder) QueryUnbondingDelegations(limit interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryUnbondingDelegations", reflect.TypeOf((*MockCovenantAPIs)(nil).QueryUnbondingDelegations), limit) -} - // SubmitCovenantSigs mocks base method. -func (m *MockCovenantAPIs) SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, sigs [][]byte) (*types.TxResponse, error) { +func (m *MockCovenantAPIs) SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, sigs [][]byte, unbondingSig *schnorr.Signature, unbondingSlashingSigs [][]byte) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitCovenantSigs", covPk, stakingTxHash, sigs) + ret := m.ctrl.Call(m, "SubmitCovenantSigs", covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // SubmitCovenantSigs indicates an expected call of SubmitCovenantSigs. -func (mr *MockCovenantAPIsMockRecorder) SubmitCovenantSigs(covPk, stakingTxHash, sigs interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantSigs", reflect.TypeOf((*MockCovenantAPIs)(nil).SubmitCovenantSigs), covPk, stakingTxHash, sigs) -} - -// SubmitCovenantUnbondingSigs mocks base method. -func (m *MockCovenantAPIs) SubmitCovenantUnbondingSigs(covPk *btcec.PublicKey, stakingTxHash string, unbondingSig *schnorr.Signature, slashUnbondingSigs [][]byte) (*types.TxResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitCovenantUnbondingSigs", covPk, stakingTxHash, unbondingSig, slashUnbondingSigs) - ret0, _ := ret[0].(*types.TxResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SubmitCovenantUnbondingSigs indicates an expected call of SubmitCovenantUnbondingSigs. -func (mr *MockCovenantAPIsMockRecorder) SubmitCovenantUnbondingSigs(covPk, stakingTxHash, unbondingSig, slashUnbondingSigs interface{}) *gomock.Call { +func (mr *MockCovenantAPIsMockRecorder) SubmitCovenantSigs(covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantUnbondingSigs", reflect.TypeOf((*MockCovenantAPIs)(nil).SubmitCovenantUnbondingSigs), covPk, stakingTxHash, unbondingSig, slashUnbondingSigs) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantSigs", reflect.TypeOf((*MockCovenantAPIs)(nil).SubmitCovenantSigs), covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs) } diff --git a/tools/go.mod b/tools/go.mod index 51c21d95..9c318e5a 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -81,6 +81,7 @@ require ( github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/distribution/reference v0.5.0 // indirect + github.com/docker/docker v23.0.1+incompatible // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/emicklei/dot v1.6.0 // indirect @@ -211,7 +212,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b // Downgraded to stable version see: https://github.com/cosmos/cosmos-sdk/pull/14952 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/tools/go.sum b/tools/go.sum index cf095a22..6b2e2198 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -272,8 +272,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX github.com/aws/aws-sdk-go v1.44.224 h1:09CiaaF35nRmxrzWZ2uRq5v6Ghg/d2RiPjZnSgtt+RQ= github.com/aws/aws-sdk-go v1.44.224/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959 h1:DbDrHk6UXI9Og0tnQscfJriTSseyD81DYTALQ9bnO1M= -github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959/go.mod h1:hUJ0eyIpD9p9S+weU48es4P0FYDgIo2Nfg39AFiKj8Q= +github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b h1:FAadQ5l5ORQa/P8IRRtHXibK7g7MHOzhKxmvObY42OI= +github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b/go.mod h1:6wqL7SJBWltXMNXgFsvavB1bR5Fft0yChfRLamBtrAY= 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= @@ -441,6 +441,8 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WA github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v23.0.1+incompatible h1:vjgvJZxprTTE1A37nm+CLNAdwu6xZekyoiVlUZEINcY= +github.com/docker/docker v23.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/types/delegation.go b/types/delegation.go index de53d4cb..92014754 100644 --- a/types/delegation.go +++ b/types/delegation.go @@ -1,6 +1,7 @@ package types import ( + bbn "github.com/babylonchain/babylon/types" "math" "github.com/btcsuite/btcd/btcec/v2" @@ -40,7 +41,7 @@ type Delegation struct { // HasCovenantQuorum returns whether a delegation has sufficient sigs // from Covenant members to make a quorum func (d *Delegation) HasCovenantQuorum(quorum uint32) bool { - return uint32(len(d.CovenantSigs)) >= quorum + return uint32(len(d.CovenantSigs)) >= quorum && d.BtcUndelegation.HasAllSignatures(quorum) } func (d *Delegation) GetStakingTime() uint16 { @@ -74,6 +75,8 @@ type Undelegation struct { // (i.e., SK corresponding to covenant_pk in params) // It must be provided after processing undelagate message by the consumer chain CovenantUnbondingSigs []*CovenantSchnorrSigInfo + // The delegator signature for the unbonding tx + DelegatorUnbondingSig *bbn.BIP340Signature } func (ud *Undelegation) HasCovenantQuorumOnSlashing(quorum uint32) bool {