From 1dfc9c88278dbd67268c8545424c9fc05020f080 Mon Sep 17 00:00:00 2001 From: Runchao Han Date: Thu, 7 Dec 2023 07:54:01 +1100 Subject: [PATCH] btcstaking: presigning unbonding tx (#135) --- go.mod | 2 +- proto/babylon/btcstaking/v1/btcstaking.proto | 35 +- proto/babylon/btcstaking/v1/tx.proto | 103 +- test/e2e/btc_staking_e2e_test.go | 277 +--- .../configurer/chain/commands_btcstaking.go | 99 +- .../configurer/chain/queries_btcstaking.go | 22 +- testutil/datagen/btc_transaction.go | 10 +- testutil/datagen/btcstaking.go | 192 ++- testutil/datagen/covenant.go | 59 + testutil/datagen/finality.go | 3 +- testutil/datagen/raw_checkpoint.go | 7 +- types/btc_schnorr_sig.go | 5 +- types/btc_schnorr_sig_test.go | 2 +- x/btcstaking/client/cli/tx.go | 241 +-- x/btcstaking/client/cli/utils.go | 49 + x/btcstaking/keeper/btc_delegators.go | 64 +- x/btcstaking/keeper/grpc_query_test.go | 115 -- x/btcstaking/keeper/msg_server.go | 532 +++--- x/btcstaking/keeper/msg_server_test.go | 540 +++--- .../keeper/voting_power_table_test.go | 11 +- x/btcstaking/types/btc_delegation.go | 90 +- x/btcstaking/types/btc_delegation_test.go | 3 + x/btcstaking/types/btc_slashing_tx.go | 3 +- x/btcstaking/types/btc_undelegation.go | 7 +- x/btcstaking/types/btc_undelegation_test.go | 17 +- x/btcstaking/types/btcstaking.pb.go | 251 +-- x/btcstaking/types/codec.go | 8 +- x/btcstaking/types/errors.go | 1 + x/btcstaking/types/msg.go | 99 +- x/btcstaking/types/tx.pb.go | 1445 +++++++---------- 30 files changed, 1862 insertions(+), 2430 deletions(-) create mode 100644 testutil/datagen/covenant.go create mode 100644 x/btcstaking/client/cli/utils.go diff --git a/go.mod b/go.mod index 5dd4cfceb..843c075d4 100644 --- a/go.mod +++ b/go.mod @@ -48,6 +48,7 @@ require ( github.com/cosmos/ibc-go/modules/capability v1.0.0 github.com/cosmos/ibc-go/v8 v8.0.0 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 + github.com/docker/docker v23.0.1+incompatible github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.3 github.com/hashicorp/go-metrics v0.5.1 @@ -161,7 +162,6 @@ require ( github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect github.com/distribution/reference v0.5.0 // indirect github.com/docker/cli v23.0.1+incompatible // indirect - github.com/docker/docker v23.0.1+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/emicklei/dot v1.6.0 // indirect diff --git a/proto/babylon/btcstaking/v1/btcstaking.proto b/proto/babylon/btcstaking/v1/btcstaking.proto index 681f58d38..0fddb4e6e 100644 --- a/proto/babylon/btcstaking/v1/btcstaking.proto +++ b/proto/babylon/btcstaking/v1/btcstaking.proto @@ -112,18 +112,24 @@ message BTCUndelegation { // It is partially signed by SK corresponding to btc_pk, but not signed by // validator or covenant yet. bytes slashing_tx = 3 [ (gogoproto.customtype) = "BTCSlashingTx" ]; + // delegator_unbonding_sig is the signature on the unbonding tx + // by the delegator (i.e., SK corresponding to btc_pk). + // It effectively proves that the delegator wants to unbond and thus + // Babylon will consider this BTC delegation unbonded. Delegator's BTC + // on Bitcoin will be unbonded after timelock + bytes delegator_unbonding_sig = 4 [ (gogoproto.customtype) = "github.com/babylonchain/babylon/types.BIP340Signature" ]; // delegator_slashing_sig is the signature on the slashing tx // by the delegator (i.e., SK corresponding to btc_pk). // It will be a part of the witness for the unbonding tx output. - bytes delegator_slashing_sig = 4 [ (gogoproto.customtype) = "github.com/babylonchain/babylon/types.BIP340Signature" ]; + bytes delegator_slashing_sig = 5 [ (gogoproto.customtype) = "github.com/babylonchain/babylon/types.BIP340Signature" ]; // covenant_slashing_sigs is a list of adaptor signatures on the slashing tx // by each covenant member // It will be a part of the witness for the staking tx output. - repeated CovenantAdaptorSignatures covenant_slashing_sigs = 5; + repeated CovenantAdaptorSignatures covenant_slashing_sigs = 6; // covenant_unbonding_sig_list is the list of signatures on the unbonding tx // by covenant members // It must be provided after processing undelagate message by Babylon - repeated SignatureInfo covenant_unbonding_sig_list = 6; + repeated SignatureInfo covenant_unbonding_sig_list = 7; } @@ -151,28 +157,21 @@ message BTCDelegatorDelegationIndex { repeated bytes staking_tx_hash_list = 1; } -// BTCDelegationStatus is the status of a delegation. There are two possible state -// transition paths: -// 1. PENDING -> ACTIVE -> UNBONDED - this is the typical path when timelock of staking -// transaction expires. -// 2. PENDING _> ACTIVE -> UNBONDING -> UNBONDED - this is the path when staker requests undelegation through -// MsgBTCUndelegate message. +// BTCDelegationStatus is the status of a delegation. The state transition path is +// PENDING -> ACTIVE -> UNBONDED with two possibilities: +// 1. the typical path when timelock of staking transaction expires. +// 2. the path when staker requests early undelegation through MsgBTCUndelegate message. enum BTCDelegationStatus { - // PENDING defines a delegation that is waiting for a covenant signature to become active. + // PENDING defines a delegation that is waiting for covenant signatures to become active. PENDING = 0; // ACTIVE defines a delegation that has voting power ACTIVE = 1; - // UNBONDING defines a delegation that is being unbonded i.e it received an unbonding tx - // from staker, but not yet received signatures from validator and covenant. - // Delegation in this state already lost its voting power. - UNBONDING = 2; // UNBONDED defines a delegation no longer has voting power: // - either reaching the end of staking transaction timelock - // - or receiving unbonding tx and then receiving signatures from validator and covenant for this - // unbonding tx. - UNBONDED = 3; + // - or receiving unbonding tx with signatures from staker and covenant committee + UNBONDED = 2; // ANY is any of the above status - ANY = 4; + ANY = 3; } // SignatureInfo is a BIP-340 signature together with its signer's BIP-340 PK diff --git a/proto/babylon/btcstaking/v1/tx.proto b/proto/babylon/btcstaking/v1/tx.proto index b8564c08f..4cbad4fb8 100644 --- a/proto/babylon/btcstaking/v1/tx.proto +++ b/proto/babylon/btcstaking/v1/tx.proto @@ -13,6 +13,7 @@ import "babylon/btcstaking/v1/pop.proto"; option go_package = "github.com/babylonchain/babylon/x/btcstaking/types"; // Msg defines the Msg service. +// TODO: handle unbonding tx with full witness service Msg { option (cosmos.msg.v1.service) = true; @@ -20,16 +21,12 @@ service Msg { rpc CreateBTCValidator(MsgCreateBTCValidator) returns (MsgCreateBTCValidatorResponse); // CreateBTCDelegation creates a new BTC delegation rpc CreateBTCDelegation(MsgCreateBTCDelegation) returns (MsgCreateBTCDelegationResponse); - // BtcUndelegate undelegates funds from exsitng btc delegation - rpc BTCUndelegate(MsgBTCUndelegate) returns (MsgBTCUndelegateResponse); - // AddCovenantSig handles a signature from covenant for slashing tx of staking tx for delegation - rpc AddCovenantSig(MsgAddCovenantSig) returns (MsgAddCovenantSigResponse); - // AddCovenantUnbondingSigs handles two signatures from covenant for: - // - unbonding tx submitted to babylon by staker - // - slashing tx corresponding to unbonding tx submitted to babylon by staker - rpc AddCovenantUnbondingSigs(MsgAddCovenantUnbondingSigs) returns (MsgAddCovenantUnbondingSigsResponse); + // AddCovenantSigs handles signatures from a covenant member + rpc AddCovenantSigs(MsgAddCovenantSigs) returns (MsgAddCovenantSigsResponse); // UpdateParams updates the btcstaking module parameters. rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse); + // BTCUndelegate handles a signature on unbonding tx from its delegator + rpc BTCUndelegate(MsgBTCUndelegate) returns (MsgBTCUndelegateResponse); } // MsgCreateBTCValidator is the message for creating a BTC validator @@ -79,40 +76,32 @@ message MsgCreateBTCDelegation { // slashing_tx is the slashing tx // Note that the tx itself does not contain signatures, which are off-chain. bytes slashing_tx = 9 [ (gogoproto.customtype) = "BTCSlashingTx" ]; - // delegator_sig is the signature on the slashing tx by the delegator (i.e., SK corresponding to btc_pk). + // delegator_slashing_sig is the signature on the slashing tx by the delegator (i.e., SK corresponding to btc_pk). // It will be a part of the witness for the staking tx output. // The staking tx output further needs signatures from covenant and validator in // order to be spendable. - bytes delegator_sig = 10 [ (gogoproto.customtype) = "github.com/babylonchain/babylon/types.BIP340Signature" ]; -} -// MsgCreateBTCDelegationResponse is the response for MsgCreateBTCDelegation -message MsgCreateBTCDelegationResponse {} + bytes delegator_slashing_sig = 10 [ (gogoproto.customtype) = "github.com/babylonchain/babylon/types.BIP340Signature" ]; -// MsgBTCUndelegate is the message undelegating existing and active delegation -message MsgBTCUndelegate { - option (cosmos.msg.v1.signer) = "signer"; - - string signer = 1; + /// fields related to on-demand unbonding // unbonding_tx is bitcoin unbonding transaction i.e transaction that spends // staking output and sends it to the unbonding output - bytes unbonding_tx = 2; + bytes unbonding_tx = 11; // unbonding_time is the time lock used in unbonding transaction - uint32 unbonding_time = 3; + uint32 unbonding_time = 12; // unbonding_value is amount of satoshis locked in unbonding output. // NOTE: staking_value and unbonding_value could be different because of the difference between the fee for staking tx and that for unbonding - int64 unbonding_value = 4; - // slashing_tx is the slashing tx which slash unbonding contract + int64 unbonding_value = 13; + // unbonding_slashing_tx is the slashing tx which slash unbonding contract // Note that the tx itself does not contain signatures, which are off-chain. - bytes slashing_tx = 5 [ (gogoproto.customtype) = "BTCSlashingTx" ]; - // delegator_slashing_sig is the signature on the slashing tx by the delegator (i.e., SK corresponding to btc_pk). - bytes delegator_slashing_sig = 6 [ (gogoproto.customtype) = "github.com/babylonchain/babylon/types.BIP340Signature" ]; + bytes unbonding_slashing_tx = 14 [ (gogoproto.customtype) = "BTCSlashingTx" ]; + // delegator_unbonding_slashing_sig is the signature on the slashing tx by the delegator (i.e., SK corresponding to btc_pk). + bytes delegator_unbonding_slashing_sig = 15 [ (gogoproto.customtype) = "github.com/babylonchain/babylon/types.BIP340Signature" ]; } +// MsgCreateBTCDelegationResponse is the response for MsgCreateBTCDelegation +message MsgCreateBTCDelegationResponse {} -// MsgBtcUndelegateResponse is the response for MsgBtcUndelegate -message MsgBTCUndelegateResponse {} - -// MsgAddCovenantSig is the message for handling a signature from covenant -message MsgAddCovenantSig { +// MsgAddCovenantSigs is the message for handling signatures from a covenant member +message MsgAddCovenantSigs { option (cosmos.msg.v1.signer) = "signer"; string signer = 1; @@ -124,10 +113,36 @@ message MsgAddCovenantSig { // sigs is a list of adaptor signatures of the covenant // the order of sigs should respect the order of validators // of the corresponding delegation - repeated bytes sigs = 4; + repeated bytes slashing_tx_sigs = 4; + // unbonding_tx_sig is the signature of the covenant on the unbonding tx submitted to babylon + // the signature follows encoding in BIP-340 spec + bytes unbonding_tx_sig = 5 [ (gogoproto.customtype) = "github.com/babylonchain/babylon/types.BIP340Signature" ]; + // slashing_unbonding_tx_sigs is a list of adaptor signatures of the covenant + // on slashing tx corresponding to unbonding tx submitted to babylon + // the order of sigs should respect the order of validators + // of the corresponding delegation + repeated bytes slashing_unbonding_tx_sigs = 6; } -// MsgAddCovenantSigResponse is the response for MsgAddCovenantSig -message MsgAddCovenantSigResponse {} +// MsgAddCovenantSigsResponse is the response for MsgAddCovenantSigs +message MsgAddCovenantSigsResponse {} + + +// MsgBTCUndelegate is the message for handling signature on unbonding tx +// from its delegator. This signature effectively proves that the delegator +// wants to unbond this BTC delegation +message MsgBTCUndelegate { + option (cosmos.msg.v1.signer) = "signer"; + + string signer = 1; + // staking_tx_hash is the hash of the staking tx. + // It uniquely identifies a BTC delegation + string staking_tx_hash = 2; + // unbonding_tx_sig is the signature of the staker on the unbonding tx submitted to babylon + // the signature follows encoding in BIP-340 spec + bytes unbonding_tx_sig = 3 [ (gogoproto.customtype) = "github.com/babylonchain/babylon/types.BIP340Signature" ]; +} +// MsgBTCUndelegateResponse is the response for MsgBTCUndelegate +message MsgBTCUndelegateResponse {} // MsgUpdateParams defines a message for updating btcstaking module parameters. message MsgUpdateParams { @@ -147,25 +162,3 @@ message MsgUpdateParams { // MsgUpdateParamsResponse is the response to the MsgUpdateParams message. message MsgUpdateParamsResponse {} - -// MsgAddCovenantUnbondingSigs is the message for handling a signature from covenant -message MsgAddCovenantUnbondingSigs { - option (cosmos.msg.v1.signer) = "signer"; - - string signer = 1; - // pk is the BTC public key of the covenant member - bytes pk = 2 [ (gogoproto.customtype) = "github.com/babylonchain/babylon/types.BIP340PubKey" ]; - // staking_tx_hash is the hash of the staking tx. - // (val_pk, del_pk, staking_tx_hash) uniquely identifies a BTC delegation - string staking_tx_hash = 3; - // unbonding_tx_sig is the signature of the covenant on the unbonding tx submitted to babylon - // the signature follows encoding in BIP-340 spec - bytes unbonding_tx_sig = 4 [ (gogoproto.customtype) = "github.com/babylonchain/babylon/types.BIP340Signature" ]; - // slashing_unbonding_tx_sigs is a list of adaptor signatures of the covenant - // on slashing tx corresponding to unbonding tx submitted to babylon - // the order of sigs should respect the order of validators - // of the corresponding delegation - repeated bytes slashing_unbonding_tx_sigs = 5; -} -// MsgAddCovenantSigResponse is the response for MsgAddCovenantSig -message MsgAddCovenantUnbondingSigsResponse {} diff --git a/test/e2e/btc_staking_e2e_test.go b/test/e2e/btc_staking_e2e_test.go index 51f675add..332d00027 100644 --- a/test/e2e/btc_staking_e2e_test.go +++ b/test/e2e/btc_staking_e2e_test.go @@ -8,15 +8,12 @@ import ( "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/wire" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/suite" - "github.com/babylonchain/babylon/btcstaking" "github.com/babylonchain/babylon/crypto/eots" - asig "github.com/babylonchain/babylon/crypto/schnorr-adaptor-signature" "github.com/babylonchain/babylon/test/e2e/configurer" "github.com/babylonchain/babylon/test/e2e/initialization" "github.com/babylonchain/babylon/test/e2e/util" @@ -133,7 +130,7 @@ func (s *BTCStakingTestSuite) Test1CreateBTCValidatorAndDelegation() { // generate proper delegator sig delegatorSig, err := testStakingInfo.SlashingTx.Sign( stakingMsgTx, - 0, + datagen.StakingOutIdx, stakingSlashingPathInfo.GetPkScriptPath(), delBTCSK, ) @@ -150,6 +147,27 @@ func (s *BTCStakingTestSuite) Test1CreateBTCValidatorAndDelegation() { } stakingTxInfo := btcctypes.NewTransactionInfoFromSpvProof(blockWithStakingTx.SpvProof) + // generate BTC undelegation stuff + stkTxHash := testStakingInfo.StakingTx.TxHash() + unbondingTime := initialization.BabylonBtcFinalizationPeriod + 1 + unbondingValue := stakingValue - datagen.UnbondingTxFee // TODO: parameterise fee + testUnbondingInfo := datagen.GenBTCUnbondingSlashingInfo( + r, + s.T(), + net, + delBTCSK, + []*btcec.PublicKey{btcVal.BtcPk.MustToBTCPK()}, + covenantBTCPKs, + covenantQuorum, + wire.NewOutPoint(&stkTxHash, datagen.StakingOutIdx), + uint16(unbondingTime), + unbondingValue, + params.SlashingAddress, changeAddress.EncodeAddress(), + params.SlashingRate, + ) + delUnbondingSlashingSig, err := testUnbondingInfo.GenDelSlashingTxSig(delBTCSK) + s.NoError(err) + // submit the message for creating BTC delegation nonValidatorNode.CreateBTCDelegation( delBabylonSK.PubKey().(*secp256k1.PubKey), @@ -161,6 +179,11 @@ func (s *BTCStakingTestSuite) Test1CreateBTCValidatorAndDelegation() { btcutil.Amount(stakingValue), testStakingInfo.SlashingTx, delegatorSig, + testUnbondingInfo.UnbondingTx, + testUnbondingInfo.SlashingTx, + uint16(unbondingTime), + btcutil.Amount(unbondingValue), + delUnbondingSlashingSig, ) // wait for a block so that above txs take effect @@ -202,23 +225,11 @@ func (s *BTCStakingTestSuite) Test2SubmitCovenantSignature() { stakingTxHash := stakingMsgTx.TxHash().String() params := nonValidatorNode.QueryBTCStakingParams() - covenantBTCPKs := []*btcec.PublicKey{} - for _, covenantPK := range params.CovenantPks { - covenantBTCPKs = append(covenantBTCPKs, covenantPK.MustToBTCPK()) - } validatorBTCPKs, err := bbn.NewBTCPKsFromBIP340PKs(pendingDel.ValBtcPkList) s.NoError(err) - stakingInfo, err := btcstaking.BuildStakingInfo( - pendingDel.BtcPk.MustToBTCPK(), - validatorBTCPKs, - covenantBTCPKs, - params.CovenantQuorum, - pendingDel.GetStakingTime(), - btcutil.Amount(pendingDel.TotalSat), - net, - ) + stakingInfo, err := pendingDel.GetStakingInfo(params, net) s.NoError(err) stakingSlashingPathInfo, err := stakingInfo.SlashingPathSpendInfo() @@ -227,7 +238,8 @@ func (s *BTCStakingTestSuite) Test2SubmitCovenantSignature() { /* generate and insert new covenant signature, in order to activate the BTC delegation */ - covenantSigs, err := datagen.GenCovenantAdaptorSigs( + // covenant signatures on slashing tx + covenantSlashingSigs, err := datagen.GenCovenantAdaptorSigs( covenantSKs, validatorBTCPKs, stakingMsgTx, @@ -235,22 +247,58 @@ func (s *BTCStakingTestSuite) Test2SubmitCovenantSignature() { slashingTx, ) s.NoError(err) - s.GreaterOrEqual(uint32(len(covenantSigs)), covenantQuorum) + + // cov Schnorr sigs on unbonding signature + unbondingPathInfo, err := stakingInfo.UnbondingPathSpendInfo() + s.NoError(err) + unbondingTx, err := bbn.NewBTCTxFromBytes(pendingDel.BtcUndelegation.UnbondingTx) + s.NoError(err) + + covUnbondingSigs, err := datagen.GenCovenantUnbondingSigs( + covenantSKs, + stakingMsgTx, + pendingDel.StakingOutputIdx, + unbondingPathInfo.GetPkScriptPath(), + unbondingTx, + ) + s.NoError(err) + + unbondingInfo, err := pendingDel.GetUnbondingInfo(params, net) + s.NoError(err) + unbondingSlashingPathInfo, err := unbondingInfo.SlashingPathSpendInfo() + s.NoError(err) + covenantUnbondingSlashingSigs, err := datagen.GenCovenantAdaptorSigs( + covenantSKs, + validatorBTCPKs, + unbondingTx, + unbondingSlashingPathInfo.GetPkScriptPath(), + pendingDel.BtcUndelegation.SlashingTx, + ) + s.NoError(err) + for i := 0; i < int(covenantQuorum); i++ { - nonValidatorNode.AddCovenantSigs(covenantSigs[i].CovPk, stakingTxHash, covenantSigs[i].AdaptorSigs) + nonValidatorNode.AddCovenantSigs( + covenantSlashingSigs[i].CovPk, + stakingTxHash, + covenantSlashingSigs[i].AdaptorSigs, + bbn.NewBIP340SignatureFromBTCSig(covUnbondingSigs[i]), + covenantUnbondingSlashingSigs[i].AdaptorSigs, + ) + // wait for a block so that above txs take effect + nonValidatorNode.WaitForNextBlock() } // wait for a block so that above txs take effect nonValidatorNode.WaitForNextBlock() nonValidatorNode.WaitForNextBlock() - // ensure the BTC delegation has covenant sig now + // ensure the BTC delegation has covenant sigs now activeDelsSet := nonValidatorNode.QueryBTCValidatorDelegations(btcVal.BtcPk.MarshalHex()) s.Len(activeDelsSet, 1) activeDels := activeDelsSet[0] s.Len(activeDels.Dels, 1) activeDel := activeDels.Dels[0] - s.NotNil(activeDel.CovenantSigs) + s.True(activeDel.HasCovenantQuorums(covenantQuorum)) // wait for a block so that above txs take effect and the voting power table // is updated in the next block's BeginBlock @@ -434,189 +482,22 @@ func (s *BTCStakingTestSuite) Test5SubmitStakerUnbonding() { activeDel := activeDels.Dels[0] s.NotNil(activeDel.CovenantSigs) - // params for covenantPk and slashing address - params := nonValidatorNode.QueryBTCStakingParams() - // get covenant BTC PKs - covenantBTCPKs := []*btcec.PublicKey{} - for _, covenantPK := range params.CovenantPks { - covenantBTCPKs = append(covenantBTCPKs, covenantPK.MustToBTCPK()) - } - - validatorBTCPKs := []*btcec.PublicKey{} - for _, valPK := range activeDel.ValBtcPkList { - validatorBTCPKs = append(validatorBTCPKs, valPK.MustToBTCPK()) - } - + // staking tx hash stakingMsgTx, err := bbn.NewBTCTxFromBytes(activeDel.StakingTx) s.NoError(err) - stakingTxHash := stakingMsgTx.TxHash().String() - stakingTxChainHash, err := chainhash.NewHashFromStr(stakingTxHash) - s.NoError(err) - - fee := int64(1000) - testUnbondingInfo := datagen.GenBTCUnbondingSlashingInfo( - r, - s.T(), - net, - delBTCSK, - validatorBTCPKs, - covenantBTCPKs, - params.CovenantQuorum, - wire.NewOutPoint(stakingTxChainHash, uint32(activeDel.StakingOutputIdx)), - initialization.BabylonBtcFinalizationPeriod+1, - stakingValue-fee, - params.SlashingAddress, changeAddress.EncodeAddress(), - params.SlashingRate, - ) - s.NoError(err) - - unbondingTxMsg := testUnbondingInfo.UnbondingTx - - unbondingTxSlashingPathInfo, err := testUnbondingInfo.UnbondingInfo.SlashingPathSpendInfo() - s.NoError(err) + stakingTxHash := stakingMsgTx.TxHash() - slashingTxSig, err := testUnbondingInfo.SlashingTx.Sign( - unbondingTxMsg, - 0, - unbondingTxSlashingPathInfo.GetPkScriptPath(), - delBTCSK, - ) + // delegator signs unbonding tx + params := nonValidatorNode.QueryBTCStakingParams() + delUnbondingSig, err := activeDel.SignUnbondingTx(params, net, delBTCSK) s.NoError(err) // submit the message for creating BTC undelegation - nonValidatorNode.CreateBTCUndelegation( - unbondingTxMsg, - testUnbondingInfo.SlashingTx, - initialization.BabylonBtcFinalizationPeriod+1, - btcutil.Amount(stakingValue-fee), - slashingTxSig, - ) + nonValidatorNode.BTCUndelegate(&stakingTxHash, delUnbondingSig) // wait for a block so that above txs take effect nonValidatorNode.WaitForNextBlock() - valDelegations := nonValidatorNode.QueryBTCValidatorDelegations(btcVal.BtcPk.MarshalHex()) - s.Len(valDelegations, 1) - s.Len(valDelegations[0].Dels, 1) - delegation := valDelegations[0].Dels[0] - s.NotNil(delegation.BtcUndelegation) -} - -// Test6SubmitStakerUnbonding is an end-to-end test for covenant and validator submitting signatures -// for unbonding transaction -func (s *BTCStakingTestSuite) Test6SubmitUnbondingSignatures() { - chainA := s.configurer.GetChainConfig(0) - chainA.WaitUntilHeight(1) - nonValidatorNode, err := chainA.GetNodeAtIndex(2) - s.NoError(err) - // wait for a block so that above txs take effect - nonValidatorNode.WaitForNextBlock() - - allDelegations := nonValidatorNode.QueryBTCValidatorDelegations(btcVal.BtcPk.MarshalHex()) - s.Len(allDelegations, 1) - delegatorDelegations := allDelegations[0] - s.Len(delegatorDelegations.Dels, 1) - delegation := delegatorDelegations.Dels[0] - - s.NotNil(delegation.BtcUndelegation) - s.Empty(delegation.BtcUndelegation.CovenantUnbondingSigList) - s.Len(delegation.BtcUndelegation.CovenantSlashingSigs, 0) - - // params for covenantPk and slashing address - params := nonValidatorNode.QueryBTCStakingParams() - // get covenant BTC PKs - covenantBTCPKs := []*btcec.PublicKey{} - for _, covenantPK := range params.CovenantPks { - covenantBTCPKs = append(covenantBTCPKs, covenantPK.MustToBTCPK()) - } - - validatorBTCPKs := []*btcec.PublicKey{} - for _, valPK := range delegation.ValBtcPkList { - validatorBTCPKs = append(validatorBTCPKs, valPK.MustToBTCPK()) - } - - stakingInfo, err := btcstaking.BuildStakingInfo( - delegation.BtcPk.MustToBTCPK(), - validatorBTCPKs, - covenantBTCPKs, - params.CovenantQuorum, - delegation.GetStakingTime(), - btcutil.Amount(delegation.TotalSat), - net, - ) - s.NoError(err) - - unbondingTx, err := bbn.NewBTCTxFromBytes(delegation.BtcUndelegation.UnbondingTx) - s.NoError(err) - stakingTx, err := bbn.NewBTCTxFromBytes(delegation.StakingTx) - s.NoError(err) - stakingTxHash := stakingTx.TxHash().String() - - unbondingInfo, err := btcstaking.BuildUnbondingInfo( - delegation.BtcPk.MustToBTCPK(), - validatorBTCPKs, - covenantBTCPKs, - params.CovenantQuorum, - uint16(delegation.BtcUndelegation.UnbondingTime), - btcutil.Amount(unbondingTx.TxOut[0].Value), - net, - ) - s.NoError(err) - - // Next send covenant signatures. - // First covenant signature on unbonding tx - stakingTxUnbondigPathInfo, err := stakingInfo.UnbondingPathSpendInfo() - s.NoError(err) - - for i := 0; i < int(covenantQuorum); i++ { - covenantUnbondingSignature, err := btcstaking.SignTxWithOneScriptSpendInputStrict( - unbondingTx, - stakingTx, - delegation.StakingOutputIdx, - stakingTxUnbondigPathInfo.GetPkScriptPath(), - covenantSKs[i], - ) - s.NoError(err) - - covenantUnbondingSig := bbn.NewBIP340SignatureFromBTCSig(covenantUnbondingSignature) - - // Next covenant signature on unbonding slashing tx - unbondingTxSlashingPath, err := unbondingInfo.SlashingPathSpendInfo() - s.NoError(err) - - // slashing signatures, each encrypted by a restaked BTC validator's PK - covenantSlashingSigs := []*asig.AdaptorSignature{} - for _, valPK := range validatorBTCPKs { - encKey, err := asig.NewEncryptionKeyFromBTCPK(valPK) - s.NoError(err) - covenantSlashingSig, err := delegation.BtcUndelegation.SlashingTx.EncSign( - unbondingTx, - 0, - unbondingTxSlashingPath.GetPkScriptPath(), - covenantSKs[i], - encKey, - ) - s.NoError(err) - covenantSlashingSigs = append(covenantSlashingSigs, covenantSlashingSig) - } - - nonValidatorNode.AddCovenantUnbondingSigs( - ¶ms.CovenantPks[i], stakingTxHash, &covenantUnbondingSig, covenantSlashingSigs) - } - - nonValidatorNode.WaitForNextBlock() - nonValidatorNode.WaitForNextBlock() - - // Check all signatures are properly registered - allDelegationsWithSigs := nonValidatorNode.QueryBTCValidatorDelegations(btcVal.BtcPk.MarshalHex()) - s.Len(allDelegationsWithSigs, 1) - delegationWithSigs := allDelegationsWithSigs[0].Dels[0] - s.NotNil(delegationWithSigs.BtcUndelegation) - s.NotEmpty(delegationWithSigs.BtcUndelegation.CovenantUnbondingSigList) - s.NotNil(delegationWithSigs.BtcUndelegation.CovenantSlashingSigs) - btcTip, err := nonValidatorNode.QueryTip() - s.NoError(err) - s.Equal( - bstypes.BTCDelegationStatus_UNBONDED, - delegationWithSigs.GetStatus(btcTip.Height, initialization.BabylonBtcFinalizationPeriod, params.CovenantQuorum), - ) + unbondedDels := nonValidatorNode.QueryUnbondedDelegations() + s.Len(unbondedDels, 1) + s.Equal(stakingTxHash, unbondedDels[0].MustGetStakingTxHash()) } diff --git a/test/e2e/configurer/chain/commands_btcstaking.go b/test/e2e/configurer/chain/commands_btcstaking.go index 98bba8bd9..505bc47db 100644 --- a/test/e2e/configurer/chain/commands_btcstaking.go +++ b/test/e2e/configurer/chain/commands_btcstaking.go @@ -3,11 +3,13 @@ package chain import ( "encoding/hex" "strconv" + "strings" + "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "cosmossdk.io/math" sdkmath "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/stretchr/testify/require" @@ -18,7 +20,7 @@ import ( bstypes "github.com/babylonchain/babylon/x/btcstaking/types" ) -func (n *NodeConfig) CreateBTCValidator(babylonPK *secp256k1.PubKey, btcPK *bbn.BIP340PubKey, pop *bstypes.ProofOfPossession, moniker, identity, website, securityContract, details string, commission *math.LegacyDec) { +func (n *NodeConfig) CreateBTCValidator(babylonPK *secp256k1.PubKey, btcPK *bbn.BIP340PubKey, pop *bstypes.ProofOfPossession, moniker, identity, website, securityContract, details string, commission *sdkmath.LegacyDec) { n.LogActionF("creating BTC validator") // get babylon PK hex @@ -49,6 +51,11 @@ func (n *NodeConfig) CreateBTCDelegation( stakingValue btcutil.Amount, slashingTx *bstypes.BTCSlashingTx, delegatorSig *bbn.BIP340Signature, + unbondingTx *wire.MsgTx, + unbondingSlashingTx *bstypes.BTCSlashingTx, + unbondingTime uint16, + unbondingValue btcutil.Amount, + delUnbondingSlashingSig *bbn.BIP340Signature, ) { n.LogActionF("creating BTC delegation") @@ -77,22 +84,50 @@ func (n *NodeConfig) CreateBTCDelegation( // get delegator sig hex delegatorSigHex := delegatorSig.ToHexStr() - cmd := []string{"babylond", "tx", "btcstaking", "create-btc-delegation", babylonPKHex, btcPkHex, popHex, stakingTxInfoHex, valPKHex, stakingTimeString, stakingValueString, slashingTxHex, delegatorSigHex, "--from=val"} + // on-demand unbonding related + unbondingTxBytes, err := bbn.SerializeBTCTx(unbondingTx) + require.NoError(n.t, err) + unbondingTxHex := hex.EncodeToString(unbondingTxBytes) + unbondingSlashingTxHex := unbondingSlashingTx.ToHexStr() + unbondingTimeStr := sdkmath.NewUint(uint64(unbondingTime)).String() + unbondingValueStr := sdkmath.NewInt(int64(unbondingValue)).String() + delUnbondingSlashingSigHex := delUnbondingSlashingSig.ToHexStr() + + cmd := []string{"babylond", "tx", "btcstaking", "create-btc-delegation", babylonPKHex, btcPkHex, popHex, stakingTxInfoHex, valPKHex, stakingTimeString, stakingValueString, slashingTxHex, delegatorSigHex, unbondingTxHex, unbondingSlashingTxHex, unbondingTimeStr, unbondingValueStr, delUnbondingSlashingSigHex, "--from=val"} _, _, err = n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd) require.NoError(n.t, err) n.LogActionF("successfully created BTC delegation") } -func (n *NodeConfig) AddCovenantSigs(covPK *bbn.BIP340PubKey, stakingTxHash string, sigs [][]byte) { +func (n *NodeConfig) AddCovenantSigs(covPK *bbn.BIP340PubKey, stakingTxHash string, slashingSigs [][]byte, unbondingSig *bbn.BIP340Signature, unbondingSlashingSigs [][]byte) { n.LogActionF("adding covenant signature") covPKHex := covPK.MarshalHex() - cmd := []string{"babylond", "tx", "btcstaking", "add-covenant-sig", covPKHex, stakingTxHash} - for _, sig := range sigs { - cmd = append(cmd, hex.EncodeToString(sig)) + cmd := []string{"babylond", "tx", "btcstaking", "add-covenant-sigs", covPKHex, stakingTxHash} + + // slashing signatures + slashingSigStrList := []string{} + for _, sig := range slashingSigs { + slashingSigStrList = append(slashingSigStrList, hex.EncodeToString(sig)) } + slashingSigStr := strings.Join(slashingSigStrList, ",") + cmd = append(cmd, slashingSigStr) + + // on-demand unbonding stuff + cmd = append(cmd, unbondingSig.ToHexStr()) + unbondingSlashingSigStrList := []string{} + for _, sig := range unbondingSlashingSigs { + unbondingSlashingSigStrList = append(unbondingSlashingSigStrList, hex.EncodeToString(sig)) + } + unbondingSlashingSigStr := strings.Join(unbondingSlashingSigStrList, ",") + cmd = append(cmd, unbondingSlashingSigStr) + + // used key cmd = append(cmd, "--from=val") + // gas + cmd = append(cmd, "--gas=auto", "--gas-prices=1ubbn", "--gas-adjustment=1.3") + _, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd) require.NoError(n.t, err) n.LogActionF("successfully added covenant sigatures") @@ -146,45 +181,6 @@ func (n *NodeConfig) AddFinalitySig(valBTCPK *bbn.BIP340PubKey, blockHeight uint n.LogActionF("successfully added finality signature") } -func (n *NodeConfig) CreateBTCUndelegation( - unbondingTx *wire.MsgTx, - slashingTx *bstypes.BTCSlashingTx, - unbondingTimeBlocks uint16, - unbondingValue btcutil.Amount, - delegatorSig *bbn.BIP340Signature) { - n.LogActionF("creating BTC undelegation") - - txBytes, err := bbn.SerializeBTCTx(unbondingTx) - require.NoError(n.t, err) - // get staking tx hex - unbondingTxHex := hex.EncodeToString(txBytes) - // get slashing tx hex - slashingTxHex := slashingTx.ToHexStr() - // get delegator sig hex - delegatorSigHex := delegatorSig.ToHexStr() - - unbondingTimeStr := sdkmath.NewUint(uint64(unbondingTimeBlocks)).String() - unbondingValueStr := sdkmath.NewInt(int64(unbondingValue)).String() - - cmd := []string{"babylond", "tx", "btcstaking", "create-btc-undelegation", unbondingTxHex, slashingTxHex, unbondingTimeStr, unbondingValueStr, delegatorSigHex, "--from=val"} - _, _, err = n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd) - require.NoError(n.t, err) - n.LogActionF("successfully created BTC delegation") -} - -func (n *NodeConfig) AddValidatorUnbondingSig(valPK *bbn.BIP340PubKey, delPK *bbn.BIP340PubKey, stakingTxHash string, sig *bbn.BIP340Signature) { - n.LogActionF("adding validator signature") - - valPKHex := valPK.MarshalHex() - delPKHex := delPK.MarshalHex() - sigHex := sig.ToHexStr() - - cmd := []string{"babylond", "tx", "btcstaking", "add-validator-unbonding-sig", valPKHex, delPKHex, stakingTxHash, sigHex, "--from=val"} - _, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd) - require.NoError(n.t, err) - n.LogActionF("successfully added validator unbonding sig") -} - func (n *NodeConfig) AddCovenantUnbondingSigs( covPK *bbn.BIP340PubKey, stakingTxHash string, @@ -204,3 +200,14 @@ func (n *NodeConfig) AddCovenantUnbondingSigs( require.NoError(n.t, err) n.LogActionF("successfully added covenant unbonding sigs") } + +func (n *NodeConfig) BTCUndelegate(stakingTxHash *chainhash.Hash, delUnbondingSig *schnorr.Signature) { + n.LogActionF("undelegate by using signature on unbonding tx from delegator") + + sigHex := bbn.NewBIP340SignatureFromBTCSig(delUnbondingSig).ToHexStr() + cmd := []string{"babylond", "tx", "btcstaking", "btc-undelegate", stakingTxHash.String(), sigHex, "--from=val"} + + _, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd) + require.NoError(n.t, err) + n.LogActionF("successfully added signature on unbonding tx from delegator") +} diff --git a/test/e2e/configurer/chain/queries_btcstaking.go b/test/e2e/configurer/chain/queries_btcstaking.go index a9bf61a0b..38963560e 100644 --- a/test/e2e/configurer/chain/queries_btcstaking.go +++ b/test/e2e/configurer/chain/queries_btcstaking.go @@ -57,29 +57,29 @@ func (n *NodeConfig) QueryBTCValidatorDelegations(valBTCPK string) []*bstypes.BT return resp.BtcDelegatorDelegations } -func (n *NodeConfig) QueryUnbondingDelegations() []*bstypes.BTCDelegation { - queryParams := url.Values{} - queryParams.Add("status", fmt.Sprintf("%d", bstypes.BTCDelegationStatus_UNBONDING)) - bz, err := n.QueryGRPCGateway("/babylon/btcstaking/v1/btc_delegations", queryParams) +func (n *NodeConfig) QueryBtcDelegation(stakingTxHash string) *bstypes.QueryBTCDelegationResponse { + path := fmt.Sprintf("/babylon/btcstaking/v1/btc_delegations/%s", stakingTxHash) + bz, err := n.QueryGRPCGateway(path, url.Values{}) require.NoError(n.t, err) - var resp bstypes.QueryBTCDelegationsResponse + var resp bstypes.QueryBTCDelegationResponse err = util.Cdc.UnmarshalJSON(bz, &resp) require.NoError(n.t, err) - return resp.BtcDelegations + return &resp } -func (n *NodeConfig) QueryBtcDelegation(stakingTxHash string) *bstypes.QueryBTCDelegationResponse { - path := fmt.Sprintf("/babylon/btcstaking/v1/btc_delegations/%s", stakingTxHash) - bz, err := n.QueryGRPCGateway(path, url.Values{}) +func (n *NodeConfig) QueryUnbondedDelegations() []*bstypes.BTCDelegation { + queryParams := url.Values{} + queryParams.Add("status", fmt.Sprintf("%d", bstypes.BTCDelegationStatus_UNBONDED)) + bz, err := n.QueryGRPCGateway("/babylon/btcstaking/v1/btc_delegations", queryParams) require.NoError(n.t, err) - var resp bstypes.QueryBTCDelegationResponse + var resp bstypes.QueryBTCDelegationsResponse err = util.Cdc.UnmarshalJSON(bz, &resp) require.NoError(n.t, err) - return &resp + return resp.BtcDelegations } func (n *NodeConfig) QueryActivatedHeight() uint64 { diff --git a/testutil/datagen/btc_transaction.go b/testutil/datagen/btc_transaction.go index e8d1a8648..5b04b2f02 100644 --- a/testutil/datagen/btc_transaction.go +++ b/testutil/datagen/btc_transaction.go @@ -10,8 +10,6 @@ import ( "time" txformat "github.com/babylonchain/babylon/btctxformatter" - - "github.com/babylonchain/babylon/btctxformatter" bbn "github.com/babylonchain/babylon/types" btcctypes "github.com/babylonchain/babylon/x/btccheckpoint/types" "github.com/btcsuite/btcd/blockchain" @@ -367,7 +365,7 @@ func GenRandomTx(r *rand.Rand) *wire.MsgTx { return tx } -func GenRandomBabylonTxPair(r *rand.Rand) ([]*wire.MsgTx, *btctxformatter.RawBtcCheckpoint) { +func GenRandomBabylonTxPair(r *rand.Rand) ([]*wire.MsgTx, *txformat.RawBtcCheckpoint) { txs := []*wire.MsgTx{GenRandomTx(r), GenRandomTx(r)} builder := txscript.NewScriptBuilder() @@ -375,9 +373,9 @@ func GenRandomBabylonTxPair(r *rand.Rand) ([]*wire.MsgTx, *btctxformatter.RawBtc rawBTCCkpt := GetRandomRawBtcCheckpoint(r) tag := GenRandomByteArray(r, 4) // encode raw checkpoint to two halves - firstHalf, secondHalf, err := btctxformatter.EncodeCheckpointData( - btctxformatter.BabylonTag(tag), - btctxformatter.CurrentVersion, + firstHalf, secondHalf, err := txformat.EncodeCheckpointData( + txformat.BabylonTag(tag), + txformat.CurrentVersion, rawBTCCkpt, ) if err != nil { diff --git a/testutil/datagen/btcstaking.go b/testutil/datagen/btcstaking.go index 48fa2f01a..2d5a80bb5 100644 --- a/testutil/datagen/btcstaking.go +++ b/testutil/datagen/btcstaking.go @@ -18,11 +18,15 @@ import ( "github.com/stretchr/testify/require" "github.com/babylonchain/babylon/btcstaking" - asig "github.com/babylonchain/babylon/crypto/schnorr-adaptor-signature" bbn "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" ) +const ( + StakingOutIdx = uint32(0) + UnbondingTxFee = int64(1000) +) + func GenRandomBTCValidator(r *rand.Rand) (*bstypes.BTCValidator, error) { // key pairs btcSK, _, err := GenRandomBTCKeyPair(r) @@ -32,36 +36,6 @@ func GenRandomBTCValidator(r *rand.Rand) (*bstypes.BTCValidator, error) { return GenRandomBTCValidatorWithBTCSK(r, btcSK) } -func GenCovenantAdaptorSigs( - covenantSKs []*btcec.PrivateKey, - valPKs []*btcec.PublicKey, - fundingTx *wire.MsgTx, - pkScriptPath []byte, - slashingTx *bstypes.BTCSlashingTx, -) ([]*bstypes.CovenantAdaptorSignatures, error) { - covenantSigs := []*bstypes.CovenantAdaptorSignatures{} - for _, covenantSK := range covenantSKs { - covMemberSigs := &bstypes.CovenantAdaptorSignatures{ - CovPk: bbn.NewBIP340PubKeyFromBTCPK(covenantSK.PubKey()), - AdaptorSigs: [][]byte{}, - } - for _, valPK := range valPKs { - encKey, err := asig.NewEncryptionKeyFromBTCPK(valPK) - if err != nil { - return nil, err - } - covenantSig, err := slashingTx.EncSign(fundingTx, 0, pkScriptPath, covenantSK, encKey) - if err != nil { - return nil, err - } - covMemberSigs.AdaptorSigs = append(covMemberSigs.AdaptorSigs, covenantSig.MustMarshal()) - } - covenantSigs = append(covenantSigs, covMemberSigs) - } - - return covenantSigs, nil -} - func GenRandomBTCValidatorWithBTCSK(r *rand.Rand, btcSK *btcec.PrivateKey) (*bstypes.BTCValidator, error) { bbnSK, _, err := GenRandomSecp256k1KeyPair(r) if err != nil { @@ -97,6 +71,7 @@ func GenRandomBTCValidatorWithBTCBabylonSKs(r *rand.Rand, btcSK *btcec.PrivateKe }, nil } +// TODO: accomodate presign unbonding flow func GenRandomBTCDelegation( r *rand.Rand, t *testing.T, @@ -141,7 +116,7 @@ func GenRandomBTCDelegation( return nil, err } // staking/slashing tx - testingInfo := GenBTCStakingSlashingInfo( + stakingSlashingInfo := GenBTCStakingSlashingInfo( r, t, net, @@ -155,24 +130,34 @@ func GenRandomBTCDelegation( slashingRate, ) - slashingPathSpendInfo, err := testingInfo.StakingInfo.SlashingPathSpendInfo() + slashingPathSpendInfo, err := stakingSlashingInfo.StakingInfo.SlashingPathSpendInfo() require.NoError(t, err) - pkScriptPath := slashingPathSpendInfo.GetPkScriptPath() - stakingMsgTx := testingInfo.StakingTx + stakingMsgTx := stakingSlashingInfo.StakingTx - // covenant sigs - covenantSigs, err := GenCovenantAdaptorSigs(covenantSKs, valPKs, stakingMsgTx, pkScriptPath, testingInfo.SlashingTx) + // delegator sig + delegatorSig, err := stakingSlashingInfo.SlashingTx.Sign( + stakingMsgTx, + StakingOutIdx, + slashingPathSpendInfo.GetPkScriptPath(), + delSK, + ) require.NoError(t, err) - // delegator sig - delegatorSig, err := testingInfo.SlashingTx.Sign(stakingMsgTx, 0, pkScriptPath, delSK) + // covenant sigs + covenantSigs, err := GenCovenantAdaptorSigs( + covenantSKs, + valPKs, + stakingMsgTx, + slashingPathSpendInfo.GetPkScriptPath(), + stakingSlashingInfo.SlashingTx, + ) require.NoError(t, err) - serializedStakingTx, err := bbn.SerializeBTCTx(testingInfo.StakingTx) + serializedStakingTx, err := bbn.SerializeBTCTx(stakingSlashingInfo.StakingTx) require.NoError(t, err) - return &bstypes.BTCDelegation{ + del := &bstypes.BTCDelegation{ BabylonPk: secp256k1PK, BtcPk: delBTCPK, Pop: pop, @@ -180,12 +165,66 @@ func GenRandomBTCDelegation( StartHeight: startHeight, EndHeight: endHeight, TotalSat: totalSat, - StakingOutputIdx: 0, + StakingOutputIdx: StakingOutIdx, DelegatorSig: delegatorSig, CovenantSigs: covenantSigs, StakingTx: serializedStakingTx, - SlashingTx: testingInfo.SlashingTx, - }, nil + SlashingTx: stakingSlashingInfo.SlashingTx, + } + + /* + construct BTC undelegation + */ + + // construct unbonding info + stkTxHash := stakingSlashingInfo.StakingTx.TxHash() + unbondingValue := totalSat - uint64(UnbondingTxFee) + w := uint16(100) // TODO: parameterise w + unbondingSlashingInfo := GenBTCUnbondingSlashingInfo( + r, + t, + net, + delSK, + valPKs, + covenantBTCPKs, + covenantQuorum, + wire.NewOutPoint(&stkTxHash, StakingOutIdx), + w+1, + int64(unbondingValue), + slashingAddress, changeAddress, + slashingRate, + ) + + unbondingTxBytes, err := bbn.SerializeBTCTx(unbondingSlashingInfo.UnbondingTx) + require.NoError(t, err) + delSlashingTxSig, err := unbondingSlashingInfo.GenDelSlashingTxSig(delSK) + require.NoError(t, err) + del.BtcUndelegation = &bstypes.BTCUndelegation{ + UnbondingTx: unbondingTxBytes, + UnbondingTime: uint32(w + 1), + SlashingTx: unbondingSlashingInfo.SlashingTx, + DelegatorSlashingSig: delSlashingTxSig, + } + + /* + covenant signs BTC undelegation + */ + + unbondingPathSpendInfo, err := stakingSlashingInfo.StakingInfo.UnbondingPathSpendInfo() + require.NoError(t, err) + + covUnbondingSlashingSigs, covUnbondingSigs, err := unbondingSlashingInfo.GenCovenantSigs( + covenantSKs, + valPKs, + stakingMsgTx, + unbondingPathSpendInfo.GetPkScriptPath(), + ) + require.NoError(t, err) + + del.BtcUndelegation.CovenantSlashingSigs = covUnbondingSlashingSigs + del.BtcUndelegation.CovenantUnbondingSigList = covUnbondingSigs + + return del, nil } type TestStakingSlashingInfo struct { @@ -246,7 +285,7 @@ func GenBTCStakingSlashingInfoWithOutPoint( require.NoError(t, err) slashingMsgTx, err := btcstaking.BuildSlashingTxFromStakingTxStrict( tx, - 0, + StakingOutIdx, slashingAddrBtc, changeAddrBtc, 2000, slashingRate, @@ -276,7 +315,7 @@ func GenBTCStakingSlashingInfo( slashingRate sdkmath.LegacyDec, ) *TestStakingSlashingInfo { // an arbitrary input - spend := makeSpendableOutWithRandOutPoint(r, btcutil.Amount(stakingValue+1000)) + spend := makeSpendableOutWithRandOutPoint(r, btcutil.Amount(stakingValue+UnbondingTxFee)) outPoint := &spend.prevOut return GenBTCStakingSlashingInfoWithOutPoint( r, @@ -332,7 +371,7 @@ func GenBTCUnbondingSlashingInfo( require.NoError(t, err) slashingMsgTx, err := btcstaking.BuildSlashingTxFromStakingTxStrict( tx, - 0, + StakingOutIdx, slashingAddrBtc, changeAddrBtc, 2000, slashingRate, @@ -347,3 +386,62 @@ func GenBTCUnbondingSlashingInfo( UnbondingInfo: unbondingInfo, } } + +func (info *TestUnbondingSlashingInfo) GenDelSlashingTxSig(sk *btcec.PrivateKey) (*bbn.BIP340Signature, error) { + unbondingTxMsg := info.UnbondingTx + unbondingTxSlashingPathInfo, err := info.UnbondingInfo.SlashingPathSpendInfo() + if err != nil { + return nil, err + } + slashingTxSig, err := info.SlashingTx.Sign( + unbondingTxMsg, + StakingOutIdx, + unbondingTxSlashingPathInfo.GetPkScriptPath(), + sk, + ) + if err != nil { + return nil, err + } + return slashingTxSig, nil +} + +func (info *TestUnbondingSlashingInfo) GenCovenantSigs( + covSKs []*btcec.PrivateKey, + valPKs []*btcec.PublicKey, + stakingTx *wire.MsgTx, + unbondingPkScriptPath []byte, +) ([]*bstypes.CovenantAdaptorSignatures, []*bstypes.SignatureInfo, error) { + unbondingSlashingPathInfo, err := info.UnbondingInfo.SlashingPathSpendInfo() + if err != nil { + return nil, nil, err + } + + covUnbondingSlashingSigs, err := GenCovenantAdaptorSigs( + covSKs, + valPKs, + info.UnbondingTx, + unbondingSlashingPathInfo.GetPkScriptPath(), + info.SlashingTx, + ) + if err != nil { + return nil, nil, err + } + covUnbondingSigs, err := GenCovenantUnbondingSigs( + covSKs, + stakingTx, + StakingOutIdx, + unbondingPkScriptPath, + info.UnbondingTx, + ) + if err != nil { + return nil, nil, err + } + covUnbondingSigList := []*bstypes.SignatureInfo{} + for i := range covUnbondingSigs { + covUnbondingSigList = append(covUnbondingSigList, &bstypes.SignatureInfo{ + Pk: bbn.NewBIP340PubKeyFromBTCPK(covSKs[i].PubKey()), + Sig: bbn.NewBIP340SignatureFromBTCSig(covUnbondingSigs[i]), + }) + } + return covUnbondingSlashingSigs, covUnbondingSigList, nil +} diff --git a/testutil/datagen/covenant.go b/testutil/datagen/covenant.go new file mode 100644 index 000000000..ae2fd835b --- /dev/null +++ b/testutil/datagen/covenant.go @@ -0,0 +1,59 @@ +package datagen + +import ( + "github.com/babylonchain/babylon/btcstaking" + asig "github.com/babylonchain/babylon/crypto/schnorr-adaptor-signature" + bbn "github.com/babylonchain/babylon/types" + bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/wire" +) + +func GenCovenantAdaptorSigs( + covenantSKs []*btcec.PrivateKey, + valPKs []*btcec.PublicKey, + fundingTx *wire.MsgTx, + pkScriptPath []byte, + slashingTx *bstypes.BTCSlashingTx, +) ([]*bstypes.CovenantAdaptorSignatures, error) { + covenantSigs := []*bstypes.CovenantAdaptorSignatures{} + for _, covenantSK := range covenantSKs { + covMemberSigs := &bstypes.CovenantAdaptorSignatures{ + CovPk: bbn.NewBIP340PubKeyFromBTCPK(covenantSK.PubKey()), + AdaptorSigs: [][]byte{}, + } + for _, valPK := range valPKs { + encKey, err := asig.NewEncryptionKeyFromBTCPK(valPK) + if err != nil { + return nil, err + } + covenantSig, err := slashingTx.EncSign(fundingTx, 0, pkScriptPath, covenantSK, encKey) + if err != nil { + return nil, err + } + covMemberSigs.AdaptorSigs = append(covMemberSigs.AdaptorSigs, covenantSig.MustMarshal()) + } + covenantSigs = append(covenantSigs, covMemberSigs) + } + + return covenantSigs, nil +} + +func GenCovenantUnbondingSigs(covenantSKs []*btcec.PrivateKey, stakingTx *wire.MsgTx, stakingOutIdx uint32, unbondingPkScriptPath []byte, unbondingTx *wire.MsgTx) ([]*schnorr.Signature, error) { + sigs := []*schnorr.Signature{} + for i := range covenantSKs { + sig, err := btcstaking.SignTxWithOneScriptSpendInputStrict( + unbondingTx, + stakingTx, + stakingOutIdx, + unbondingPkScriptPath, + covenantSKs[i], + ) + if err != nil { + return nil, err + } + sigs = append(sigs, sig) + } + return sigs, nil +} diff --git a/testutil/datagen/finality.go b/testutil/datagen/finality.go index 11cf971cc..f4cb4dd7a 100644 --- a/testutil/datagen/finality.go +++ b/testutil/datagen/finality.go @@ -46,8 +46,7 @@ func GenRandomMsgCommitPubRandList(r *rand.Rand, sk *btcec.PrivateKey, startHeig if err != nil { return nil, nil, err } - sig := bbn.NewBIP340SignatureFromBTCSig(schnorrSig) - msg.Sig = &sig + msg.Sig = bbn.NewBIP340SignatureFromBTCSig(schnorrSig) return srList, msg, nil } diff --git a/testutil/datagen/raw_checkpoint.go b/testutil/datagen/raw_checkpoint.go index 8e76b28ac..b59a0c2cb 100644 --- a/testutil/datagen/raw_checkpoint.go +++ b/testutil/datagen/raw_checkpoint.go @@ -5,7 +5,6 @@ import ( "github.com/boljen/go-bitmap" - "github.com/babylonchain/babylon/btctxformatter" txformat "github.com/babylonchain/babylon/btctxformatter" "github.com/babylonchain/babylon/crypto/bls12381" "github.com/babylonchain/babylon/x/checkpointing/types" @@ -25,13 +24,13 @@ func GenRandomBitmap(r *rand.Rand) (bitmap.Bitmap, int) { return bm, numSubset } -func GetRandomRawBtcCheckpoint(r *rand.Rand) *btctxformatter.RawBtcCheckpoint { +func GetRandomRawBtcCheckpoint(r *rand.Rand) *txformat.RawBtcCheckpoint { rawCkpt := GenRandomRawCheckpoint(r) - return &btctxformatter.RawBtcCheckpoint{ + return &txformat.RawBtcCheckpoint{ Epoch: rawCkpt.EpochNum, AppHash: *rawCkpt.AppHash, BitMap: rawCkpt.Bitmap, - SubmitterAddress: GenRandomByteArray(r, btctxformatter.AddressLength), + SubmitterAddress: GenRandomByteArray(r, txformat.AddressLength), BlsSig: rawCkpt.BlsMultiSig.Bytes(), } } diff --git a/types/btc_schnorr_sig.go b/types/btc_schnorr_sig.go index 82c4263bb..58342323f 100644 --- a/types/btc_schnorr_sig.go +++ b/types/btc_schnorr_sig.go @@ -25,9 +25,10 @@ func NewBIP340SignatureFromHex(sigHex string) (*BIP340Signature, error) { return NewBIP340Signature(sigBytes) } -func NewBIP340SignatureFromBTCSig(btcSig *schnorr.Signature) BIP340Signature { +func NewBIP340SignatureFromBTCSig(btcSig *schnorr.Signature) *BIP340Signature { sigBytes := btcSig.Serialize() - return BIP340Signature(sigBytes) + sig := BIP340Signature(sigBytes) + return &sig } func (sig BIP340Signature) ToBTCSig() (*schnorr.Signature, error) { diff --git a/types/btc_schnorr_sig_test.go b/types/btc_schnorr_sig_test.go index e25e4a43b..c8a7f2ad8 100644 --- a/types/btc_schnorr_sig_test.go +++ b/types/btc_schnorr_sig_test.go @@ -36,6 +36,6 @@ func FuzzBIP340Signature(f *testing.F) { require.NoError(t, err) err = sig2.Unmarshal(sigBytes) require.NoError(t, err) - require.Equal(t, sig, sig2) + require.Equal(t, *sig, sig2) }) } diff --git a/x/btcstaking/client/cli/tx.go b/x/btcstaking/client/cli/tx.go index 6f571dea4..df640e9ac 100644 --- a/x/btcstaking/client/cli/tx.go +++ b/x/btcstaking/client/cli/tx.go @@ -3,11 +3,9 @@ package cli import ( "encoding/hex" "fmt" - "math" "strings" sdkmath "cosmossdk.io/math" - "github.com/btcsuite/btcd/btcutil" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" @@ -43,9 +41,8 @@ func GetTxCmd() *cobra.Command { cmd.AddCommand( NewCreateBTCValidatorCmd(), NewCreateBTCDelegationCmd(), - NewAddCovenantSigCmd(), - NewCreateBTCUndelegationCmd(), - NewAddCovenantUnbondingSigsCmd(), + NewAddCovenantSigsCmd(), + NewBTCUndelegateCmd(), ) return cmd @@ -135,50 +132,10 @@ func NewCreateBTCValidatorCmd() *cobra.Command { return cmd } -func parseLockTime(str string) (uint16, error) { - num, ok := sdkmath.NewIntFromString(str) - - if !ok { - return 0, fmt.Errorf("invalid staking time: %s", str) - } - - if !num.IsUint64() { - return 0, fmt.Errorf("staking time is not valid uint") - } - - asUint64 := num.Uint64() - - if asUint64 > math.MaxUint16 { - return 0, fmt.Errorf("staking time is too large. Max is %d", math.MaxUint16) - } - - return uint16(asUint64), nil -} - -func parseBtcAmount(str string) (btcutil.Amount, error) { - num, ok := sdkmath.NewIntFromString(str) - - if !ok { - return 0, fmt.Errorf("invalid staking value: %s", str) - } - - if num.IsNegative() { - return 0, fmt.Errorf("staking value is negative") - } - - if !num.IsInt64() { - return 0, fmt.Errorf("staking value is not valid uint") - } - - asInt64 := num.Int64() - - return btcutil.Amount(asInt64), nil -} - func NewCreateBTCDelegationCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "create-btc-delegation [babylon_pk] [btc_pk] [pop] [staking_tx_info] [val_pk] [staking_time] [staking_value] [slashing_tx] [delegator_sig]", - Args: cobra.ExactArgs(9), + Use: "create-btc-delegation [babylon_pk] [btc_pk] [pop] [staking_tx_info] [val_pk] [staking_time] [staking_value] [slashing_tx] [delegator_slashing_sig] [unbonding_tx] [unbonding_slashing_tx] [unbonding_time] [unbonding_value] [delegator_unbonding_slashing_sig]", + Args: cobra.ExactArgs(14), Short: "Create a BTC delegation", Long: strings.TrimSpace( `Create a BTC delegation.`, // TODO: example @@ -227,13 +184,11 @@ func NewCreateBTCDelegationCmd() *cobra.Command { // get staking time stakingTime, err := parseLockTime(args[5]) - if err != nil { return err } stakingValue, err := parseBtcAmount(args[6]) - if err != nil { return err } @@ -244,70 +199,57 @@ func NewCreateBTCDelegationCmd() *cobra.Command { return err } - // get delegator sig - delegatorSig, err := bbn.NewBIP340SignatureFromHex(args[8]) + // get delegator sig on slashing tx + delegatorSlashingSig, err := bbn.NewBIP340SignatureFromHex(args[8]) if err != nil { return err } - msg := types.MsgCreateBTCDelegation{ - Signer: clientCtx.FromAddress.String(), - BabylonPk: &babylonPK, - BtcPk: btcPK, - ValBtcPkList: []bbn.BIP340PubKey{*valPK}, - Pop: pop, - StakingTime: uint32(stakingTime), - StakingValue: int64(stakingValue), - StakingTx: stakingTxInfo, - SlashingTx: slashingTx, - DelegatorSig: delegatorSig, + // get unbonding tx + _, unbondingTxBytes, err := bbn.NewBTCTxFromHex(args[9]) + if err != nil { + return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -func NewAddCovenantSigCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "add-covenant-sig [covenant_pk] [staking_tx_hash] [sig1] [sig2] ...", - Args: cobra.MinimumNArgs(3), - Short: "Add a covenant signature", - Long: strings.TrimSpace( - `Add a covenant signature.`, // TODO: example - ), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) + // get unbonding slashing tx + unbondingSlashingTx, err := types.NewBTCSlashingTxFromHex(args[10]) if err != nil { return err } - covPK, err := bbn.NewBIP340PubKeyFromHex(args[0]) + // get staking time + unbondingTime, err := parseLockTime(args[11]) if err != nil { - return fmt.Errorf("invalid public key: %w", err) + return err } - // get staking tx hash - stakingTxHash := args[1] + unbondingValue, err := parseBtcAmount(args[12]) + if err != nil { + return err + } - sigs := [][]byte{} - for _, sigHex := range args[2:] { - sig, err := asig.NewAdaptorSignatureFromHex(sigHex) - if err != nil { - return fmt.Errorf("invalid covenant signature: %w", err) - } - sigs = append(sigs, sig.MustMarshal()) + // get delegator sig on unbonding slashing tx + delegatorUnbondingSlashingSig, err := bbn.NewBIP340SignatureFromHex(args[13]) + if err != nil { + return err } - msg := types.MsgAddCovenantSig{ - Signer: clientCtx.FromAddress.String(), - Pk: covPK, - StakingTxHash: stakingTxHash, - Sigs: sigs, + msg := types.MsgCreateBTCDelegation{ + Signer: clientCtx.FromAddress.String(), + BabylonPk: &babylonPK, + BtcPk: btcPK, + ValBtcPkList: []bbn.BIP340PubKey{*valPK}, + Pop: pop, + StakingTime: uint32(stakingTime), + StakingValue: int64(stakingValue), + StakingTx: stakingTxInfo, + SlashingTx: slashingTx, + DelegatorSlashingSig: delegatorSlashingSig, + UnbondingTx: unbondingTxBytes, + UnbondingTime: uint32(unbondingTime), + UnbondingValue: int64(unbondingValue), + UnbondingSlashingTx: unbondingSlashingTx, + DelegatorUnbondingSlashingSig: delegatorUnbondingSlashingSig, } return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) @@ -319,13 +261,13 @@ func NewAddCovenantSigCmd() *cobra.Command { return cmd } -func NewCreateBTCUndelegationCmd() *cobra.Command { +func NewAddCovenantSigsCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "create-btc-undelegation [unbonding_tx] [slashing_tx] [unbonding_time] [unbonding_value] [delegator_sig]", + Use: "add-covenant-sigs [covenant_pk] [staking_tx_hash] [slashing_tx_sig1],[slashing_tx_sig2],... [unbonding_tx_sig] [slashing_unbonding_tx_sig1],[slashing_unbonding_tx_sig2],...", Args: cobra.ExactArgs(5), - Short: "Create a BTC undelegation", + Short: "Add a covenant signature", Long: strings.TrimSpace( - `Create a BTC undelegation.`, // TODO: example + `Add a covenant signature.`, // TODO: example ), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientTxContext(cmd) @@ -333,44 +275,47 @@ func NewCreateBTCUndelegationCmd() *cobra.Command { return err } - // get staking tx - _, unbondingTxBytes, err := bbn.NewBTCTxFromHex(args[0]) - if err != nil { - return err - } - - // get slashing tx - slashingTx, err := types.NewBTCSlashingTxFromHex(args[1]) + covPK, err := bbn.NewBIP340PubKeyFromHex(args[0]) if err != nil { - return err + return fmt.Errorf("invalid public key: %w", err) } - // get staking time - unbondingTime, err := parseLockTime(args[2]) + // get staking tx hash + stakingTxHash := args[1] - if err != nil { - return err + // parse slashing tx sigs + slashingTxSigs := [][]byte{} + for _, sigHex := range strings.Split(args[2], ",") { + sig, err := asig.NewAdaptorSignatureFromHex(sigHex) + if err != nil { + return fmt.Errorf("invalid covenant signature: %w", err) + } + slashingTxSigs = append(slashingTxSigs, sig.MustMarshal()) } - unbondingValue, err := parseBtcAmount(args[3]) - + // get covenant signature for unbonding tx + unbondingTxSig, err := bbn.NewBIP340SignatureFromHex(args[3]) if err != nil { return err } - // get delegator sig - delegatorSig, err := bbn.NewBIP340SignatureFromHex(args[4]) - if err != nil { - return err + // parse unbonding slashing tx sigs + unbondingSlashingSigs := [][]byte{} + for _, sigHex := range strings.Split(args[4], ",") { + slashingSig, err := asig.NewAdaptorSignatureFromHex(sigHex) + if err != nil { + return fmt.Errorf("invalid covenant signature: %w", err) + } + unbondingSlashingSigs = append(unbondingSlashingSigs, slashingSig.MustMarshal()) } - msg := types.MsgBTCUndelegate{ - Signer: clientCtx.FromAddress.String(), - UnbondingTx: unbondingTxBytes, - UnbondingTime: uint32(unbondingTime), - UnbondingValue: int64(unbondingValue), - SlashingTx: slashingTx, - DelegatorSlashingSig: delegatorSig, + msg := types.MsgAddCovenantSigs{ + Signer: clientCtx.FromAddress.String(), + Pk: covPK, + StakingTxHash: stakingTxHash, + SlashingTxSigs: slashingTxSigs, + UnbondingTxSig: unbondingTxSig, + SlashingUnbondingTxSigs: unbondingSlashingSigs, } return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) @@ -382,47 +327,33 @@ func NewCreateBTCUndelegationCmd() *cobra.Command { return cmd } -func NewAddCovenantUnbondingSigsCmd() *cobra.Command { +func NewBTCUndelegateCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "add-covenant-unbonding-sigs [covenant_pk] [staking_tx_hash] [unbonding_tx_sg] [slashing_unbonding_tx_sig1] [slashing_unbonding_tx_sig2] ...", - Args: cobra.MinimumNArgs(4), - Short: "Add covenant signatures for unbonding tx and slash unbonding tx", + Use: "btc-undelegate [staking_tx_hash] [unbonding_tx_sig]", + Args: cobra.ExactArgs(2), + Short: "Add a signature on the unbonding tx of a BTC delegation identified by a given staking tx hash. ", + Long: strings.TrimSpace( + `Add a signature on the unbonding tx of a BTC delegation identified by a given staking tx hash signed by the delegator. The signature proves that delegator wants to unbond, and Babylon will consider the BTC delegation unbonded.`, // TODO: example + ), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err } - // get covenant PK - covPK, err := bbn.NewBIP340PubKeyFromHex(args[0]) - if err != nil { - return err - } - // get staking tx hash - stakingTxHash := args[1] + stakingTxHash := args[0] - // get covenant sigature for unbonding tx - unbondingSig, err := bbn.NewBIP340SignatureFromHex(args[2]) + // get delegator signature for unbonding tx + unbondingTxSig, err := bbn.NewBIP340SignatureFromHex(args[1]) if err != nil { return err } - slashingSigs := [][]byte{} - for _, sigHex := range args[3:] { - slashingSig, err := asig.NewAdaptorSignatureFromHex(sigHex) - if err != nil { - return fmt.Errorf("invalid covenant signature: %w", err) - } - slashingSigs = append(slashingSigs, slashingSig.MustMarshal()) - } - - msg := types.MsgAddCovenantUnbondingSigs{ - Signer: clientCtx.FromAddress.String(), - Pk: covPK, - StakingTxHash: stakingTxHash, - UnbondingTxSig: unbondingSig, - SlashingUnbondingTxSigs: slashingSigs, + msg := types.MsgBTCUndelegate{ + Signer: clientCtx.FromAddress.String(), + StakingTxHash: stakingTxHash, + UnbondingTxSig: unbondingTxSig, } return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) diff --git a/x/btcstaking/client/cli/utils.go b/x/btcstaking/client/cli/utils.go new file mode 100644 index 000000000..cec621388 --- /dev/null +++ b/x/btcstaking/client/cli/utils.go @@ -0,0 +1,49 @@ +package cli + +import ( + "fmt" + "math" + + sdkmath "cosmossdk.io/math" + "github.com/btcsuite/btcd/btcutil" +) + +func parseLockTime(str string) (uint16, error) { + num, ok := sdkmath.NewIntFromString(str) + + if !ok { + return 0, fmt.Errorf("invalid staking time: %s", str) + } + + if !num.IsUint64() { + return 0, fmt.Errorf("staking time is not valid uint") + } + + asUint64 := num.Uint64() + + if asUint64 > math.MaxUint16 { + return 0, fmt.Errorf("staking time is too large. Max is %d", math.MaxUint16) + } + + return uint16(asUint64), nil +} + +func parseBtcAmount(str string) (btcutil.Amount, error) { + num, ok := sdkmath.NewIntFromString(str) + + if !ok { + return 0, fmt.Errorf("invalid staking value: %s", str) + } + + if num.IsNegative() { + return 0, fmt.Errorf("staking value is negative") + } + + if !num.IsInt64() { + return 0, fmt.Errorf("staking value is not valid uint") + } + + asInt64 := num.Int64() + + return btcutil.Amount(asInt64), nil +} diff --git a/x/btcstaking/keeper/btc_delegators.go b/x/btcstaking/keeper/btc_delegators.go index 5ea5c4e7d..fe07edc40 100644 --- a/x/btcstaking/keeper/btc_delegators.go +++ b/x/btcstaking/keeper/btc_delegators.go @@ -79,30 +79,6 @@ func (k Keeper) updateBTCDelegation( return nil } -// AddCovenantSigsToBTCDelegation adds a given covenant sig to a BTC delegation -// with the given staking tx hash -func (k Keeper) AddCovenantSigsToBTCDelegation( - ctx context.Context, - stakingTxHash string, - covenantSigs [][]byte, - covPk *bbn.BIP340PubKey, - quorum uint32, -) error { - adaptorSigs := make([]asig.AdaptorSignature, 0, len(covenantSigs)) - for _, s := range covenantSigs { - as, err := asig.NewAdaptorSignatureFromBytes(s) - if err != nil { - return err - } - adaptorSigs = append(adaptorSigs, *as) - } - addCovenantSig := func(btcDel *types.BTCDelegation) error { - return btcDel.AddCovenantSigs(covPk, adaptorSigs, quorum) - } - - return k.updateBTCDelegation(ctx, stakingTxHash, addCovenantSig) -} - func (k Keeper) AddUndelegationToBTCDelegation( ctx context.Context, stakingTxHash string, @@ -119,31 +95,49 @@ func (k Keeper) AddUndelegationToBTCDelegation( return k.updateBTCDelegation(ctx, stakingTxHash, addUndelegation) } -func (k Keeper) AddCovenantSigsToUndelegation( +// AddCovenantSigsToBTCDelegation adds covenant signatures to a BTC delegation +// with the given staking tx hash, including +// - a list of adaptor signatures over slashing tx, each encrypted by a restaked validator's PK +// - a Schnorr signature over unbonding tx +// - a list of adaptor signatures over unbonding slashing tx, each encrypted by a restaked validator's PK +func (k Keeper) AddCovenantSigsToBTCDelegation( ctx context.Context, stakingTxHash string, covPk *bbn.BIP340PubKey, + slashingSigsByte [][]byte, unbondingTxSigInfo *bbn.BIP340Signature, - slashUnbondingTxSigs [][]byte, - quorum uint32, + slashUnbondingTxSigsByte [][]byte, ) error { - adaptorSigs := make([]asig.AdaptorSignature, 0, len(slashUnbondingTxSigs)) - for _, s := range slashUnbondingTxSigs { + quorum := k.GetParams(ctx).CovenantQuorum + + slashingSigs := make([]asig.AdaptorSignature, 0, len(slashingSigsByte)) + for _, s := range slashingSigsByte { as, err := asig.NewAdaptorSignatureFromBytes(s) if err != nil { return err } - adaptorSigs = append(adaptorSigs, *as) + slashingSigs = append(slashingSigs, *as) } - addCovenantSigs := func(btcDel *types.BTCDelegation) error { - if btcDel.BtcUndelegation == nil { - return fmt.Errorf("the BTC delegation with staking tx hash %s did not receive undelegation request yet", stakingTxHash) + slashUnbondingTxSigs := make([]asig.AdaptorSignature, 0, len(slashUnbondingTxSigsByte)) + for _, s := range slashUnbondingTxSigsByte { + as, err := asig.NewAdaptorSignatureFromBytes(s) + if err != nil { + return err } + slashUnbondingTxSigs = append(slashUnbondingTxSigs, *as) + } - return btcDel.BtcUndelegation.AddCovenantSigs(covPk, unbondingTxSigInfo, adaptorSigs, quorum) + addCovenantSig := func(btcDel *types.BTCDelegation) error { + if err := btcDel.AddCovenantSigs(covPk, slashingSigs, quorum); err != nil { + return err + } + if err := btcDel.BtcUndelegation.AddCovenantSigs(covPk, unbondingTxSigInfo, slashUnbondingTxSigs, quorum); err != nil { + return err + } + return nil } - return k.updateBTCDelegation(ctx, stakingTxHash, addCovenantSigs) + return k.updateBTCDelegation(ctx, stakingTxHash, addCovenantSig) } // hasBTCDelegatorDelegations checks if the given BTC delegator has any BTC delegations under a given BTC validator diff --git a/x/btcstaking/keeper/grpc_query_test.go b/x/btcstaking/keeper/grpc_query_test.go index ee239e56d..333aa36f2 100644 --- a/x/btcstaking/keeper/grpc_query_test.go +++ b/x/btcstaking/keeper/grpc_query_test.go @@ -6,7 +6,6 @@ import ( "testing" sdkmath "cosmossdk.io/math" - "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/chaincfg" sdk "github.com/cosmos/cosmos-sdk/types" @@ -268,120 +267,6 @@ func FuzzPendingBTCDelegations(f *testing.F) { }) } -func FuzzUnbondingBTCDelegations(f *testing.F) { - datagen.AddRandomSeedsToFuzzer(f, 10) - f.Fuzz(func(t *testing.T, seed int64) { - r := rand.New(rand.NewSource(seed)) - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - // Setup keeper and context - btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) - btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - btccKeeper.EXPECT().GetParams(gomock.Any()).Return(btcctypes.DefaultParams()).AnyTimes() - keeper, ctx := testkeeper.BTCStakingKeeper(t, btclcKeeper, btccKeeper) - - // covenant and slashing addr - covenantSKs, covenantPKs, covenantQuorum := types.DefaultCovenantCommittee() - covBTCPKs := bbn.NewBIP340PKsFromBTCPKs(covenantPKs) - slashingAddress, err := datagen.GenRandomBTCAddress(r, &chaincfg.SimNetParams) - require.NoError(t, err) - changeAddress, err := datagen.GenRandomBTCAddress(r, &chaincfg.SimNetParams) - require.NoError(t, err) - // Generate a slashing rate in the range [0.1, 0.50] i.e., 10-50%. - // NOTE - if the rate is higher or lower, it may produce slashing or change outputs - // with value below the dust threshold, causing test failure. - // Our goal is not to test failure due to such extreme cases here; - // this is already covered in FuzzGeneratingValidStakingSlashingTx - slashingRate := sdkmath.LegacyNewDecWithPrec(int64(datagen.RandomInt(r, 41)+10), 2) - - // Generate a random number of BTC validators - numBTCVals := datagen.RandomInt(r, 5) + 1 - btcVals := []*types.BTCValidator{} - for i := uint64(0); i < numBTCVals; i++ { - btcVal, err := datagen.GenRandomBTCValidator(r) - require.NoError(t, err) - keeper.SetBTCValidator(ctx, btcVal) - btcVals = append(btcVals, btcVal) - } - - // Generate a random number of BTC delegations under each validator - startHeight := datagen.RandomInt(r, 100) + 1 - endHeight := datagen.RandomInt(r, 1000) + startHeight + btcctypes.DefaultParams().CheckpointFinalizationTimeout + 1 - numBTCDels := datagen.RandomInt(r, 10) + 1 - unbondingBtcDelsMap := make(map[string]*types.BTCDelegation) - for _, btcVal := range btcVals { - for j := uint64(0); j < numBTCDels; j++ { - delSK, _, err := datagen.GenRandomBTCKeyPair(r) - require.NoError(t, err) - btcDel, err := datagen.GenRandomBTCDelegation( - r, - t, - []bbn.BIP340PubKey{*btcVal.BtcPk}, - delSK, - covenantSKs, - covenantQuorum, - slashingAddress.EncodeAddress(), changeAddress.EncodeAddress(), - startHeight, endHeight, 10000, - slashingRate, - ) - require.NoError(t, err) - - if datagen.RandomInt(r, 2) == 1 { - // add unbonding object in random BTC delegations to make them ready to receive covenant sig - btcDel.BtcUndelegation = &types.BTCUndelegation{} - - if datagen.RandomInt(r, 2) == 1 { - // these BTC delegations are unbonded - for i := range covenantSKs { - sig, err := schnorr.Sign(covenantSKs[i], datagen.GenRandomByteArray(r, 32)) - require.NoError(t, err) - unbondingSig := bbn.NewBIP340SignatureFromBTCSig(sig) - unbondingSigInfo := types.NewSignatureInfo(&covBTCPKs[i], &unbondingSig) - btcDel.BtcUndelegation.CovenantUnbondingSigList = append(btcDel.BtcUndelegation.CovenantUnbondingSigList, unbondingSigInfo) - } - btcDel.BtcUndelegation.CovenantSlashingSigs = btcDel.CovenantSigs - } else { - // these BTC delegations are unbonding - unbondingBtcDelsMap[btcDel.BtcPk.MarshalHex()] = btcDel - } - } - - err = keeper.AddBTCDelegation(ctx, btcDel) - require.NoError(t, err) - } - } - - babylonHeight := datagen.RandomInt(r, 10) + 1 - ctx = ctx.WithBlockHeight(int64(babylonHeight)) - btclcKeeper.EXPECT().GetTipInfo(gomock.Any()).Return(&btclctypes.BTCHeaderInfo{Height: startHeight}).Times(1) - keeper.IndexBTCHeight(ctx) - - // querying paginated BTC delegations and assert - // Generate a page request with a limit and a nil key - if len(unbondingBtcDelsMap) == 0 { - return - } - limit := datagen.RandomInt(r, len(unbondingBtcDelsMap)) + 1 - pagination := constructRequestWithLimit(r, limit) - req := &types.QueryBTCDelegationsRequest{ - Status: types.BTCDelegationStatus_UNBONDING, - Pagination: pagination, - } - for i := uint64(0); i < numBTCDels; i += limit { - resp, err := keeper.BTCDelegations(ctx, req) - require.NoError(t, err) - require.NotNil(t, resp) - for _, btcDel := range resp.BtcDelegations { - _, ok := unbondingBtcDelsMap[btcDel.BtcPk.MarshalHex()] - require.True(t, ok) - } - // Construct the next page request - pagination.Key = resp.Pagination.NextKey - } - }) -} - func FuzzBTCValidatorVotingPowerAtHeight(f *testing.F) { datagen.AddRandomSeedsToFuzzer(f, 10) f.Fuzz(func(t *testing.T, seed int64) { diff --git a/x/btcstaking/keeper/msg_server.go b/x/btcstaking/keeper/msg_server.go index 1a82ebb13..a109a3695 100644 --- a/x/btcstaking/keeper/msg_server.go +++ b/x/btcstaking/keeper/msg_server.go @@ -2,13 +2,13 @@ package keeper import ( "context" - sdkmath "cosmossdk.io/math" "fmt" - "math" + + sdkmath "cosmossdk.io/math" errorsmod "cosmossdk.io/errors" - "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/wire" sdk "github.com/cosmos/cosmos-sdk/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "google.golang.org/grpc/codes" @@ -89,6 +89,7 @@ func (ms msgServer) CreateBTCValidator(goCtx context.Context, req *types.MsgCrea } // CreateBTCDelegation creates a BTC delegation +// TODO: refactor this handler. It's now too convoluted func (ms msgServer) CreateBTCDelegation(goCtx context.Context, req *types.MsgCreateBTCDelegation) (*types.MsgCreateBTCDelegationResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) @@ -96,81 +97,61 @@ func (ms msgServer) CreateBTCDelegation(goCtx context.Context, req *types.MsgCre btccParams := ms.btccKeeper.GetParams(ctx) kValue, wValue := btccParams.BtcConfirmationDepth, btccParams.CheckpointFinalizationTimeout - // 1. verify proof of possession + // verify proof of possession if err := req.Pop.Verify(req.BabylonPk, req.BtcPk, ms.btcNet); err != nil { return nil, types.ErrInvalidProofOfPossession.Wrapf("error while validating proof of posession: %v", err) } - // 2. Ensure list of validator BTC PKs is not empty - if len(req.ValBtcPkList) == 0 { - return nil, types.ErrEmptyValidatorList - } - - // 3. Ensure list of validator BTC PKs is not duplicated - if types.ExistsDup(req.ValBtcPkList) { - return nil, types.ErrDuplicatedValidator - } - - // 4. Ensure all validators are known to Babylon + // Ensure all validators are known to Babylon for _, valBTCPK := range req.ValBtcPkList { if !ms.HasBTCValidator(ctx, valBTCPK) { return nil, types.ErrBTCValNotFound.Wrapf("validator pk: %s", valBTCPK.MarshalHex()) } } - // 5. Parse staking tx + // Parse staking tx stakingMsgTx, err := bbn.NewBTCTxFromBytes(req.StakingTx.Transaction) - if err != nil { return nil, types.ErrInvalidStakingTx.Wrapf("cannot be parsed: %v", err) } - // 6. Check staking tx is not duplicated + // Check staking tx is not duplicated stakingTxHash := stakingMsgTx.TxHash() - delgation := ms.getBTCDelegation(ctx, stakingTxHash) - if delgation != nil { return nil, types.ErrReusedStakingTx.Wrapf("duplicated tx hash: %s", stakingTxHash.String()) } - // 7. Check staking time is at most uint16 - if req.StakingTime > math.MaxUint16 { - return nil, types.ErrInvalidStakingTx.Wrapf("invalid lock time: %d, max: %d", req.StakingTime, math.MaxUint16) - } - - // 8. Check if data provided in request, matches data to which staking tx is comitted - validatorKeys := make([]*btcec.PublicKey, 0, len(req.ValBtcPkList)) - for _, valBTCPK := range req.ValBtcPkList { - validatorKeys = append(validatorKeys, valBTCPK.MustToBTCPK()) + // Check if data provided in request, matches data to which staking tx is committed + valPKs, err := bbn.NewBTCPKsFromBIP340PKs(req.ValBtcPkList) + if err != nil { + return nil, types.ErrInvalidStakingTx.Wrapf("cannot parse validator PK list: %v", err) } - - covenantKeys := make([]*btcec.PublicKey, 0, len(params.CovenantPks)) - for _, covenantPK := range params.CovenantPks { - covenantKeys = append(covenantKeys, covenantPK.MustToBTCPK()) + covenantPKs, err := bbn.NewBTCPKsFromBIP340PKs(params.CovenantPks) + if err != nil { + // programming error + panic("failed to parse covenant PKs in KVStore") } stakingInfo, err := btcstaking.BuildStakingInfo( req.BtcPk.MustToBTCPK(), - validatorKeys, - covenantKeys, + valPKs, + covenantPKs, params.CovenantQuorum, uint16(req.StakingTime), btcutil.Amount(req.StakingValue), ms.btcNet, ) - if err != nil { return nil, types.ErrInvalidStakingTx.Wrapf("err: %v", err) } stakingOutputIdx, err := bbn.GetOutputIdxInBTCTx(stakingMsgTx, stakingInfo.StakingOutput) - if err != nil { return nil, types.ErrInvalidStakingTx.Wrap("staking tx does not contain expected staking output") } - // 9. Check staking tx timelock has correct values + // Check staking tx timelock has correct values // get startheight and endheight of the timelock stakingTxHeader := ms.btclcKeeper.GetHeaderByHash(ctx, req.StakingTx.Key.Hash) if stakingTxHeader == nil { @@ -190,12 +171,12 @@ func (ms msgServer) CreateBTCDelegation(goCtx context.Context, req *types.MsgCre return nil, types.ErrInvalidStakingTx.Wrapf("staking tx's timelock has no more than w(=%d) blocks left", wValue) } - // 10. verify staking tx info, i.e., inclusion proof + // verify staking tx info, i.e., inclusion proof if err := req.StakingTx.VerifyInclusion(stakingTxHeader.Header, ms.btccKeeper.GetPowLimit()); err != nil { return nil, types.ErrInvalidStakingTx.Wrapf("not included in the Bitcoin chain: %v", err) } - // 11. check slashing tx and its consistency with staking tx + // check slashing tx and its consistency with staking tx slashingMsgTx, err := req.SlashingTx.ToMsgTx() if err != nil { return nil, types.ErrInvalidSlashingTx.Wrapf("cannot be converted to wire.MsgTx: %v", err) @@ -208,7 +189,7 @@ func (ms msgServer) CreateBTCDelegation(goCtx context.Context, req *types.MsgCre panic(fmt.Errorf("failed to decode slashing address in genesis: %w", err)) } - // 12. Check slashing tx and staking tx are valid and consistent + // Check slashing tx and staking tx are valid and consistent if err := btcstaking.CheckTransactions( slashingMsgTx, stakingMsgTx, @@ -221,23 +202,19 @@ func (ms msgServer) CreateBTCDelegation(goCtx context.Context, req *types.MsgCre return nil, types.ErrInvalidStakingTx.Wrap(err.Error()) } - stakingOutput := stakingMsgTx.TxOut[stakingOutputIdx] - - // 13. verify delegator sig against slashing path of the script + // verify delegator sig against slashing path of the staking tx's script slashingSpendInfo, err := stakingInfo.SlashingPathSpendInfo() - if err != nil { panic(fmt.Errorf("failed to construct slashing path from the staking tx: %w", err)) } err = req.SlashingTx.VerifySignature( - stakingOutput.PkScript, - stakingOutput.Value, + stakingInfo.StakingOutput.PkScript, + stakingInfo.StakingOutput.Value, slashingSpendInfo.GetPkScriptPath(), req.BtcPk.MustToBTCPK(), - req.DelegatorSig, + req.DelegatorSlashingSig, ) - if err != nil { return nil, types.ErrInvalidSlashingTx.Wrapf("invalid delegator signature: %v", err) } @@ -253,166 +230,92 @@ func (ms msgServer) CreateBTCDelegation(goCtx context.Context, req *types.MsgCre ValBtcPkList: req.ValBtcPkList, StartHeight: startHeight, EndHeight: endHeight, - TotalSat: uint64(stakingOutput.Value), + TotalSat: uint64(stakingInfo.StakingOutput.Value), StakingTx: req.StakingTx.Transaction, StakingOutputIdx: stakingOutputIdx, SlashingTx: req.SlashingTx, - DelegatorSig: req.DelegatorSig, + DelegatorSig: req.DelegatorSlashingSig, CovenantSigs: nil, // NOTE: covenant signature will be submitted in a separate msg by covenant - BtcUndelegation: nil, - } - if err := ms.AddBTCDelegation(ctx, newBTCDel); err != nil { - panic("failed to set BTC delegation that has passed verification") + BtcUndelegation: nil, // this will be constructed in below code } - // notify subscriber - if err := ctx.EventManager().EmitTypedEvent(&types.EventNewBTCDelegation{BtcDel: newBTCDel}); err != nil { - panic(fmt.Errorf("failed to emit EventNewBTCDelegation: %w", err)) - } - - return &types.MsgCreateBTCDelegationResponse{}, nil -} - -// BtcUndelegate undelegates funds from existing delegation -func (ms msgServer) BTCUndelegate(goCtx context.Context, req *types.MsgBTCUndelegate) (*types.MsgBTCUndelegateResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - params := ms.GetParams(ctx) - slashingAddress := params.MustGetSlashingAddress(ms.btcNet) - wValue := ms.btccKeeper.GetParams(ctx).CheckpointFinalizationTimeout + /* + logics about early unbonding + */ - // 1. deserialize provided transactions - slashingMsgTx, err := req.SlashingTx.ToMsgTx() + // deserialize provided transactions + unbondingSlashingMsgTx, err := req.UnbondingSlashingTx.ToMsgTx() if err != nil { - return nil, types.ErrInvalidSlashingTx.Wrapf("cannot be converted to wire.MsgTx: %v", err) + return nil, types.ErrInvalidSlashingTx.Wrapf("cannot convert unbonding slashing tx to wire.MsgTx: %v", err) } - unbondingMsgTx, err := bbn.NewBTCTxFromBytes(req.UnbondingTx) if err != nil { return nil, types.ErrInvalidUnbondingTx.Wrapf("cannot be converted to wire.MsgTx: %v", err) } - // 2. basic stateless checks for unbonding tx - if err := btcstaking.IsSimpleTransfer(unbondingMsgTx); err != nil { - return nil, types.ErrInvalidUnbondingTx.Wrapf("err: %v", err) - } - - // 3. Check unbonding time (staking time from unbonding tx) is larger than finalization time + // Check unbonding time (staking time from unbonding tx) is larger than finalization time // Unbonding time must be strictly larger that babylon finalization time. if uint64(req.UnbondingTime) <= wValue { return nil, types.ErrInvalidUnbondingTx.Wrapf("unbonding time %d must be larger than finalization time %d", req.UnbondingTime, wValue) } - // 4. Check unbonding time is lower than max uint16 - if uint64(req.UnbondingTime) > math.MaxUint16 { - return nil, types.ErrInvalidUnbondingTx.Wrapf("unbonding time %d must be lower than %d", req.UnbondingTime, math.MaxUint16) - } - - // retrieve staking tx hash from unbonding tx, at this point we know that unbonding tx is a simple transfer with - // one input and one output - unbondingTxFundingOutpoint := unbondingMsgTx.TxIn[0].PreviousOutPoint - stakingTxHash := unbondingTxFundingOutpoint.Hash.String() - - // 5. Check delegation wchich should be undelegeated exists and it is in correct state - del, err := ms.GetBTCDelegation(ctx, stakingTxHash) - - if err != nil { - return nil, types.ErrInvalidDelegationState.Wrapf("couldn't retrieve delegation for staking tx hash %s, err: %v", stakingTxHash, err) - } - - // 6. Check delegation state. Only active delegations can be unbonded. - btcTip := ms.btclcKeeper.GetTipInfo(ctx) - status := del.GetStatus(btcTip.Height, wValue, params.CovenantQuorum) - - if status != types.BTCDelegationStatus_ACTIVE { - return nil, types.ErrInvalidDelegationState.Wrapf("current status: %v, want: %s", status.String(), types.BTCDelegationStatus_ACTIVE.String()) - } - - // 7. Check unbonding tx commits to valid scripts - validatorKeys := make([]*btcec.PublicKey, 0, len(del.ValBtcPkList)) - // We retrieve validator keys from the delegation, as we want to check that unbonding tx commits to the same - // validator keys as staking tx. - for _, valBTCPK := range del.ValBtcPkList { - validatorKeys = append(validatorKeys, valBTCPK.MustToBTCPK()) - } - - covenantKeys := make([]*btcec.PublicKey, 0, len(params.CovenantPks)) - // as we do not rotate covenant keys, we can retrieve them from params - for _, covenantPK := range params.CovenantPks { - covenantKeys = append(covenantKeys, covenantPK.MustToBTCPK()) - } - + // building unbonding info unbondingInfo, err := btcstaking.BuildUnbondingInfo( - del.BtcPk.MustToBTCPK(), - validatorKeys, - covenantKeys, + newBTCDel.BtcPk.MustToBTCPK(), + valPKs, + covenantPKs, params.CovenantQuorum, uint16(req.UnbondingTime), btcutil.Amount(req.UnbondingValue), ms.btcNet, ) - if err != nil { return nil, types.ErrInvalidUnbondingTx.Wrapf("err: %v", err) } + // get unbonding output index unbondingOutputIdx, err := bbn.GetOutputIdxInBTCTx(unbondingMsgTx, unbondingInfo.UnbondingOutput) - if err != nil { return nil, types.ErrInvalidUnbondingTx.Wrapf("unbonding tx does not contain expected unbonding output") } - // 8. Check that slashing tx and unbonding tx are valid and consistent + // Check that slashing tx and unbonding tx are valid and consistent err = btcstaking.CheckTransactions( - slashingMsgTx, + unbondingSlashingMsgTx, unbondingMsgTx, unbondingOutputIdx, params.MinSlashingTxFeeSat, params.SlashingRate, - slashingAddress, + params.MustGetSlashingAddress(ms.btcNet), ms.btcNet, ) if err != nil { return nil, types.ErrInvalidUnbondingTx.Wrapf("err: %v", err) } - // 9. Check staker signature against slashing path of the unbonding tx - unbondingOutput := unbondingMsgTx.TxOut[unbondingOutputIdx] - - slashingSpendInfo, err := unbondingInfo.SlashingPathSpendInfo() - + // Check staker signature against slashing path of the unbonding tx + unbondingSlashingSpendInfo, err := unbondingInfo.SlashingPathSpendInfo() if err != nil { // our staking info was constructed by using BuildStakingInfo constructor, so if // this fails, it is a programming error panic(err) } - err = req.SlashingTx.VerifySignature( - unbondingOutput.PkScript, - unbondingOutput.Value, - slashingSpendInfo.GetPkScriptPath(), - del.BtcPk.MustToBTCPK(), - req.DelegatorSlashingSig, + err = req.UnbondingSlashingTx.VerifySignature( + unbondingInfo.UnbondingOutput.PkScript, + unbondingInfo.UnbondingOutput.Value, + unbondingSlashingSpendInfo.GetPkScriptPath(), + newBTCDel.BtcPk.MustToBTCPK(), + req.DelegatorUnbondingSlashingSig, ) if err != nil { return nil, types.ErrInvalidSlashingTx.Wrapf("invalid delegator signature: %v", err) } - // 8. Check unbonding tx against staking tx. + // Check unbonding tx against staking tx. // - that input points to the staking tx, staking output // - fee is larger than 0 - stakingTxMsg, err := bbn.NewBTCTxFromBytes(del.StakingTx) - if err != nil { - // failing to get staking output info from a verified staking tx is a programming error - panic(fmt.Errorf("failed deserialize staking tx from db")) - } - - // we only check index of the staking output, as we already retrieved delegation - // by stakingTxHash computed from unbonding tx input - if unbondingTxFundingOutpoint.Index != uint32(del.StakingOutputIdx) { - return nil, types.ErrInvalidUnbondingTx.Wrapf("unbonding tx does not point to staking tx staking output") - } - - if unbondingMsgTx.TxOut[0].Value >= stakingTxMsg.TxOut[del.StakingOutputIdx].Value { + if unbondingMsgTx.TxOut[0].Value >= stakingMsgTx.TxOut[newBTCDel.StakingOutputIdx].Value { // Note: we do not enfore any minimum fee for unbonding tx, we only require that it is larger than 0 // Given that unbonding tx must not be replacable and we do not allow sending it second time, it places // burden on staker to choose right fee. @@ -421,44 +324,34 @@ func (ms msgServer) BTCUndelegate(goCtx context.Context, req *types.MsgBTCUndele return nil, types.ErrInvalidUnbondingTx.Wrapf("unbonding tx fee must be larger that 0") } - ud := types.BTCUndelegation{ - UnbondingTx: req.UnbondingTx, - SlashingTx: req.SlashingTx, - DelegatorSlashingSig: req.DelegatorSlashingSig, - // following objects needs to be filled by covenant and validator - // covenant emulators need to provide two sigs: - // - one for unbonding tx (schnorr sig) - // - one for validator of the slashing tx of unbonding tx (adaptor sig) + // all good, add BTC undelegation + newBTCDel.BtcUndelegation = &types.BTCUndelegation{ + UnbondingTx: req.UnbondingTx, + SlashingTx: req.UnbondingSlashingTx, + DelegatorSlashingSig: req.DelegatorUnbondingSlashingSig, + DelegatorUnbondingSig: nil, CovenantSlashingSigs: nil, CovenantUnbondingSigList: nil, UnbondingTime: req.UnbondingTime, } - if err := ms.AddUndelegationToBTCDelegation( - ctx, - stakingTxHash, - &ud); err != nil { + if err := ms.AddBTCDelegation(ctx, newBTCDel); err != nil { panic(fmt.Errorf("failed to set BTC delegation that has passed verification: %w", err)) } // notify subscriber - event := &types.EventUnbondingBTCDelegation{ - BtcPk: del.BtcPk, - ValBtcPkList: del.ValBtcPkList, - StakingTxHash: stakingTxHash, - UnbondingTxHash: unbondingMsgTx.TxHash().String(), - } - if err := ctx.EventManager().EmitTypedEvent(event); err != nil { - panic(fmt.Errorf("failed to emit EventUnbondingBTCDelegation: %w", err)) + if err := ctx.EventManager().EmitTypedEvent(&types.EventNewBTCDelegation{BtcDel: newBTCDel}); err != nil { + panic(fmt.Errorf("failed to emit EventNewBTCDelegation: %w", err)) } - return &types.MsgBTCUndelegateResponse{}, nil + return &types.MsgCreateBTCDelegationResponse{}, nil } // AddCovenantSig adds a signature from covenant to a BTC delegation -func (ms msgServer) AddCovenantSig(goCtx context.Context, req *types.MsgAddCovenantSig) (*types.MsgAddCovenantSigResponse, error) { +// TODO: refactor this handler. Now it's too convoluted +func (ms msgServer) AddCovenantSigs(goCtx context.Context, req *types.MsgAddCovenantSigs) (*types.MsgAddCovenantSigsResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - covenantQuorum := ms.GetParams(ctx).CovenantQuorum + params := ms.GetParams(ctx) // ensure BTC delegation exists btcDel, err := ms.GetBTCDelegation(ctx, req.StakingTxHash) @@ -466,158 +359,73 @@ func (ms msgServer) AddCovenantSig(goCtx context.Context, req *types.MsgAddCoven return nil, err } + // ensure that the given covenant PK is in the parameter + if !params.HasCovenantPK(req.Pk) { + return nil, types.ErrInvalidCovenantPK.Wrapf("covenant pk: %s", req.Pk.MarshalHex()) + } + // Note: we assume the order of adaptor sigs is matched to the // order of validators in the delegation - // TODO ensure the order, currently, we only have one validator + // TODO: ensure the order for restaking, currently, we only have one validator // one covenant emulator - numAdaptorSig := len(req.Sigs) - numVals := len(btcDel.ValBtcPkList) - if numAdaptorSig != numVals { + if len(req.SlashingTxSigs) != len(btcDel.ValBtcPkList) { return nil, types.ErrInvalidCovenantSig.Wrapf( "number of covenant signatures: %d, number of validators being staked to: %d", - numAdaptorSig, numVals) - } - - // ensure that the given covenant PK is in the parameter - params := ms.GetParams(ctx) - if !params.HasCovenantPK(req.Pk) { - return nil, types.ErrInvalidCovenantPK.Wrapf("covenant pk: %s", req.Pk.MarshalHex()) + len(req.SlashingTxSigs), len(btcDel.ValBtcPkList)) } + /* + Verify each covenant adaptor signature over slashing tx + */ stakingInfo, err := btcDel.GetStakingInfo(¶ms, ms.btcNet) if err != nil { panic(fmt.Errorf("failed to get staking info from a verified delegation: %w", err)) } - slashingSpendInfo, err := stakingInfo.SlashingPathSpendInfo() if err != nil { // our staking info was constructed by using BuildStakingInfo constructor, so if // this fails, it is a programming error panic(err) } - - // verify each covenant adaptor signature with the corresponding validator public key - for i, sig := range req.Sigs { - err := verifySlashingTxAdaptorSig( - btcDel.SlashingTx, - stakingInfo.StakingOutput.PkScript, - stakingInfo.StakingOutput.Value, - slashingSpendInfo.GetPkScriptPath(), - req.Pk.MustToBTCPK(), - btcDel.ValBtcPkList[i].MustToBTCPK(), - sig, - ) - if err != nil { - return nil, types.ErrInvalidCovenantSig.Wrapf("err: %v", err) - } - } - - // all good, add signatures to BTC delegation and set it back to KVStore - if err := ms.AddCovenantSigsToBTCDelegation(ctx, req.StakingTxHash, req.Sigs, req.Pk, covenantQuorum); err != nil { - panic("failed to set BTC delegation that has passed verification") - } - - // notify subscriber - if err := ctx.EventManager().EmitTypedEvent(&types.EventActivateBTCDelegation{BtcDel: btcDel}); err != nil { - panic(fmt.Errorf("failed to emit EventActivateBTCDelegation: %w", err)) - } - - return &types.MsgAddCovenantSigResponse{}, nil -} - -func verifySlashingTxAdaptorSig( - slashingTx *types.BTCSlashingTx, - stakingPkScript []byte, - stakingAmount int64, - stakingScript []byte, - pk *btcec.PublicKey, - valPk *btcec.PublicKey, - sig []byte) error { - adaptorSig, err := asig.NewAdaptorSignatureFromBytes(sig) - if err != nil { - return err - } - - encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) - if err != nil { - return err - } - - return slashingTx.EncVerifyAdaptorSignature( - stakingPkScript, - stakingAmount, - stakingScript, - pk, - encKey, - adaptorSig, + err = verifySlashingTxAdaptorSigs( + stakingInfo.StakingOutput, + slashingSpendInfo, + btcDel.SlashingTx, + req.Pk, + btcDel.ValBtcPkList, + req.SlashingTxSigs, ) -} - -func (ms msgServer) AddCovenantUnbondingSigs( - goCtx context.Context, - req *types.MsgAddCovenantUnbondingSigs, -) (*types.MsgAddCovenantUnbondingSigsResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - wValue := ms.btccKeeper.GetParams(ctx).CheckpointFinalizationTimeout - covenantQuorum := ms.GetParams(ctx).CovenantQuorum - - // 1. Check that delegation even exists for provided params - btcDel, err := ms.GetBTCDelegation(ctx, req.StakingTxHash) if err != nil { - return nil, err - } - - btcTip := ms.btclcKeeper.GetTipInfo(ctx) - status := btcDel.GetStatus(btcTip.Height, wValue, covenantQuorum) - - // 2. Check that we are in proper status - if status != types.BTCDelegationStatus_UNBONDING { - return nil, types.ErrInvalidDelegationState.Wrapf("Expected status: %s, actual: %s", types.BTCDelegationStatus_UNBONDING.String(), status.String()) + return nil, types.ErrInvalidCovenantSig.Wrapf("err: %v", err) } - // 3. Check that the number of covenant sigs and number of the + // Check that the number of covenant sigs and number of the // validators are matched // Note: we assume the order of adaptor sigs is matched to the // order of validators in the delegation - // TODO ensure the order, currently, we only have one validator + // TODO: ensure the order for restaking, currently, we only have one validator // one covenant emulator - numAdaptorSig := len(req.SlashingUnbondingTxSigs) - numVals := len(btcDel.ValBtcPkList) - if numAdaptorSig != numVals { + if len(req.SlashingUnbondingTxSigs) != len(btcDel.ValBtcPkList) { return nil, types.ErrInvalidCovenantSig.Wrapf( "number of covenant signatures: %d, number of validators being staked to: %d", - numAdaptorSig, numVals) + len(req.SlashingUnbondingTxSigs), len(btcDel.ValBtcPkList)) } - // ensure that the given covenant PK is in the parameter - params := ms.GetParams(ctx) - if !params.HasCovenantPK(req.Pk) { - return nil, types.ErrInvalidCovenantPK - } - - unbondingTxMsg, err := bbn.NewBTCTxFromBytes(btcDel.BtcUndelegation.UnbondingTx) - + /* + Verify Schnorr signature over unbonding tx + */ + unbondingMsgTx, err := bbn.NewBTCTxFromBytes(btcDel.BtcUndelegation.UnbondingTx) if err != nil { panic(fmt.Errorf("failed to parse unbonding tx from existing delegation with hash %s : %v", req.StakingTxHash, err)) } - - unbondingTxHash := unbondingTxMsg.TxHash().String() - - stakingInfo, err := btcDel.GetStakingInfo(¶ms, ms.btcNet) - if err != nil { - panic(err) - } - unbondingSpendInfo, err := stakingInfo.UnbondingPathSpendInfo() if err != nil { // our staking info was constructed by using BuildStakingInfo constructor, so if // this fails, it is a programming error panic(err) } - - // 4. Verify signature of unbonding tx against staking tx output if err := btcstaking.VerifyTransactionSigWithOutputData( - unbondingTxMsg, + unbondingMsgTx, stakingInfo.StakingOutput.PkScript, stakingInfo.StakingOutput.Value, unbondingSpendInfo.GetPkScriptPath(), @@ -627,61 +435,153 @@ func (ms msgServer) AddCovenantUnbondingSigs( return nil, types.ErrInvalidCovenantSig.Wrap(err.Error()) } - // 5. Verify signature of slashing tx against unbonding tx output - // unbonding tx always have only one output - unbondingOutput := unbondingTxMsg.TxOut[0] + /* + verify each adaptor signature on slashing unbonding tx + */ + unbondingOutput := unbondingMsgTx.TxOut[0] // unbonding tx always have only one output unbondingInfo, err := btcDel.GetUnbondingInfo(¶ms, ms.btcNet) if err != nil { panic(err) } - - slashingSpendInfo, err := unbondingInfo.SlashingPathSpendInfo() - + unbondingSlashingSpendInfo, err := unbondingInfo.SlashingPathSpendInfo() if err != nil { // our unbonding info was constructed by using BuildStakingInfo constructor, so if // this fails, it is a programming error panic(err) } - - // verify each covenant adaptor signature with the corresponding validator public key - for i, sig := range req.SlashingUnbondingTxSigs { - err := verifySlashingTxAdaptorSig( - btcDel.BtcUndelegation.SlashingTx, - unbondingOutput.PkScript, - unbondingOutput.Value, - slashingSpendInfo.GetPkScriptPath(), - req.Pk.MustToBTCPK(), - btcDel.ValBtcPkList[i].MustToBTCPK(), - sig, - ) - if err != nil { - return nil, types.ErrInvalidCovenantSig.Wrapf("err: %v", err) - } + err = verifySlashingTxAdaptorSigs( + unbondingOutput, + unbondingSlashingSpendInfo, + btcDel.BtcUndelegation.SlashingTx, + req.Pk, + btcDel.ValBtcPkList, + req.SlashingUnbondingTxSigs, + ) + if err != nil { + return nil, types.ErrInvalidCovenantSig.Wrapf("err: %v", err) } - // all good, add signature to BTC undelegation and set it back to KVStore - if err := ms.AddCovenantSigsToUndelegation( + // all good, add signatures to BTC delegation/undelegation and set it back to KVStore + if err := ms.AddCovenantSigsToBTCDelegation( ctx, req.StakingTxHash, req.Pk, + req.SlashingTxSigs, req.UnbondingTxSig, req.SlashingUnbondingTxSigs, - covenantQuorum, ); err != nil { - panic("failed to set BTC delegation that has passed verification") + return nil, types.ErrInvalidCovenantSig.Wrapf("failed to add covenant signatures to BTC delegation: %v", err) } + // notify subscriber + if err := ctx.EventManager().EmitTypedEvent(&types.EventActivateBTCDelegation{BtcDel: btcDel}); err != nil { + panic(fmt.Errorf("failed to emit EventActivateBTCDelegation: %w", err)) + } + + return &types.MsgAddCovenantSigsResponse{}, nil +} + +// AddCovenantSig adds a signature from covenant to a BTC delegation +func (ms msgServer) BTCUndelegate(goCtx context.Context, req *types.MsgBTCUndelegate) (*types.MsgBTCUndelegateResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + bsParams := ms.GetParams(ctx) + + // ensure BTC delegation exists + btcDel, err := ms.GetBTCDelegation(ctx, req.StakingTxHash) + if err != nil { + return nil, err + } + + // ensure the BTC delegation with the given staking tx hash is active + btcTip := ms.btclcKeeper.GetTipInfo(ctx) + wValue := ms.btccKeeper.GetParams(ctx).CheckpointFinalizationTimeout + if btcDel.GetStatus(btcTip.Height, wValue, bsParams.CovenantQuorum) != types.BTCDelegationStatus_ACTIVE { + return nil, types.ErrInvalidBTCUndelegateReq.Wrap("cannot unbond an inactive BTC delegation") + } + + // verify the signature on unbonding tx from delegator + unbondingMsgTx, err := bbn.NewBTCTxFromBytes(btcDel.BtcUndelegation.UnbondingTx) + if err != nil { + panic(fmt.Errorf("failed to parse unbonding tx from existing delegation with hash %s : %v", req.StakingTxHash, err)) + } + stakingInfo, err := btcDel.GetStakingInfo(&bsParams, ms.btcNet) + if err != nil { + panic(fmt.Errorf("failed to get staking info from a verified delegation: %w", err)) + } + unbondingSpendInfo, err := stakingInfo.UnbondingPathSpendInfo() + if err != nil { + // our staking info was constructed by using BuildStakingInfo constructor, so if + // this fails, it is a programming error + panic(err) + } + if err := btcstaking.VerifyTransactionSigWithOutputData( + unbondingMsgTx, + stakingInfo.StakingOutput.PkScript, + stakingInfo.StakingOutput.Value, + unbondingSpendInfo.GetPkScriptPath(), + btcDel.BtcPk.MustToBTCPK(), + *req.UnbondingTxSig, + ); err != nil { + return nil, types.ErrInvalidCovenantSig.Wrap(err.Error()) + } + + // all good, add the signature to BTC delegation's undelegation + // and set back + err = ms.updateBTCDelegation(ctx, req.StakingTxHash, func(del *types.BTCDelegation) error { + del.BtcUndelegation.DelegatorUnbondingSig = req.UnbondingTxSig + return nil + }) + if err != nil { + return nil, err + } + + // notify subscriber about this unbonded BTC delegation event := &types.EventUnbondedBTCDelegation{ BtcPk: btcDel.BtcPk, ValBtcPkList: btcDel.ValBtcPkList, StakingTxHash: req.StakingTxHash, - UnbondingTxHash: unbondingTxHash, - FromState: types.BTCDelegationStatus_UNBONDING, + UnbondingTxHash: unbondingMsgTx.TxHash().String(), + FromState: types.BTCDelegationStatus_ACTIVE, } - if err := ctx.EventManager().EmitTypedEvent(event); err != nil { panic(fmt.Errorf("failed to emit EventUnbondedBTCDelegation: %w", err)) } - return nil, nil + return &types.MsgBTCUndelegateResponse{}, nil +} + +// verifySlashingTxAdaptorSigs verifies a list of adaptor signatures, each +// encrypted by a restaked validator PK and signed by the given PK, w.r.t. the +// given funding output (in staking or unbonding tx), slashing spend info and +// slashing tx +func verifySlashingTxAdaptorSigs( + fundingOut *wire.TxOut, + slashingSpendInfo *btcstaking.SpendInfo, + slashingTx *types.BTCSlashingTx, + pk *bbn.BIP340PubKey, + valPKs []bbn.BIP340PubKey, + sigs [][]byte, +) error { + for i, sig := range sigs { + adaptorSig, err := asig.NewAdaptorSignatureFromBytes(sig) + if err != nil { + return err + } + encKey, err := asig.NewEncryptionKeyFromBTCPK(valPKs[i].MustToBTCPK()) + if err != nil { + return err + } + err = slashingTx.EncVerifyAdaptorSignature( + fundingOut.PkScript, + fundingOut.Value, + slashingSpendInfo.GetPkScriptPath(), + pk.MustToBTCPK(), + encKey, + adaptorSig, + ) + if err != nil { + return types.ErrInvalidCovenantSig.Wrapf("err: %v", err) + } + } + return nil } diff --git a/x/btcstaking/keeper/msg_server_test.go b/x/btcstaking/keeper/msg_server_test.go index b6c1a7511..67572228c 100644 --- a/x/btcstaking/keeper/msg_server_test.go +++ b/x/btcstaking/keeper/msg_server_test.go @@ -10,15 +10,12 @@ import ( sdkmath "cosmossdk.io/math" "github.com/btcsuite/btcd/btcec/v2" - "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" - "github.com/babylonchain/babylon/btcstaking" - asig "github.com/babylonchain/babylon/crypto/schnorr-adaptor-signature" "github.com/babylonchain/babylon/testutil/datagen" keepertest "github.com/babylonchain/babylon/testutil/keeper" bbn "github.com/babylonchain/babylon/types" @@ -59,7 +56,11 @@ func (h *Helper) NoError(err error) { } func (h *Helper) GenAndApplyParams(r *rand.Rand) ([]*btcec.PrivateKey, []*btcec.PublicKey) { - // TODO: randomise covenant committee and quorum? + // mocking stuff for BTC checkpoint keeper + h.BTCCheckpointKeeper.EXPECT().GetPowLimit().Return(h.Net.PowLimit).AnyTimes() + h.BTCCheckpointKeeper.EXPECT().GetParams(gomock.Any()).Return(btcctypes.DefaultParams()).AnyTimes() + + // randomise covenant committee covenantSKs, covenantPKs, err := datagen.GenRandomBTCKeyPairs(r, 5) h.NoError(err) slashingAddress, err := datagen.GenRandomBTCAddress(r, h.Net) @@ -99,12 +100,12 @@ func (h *Helper) CreateDelegation( r *rand.Rand, validatorPK *btcec.PublicKey, changeAddress string, + stakingValue int64, stakingTime uint16, ) (string, *btcec.PrivateKey, *btcec.PublicKey, *types.MsgCreateBTCDelegation) { delSK, delPK, err := datagen.GenRandomBTCKeyPair(r) h.NoError(err) stakingTimeBlocks := stakingTime - stakingValue := int64(2 * 10e8) bsParams := h.BTCStakingKeeper.GetParams(h.Ctx) covPKs, err := bbn.NewBTCPKsFromBIP340PKs(bsParams.CovenantPks) h.NoError(err) @@ -143,10 +144,8 @@ func (h *Helper) CreateDelegation( txInfo := btcctypes.NewTransactionInfo(&btcctypes.TransactionKey{Index: 1, Hash: btcHeader.Hash()}, serializedStakingTx, btcHeaderWithProof.SpvProof.MerkleNodes) // mock for testing k-deep stuff - h.BTCCheckpointKeeper.EXPECT().GetPowLimit().Return(h.Net.PowLimit).AnyTimes() - h.BTCCheckpointKeeper.EXPECT().GetParams(gomock.Any()).Return(btcctypes.DefaultParams()).AnyTimes() h.BTCLightClientKeeper.EXPECT().GetHeaderByHash(gomock.Any(), gomock.Eq(btcHeader.Hash())).Return(&btclctypes.BTCHeaderInfo{Header: &btcHeader, Height: 10}).AnyTimes() - h.BTCLightClientKeeper.EXPECT().GetTipInfo(gomock.Any()).Return(&btclctypes.BTCHeaderInfo{Height: 30}) + h.BTCLightClientKeeper.EXPECT().GetTipInfo(gomock.Any()).Return(&btclctypes.BTCHeaderInfo{Height: 30}).AnyTimes() slashingSpendInfo, err := testStakingInfo.StakingInfo.SlashingPathSpendInfo() h.NoError(err) @@ -163,19 +162,57 @@ func (h *Helper) CreateDelegation( stakerPk := delSK.PubKey() stPk := bbn.NewBIP340PubKeyFromBTCPK(stakerPk) + /* + logics related to on-demand unbonding + */ + stkTxHash := testStakingInfo.StakingTx.TxHash() + stkOutputIdx := uint32(0) + defaultParams := btcctypes.DefaultParams() + + unbondingTime := uint16(defaultParams.CheckpointFinalizationTimeout) + 1 + unbondingValue := stakingValue - 1000 + testUnbondingInfo := datagen.GenBTCUnbondingSlashingInfo( + r, + h.t, + h.Net, + delSK, + []*btcec.PublicKey{validatorPK}, + covPKs, + bsParams.CovenantQuorum, + wire.NewOutPoint(&stkTxHash, stkOutputIdx), + unbondingTime, + unbondingValue, + bsParams.SlashingAddress, + changeAddress, + bsParams.SlashingRate, + ) + h.NoError(err) + + delSlashingTxSig, err := testUnbondingInfo.GenDelSlashingTxSig(delSK) + h.NoError(err) + + serializedUnbondingTx, err := bbn.SerializeBTCTx(testUnbondingInfo.UnbondingTx) + h.NoError(err) + // all good, construct and send MsgCreateBTCDelegation message msgCreateBTCDel := &types.MsgCreateBTCDelegation{ - Signer: signer, - BabylonPk: delBabylonPK.(*secp256k1.PubKey), - BtcPk: stPk, - ValBtcPkList: []bbn.BIP340PubKey{*bbn.NewBIP340PubKeyFromBTCPK(validatorPK)}, - Pop: pop, - StakingTime: uint32(stakingTimeBlocks), - StakingValue: stakingValue, - StakingTx: txInfo, - SlashingTx: testStakingInfo.SlashingTx, - DelegatorSig: delegatorSig, + Signer: signer, + BabylonPk: delBabylonPK.(*secp256k1.PubKey), + BtcPk: stPk, + ValBtcPkList: []bbn.BIP340PubKey{*bbn.NewBIP340PubKeyFromBTCPK(validatorPK)}, + Pop: pop, + StakingTime: uint32(stakingTimeBlocks), + StakingValue: stakingValue, + StakingTx: txInfo, + SlashingTx: testStakingInfo.SlashingTx, + DelegatorSlashingSig: delegatorSig, + UnbondingTx: serializedUnbondingTx, + UnbondingTime: uint32(unbondingTime), + UnbondingValue: unbondingValue, + UnbondingSlashingTx: testUnbondingInfo.SlashingTx, + DelegatorUnbondingSlashingSig: delSlashingTxSig, } + _, err = h.MsgServer.CreateBTCDelegation(h.Ctx, msgCreateBTCDel) h.NoError(err) return stakingTxHash, delSK, delPK, msgCreateBTCDel @@ -185,35 +222,27 @@ func (h *Helper) CreateCovenantSigs( r *rand.Rand, covenantSKs []*btcec.PrivateKey, msgCreateBTCDel *types.MsgCreateBTCDelegation, - delegation *types.BTCDelegation, + del *types.BTCDelegation, ) { - stakingTx, err := bbn.NewBTCTxFromBytes(delegation.StakingTx) + stakingTx, err := bbn.NewBTCTxFromBytes(del.StakingTx) h.NoError(err) stakingTxHash := stakingTx.TxHash().String() bsParams := h.BTCStakingKeeper.GetParams(h.Ctx) - cPks, err := bbn.NewBTCPKsFromBIP340PKs(bsParams.CovenantPks) - h.NoError(err) - vPKs, err := bbn.NewBTCPKsFromBIP340PKs(delegation.ValBtcPkList) + vPKs, err := bbn.NewBTCPKsFromBIP340PKs(del.ValBtcPkList) h.NoError(err) - info, err := btcstaking.BuildStakingInfo( - delegation.BtcPk.MustToBTCPK(), - vPKs, - cPks, - bsParams.CovenantQuorum, - delegation.GetStakingTime(), - btcutil.Amount(delegation.TotalSat), - h.Net, - ) + stakingInfo, err := del.GetStakingInfo(&bsParams, h.Net) h.NoError(err) - slashingPathInfo, err := info.SlashingPathSpendInfo() + unbondingPathInfo, err := stakingInfo.UnbondingPathSpendInfo() + h.NoError(err) + slashingPathInfo, err := stakingInfo.SlashingPathSpendInfo() h.NoError(err) // generate all covenant signatures from all covenant members - covenantSigs, err := datagen.GenCovenantAdaptorSigs( + covenantSlashingTxSigs, err := datagen.GenCovenantAdaptorSigs( covenantSKs, vPKs, stakingTx, @@ -222,25 +251,60 @@ func (h *Helper) CreateCovenantSigs( ) h.NoError(err) + /* + Logics about on-demand unbonding + */ + + // slash unbonding tx spends unbonding tx + unbondingTx, err := bbn.NewBTCTxFromBytes(del.BtcUndelegation.UnbondingTx) + h.NoError(err) + unbondingInfo, err := del.GetUnbondingInfo(&bsParams, h.Net) + h.NoError(err) + unbondingSlashingPathInfo, err := unbondingInfo.SlashingPathSpendInfo() + h.NoError(err) + + // generate all covenant signatures from all covenant members + covenantUnbondingSlashingTxSigs, err := datagen.GenCovenantAdaptorSigs( + covenantSKs, + vPKs, + unbondingTx, + unbondingSlashingPathInfo.GetPkScriptPath(), + del.BtcUndelegation.SlashingTx, + ) + h.NoError(err) + // each covenant member submits signatures - for i := 0; i < len(covenantSigs); i++ { - msgAddCovenantSig := &types.MsgAddCovenantSig{ - Signer: msgCreateBTCDel.Signer, - Pk: covenantSigs[i].CovPk, - StakingTxHash: stakingTxHash, - Sigs: covenantSigs[i].AdaptorSigs, + covUnbondingSigs, err := datagen.GenCovenantUnbondingSigs(covenantSKs, stakingTx, del.StakingOutputIdx, unbondingPathInfo.GetPkScriptPath(), unbondingTx) + h.NoError(err) + + for i := 0; i < len(bsParams.CovenantPks); i++ { + msgAddCovenantSig := &types.MsgAddCovenantSigs{ + Signer: msgCreateBTCDel.Signer, + Pk: covenantSlashingTxSigs[i].CovPk, + StakingTxHash: stakingTxHash, + SlashingTxSigs: covenantSlashingTxSigs[i].AdaptorSigs, + UnbondingTxSig: bbn.NewBIP340SignatureFromBTCSig(covUnbondingSigs[i]), + SlashingUnbondingTxSigs: covenantUnbondingSlashingTxSigs[i].AdaptorSigs, } - _, err = h.MsgServer.AddCovenantSig(h.Ctx, msgAddCovenantSig) + _, err = h.MsgServer.AddCovenantSigs(h.Ctx, msgAddCovenantSig) h.NoError(err) } /* ensure covenant sig is added successfully */ - actualDelWithCovenantSig, err := h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) + actualDelWithCovenantSigs, err := h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) h.NoError(err) - require.Equal(h.t, len(actualDelWithCovenantSig.CovenantSigs), int(bsParams.CovenantQuorum)) // TODO: fix - require.True(h.t, actualDelWithCovenantSig.HasCovenantQuorum(h.BTCStakingKeeper.GetParams(h.Ctx).CovenantQuorum)) + require.Equal(h.t, len(actualDelWithCovenantSigs.CovenantSigs), int(bsParams.CovenantQuorum)) // TODO: fix + require.True(h.t, actualDelWithCovenantSigs.HasCovenantQuorums(h.BTCStakingKeeper.GetParams(h.Ctx).CovenantQuorum)) + + require.NotNil(h.t, actualDelWithCovenantSigs.BtcUndelegation) + require.NotNil(h.t, actualDelWithCovenantSigs.BtcUndelegation.CovenantSlashingSigs) + require.NotNil(h.t, actualDelWithCovenantSigs.BtcUndelegation.CovenantUnbondingSigList) + require.Len(h.t, actualDelWithCovenantSigs.BtcUndelegation.CovenantUnbondingSigList, int(bsParams.CovenantQuorum)) + require.Len(h.t, actualDelWithCovenantSigs.BtcUndelegation.CovenantSlashingSigs, int(bsParams.CovenantQuorum)) + require.Len(h.t, actualDelWithCovenantSigs.BtcUndelegation.CovenantSlashingSigs[0].AdaptorSigs, 1) + } func (h *Helper) GetDelegationAndCheckValues( @@ -260,75 +324,10 @@ func (h *Helper) GetDelegationAndCheckValues( err = actualDel.ValidateBasic() h.NoError(err) // delegation is not activated by covenant yet - require.False(h.t, actualDel.HasCovenantQuorum(h.BTCStakingKeeper.GetParams(h.Ctx).CovenantQuorum)) + require.False(h.t, actualDel.HasCovenantQuorums(h.BTCStakingKeeper.GetParams(h.Ctx).CovenantQuorum)) return actualDel } -func (h *Helper) CreateUndelegation( - r *rand.Rand, - actualDel *types.BTCDelegation, - delSK *btcec.PrivateKey, - validatorPK *btcec.PublicKey, - changeAddress string, -) *types.MsgBTCUndelegate { - stkTxHash, err := actualDel.GetStakingTxHash() - h.NoError(err) - stkOutputIdx := uint32(0) - defaultParams := btcctypes.DefaultParams() - - unbondingTime := uint16(defaultParams.CheckpointFinalizationTimeout) + 1 - unbondingValue := int64(actualDel.TotalSat) - 1000 - bsParams := h.BTCStakingKeeper.GetParams(h.Ctx) - covPKs, err := bbn.NewBTCPKsFromBIP340PKs(bsParams.CovenantPks) - h.NoError(err) - testUnbondingInfo := datagen.GenBTCUnbondingSlashingInfo( - r, - h.t, - h.Net, - delSK, - []*btcec.PublicKey{validatorPK}, - covPKs, - bsParams.CovenantQuorum, - wire.NewOutPoint(&stkTxHash, stkOutputIdx), - unbondingTime, - unbondingValue, - bsParams.SlashingAddress, - changeAddress, - bsParams.SlashingRate, - ) - h.NoError(err) - // random signer - signer := datagen.GenRandomAccount().Address - unbondingTxMsg := testUnbondingInfo.UnbondingTx - - unbondingSlashingPathInfo, err := testUnbondingInfo.UnbondingInfo.SlashingPathSpendInfo() - h.NoError(err) - - sig, err := testUnbondingInfo.SlashingTx.Sign( - unbondingTxMsg, - 0, - unbondingSlashingPathInfo.GetPkScriptPath(), - delSK, - ) - h.NoError(err) - - serializedUnbondingTx, err := bbn.SerializeBTCTx(testUnbondingInfo.UnbondingTx) - h.NoError(err) - - msg := &types.MsgBTCUndelegate{ - Signer: signer, - UnbondingTx: serializedUnbondingTx, - UnbondingTime: uint32(unbondingTime), - UnbondingValue: unbondingValue, - SlashingTx: testUnbondingInfo.SlashingTx, - DelegatorSlashingSig: sig, - } - h.BTCLightClientKeeper.EXPECT().GetTipInfo(gomock.Any()).Return(&btclctypes.BTCHeaderInfo{Height: actualDel.StartHeight + 1}) - _, err = h.MsgServer.BTCUndelegate(h.Ctx, msg) - h.NoError(err) - return msg -} - func FuzzMsgCreateBTCValidator(f *testing.F) { datagen.AddRandomSeedsToFuzzer(f, 10) @@ -376,12 +375,11 @@ func FuzzMsgCreateBTCValidator(f *testing.F) { }) } -func FuzzCreateBTCDelegationAndAddCovenantSig(f *testing.F) { +func FuzzCreateBTCDelegationAndAddCovenantSigs(f *testing.F) { datagen.AddRandomSeedsToFuzzer(f, 10) f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) - net := &chaincfg.SimNetParams ctrl := gomock.NewController(t) defer ctrl.Finish() @@ -390,43 +388,117 @@ func FuzzCreateBTCDelegationAndAddCovenantSig(f *testing.F) { btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) h := NewHelper(t, btclcKeeper, btccKeeper) - // set covenant PKs to params + // set all parameters covenantSKs, _ := h.GenAndApplyParams(r) - changeAddress, err := datagen.GenRandomBTCAddress(r, net) + changeAddress, err := datagen.GenRandomBTCAddress(r, h.Net) require.NoError(t, err) - /* - generate and insert new BTC validator - */ + // generate and insert new BTC validator _, validatorPK, _ := h.CreateValidator(r) - /* - generate and insert new BTC delegation - */ - stakingTxHash, _, delPK, msgCreateBTCDel := h.CreateDelegation( + // generate and insert new BTC delegation + stakingValue := int64(2 * 10e8) + stakingTxHash, _, _, msgCreateBTCDel := h.CreateDelegation( r, validatorPK, changeAddress.EncodeAddress(), + stakingValue, 1000, ) - /* - verify the new BTC delegation - */ - // check existence - actualDel := h.GetDelegationAndCheckValues(r, msgCreateBTCDel, validatorPK, delPK, stakingTxHash) + // ensure consistency between the msg and the BTC delegation in DB + actualDel, err := h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) + h.NoError(err) + require.Equal(h.t, msgCreateBTCDel.BabylonPk, actualDel.BabylonPk) + require.Equal(h.t, msgCreateBTCDel.Pop, actualDel.Pop) + require.Equal(h.t, msgCreateBTCDel.StakingTx.Transaction, actualDel.StakingTx) + require.Equal(h.t, msgCreateBTCDel.SlashingTx, actualDel.SlashingTx) + // ensure the BTC delegation in DB is correctly formatted + err = actualDel.ValidateBasic() + h.NoError(err) + // delegation is not activated by covenant yet + require.False(h.t, actualDel.HasCovenantQuorums(h.BTCStakingKeeper.GetParams(h.Ctx).CovenantQuorum)) + + //generate and insert new covenant signatures + h.CreateCovenantSigs(r, covenantSKs, msgCreateBTCDel, actualDel) + + // ensure the BTC delegation now has voting power + actualDel, err = h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) + h.NoError(err) + require.True(h.t, actualDel.HasCovenantQuorums(h.BTCStakingKeeper.GetParams(h.Ctx).CovenantQuorum)) + votingPower := actualDel.VotingPower(h.BTCLightClientKeeper.GetTipInfo(h.Ctx).Height, h.BTCCheckpointKeeper.GetParams(h.Ctx).CheckpointFinalizationTimeout, h.BTCStakingKeeper.GetParams(h.Ctx).CovenantQuorum) + require.Equal(t, uint64(stakingValue), votingPower) + }) +} + +func FuzzBTCUndelegate(f *testing.F) { + datagen.AddRandomSeedsToFuzzer(f, 10) + + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + // mock BTC light client and BTC checkpoint modules + btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) + btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) + h := NewHelper(t, btclcKeeper, btccKeeper) + + // set all parameters + covenantSKs, _ := h.GenAndApplyParams(r) + + bsParams := h.BTCStakingKeeper.GetParams(h.Ctx) + wValue := h.BTCCheckpointKeeper.GetParams(h.Ctx).CheckpointFinalizationTimeout - /* - generate and insert new covenant signature - */ + changeAddress, err := datagen.GenRandomBTCAddress(r, h.Net) + require.NoError(t, err) + + // generate and insert new BTC validator + _, validatorPK, _ := h.CreateValidator(r) + + // generate and insert new BTC delegation + stakingValue := int64(2 * 10e8) + stakingTxHash, delSK, _, msgCreateBTCDel := h.CreateDelegation( + r, + validatorPK, + changeAddress.EncodeAddress(), + stakingValue, + 1000, + ) + + // add covenant signatures to this BTC delegation + actualDel, err := h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) + h.NoError(err) h.CreateCovenantSigs(r, covenantSKs, msgCreateBTCDel, actualDel) + + // ensure the BTC delegation is bonded right now + actualDel, err = h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) + h.NoError(err) + btcTip := h.BTCLightClientKeeper.GetTipInfo(h.Ctx).Height + status := actualDel.GetStatus(btcTip, wValue, bsParams.CovenantQuorum) + require.Equal(t, types.BTCDelegationStatus_ACTIVE, status) + + // delegator wants to unbond + delUnbondingSig, err := actualDel.SignUnbondingTx(&bsParams, h.Net, delSK) + h.NoError(err) + _, err = h.MsgServer.BTCUndelegate(h.Ctx, &types.MsgBTCUndelegate{ + Signer: datagen.GenRandomAccount().Address, + StakingTxHash: stakingTxHash, + UnbondingTxSig: bbn.NewBIP340SignatureFromBTCSig(delUnbondingSig), + }) + h.NoError(err) + + // ensure the BTC delegation is unbonded + actualDel, err = h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) + h.NoError(err) + status = actualDel.GetStatus(btcTip, wValue, bsParams.CovenantQuorum) + require.Equal(t, types.BTCDelegationStatus_UNBONDED, status) }) } func TestDoNotAllowDelegationWithoutValidator(t *testing.T) { r := rand.New(rand.NewSource(time.Now().UnixNano())) - net := &chaincfg.SimNetParams ctrl := gomock.NewController(t) defer ctrl.Finish() @@ -440,7 +512,7 @@ func TestDoNotAllowDelegationWithoutValidator(t *testing.T) { _, covenantPKs := h.GenAndApplyParams(r) bsParams := h.BTCStakingKeeper.GetParams(h.Ctx) - changeAddress, err := datagen.GenRandomBTCAddress(r, net) + changeAddress, err := datagen.GenRandomBTCAddress(r, h.Net) require.NoError(t, err) // We only generate a validator, but not insert it into KVStore. So later @@ -458,7 +530,7 @@ func TestDoNotAllowDelegationWithoutValidator(t *testing.T) { testStakingInfo := datagen.GenBTCStakingSlashingInfo( r, t, - net, + h.Net, delSK, []*btcec.PublicKey{validatorPK}, covenantPKs, @@ -505,202 +577,18 @@ func TestDoNotAllowDelegationWithoutValidator(t *testing.T) { // all good, construct and send MsgCreateBTCDelegation message msgCreateBTCDel := &types.MsgCreateBTCDelegation{ - Signer: signer, - BabylonPk: delBabylonPK.(*secp256k1.PubKey), - ValBtcPkList: []bbn.BIP340PubKey{*bbn.NewBIP340PubKeyFromBTCPK(validatorPK)}, - BtcPk: bbn.NewBIP340PubKeyFromBTCPK(delSK.PubKey()), - Pop: pop, - StakingTime: uint32(stakingTimeBlocks), - StakingValue: stakingValue, - StakingTx: txInfo, - SlashingTx: testStakingInfo.SlashingTx, - DelegatorSig: delegatorSig, + Signer: signer, + BabylonPk: delBabylonPK.(*secp256k1.PubKey), + ValBtcPkList: []bbn.BIP340PubKey{*bbn.NewBIP340PubKeyFromBTCPK(validatorPK)}, + BtcPk: bbn.NewBIP340PubKeyFromBTCPK(delSK.PubKey()), + Pop: pop, + StakingTime: uint32(stakingTimeBlocks), + StakingValue: stakingValue, + StakingTx: txInfo, + SlashingTx: testStakingInfo.SlashingTx, + DelegatorSlashingSig: delegatorSig, } _, err = h.MsgServer.CreateBTCDelegation(h.Ctx, msgCreateBTCDel) require.Error(t, err) require.True(t, errors.Is(err, types.ErrBTCValNotFound)) } - -func FuzzCreateBTCDelegationAndUndelegation(f *testing.F) { - datagen.AddRandomSeedsToFuzzer(f, 10) - - f.Fuzz(func(t *testing.T, seed int64) { - r := rand.New(rand.NewSource(seed)) - net := &chaincfg.SimNetParams - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - // mock BTC light client and BTC checkpoint modules - btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) - btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) - - covenantSKs, _ := h.GenAndApplyParams(r) - changeAddress, err := datagen.GenRandomBTCAddress(r, net) - require.NoError(t, err) - _, validatorPK, _ := h.CreateValidator(r) - stakingTxHash, delSK, delPK, msgCreateBTCDel := h.CreateDelegation( - r, - validatorPK, - changeAddress.EncodeAddress(), - 1000, - ) - actualDel := h.GetDelegationAndCheckValues(r, msgCreateBTCDel, validatorPK, delPK, stakingTxHash) - h.CreateCovenantSigs(r, covenantSKs, msgCreateBTCDel, actualDel) - - undelegateMsg := h.CreateUndelegation( - r, - actualDel, - delSK, - validatorPK, - changeAddress.EncodeAddress(), - ) - - actualDelegationWithUnbonding, err := h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) - require.NoError(t, err) - - require.NotNil(t, actualDelegationWithUnbonding.BtcUndelegation) - require.Equal(t, actualDelegationWithUnbonding.BtcUndelegation.UnbondingTx, undelegateMsg.UnbondingTx) - require.Equal(t, actualDelegationWithUnbonding.BtcUndelegation.SlashingTx, undelegateMsg.SlashingTx) - require.Equal(t, actualDelegationWithUnbonding.BtcUndelegation.DelegatorSlashingSig, undelegateMsg.DelegatorSlashingSig) - require.Nil(t, actualDelegationWithUnbonding.BtcUndelegation.CovenantSlashingSigs) - require.Equal(t, actualDelegationWithUnbonding.BtcUndelegation.UnbondingTime, undelegateMsg.UnbondingTime) - require.Nil(t, actualDelegationWithUnbonding.BtcUndelegation.CovenantUnbondingSigList) - }) -} - -func FuzzAddCovenantSigToUnbonding(f *testing.F) { - datagen.AddRandomSeedsToFuzzer(f, 10) - - f.Fuzz(func(t *testing.T, seed int64) { - r := rand.New(rand.NewSource(seed)) - net := &chaincfg.SimNetParams - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - // mock BTC light client and BTC checkpoint modules - btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) - btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) - - covenantSKs, covenantPKs := h.GenAndApplyParams(r) - bsParams := h.BTCStakingKeeper.GetParams(h.Ctx) - - changeAddress, err := datagen.GenRandomBTCAddress(r, net) - require.NoError(t, err) - _, validatorPK, _ := h.CreateValidator(r) - stakingTxHash, delSK, delPK, msgCreateBTCDel := h.CreateDelegation( - r, - validatorPK, - changeAddress.EncodeAddress(), - 1000, - ) - actualDel := h.GetDelegationAndCheckValues(r, msgCreateBTCDel, validatorPK, delPK, stakingTxHash) - h.CreateCovenantSigs(r, covenantSKs, msgCreateBTCDel, actualDel) - - undelegateMsg := h.CreateUndelegation( - r, - actualDel, - delSK, - validatorPK, - changeAddress.EncodeAddress(), - ) - - del, err := h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) - require.NoError(t, err) - require.NotNil(t, del.BtcUndelegation) - - stakingTx, err := bbn.NewBTCTxFromBytes(del.StakingTx) - require.NoError(t, err) - - unbondingTx, err := bbn.NewBTCTxFromBytes(del.BtcUndelegation.UnbondingTx) - require.NoError(t, err) - - // Check sending covenant signatures - // unbonding tx spends staking tx - stakingInfo, err := btcstaking.BuildStakingInfo( - del.BtcPk.MustToBTCPK(), - []*btcec.PublicKey{validatorPK}, - covenantPKs, - bsParams.CovenantQuorum, - uint16(del.GetStakingTime()), - btcutil.Amount(del.TotalSat), - net, - ) - require.NoError(t, err) - - unbondingPathInfo, err := stakingInfo.UnbondingPathSpendInfo() - require.NoError(t, err) - - // slash unbonding tx spends unbonding tx - unbondingInfo, err := btcstaking.BuildUnbondingInfo( - del.BtcPk.MustToBTCPK(), - []*btcec.PublicKey{validatorPK}, - covenantPKs, - bsParams.CovenantQuorum, - uint16(del.BtcUndelegation.GetUnbondingTime()), - btcutil.Amount(unbondingTx.TxOut[0].Value), - net, - ) - require.NoError(t, err) - - unbondingSlashingPathInfo, err := unbondingInfo.SlashingPathSpendInfo() - require.NoError(t, err) - - enckey, err := asig.NewEncryptionKeyFromBTCPK(validatorPK) - require.NoError(t, err) - - // submit covenant signatures for each covenant member - for i := 0; i < int(bsParams.CovenantQuorum); i++ { - covenantUnbondingBTCSig, err := btcstaking.SignTxWithOneScriptSpendInputStrict( - unbondingTx, - stakingTx, - del.StakingOutputIdx, - unbondingPathInfo.GetPkScriptPath(), - covenantSKs[i], - ) - - covenantUnbondingSig := bbn.NewBIP340SignatureFromBTCSig(covenantUnbondingBTCSig) - require.NoError(t, err) - - slashUnbondingTxSig, err := undelegateMsg.SlashingTx.EncSign( - unbondingTx, - 0, - unbondingSlashingPathInfo.GetPkScriptPath(), - covenantSKs[i], - enckey, - ) - require.NoError(t, err) - - covenantSigsMsg := types.MsgAddCovenantUnbondingSigs{ - Signer: datagen.GenRandomAccount().Address, - Pk: bbn.NewBIP340PubKeyFromBTCPK(covenantSKs[i].PubKey()), - StakingTxHash: stakingTxHash, - UnbondingTxSig: &covenantUnbondingSig, - SlashingUnbondingTxSigs: [][]byte{slashUnbondingTxSig.MustMarshal()}, - } - - btclcKeeper.EXPECT().GetTipInfo(gomock.Any()).Return(&btclctypes.BTCHeaderInfo{Height: actualDel.StartHeight + 1}) - _, err = h.MsgServer.AddCovenantUnbondingSigs(h.Ctx, &covenantSigsMsg) - require.NoError(t, err) - } - - delWithUnbondingSigs, err := h.BTCStakingKeeper.GetBTCDelegation(h.Ctx, stakingTxHash) - require.NoError(t, err) - require.NotNil(t, delWithUnbondingSigs.BtcUndelegation) - require.NotNil(t, delWithUnbondingSigs.BtcUndelegation.CovenantSlashingSigs) - require.NotNil(t, delWithUnbondingSigs.BtcUndelegation.CovenantUnbondingSigList) - require.Len(t, delWithUnbondingSigs.BtcUndelegation.CovenantUnbondingSigList, int(bsParams.CovenantQuorum)) - require.Len(t, delWithUnbondingSigs.BtcUndelegation.CovenantSlashingSigs, int(bsParams.CovenantQuorum)) - require.Len(t, delWithUnbondingSigs.BtcUndelegation.CovenantSlashingSigs[0].AdaptorSigs, 1) - - covPKMap := map[string]struct{}{} - for _, covPK := range covenantPKs { - covPKMap[bbn.NewBIP340PubKeyFromBTCPK(covPK).MarshalHex()] = struct{}{} - } - for _, actualCovSigs := range delWithUnbondingSigs.BtcUndelegation.CovenantSlashingSigs { - _, ok := covPKMap[actualCovSigs.CovPk.MarshalHex()] - require.True(t, ok) - } - }) -} diff --git a/x/btcstaking/keeper/voting_power_table_test.go b/x/btcstaking/keeper/voting_power_table_test.go index be0148915..1bc4b219a 100644 --- a/x/btcstaking/keeper/voting_power_table_test.go +++ b/x/btcstaking/keeper/voting_power_table_test.go @@ -80,22 +80,19 @@ func FuzzVotingPowerTable(f *testing.F) { } /* - Case 1: assert none of validators has voting power (since BTC height is 0) + Case 1: BTC height is 0 that is smaller than start height 1. + No BTC validator will have voting power */ babylonHeight := datagen.RandomInt(r, 10) + 1 ctx = ctx.WithBlockHeight(int64(babylonHeight)) btclcKeeper.EXPECT().GetTipInfo(gomock.Any()).Return(&btclctypes.BTCHeaderInfo{Height: 0}).Times(1) keeper.IndexBTCHeight(ctx) keeper.RecordVotingPowerTable(ctx) - for _, btcVal := range btcVals { - power := keeper.GetVotingPower(ctx, *btcVal.BtcPk, babylonHeight) + for i := uint64(0); i < numBTCVals; i++ { + power := keeper.GetVotingPower(ctx, *btcVals[i].BtcPk, babylonHeight) require.Zero(t, power) } - // since there is no BTC validator with BTC delegation, the BTC staking protocol is not activated yet - _, err = keeper.GetBTCStakingActivatedHeight(ctx) - require.Error(t, err) - /* Case 2: move to 1st BTC block, then assert the first numBTCValsWithVotingPower validators have voting power */ diff --git a/x/btcstaking/types/btc_delegation.go b/x/btcstaking/types/btc_delegation.go index ce883796b..3b037fc23 100644 --- a/x/btcstaking/types/btc_delegation.go +++ b/x/btcstaking/types/btc_delegation.go @@ -9,6 +9,7 @@ import ( asig "github.com/babylonchain/babylon/crypto/schnorr-adaptor-signature" bbn "github.com/babylonchain/babylon/types" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -21,8 +22,6 @@ func NewBTCDelegationStatusFromString(statusStr string) (BTCDelegationStatus, er return BTCDelegationStatus_PENDING, nil case "active": return BTCDelegationStatus_ACTIVE, nil - case "unbonding": - return BTCDelegationStatus_UNBONDING, nil case "unbonded": return BTCDelegationStatus_UNBONDED, nil case "any": @@ -50,30 +49,31 @@ func (d *BTCDelegation) GetStakingTime() uint16 { // This is covered by expired for now as it is the default value. // Active: the BTC height is in the range of d's [startHeight, endHeight-w] and the delegation has a covenant sig // Pending: the BTC height is in the range of d's [startHeight, endHeight-w] and the delegation does not have a covenant sig +// TODO: fix comment above // Expired: Delegation timelock func (d *BTCDelegation) GetStatus(btcHeight uint64, w uint64, covenantQuorum uint32) BTCDelegationStatus { - if d.BtcUndelegation != nil { - if d.BtcUndelegation.HasAllSignatures(covenantQuorum) { - return 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 Babylon chain, only time lock on BTC chain - // we may consider adding unbonding time on Babylon chain later to avoid situation where - // we can lose to much voting power in to short time. - return BTCDelegationStatus_UNBONDING - } - - if d.StartHeight <= btcHeight && btcHeight+w <= d.EndHeight { - if d.HasCovenantQuorum(covenantQuorum) { - return BTCDelegationStatus_ACTIVE - } else { - return BTCDelegationStatus_PENDING - } + if d.BtcUndelegation.DelegatorUnbondingSig != nil { + // this means the delegator has signed unbonding signature, and Babylon will consider + // this BTC delegation unbonded directly + return BTCDelegationStatus_UNBONDED + } + + if btcHeight < d.StartHeight || btcHeight+w > d.EndHeight { + // staking tx's timelock has not begun, or is less than w BTC + // blocks left, or is expired + return BTCDelegationStatus_UNBONDED } - return BTCDelegationStatus_UNBONDED + + // at this point, BTC delegation has an active timelock, and Babylon is not + // aware of unbonding tx with delegator's signature + if d.HasCovenantQuorums(covenantQuorum) { + // this BTC delegation receives covenant quorums on + // {slashing/unbonding/unbondingslashing} txs, thus is active + return BTCDelegationStatus_ACTIVE + } + + // no covenant quorum yet, pending + return BTCDelegationStatus_PENDING } // VotingPower returns the voting power of the BTC delegation at a given BTC height @@ -143,10 +143,13 @@ func (d *BTCDelegation) ValidateBasic() error { return nil } -// HasCovenantQuorum returns whether a BTC delegation has sufficient sigs -// from Covenant members to make a quorum -func (d *BTCDelegation) HasCovenantQuorum(quorum uint32) bool { - return uint32(len(d.CovenantSigs)) >= quorum +// HasCovenantQuorum returns whether a BTC delegation has a quorum number of signatures +// from covenant members, including +// - adaptor signatures on slashing tx +// - Schnorr signatures on unbonding tx +// - adaptor signatrues on unbonding slashing tx +func (d *BTCDelegation) HasCovenantQuorums(quorum uint32) bool { + return uint32(len(d.CovenantSigs)) >= quorum && d.BtcUndelegation.HasCovenantQuorums(quorum) } // IsSignedByCovMember checks whether the given covenant PK has signed the delegation @@ -165,7 +168,7 @@ func (d *BTCDelegation) IsSignedByCovMember(covPk *bbn.BIP340PubKey) bool { // each BTC validator's PK this BTC delegation restakes to func (d *BTCDelegation) AddCovenantSigs(covPk *bbn.BIP340PubKey, sigs []asig.AdaptorSignature, quorum uint32) error { // we can ignore the covenant sig if quorum is already reached - if d.HasCovenantQuorum(quorum) { + if d.HasCovenantQuorums(quorum) { return nil } // ensure that this covenant member has not signed the delegation yet @@ -211,6 +214,37 @@ func (d *BTCDelegation) GetStakingInfo(bsParams *Params, btcNet *chaincfg.Params return stakingInfo, nil } +func (d *BTCDelegation) SignUnbondingTx(bsParams *Params, btcNet *chaincfg.Params, sk *btcec.PrivateKey) (*schnorr.Signature, error) { + stakingTx, err := bbn.NewBTCTxFromBytes(d.StakingTx) + if err != nil { + return nil, fmt.Errorf("failed to parse staking transaction: %v", err) + } + unbondingTx, err := bbn.NewBTCTxFromBytes(d.BtcUndelegation.UnbondingTx) + if err != nil { + return nil, fmt.Errorf("failed to parse unbonding transaction: %v", err) + } + stakingInfo, err := d.GetStakingInfo(bsParams, btcNet) + if err != nil { + return nil, err + } + unbondingPath, err := stakingInfo.UnbondingPathSpendInfo() + if err != nil { + return nil, err + } + + sig, err := btcstaking.SignTxWithOneScriptSpendInputStrict( + unbondingTx, + stakingTx, + d.StakingOutputIdx, + unbondingPath.GetPkScriptPath(), + sk, + ) + if err != nil { + return nil, err + } + return sig, nil +} + // GetUnbondingInfo returns the unbonding info of the BTC delegation // the unbonding info can be used for constructing witness of unbonding slashing // tx with access to a BTC validator's SK diff --git a/x/btcstaking/types/btc_delegation_test.go b/x/btcstaking/types/btc_delegation_test.go index 2158aad73..59fed517b 100644 --- a/x/btcstaking/types/btc_delegation_test.go +++ b/x/btcstaking/types/btc_delegation_test.go @@ -25,6 +25,7 @@ func FuzzBTCDelegation(f *testing.F) { btcDel := &types.BTCDelegation{} // randomise voting power btcDel.TotalSat = datagen.RandomInt(r, 100000) + btcDel.BtcUndelegation = &types.BTCUndelegation{} // randomise covenant sig hasCovenantSig := datagen.RandomInt(r, 2) == 0 @@ -43,6 +44,8 @@ func FuzzBTCDelegation(f *testing.F) { AdaptorSigs: [][]byte{covenantSig.MustMarshal()}, } btcDel.CovenantSigs = []*types.CovenantAdaptorSignatures{covSigInfo} + btcDel.BtcUndelegation.CovenantSlashingSigs = btcDel.CovenantSigs // doesn't matter + btcDel.BtcUndelegation.CovenantUnbondingSigList = []*types.SignatureInfo{&types.SignatureInfo{}} // doesn't matter } // randomise start height and end height diff --git a/x/btcstaking/types/btc_slashing_tx.go b/x/btcstaking/types/btc_slashing_tx.go index 77f3728ed..4e51ade3c 100644 --- a/x/btcstaking/types/btc_slashing_tx.go +++ b/x/btcstaking/types/btc_slashing_tx.go @@ -130,8 +130,7 @@ func (tx *BTCSlashingTx) Sign( if err != nil { return nil, err } - sig := bbn.NewBIP340SignatureFromBTCSig(schnorrSig) - return &sig, nil + return bbn.NewBIP340SignatureFromBTCSig(schnorrSig), nil } // VerifySignature verifies a signature on the slashing tx signed by staker, validator or covenant diff --git a/x/btcstaking/types/btc_undelegation.go b/x/btcstaking/types/btc_undelegation.go index 6363a79c4..61063efa4 100644 --- a/x/btcstaking/types/btc_undelegation.go +++ b/x/btcstaking/types/btc_undelegation.go @@ -37,8 +37,9 @@ func (ud *BTCUndelegation) IsSignedByCovMember(covPk *bbn.BIP340PubKey) bool { return ud.IsSignedByCovMemberOnUnbonding(covPk) && ud.IsSignedByCovMemberOnSlashing(covPk) } -func (ud *BTCUndelegation) HasAllSignatures(covenantQuorum uint32) bool { - return ud.HasCovenantQuorumOnUnbonding(covenantQuorum) && ud.HasCovenantQuorumOnSlashing(covenantQuorum) +func (ud *BTCUndelegation) HasCovenantQuorums(covenantQuorum uint32) bool { + return ud.HasCovenantQuorumOnUnbonding(covenantQuorum) && + ud.HasCovenantQuorumOnSlashing(covenantQuorum) } // AddCovenantSigs adds a Schnorr signature on the unbonding tx, and @@ -52,7 +53,7 @@ func (ud *BTCUndelegation) AddCovenantSigs( quorum uint32, ) error { // we can ignore the covenant slashing sig if quorum is already reached - if ud.HasAllSignatures(quorum) { + if ud.HasCovenantQuorums(quorum) { return nil } diff --git a/x/btcstaking/types/btc_undelegation_test.go b/x/btcstaking/types/btc_undelegation_test.go index e84f8a319..49383630f 100644 --- a/x/btcstaking/types/btc_undelegation_test.go +++ b/x/btcstaking/types/btc_undelegation_test.go @@ -81,22 +81,16 @@ func FuzzBTCUndelegation_SlashingTx(f *testing.F) { ) require.NoError(t, err) + // delegator signs the unbonding slashing tx + delSlashingTxSig, err := testInfo.GenDelSlashingTxSig(delSK) + require.NoError(t, err) + unbondingTxBytes, err := bbn.SerializeBTCTx(testInfo.UnbondingTx) require.NoError(t, err) // spend info of the unbonding slashing tx unbondingSlashingSpendInfo, err := testInfo.UnbondingInfo.SlashingPathSpendInfo() require.NoError(t, err) - - // delegator signs the unbonding slashing tx - delSig, err := testInfo.SlashingTx.Sign( - testInfo.UnbondingTx, - 0, - unbondingSlashingSpendInfo.GetPkScriptPath(), - delSK, - ) - require.NoError(t, err) - // covenant signs (using adaptor signature) the slashing tx covenantSigs, err := datagen.GenCovenantAdaptorSigs( covenantSKs, @@ -111,7 +105,8 @@ func FuzzBTCUndelegation_SlashingTx(f *testing.F) { UnbondingTx: unbondingTxBytes, UnbondingTime: 100 + 1, SlashingTx: testInfo.SlashingTx, - DelegatorSlashingSig: delSig, + DelegatorUnbondingSig: nil, // not relevant here + DelegatorSlashingSig: delSlashingTxSig, CovenantSlashingSigs: covenantSigs, CovenantUnbondingSigList: nil, // not relevant here } diff --git a/x/btcstaking/types/btcstaking.pb.go b/x/btcstaking/types/btcstaking.pb.go index 00ee07a55..139a02109 100644 --- a/x/btcstaking/types/btcstaking.pb.go +++ b/x/btcstaking/types/btcstaking.pb.go @@ -28,46 +28,37 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package -// BTCDelegationStatus is the status of a delegation. There are two possible state -// transition paths: -// 1. PENDING -> ACTIVE -> UNBONDED - this is the typical path when timelock of staking -// transaction expires. -// 2. PENDING _> ACTIVE -> UNBONDING -> UNBONDED - this is the path when staker requests undelegation through -// MsgBTCUndelegate message. +// BTCDelegationStatus is the status of a delegation. The state transition path is +// PENDING -> ACTIVE -> UNBONDED with two possibilities: +// 1. the typical path when timelock of staking transaction expires. +// 2. the path when staker requests early undelegation through MsgBTCUndelegate message. type BTCDelegationStatus int32 const ( - // PENDING defines a delegation that is waiting for a covenant signature to become active. + // PENDING defines a delegation that is waiting for covenant signatures to become active. BTCDelegationStatus_PENDING BTCDelegationStatus = 0 // ACTIVE defines a delegation that has voting power BTCDelegationStatus_ACTIVE BTCDelegationStatus = 1 - // UNBONDING defines a delegation that is being unbonded i.e it received an unbonding tx - // from staker, but not yet received signatures from validator and covenant. - // Delegation in this state already lost its voting power. - BTCDelegationStatus_UNBONDING BTCDelegationStatus = 2 // UNBONDED defines a delegation no longer has voting power: // - either reaching the end of staking transaction timelock - // - or receiving unbonding tx and then receiving signatures from validator and covenant for this - // unbonding tx. - BTCDelegationStatus_UNBONDED BTCDelegationStatus = 3 + // - or receiving unbonding tx with signatures from staker and covenant committee + BTCDelegationStatus_UNBONDED BTCDelegationStatus = 2 // ANY is any of the above status - BTCDelegationStatus_ANY BTCDelegationStatus = 4 + BTCDelegationStatus_ANY BTCDelegationStatus = 3 ) var BTCDelegationStatus_name = map[int32]string{ 0: "PENDING", 1: "ACTIVE", - 2: "UNBONDING", - 3: "UNBONDED", - 4: "ANY", + 2: "UNBONDED", + 3: "ANY", } var BTCDelegationStatus_value = map[string]int32{ - "PENDING": 0, - "ACTIVE": 1, - "UNBONDING": 2, - "UNBONDED": 3, - "ANY": 4, + "PENDING": 0, + "ACTIVE": 1, + "UNBONDED": 2, + "ANY": 3, } func (x BTCDelegationStatus) String() string { @@ -403,18 +394,24 @@ type BTCUndelegation struct { // It is partially signed by SK corresponding to btc_pk, but not signed by // validator or covenant yet. SlashingTx *BTCSlashingTx `protobuf:"bytes,3,opt,name=slashing_tx,json=slashingTx,proto3,customtype=BTCSlashingTx" json:"slashing_tx,omitempty"` + // delegator_unbonding_sig is the signature on the unbonding tx + // by the delegator (i.e., SK corresponding to btc_pk). + // It effectively proves that the delegator wants to unbond and thus + // Babylon will consider this BTC delegation unbonded. Delegator's BTC + // on Bitcoin will be unbonded after timelock + DelegatorUnbondingSig *github_com_babylonchain_babylon_types.BIP340Signature `protobuf:"bytes,4,opt,name=delegator_unbonding_sig,json=delegatorUnbondingSig,proto3,customtype=github.com/babylonchain/babylon/types.BIP340Signature" json:"delegator_unbonding_sig,omitempty"` // delegator_slashing_sig is the signature on the slashing tx // by the delegator (i.e., SK corresponding to btc_pk). // It will be a part of the witness for the unbonding tx output. - DelegatorSlashingSig *github_com_babylonchain_babylon_types.BIP340Signature `protobuf:"bytes,4,opt,name=delegator_slashing_sig,json=delegatorSlashingSig,proto3,customtype=github.com/babylonchain/babylon/types.BIP340Signature" json:"delegator_slashing_sig,omitempty"` + DelegatorSlashingSig *github_com_babylonchain_babylon_types.BIP340Signature `protobuf:"bytes,5,opt,name=delegator_slashing_sig,json=delegatorSlashingSig,proto3,customtype=github.com/babylonchain/babylon/types.BIP340Signature" json:"delegator_slashing_sig,omitempty"` // covenant_slashing_sigs is a list of adaptor signatures on the slashing tx // by each covenant member // It will be a part of the witness for the staking tx output. - CovenantSlashingSigs []*CovenantAdaptorSignatures `protobuf:"bytes,5,rep,name=covenant_slashing_sigs,json=covenantSlashingSigs,proto3" json:"covenant_slashing_sigs,omitempty"` + CovenantSlashingSigs []*CovenantAdaptorSignatures `protobuf:"bytes,6,rep,name=covenant_slashing_sigs,json=covenantSlashingSigs,proto3" json:"covenant_slashing_sigs,omitempty"` // covenant_unbonding_sig_list is the list of signatures on the unbonding tx // by covenant members // It must be provided after processing undelagate message by Babylon - CovenantUnbondingSigList []*SignatureInfo `protobuf:"bytes,6,rep,name=covenant_unbonding_sig_list,json=covenantUnbondingSigList,proto3" json:"covenant_unbonding_sig_list,omitempty"` + CovenantUnbondingSigList []*SignatureInfo `protobuf:"bytes,7,rep,name=covenant_unbonding_sig_list,json=covenantUnbondingSigList,proto3" json:"covenant_unbonding_sig_list,omitempty"` } func (m *BTCUndelegation) Reset() { *m = BTCUndelegation{} } @@ -741,77 +738,78 @@ func init() { } var fileDescriptor_3851ae95ccfaf7db = []byte{ - // 1111 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xdd, 0x6e, 0xe3, 0x44, - 0x14, 0xae, 0xe3, 0x34, 0x6d, 0x4e, 0x12, 0x9a, 0x1d, 0x42, 0xf1, 0xb6, 0x22, 0x09, 0x61, 0x59, - 0x45, 0x88, 0x75, 0xb6, 0xdd, 0x1f, 0x01, 0x17, 0x48, 0x4d, 0x53, 0xd8, 0x68, 0xfb, 0x13, 0x9c, - 0x74, 0x11, 0x48, 0x10, 0x4d, 0xec, 0xa9, 0x63, 0x25, 0xf1, 0x58, 0x99, 0x49, 0x48, 0xee, 0xb9, - 0x45, 0xe2, 0x1d, 0xe0, 0x11, 0x78, 0x04, 0x2e, 0xb8, 0x41, 0x5a, 0xc1, 0x0d, 0xea, 0x45, 0x85, - 0xda, 0x17, 0x41, 0x1e, 0x4f, 0x62, 0xb7, 0xb4, 0xfb, 0xd7, 0xde, 0x65, 0xce, 0xcf, 0x77, 0xce, - 0xf9, 0xbe, 0x33, 0x13, 0xc3, 0xdd, 0x0e, 0xee, 0x4c, 0xfb, 0xd4, 0xad, 0x74, 0xb8, 0xc9, 0x38, - 0xee, 0x39, 0xae, 0x5d, 0x19, 0x6f, 0x44, 0x4e, 0xba, 0x37, 0xa4, 0x9c, 0xa2, 0x77, 0x64, 0x9c, - 0x1e, 0xf1, 0x8c, 0x37, 0xd6, 0x72, 0x36, 0xb5, 0xa9, 0x88, 0xa8, 0xf8, 0xbf, 0x82, 0xe0, 0xb5, - 0xdb, 0x26, 0x65, 0x03, 0xca, 0xda, 0x81, 0x23, 0x38, 0x48, 0x57, 0x29, 0x38, 0x55, 0xcc, 0xe1, - 0xd4, 0xe3, 0xb4, 0xc2, 0x88, 0xe9, 0x6d, 0x3e, 0x7a, 0xdc, 0xdb, 0xa8, 0xf4, 0xc8, 0x74, 0x16, - 0x73, 0x47, 0xc6, 0x84, 0xfd, 0x74, 0x08, 0xc7, 0x1b, 0x95, 0x73, 0x1d, 0xad, 0x15, 0x2e, 0xef, - 0xdc, 0xa3, 0x5e, 0x10, 0x50, 0xfa, 0x5b, 0x85, 0x74, 0xb5, 0xb5, 0xfd, 0x0c, 0xf7, 0x1d, 0x0b, - 0x73, 0x3a, 0x44, 0x3b, 0x90, 0xb2, 0x08, 0x33, 0x87, 0x8e, 0xc7, 0x1d, 0xea, 0x6a, 0x4a, 0x51, - 0x29, 0xa7, 0x36, 0x3f, 0xd0, 0x65, 0x7f, 0xe1, 0x54, 0xa2, 0x9a, 0x5e, 0x0b, 0x43, 0x8d, 0x68, - 0x1e, 0xda, 0x03, 0x30, 0xe9, 0x60, 0xe0, 0x30, 0xe6, 0xa3, 0xc4, 0x8a, 0x4a, 0x39, 0x59, 0xbd, - 0x77, 0x7c, 0x52, 0x58, 0x0f, 0x80, 0x98, 0xd5, 0xd3, 0x1d, 0x5a, 0x19, 0x60, 0xde, 0xd5, 0x77, - 0x89, 0x8d, 0xcd, 0x69, 0x8d, 0x98, 0x7f, 0xfd, 0x76, 0x0f, 0x64, 0x9d, 0x1a, 0x31, 0x8d, 0x08, - 0x00, 0xfa, 0x1c, 0x40, 0x4e, 0xd2, 0xf6, 0x7a, 0x9a, 0x2a, 0x9a, 0x2a, 0xcc, 0x9a, 0x0a, 0x68, - 0xd2, 0xe7, 0x34, 0xe9, 0x8d, 0x51, 0xe7, 0x29, 0x99, 0x1a, 0x49, 0x99, 0xd2, 0xe8, 0xa1, 0x3d, - 0x48, 0x74, 0xb8, 0xe9, 0xe7, 0xc6, 0x8b, 0x4a, 0x39, 0x5d, 0x7d, 0x7c, 0x7c, 0x52, 0xd8, 0xb4, - 0x1d, 0xde, 0x1d, 0x75, 0x74, 0x93, 0x0e, 0x2a, 0x32, 0xd2, 0xec, 0x62, 0xc7, 0x9d, 0x1d, 0x2a, - 0x7c, 0xea, 0x11, 0xa6, 0x57, 0xeb, 0x8d, 0x07, 0x0f, 0xef, 0x4b, 0xc8, 0xc5, 0x0e, 0x37, 0x1b, - 0x3d, 0xf4, 0x19, 0xa8, 0x1e, 0xf5, 0xb4, 0x45, 0xd1, 0x47, 0x59, 0xbf, 0x54, 0x76, 0xbd, 0x31, - 0xa4, 0xf4, 0xe8, 0xe0, 0xa8, 0x41, 0x19, 0x23, 0x62, 0x0a, 0xc3, 0x4f, 0x42, 0x0f, 0x61, 0x95, - 0xf5, 0x31, 0xeb, 0x12, 0xab, 0x3d, 0x1b, 0xa9, 0x4b, 0x1c, 0xbb, 0xcb, 0xb5, 0x44, 0x51, 0x29, - 0xc7, 0x8d, 0x9c, 0xf4, 0x56, 0x03, 0xe7, 0x13, 0xe1, 0x43, 0x1f, 0x03, 0x9a, 0x67, 0x71, 0x73, - 0x96, 0xb1, 0x24, 0x32, 0xb2, 0xb3, 0x0c, 0x6e, 0x06, 0xd1, 0xa5, 0x1f, 0x63, 0x90, 0x8b, 0xaa, - 0xfa, 0xb5, 0xc3, 0xbb, 0x7b, 0x84, 0xe3, 0x08, 0x0f, 0xca, 0x4d, 0xf0, 0xb0, 0x0a, 0x09, 0xd9, - 0x49, 0x4c, 0x74, 0x22, 0x4f, 0xe8, 0x7d, 0x48, 0x8f, 0x29, 0x77, 0x5c, 0xbb, 0xed, 0xd1, 0x1f, - 0xc8, 0x50, 0x08, 0x16, 0x37, 0x52, 0x81, 0xad, 0xe1, 0x9b, 0x5e, 0x40, 0x43, 0xfc, 0xb5, 0x69, - 0x58, 0xbc, 0x82, 0x86, 0x5f, 0x12, 0x90, 0xa9, 0xb6, 0xb6, 0x6b, 0xa4, 0x4f, 0x6c, 0xcc, 0xff, - 0xbf, 0x47, 0xca, 0x35, 0xf6, 0x28, 0x76, 0x83, 0x7b, 0xa4, 0xbe, 0xc9, 0x1e, 0x7d, 0x07, 0x2b, - 0x63, 0xdc, 0x6f, 0x07, 0xed, 0xb4, 0xfb, 0x0e, 0xf3, 0x99, 0x53, 0xaf, 0xd1, 0x53, 0x7a, 0x8c, - 0xfb, 0x55, 0xbf, 0xad, 0x5d, 0x87, 0x09, 0x09, 0x19, 0xc7, 0x43, 0x7e, 0x9e, 0xe3, 0x94, 0xb0, - 0x49, 0x31, 0xde, 0x03, 0x20, 0xae, 0x75, 0x7e, 0x7b, 0x93, 0xc4, 0xb5, 0xa4, 0x7b, 0x1d, 0x92, - 0x9c, 0x72, 0xdc, 0x6f, 0x33, 0x3c, 0xdb, 0xd4, 0x65, 0x61, 0x68, 0x62, 0x91, 0x2b, 0x47, 0x6c, - 0xf3, 0x89, 0xb6, 0xec, 0x93, 0x69, 0x24, 0xa5, 0xa5, 0x35, 0x11, 0x3a, 0x4b, 0x37, 0x1d, 0x71, - 0x6f, 0xc4, 0xdb, 0x8e, 0x35, 0xd1, 0x92, 0x45, 0xa5, 0x9c, 0x31, 0xb2, 0xd2, 0x73, 0x20, 0x1c, - 0x75, 0x6b, 0x82, 0x36, 0x21, 0x25, 0xb4, 0x97, 0x68, 0x20, 0xa4, 0xb9, 0x75, 0x7c, 0x52, 0xf0, - 0xd5, 0x6f, 0x4a, 0x4f, 0x6b, 0x62, 0x00, 0x9b, 0xff, 0x46, 0xdf, 0x43, 0xc6, 0x0a, 0xf6, 0x82, - 0x0e, 0xdb, 0xcc, 0xb1, 0xb5, 0x94, 0xc8, 0xfa, 0xf4, 0xf8, 0xa4, 0xf0, 0xe8, 0x75, 0xc8, 0x6b, - 0x3a, 0xb6, 0x8b, 0xf9, 0x68, 0x48, 0x8c, 0xf4, 0x1c, 0xaf, 0xe9, 0xd8, 0xe8, 0x10, 0x32, 0x26, - 0x1d, 0x13, 0x17, 0xbb, 0xdc, 0x87, 0x67, 0x5a, 0xba, 0xa8, 0x96, 0x53, 0x9b, 0xf7, 0xaf, 0x10, - 0x79, 0x5b, 0xc6, 0x6e, 0x59, 0xd8, 0x0b, 0x10, 0x02, 0x54, 0x66, 0xa4, 0x67, 0x30, 0x4d, 0xc7, - 0x66, 0xe8, 0x2b, 0xc8, 0xfa, 0x8a, 0x8f, 0x5c, 0x6b, 0xbe, 0xd4, 0x5a, 0x46, 0xac, 0xcf, 0xdd, - 0x2b, 0x90, 0xab, 0xad, 0xed, 0xc3, 0x48, 0xb4, 0xb1, 0xd2, 0xe1, 0x66, 0xd4, 0x50, 0xfa, 0x53, - 0x85, 0x95, 0x0b, 0x41, 0xbe, 0xfa, 0x23, 0xb7, 0x43, 0x5d, 0x4b, 0x52, 0x2a, 0x5e, 0x0b, 0x23, - 0x35, 0xb7, 0xb5, 0x26, 0xe8, 0x43, 0x78, 0x2b, 0x12, 0xe2, 0x0c, 0x88, 0xb8, 0x12, 0x19, 0x23, - 0x13, 0x06, 0x39, 0x03, 0x72, 0x51, 0x1b, 0xf5, 0x55, 0xb4, 0xa1, 0xb0, 0x1a, 0xd1, 0x66, 0x96, - 0xed, 0x8b, 0x14, 0xbf, 0xae, 0x48, 0xb9, 0x50, 0x24, 0x89, 0xeb, 0x8b, 0x75, 0x04, 0xab, 0xa1, - 0x58, 0x91, 0x7a, 0x4c, 0x5b, 0x7c, 0x43, 0xd5, 0x72, 0x73, 0xd5, 0xc2, 0x32, 0x0c, 0x99, 0xb0, - 0x3e, 0xaf, 0x13, 0x92, 0xc7, 0x1c, 0x3b, 0xb8, 0xbf, 0x09, 0x51, 0xec, 0xce, 0x15, 0xc5, 0xe6, - 0xe8, 0x75, 0xf7, 0x88, 0x1a, 0xda, 0x0c, 0xe8, 0x70, 0x86, 0xd3, 0x74, 0x6c, 0xff, 0xe6, 0x96, - 0x7e, 0x57, 0xe0, 0xed, 0x0b, 0x7a, 0xfa, 0x19, 0x37, 0xa8, 0xe9, 0x4b, 0xc6, 0x50, 0x6f, 0x64, - 0x8c, 0x26, 0xbc, 0x1b, 0xbe, 0xdd, 0x74, 0x18, 0x3e, 0xe2, 0x0c, 0x7d, 0x02, 0x71, 0x8b, 0xf4, - 0x99, 0xa6, 0xbc, 0xb0, 0xd0, 0xb9, 0x97, 0xdf, 0x10, 0x19, 0xa5, 0x7d, 0x58, 0xbf, 0x1c, 0xb4, - 0xee, 0x5a, 0x64, 0x82, 0x2a, 0x90, 0x0b, 0x5f, 0xa5, 0x76, 0x17, 0xb3, 0x6e, 0x30, 0x91, 0x5f, - 0x28, 0x6d, 0xdc, 0x9a, 0xbf, 0x4f, 0x4f, 0x30, 0xeb, 0x8a, 0x26, 0x7f, 0x55, 0x20, 0x73, 0x6e, - 0x20, 0xf4, 0x05, 0xc4, 0xae, 0xfd, 0xef, 0x1a, 0xf3, 0x7a, 0xe8, 0x29, 0xa8, 0xfe, 0xc2, 0xc7, - 0xae, 0xbb, 0xf0, 0x3e, 0x4a, 0xe9, 0x27, 0x05, 0x6e, 0x5f, 0xb9, 0xab, 0xfe, 0x9f, 0x9a, 0x49, - 0xc7, 0x37, 0xf0, 0x51, 0x60, 0xd2, 0x71, 0xa3, 0xe7, 0xef, 0x19, 0x0e, 0x6a, 0x04, 0x57, 0x28, - 0x26, 0xc8, 0x4b, 0xe1, 0x79, 0x5d, 0xf6, 0x51, 0x4b, 0x6c, 0x68, 0xc8, 0x7e, 0x93, 0x63, 0x3e, - 0x62, 0x28, 0x05, 0x4b, 0x8d, 0x9d, 0xfd, 0x5a, 0x7d, 0xff, 0xcb, 0xec, 0x02, 0x02, 0x48, 0x6c, - 0x6d, 0xb7, 0xea, 0xcf, 0x76, 0xb2, 0x0a, 0xca, 0x40, 0xf2, 0x70, 0xbf, 0x7a, 0x10, 0xb8, 0x62, - 0x28, 0x0d, 0xcb, 0xc1, 0x71, 0xa7, 0x96, 0x55, 0xd1, 0x12, 0xa8, 0x5b, 0xfb, 0xdf, 0x64, 0xe3, - 0xd5, 0xdd, 0x3f, 0x4e, 0xf3, 0xca, 0xf3, 0xd3, 0xbc, 0xf2, 0xef, 0x69, 0x5e, 0xf9, 0xf9, 0x2c, - 0xbf, 0xf0, 0xfc, 0x2c, 0xbf, 0xf0, 0xcf, 0x59, 0x7e, 0xe1, 0xdb, 0x97, 0x4e, 0x33, 0x89, 0x7e, - 0x20, 0x8b, 0xd1, 0x3a, 0x09, 0xf1, 0x81, 0xfc, 0xe0, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x84, - 0x7f, 0xe0, 0x9e, 0xfd, 0x0b, 0x00, 0x00, + // 1123 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4d, 0x6f, 0x1a, 0x47, + 0x18, 0xf6, 0x02, 0xc6, 0xe1, 0x05, 0x1a, 0x32, 0x25, 0xce, 0x26, 0x56, 0x81, 0xd2, 0x34, 0x42, + 0x55, 0xb3, 0xc4, 0xce, 0x87, 0xda, 0x1e, 0x2a, 0x05, 0xe3, 0x36, 0x28, 0x09, 0xa1, 0x0b, 0x4e, + 0xd5, 0x4a, 0x2d, 0x1a, 0x76, 0xc7, 0xcb, 0x0a, 0xd8, 0xd9, 0x32, 0x03, 0x85, 0x7b, 0xaf, 0x95, + 0xfa, 0x1f, 0xda, 0x9f, 0xd0, 0x1f, 0xd0, 0x43, 0x0f, 0x3d, 0x46, 0xed, 0xa5, 0xf2, 0xc1, 0xaa, + 0xec, 0x3f, 0x52, 0xed, 0xec, 0xb0, 0xbb, 0xb8, 0x76, 0xd2, 0x04, 0xdf, 0x98, 0xf7, 0xe3, 0x79, + 0x3f, 0x9e, 0x87, 0x99, 0x85, 0x5b, 0x3d, 0xdc, 0x9b, 0x0f, 0xa9, 0x53, 0xed, 0x71, 0x83, 0x71, + 0x3c, 0xb0, 0x1d, 0xab, 0x3a, 0xdd, 0x8e, 0x9c, 0x34, 0x77, 0x4c, 0x39, 0x45, 0x57, 0x65, 0x9c, + 0x16, 0xf1, 0x4c, 0xb7, 0x6f, 0xe4, 0x2d, 0x6a, 0x51, 0x11, 0x51, 0xf5, 0x7e, 0xf9, 0xc1, 0x37, + 0xae, 0x1b, 0x94, 0x8d, 0x28, 0xeb, 0xfa, 0x0e, 0xff, 0x20, 0x5d, 0x65, 0xff, 0x54, 0x35, 0xc6, + 0x73, 0x97, 0xd3, 0x2a, 0x23, 0x86, 0xbb, 0x73, 0xff, 0xc1, 0x60, 0xbb, 0x3a, 0x20, 0xf3, 0x45, + 0xcc, 0x4d, 0x19, 0x13, 0xf6, 0xd3, 0x23, 0x1c, 0x6f, 0x57, 0x97, 0x3a, 0xba, 0x51, 0x3c, 0xbb, + 0x73, 0x97, 0xba, 0x7e, 0x40, 0xf9, 0xaf, 0x38, 0x64, 0x6a, 0x9d, 0xdd, 0xe7, 0x78, 0x68, 0x9b, + 0x98, 0xd3, 0x31, 0xda, 0x83, 0xb4, 0x49, 0x98, 0x31, 0xb6, 0x5d, 0x6e, 0x53, 0x47, 0x55, 0x4a, + 0x4a, 0x25, 0xbd, 0xf3, 0x9e, 0x26, 0xfb, 0x0b, 0xa7, 0x12, 0xd5, 0xb4, 0x7a, 0x18, 0xaa, 0x47, + 0xf3, 0xd0, 0x53, 0x00, 0x83, 0x8e, 0x46, 0x36, 0x63, 0x1e, 0x4a, 0xac, 0xa4, 0x54, 0x52, 0xb5, + 0xdb, 0x87, 0x47, 0xc5, 0x2d, 0x1f, 0x88, 0x99, 0x03, 0xcd, 0xa6, 0xd5, 0x11, 0xe6, 0x7d, 0xed, + 0x09, 0xb1, 0xb0, 0x31, 0xaf, 0x13, 0xe3, 0xcf, 0x5f, 0x6f, 0x83, 0xac, 0x53, 0x27, 0x86, 0x1e, + 0x01, 0x40, 0x9f, 0x02, 0xc8, 0x49, 0xba, 0xee, 0x40, 0x8d, 0x8b, 0xa6, 0x8a, 0x8b, 0xa6, 0xfc, + 0x35, 0x69, 0xc1, 0x9a, 0xb4, 0xd6, 0xa4, 0xf7, 0x98, 0xcc, 0xf5, 0x94, 0x4c, 0x69, 0x0d, 0xd0, + 0x53, 0x48, 0xf6, 0xb8, 0xe1, 0xe5, 0x26, 0x4a, 0x4a, 0x25, 0x53, 0x7b, 0x70, 0x78, 0x54, 0xdc, + 0xb1, 0x6c, 0xde, 0x9f, 0xf4, 0x34, 0x83, 0x8e, 0xaa, 0x32, 0xd2, 0xe8, 0x63, 0xdb, 0x59, 0x1c, + 0xaa, 0x7c, 0xee, 0x12, 0xa6, 0xd5, 0x1a, 0xad, 0xbb, 0xf7, 0xee, 0x48, 0xc8, 0xf5, 0x1e, 0x37, + 0x5a, 0x03, 0xf4, 0x09, 0xc4, 0x5d, 0xea, 0xaa, 0xeb, 0xa2, 0x8f, 0x8a, 0x76, 0x26, 0xed, 0x5a, + 0x6b, 0x4c, 0xe9, 0xc1, 0xb3, 0x83, 0x16, 0x65, 0x8c, 0x88, 0x29, 0x74, 0x2f, 0x09, 0xdd, 0x83, + 0x4d, 0x36, 0xc4, 0xac, 0x4f, 0xcc, 0xee, 0x62, 0xa4, 0x3e, 0xb1, 0xad, 0x3e, 0x57, 0x93, 0x25, + 0xa5, 0x92, 0xd0, 0xf3, 0xd2, 0x5b, 0xf3, 0x9d, 0x8f, 0x84, 0x0f, 0x7d, 0x08, 0x28, 0xc8, 0xe2, + 0xc6, 0x22, 0x63, 0x43, 0x64, 0xe4, 0x16, 0x19, 0xdc, 0xf0, 0xa3, 0xcb, 0x3f, 0xc4, 0x20, 0x1f, + 0x65, 0xf5, 0x4b, 0x9b, 0xf7, 0x9f, 0x12, 0x8e, 0x23, 0x7b, 0x50, 0x2e, 0x62, 0x0f, 0x9b, 0x90, + 0x94, 0x9d, 0xc4, 0x44, 0x27, 0xf2, 0x84, 0xde, 0x85, 0xcc, 0x94, 0x72, 0xdb, 0xb1, 0xba, 0x2e, + 0xfd, 0x9e, 0x8c, 0x05, 0x61, 0x09, 0x3d, 0xed, 0xdb, 0x5a, 0x9e, 0xe9, 0x25, 0x6b, 0x48, 0xbc, + 0xf6, 0x1a, 0xd6, 0xcf, 0x59, 0xc3, 0xcf, 0x49, 0xc8, 0xd6, 0x3a, 0xbb, 0x75, 0x32, 0x24, 0x16, + 0xe6, 0xff, 0xd5, 0x91, 0xb2, 0x82, 0x8e, 0x62, 0x17, 0xa8, 0xa3, 0xf8, 0x9b, 0xe8, 0xe8, 0x1b, + 0xb8, 0x3c, 0xc5, 0xc3, 0xae, 0xdf, 0x4e, 0x77, 0x68, 0x33, 0x6f, 0x73, 0xf1, 0x15, 0x7a, 0xca, + 0x4c, 0xf1, 0xb0, 0xe6, 0xb5, 0xf5, 0xc4, 0x66, 0x82, 0x42, 0xc6, 0xf1, 0x98, 0x2f, 0xef, 0x38, + 0x2d, 0x6c, 0x92, 0x8c, 0x77, 0x00, 0x88, 0x63, 0x2e, 0xab, 0x37, 0x45, 0x1c, 0x53, 0xba, 0xb7, + 0x20, 0xc5, 0x29, 0xc7, 0xc3, 0x2e, 0xc3, 0x0b, 0xa5, 0x5e, 0x12, 0x86, 0x36, 0x16, 0xb9, 0x72, + 0xc4, 0x2e, 0x9f, 0xa9, 0x97, 0xbc, 0x65, 0xea, 0x29, 0x69, 0xe9, 0xcc, 0x04, 0xcf, 0xd2, 0x4d, + 0x27, 0xdc, 0x9d, 0xf0, 0xae, 0x6d, 0xce, 0xd4, 0x54, 0x49, 0xa9, 0x64, 0xf5, 0x9c, 0xf4, 0x3c, + 0x13, 0x8e, 0x86, 0x39, 0x43, 0x3b, 0x90, 0x16, 0xdc, 0x4b, 0x34, 0x10, 0xd4, 0x5c, 0x39, 0x3c, + 0x2a, 0x7a, 0xec, 0xb7, 0xa5, 0xa7, 0x33, 0xd3, 0x81, 0x05, 0xbf, 0xd1, 0xb7, 0x90, 0x35, 0x7d, + 0x5d, 0xd0, 0x71, 0x97, 0xd9, 0x96, 0x9a, 0x16, 0x59, 0x1f, 0x1f, 0x1e, 0x15, 0xef, 0xbf, 0xce, + 0xf2, 0xda, 0xb6, 0xe5, 0x60, 0x3e, 0x19, 0x13, 0x3d, 0x13, 0xe0, 0xb5, 0x6d, 0x0b, 0xed, 0x43, + 0xd6, 0xa0, 0x53, 0xe2, 0x60, 0x87, 0x7b, 0xf0, 0x4c, 0xcd, 0x94, 0xe2, 0x95, 0xf4, 0xce, 0x9d, + 0x73, 0x48, 0xde, 0x95, 0xb1, 0x0f, 0x4d, 0xec, 0xfa, 0x08, 0x3e, 0x2a, 0xd3, 0x33, 0x0b, 0x98, + 0xb6, 0x6d, 0x31, 0xf4, 0x05, 0xe4, 0x3c, 0xc6, 0x27, 0x8e, 0x19, 0x88, 0x5a, 0xcd, 0x0a, 0xf9, + 0xdc, 0x3a, 0x07, 0xb9, 0xd6, 0xd9, 0xdd, 0x8f, 0x44, 0xeb, 0x97, 0x7b, 0xdc, 0x88, 0x1a, 0xca, + 0xbf, 0x25, 0xe0, 0xf2, 0xa9, 0x20, 0x8f, 0xfd, 0x89, 0xd3, 0xa3, 0x8e, 0x29, 0x57, 0x2a, 0x6e, + 0x0b, 0x3d, 0x1d, 0xd8, 0x3a, 0x33, 0xf4, 0x3e, 0xbc, 0x15, 0x09, 0xb1, 0x47, 0x44, 0xfc, 0x25, + 0xb2, 0x7a, 0x36, 0x0c, 0xb2, 0x47, 0xe4, 0x34, 0x37, 0xf1, 0xff, 0xc3, 0xcd, 0x77, 0x70, 0x2d, + 0xe4, 0x26, 0x2c, 0xe2, 0xb1, 0x94, 0x58, 0x95, 0xa5, 0xab, 0x01, 0xf2, 0xfe, 0x02, 0xd8, 0xa3, + 0x8b, 0xc2, 0x66, 0x44, 0x0e, 0x8b, 0x86, 0xbd, 0x8a, 0xeb, 0xab, 0x56, 0xcc, 0x87, 0xba, 0x90, + 0xb8, 0x5e, 0xc1, 0x03, 0xd8, 0x0c, 0xf5, 0x11, 0xa9, 0xc7, 0xd4, 0xe4, 0x1b, 0x0a, 0x25, 0x1f, + 0x08, 0x25, 0x2c, 0xc3, 0x90, 0x01, 0x5b, 0x41, 0x9d, 0xa5, 0x55, 0xfa, 0x57, 0xc6, 0x86, 0x28, + 0x76, 0xf3, 0x9c, 0x62, 0x01, 0x7a, 0xc3, 0x39, 0xa0, 0xba, 0xba, 0x00, 0x8a, 0x6e, 0xce, 0xbb, + 0x2c, 0xca, 0xbf, 0x2b, 0xf0, 0xf6, 0x29, 0x09, 0x79, 0x19, 0x17, 0x28, 0xa3, 0x57, 0x8c, 0x11, + 0xbf, 0x90, 0x31, 0xda, 0x70, 0x2d, 0x7c, 0x2e, 0xe8, 0x38, 0x7c, 0x37, 0x18, 0xfa, 0x08, 0x12, + 0x26, 0x19, 0x32, 0x55, 0x79, 0x69, 0xa1, 0xa5, 0xc7, 0x46, 0x17, 0x19, 0xe5, 0x26, 0x6c, 0x9d, + 0x0d, 0xda, 0x70, 0x4c, 0x32, 0x43, 0x55, 0xc8, 0x87, 0x17, 0x61, 0xb7, 0x8f, 0x59, 0xdf, 0x9f, + 0xc8, 0x2b, 0x94, 0xd1, 0xaf, 0x04, 0x57, 0xe2, 0x23, 0xcc, 0xfa, 0xa2, 0xc9, 0x5f, 0x14, 0xc8, + 0x2e, 0x0d, 0x84, 0x3e, 0x83, 0xd8, 0xca, 0x0f, 0x7a, 0xcc, 0x1d, 0xa0, 0xc7, 0x10, 0xf7, 0x04, + 0x1f, 0x5b, 0x55, 0xf0, 0x1e, 0x4a, 0xf9, 0x47, 0x05, 0xae, 0x9f, 0xab, 0x55, 0xef, 0x1d, 0x35, + 0xe8, 0xf4, 0x02, 0xbe, 0x43, 0x0c, 0x3a, 0x6d, 0x0d, 0x3c, 0x9d, 0x61, 0xbf, 0x86, 0xff, 0x17, + 0x8a, 0x89, 0xe5, 0xa5, 0x71, 0x50, 0x97, 0x7d, 0xb0, 0x27, 0x14, 0x1a, 0x6e, 0xbf, 0xcd, 0x31, + 0x9f, 0x30, 0x94, 0x86, 0x8d, 0xd6, 0x5e, 0xb3, 0xde, 0x68, 0x7e, 0x9e, 0x5b, 0x43, 0x00, 0xc9, + 0x87, 0xbb, 0x9d, 0xc6, 0xf3, 0xbd, 0x9c, 0x82, 0x32, 0x70, 0x69, 0xbf, 0x59, 0x7b, 0xd6, 0xac, + 0xef, 0xd5, 0x73, 0x31, 0xb4, 0x01, 0xf1, 0x87, 0xcd, 0xaf, 0x72, 0xf1, 0xda, 0x93, 0x3f, 0x8e, + 0x0b, 0xca, 0x8b, 0xe3, 0x82, 0xf2, 0xcf, 0x71, 0x41, 0xf9, 0xe9, 0xa4, 0xb0, 0xf6, 0xe2, 0xa4, + 0xb0, 0xf6, 0xf7, 0x49, 0x61, 0xed, 0xeb, 0x57, 0xb6, 0x3f, 0x8b, 0x7e, 0x84, 0x8b, 0x59, 0x7a, + 0x49, 0xf1, 0x11, 0x7e, 0xf7, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x8e, 0xcb, 0xae, 0x61, + 0x0c, 0x00, 0x00, } func (m *BTCValidator) Marshal() (dAtA []byte, err error) { @@ -1143,7 +1141,7 @@ func (m *BTCUndelegation) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintBtcstaking(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x32 + dAtA[i] = 0x3a } } if len(m.CovenantSlashingSigs) > 0 { @@ -1157,7 +1155,7 @@ func (m *BTCUndelegation) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintBtcstaking(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x2a + dAtA[i] = 0x32 } } if m.DelegatorSlashingSig != nil { @@ -1170,6 +1168,18 @@ func (m *BTCUndelegation) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintBtcstaking(dAtA, i, uint64(size)) } i-- + dAtA[i] = 0x2a + } + if m.DelegatorUnbondingSig != nil { + { + size := m.DelegatorUnbondingSig.Size() + i -= size + if _, err := m.DelegatorUnbondingSig.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintBtcstaking(dAtA, i, uint64(size)) + } + i-- dAtA[i] = 0x22 } if m.SlashingTx != nil { @@ -1557,6 +1567,10 @@ func (m *BTCUndelegation) Size() (n int) { l = m.SlashingTx.Size() n += 1 + l + sovBtcstaking(uint64(l)) } + if m.DelegatorUnbondingSig != nil { + l = m.DelegatorUnbondingSig.Size() + n += 1 + l + sovBtcstaking(uint64(l)) + } if m.DelegatorSlashingSig != nil { l = m.DelegatorSlashingSig.Size() n += 1 + l + sovBtcstaking(uint64(l)) @@ -2658,6 +2672,41 @@ func (m *BTCUndelegation) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DelegatorUnbondingSig", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBtcstaking + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthBtcstaking + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthBtcstaking + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var v github_com_babylonchain_babylon_types.BIP340Signature + m.DelegatorUnbondingSig = &v + if err := m.DelegatorUnbondingSig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field DelegatorSlashingSig", wireType) } @@ -2692,7 +2741,7 @@ func (m *BTCUndelegation) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 5: + case 6: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field CovenantSlashingSigs", wireType) } @@ -2726,7 +2775,7 @@ func (m *BTCUndelegation) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 6: + case 7: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field CovenantUnbondingSigList", wireType) } diff --git a/x/btcstaking/types/codec.go b/x/btcstaking/types/codec.go index afc7b1955..b272c8b50 100644 --- a/x/btcstaking/types/codec.go +++ b/x/btcstaking/types/codec.go @@ -10,10 +10,8 @@ import ( func RegisterCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgCreateBTCValidator{}, "btcstaking/MsgCreateBTCValidator", nil) cdc.RegisterConcrete(&MsgCreateBTCDelegation{}, "btcstaking/MsgCreateBTCDelegation", nil) - cdc.RegisterConcrete(&MsgAddCovenantSig{}, "btcstaking/MsgAddCovenantSig", nil) + cdc.RegisterConcrete(&MsgAddCovenantSigs{}, "btcstaking/MsgAddCovenantSigs", nil) cdc.RegisterConcrete(&MsgUpdateParams{}, "btcstaking/MsgUpdateParams", nil) - cdc.RegisterConcrete(&MsgBTCUndelegate{}, "btcstaking/MsgBtcUndelegate", nil) - cdc.RegisterConcrete(&MsgAddCovenantUnbondingSigs{}, "btcstaking/MsgAddCovenantUnbondingSigs", nil) } func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { @@ -22,10 +20,8 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { (*sdk.Msg)(nil), &MsgCreateBTCValidator{}, &MsgCreateBTCDelegation{}, - &MsgAddCovenantSig{}, + &MsgAddCovenantSigs{}, &MsgUpdateParams{}, - &MsgBTCUndelegate{}, - &MsgAddCovenantUnbondingSigs{}, ) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) diff --git a/x/btcstaking/types/errors.go b/x/btcstaking/types/errors.go index 418ac8d30..d3409914e 100644 --- a/x/btcstaking/types/errors.go +++ b/x/btcstaking/types/errors.go @@ -27,4 +27,5 @@ var ( ErrEmptyValidatorList = errorsmod.Register(ModuleName, 1118, "the validator list is empty") ErrInvalidProofOfPossession = errorsmod.Register(ModuleName, 1119, "the proof of possession is not valid") ErrDuplicatedValidator = errorsmod.Register(ModuleName, 1120, "the staking request contains duplicated validator public key") + ErrInvalidBTCUndelegateReq = errorsmod.Register(ModuleName, 1121, "invalid undelegation request") ) diff --git a/x/btcstaking/types/msg.go b/x/btcstaking/types/msg.go index ece606e84..b4adb0e76 100644 --- a/x/btcstaking/types/msg.go +++ b/x/btcstaking/types/msg.go @@ -2,6 +2,7 @@ package types import ( "fmt" + math "math" errorsmod "cosmossdk.io/errors" @@ -17,9 +18,8 @@ var ( _ sdk.Msg = &MsgUpdateParams{} _ sdk.Msg = &MsgCreateBTCValidator{} _ sdk.Msg = &MsgCreateBTCDelegation{} - _ sdk.Msg = &MsgAddCovenantSig{} + _ sdk.Msg = &MsgAddCovenantSigs{} _ sdk.Msg = &MsgBTCUndelegate{} - _ sdk.Msg = &MsgAddCovenantUnbondingSigs{} ) // GetSigners returns the expected signers for a MsgUpdateParams message. @@ -102,13 +102,26 @@ func (m *MsgCreateBTCDelegation) ValidateBasic() error { if m.SlashingTx == nil { return fmt.Errorf("empty slashing tx") } - if m.DelegatorSig == nil { + if m.DelegatorSlashingSig == nil { return fmt.Errorf("empty delegator signature") } if _, err := sdk.AccAddressFromBech32(m.Signer); err != nil { return err } + // Check staking time is at most uint16 + if m.StakingTime > math.MaxUint16 { + return ErrInvalidStakingTx.Wrapf("invalid lock time: %d, max: %d", m.StakingTime, math.MaxUint16) + } + // Ensure list of validator BTC PKs is not empty + if len(m.ValBtcPkList) == 0 { + return ErrEmptyValidatorList + } + // Ensure list of validator BTC PKs is not duplicated + if ExistsDup(m.ValBtcPkList) { + return ErrDuplicatedValidator + } + // staking tx should be correctly formatted if err := m.StakingTx.ValidateBasic(); err != nil { return err @@ -117,67 +130,33 @@ func (m *MsgCreateBTCDelegation) ValidateBasic() error { return err } - return nil -} - -func (m *MsgAddCovenantSig) GetSigners() []sdk.AccAddress { - signer, err := sdk.AccAddressFromBech32(m.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{signer} -} - -func (m *MsgAddCovenantSig) ValidateBasic() error { - if m.Pk == nil { - return fmt.Errorf("empty BTC covenant public key") - } - if m.Sigs == nil { - return fmt.Errorf("empty covenant signature") - } - if len(m.StakingTxHash) != chainhash.MaxHashStringSize { - return fmt.Errorf("staking tx hash is not %d", chainhash.MaxHashStringSize) - } - - return nil -} - -func (m *MsgBTCUndelegate) ValidateBasic() error { + // verifications about on-demand unbonding if m.UnbondingTx == nil { return fmt.Errorf("empty unbonding tx") } - if m.SlashingTx == nil { + if m.UnbondingSlashingTx == nil { return fmt.Errorf("empty slashing tx") } - if m.DelegatorSlashingSig == nil { + if m.DelegatorUnbondingSlashingSig == nil { return fmt.Errorf("empty delegator signature") } - - if _, err := sdk.AccAddressFromBech32(m.Signer); err != nil { - return err - } unbondingTxMsg, err := bbn.NewBTCTxFromBytes(m.UnbondingTx) - if err != nil { return err } - if err := btcstaking.IsSimpleTransfer(unbondingTxMsg); err != nil { return err } - return nil -} - -func (m *MsgBTCUndelegate) GetSigners() []sdk.AccAddress { - signer, err := sdk.AccAddressFromBech32(m.Signer) - if err != nil { - panic(err) + // Check unbonding time is lower than max uint16 + if uint64(m.UnbondingTime) > math.MaxUint16 { + return ErrInvalidUnbondingTx.Wrapf("unbonding time %d must be lower than %d", m.UnbondingTime, math.MaxUint16) } - return []sdk.AccAddress{signer} + + return nil } -func (m *MsgAddCovenantUnbondingSigs) GetSigners() []sdk.AccAddress { +func (m *MsgAddCovenantSigs) GetSigners() []sdk.AccAddress { signer, err := sdk.AccAddressFromBech32(m.Signer) if err != nil { panic(err) @@ -185,18 +164,44 @@ func (m *MsgAddCovenantUnbondingSigs) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{signer} } -func (m *MsgAddCovenantUnbondingSigs) ValidateBasic() error { +func (m *MsgAddCovenantSigs) ValidateBasic() error { if m.Pk == nil { return fmt.Errorf("empty BTC covenant public key") } + if m.SlashingTxSigs == nil { + return fmt.Errorf("empty covenant signatures on slashing tx") + } + if len(m.StakingTxHash) != chainhash.MaxHashStringSize { + return fmt.Errorf("staking tx hash is not %d", chainhash.MaxHashStringSize) + } + + // verifications about on-demand unbonding if m.UnbondingTxSig == nil { return fmt.Errorf("empty covenant signature") } if m.SlashingUnbondingTxSigs == nil { return fmt.Errorf("empty covenant signature") } + + return nil +} + +func (m *MsgBTCUndelegate) GetSigners() []sdk.AccAddress { + signer, err := sdk.AccAddressFromBech32(m.Signer) + if err != nil { + panic(err) + } + return []sdk.AccAddress{signer} +} + +func (m *MsgBTCUndelegate) ValidateBasic() error { if len(m.StakingTxHash) != chainhash.MaxHashStringSize { return fmt.Errorf("staking tx hash is not %d", chainhash.MaxHashStringSize) } + + if m.UnbondingTxSig == nil { + return fmt.Errorf("empty signature from the delegator") + } + return nil } diff --git a/x/btcstaking/types/tx.pb.go b/x/btcstaking/types/tx.pb.go index c0afcdf69..45459b2e9 100644 --- a/x/btcstaking/types/tx.pb.go +++ b/x/btcstaking/types/tx.pb.go @@ -170,11 +170,25 @@ type MsgCreateBTCDelegation struct { // slashing_tx is the slashing tx // Note that the tx itself does not contain signatures, which are off-chain. SlashingTx *BTCSlashingTx `protobuf:"bytes,9,opt,name=slashing_tx,json=slashingTx,proto3,customtype=BTCSlashingTx" json:"slashing_tx,omitempty"` - // delegator_sig is the signature on the slashing tx by the delegator (i.e., SK corresponding to btc_pk). + // delegator_slashing_sig is the signature on the slashing tx by the delegator (i.e., SK corresponding to btc_pk). // It will be a part of the witness for the staking tx output. // The staking tx output further needs signatures from covenant and validator in // order to be spendable. - DelegatorSig *github_com_babylonchain_babylon_types.BIP340Signature `protobuf:"bytes,10,opt,name=delegator_sig,json=delegatorSig,proto3,customtype=github.com/babylonchain/babylon/types.BIP340Signature" json:"delegator_sig,omitempty"` + DelegatorSlashingSig *github_com_babylonchain_babylon_types.BIP340Signature `protobuf:"bytes,10,opt,name=delegator_slashing_sig,json=delegatorSlashingSig,proto3,customtype=github.com/babylonchain/babylon/types.BIP340Signature" json:"delegator_slashing_sig,omitempty"` + /// fields related to on-demand unbonding + // unbonding_tx is bitcoin unbonding transaction i.e transaction that spends + // staking output and sends it to the unbonding output + UnbondingTx []byte `protobuf:"bytes,11,opt,name=unbonding_tx,json=unbondingTx,proto3" json:"unbonding_tx,omitempty"` + // unbonding_time is the time lock used in unbonding transaction + UnbondingTime uint32 `protobuf:"varint,12,opt,name=unbonding_time,json=unbondingTime,proto3" json:"unbonding_time,omitempty"` + // unbonding_value is amount of satoshis locked in unbonding output. + // NOTE: staking_value and unbonding_value could be different because of the difference between the fee for staking tx and that for unbonding + UnbondingValue int64 `protobuf:"varint,13,opt,name=unbonding_value,json=unbondingValue,proto3" json:"unbonding_value,omitempty"` + // unbonding_slashing_tx is the slashing tx which slash unbonding contract + // Note that the tx itself does not contain signatures, which are off-chain. + UnbondingSlashingTx *BTCSlashingTx `protobuf:"bytes,14,opt,name=unbonding_slashing_tx,json=unbondingSlashingTx,proto3,customtype=BTCSlashingTx" json:"unbonding_slashing_tx,omitempty"` + // delegator_unbonding_slashing_sig is the signature on the slashing tx by the delegator (i.e., SK corresponding to btc_pk). + DelegatorUnbondingSlashingSig *github_com_babylonchain_babylon_types.BIP340Signature `protobuf:"bytes,15,opt,name=delegator_unbonding_slashing_sig,json=delegatorUnbondingSlashingSig,proto3,customtype=github.com/babylonchain/babylon/types.BIP340Signature" json:"delegator_unbonding_slashing_sig,omitempty"` } func (m *MsgCreateBTCDelegation) Reset() { *m = MsgCreateBTCDelegation{} } @@ -252,6 +266,27 @@ func (m *MsgCreateBTCDelegation) GetStakingTx() *types1.TransactionInfo { return nil } +func (m *MsgCreateBTCDelegation) GetUnbondingTx() []byte { + if m != nil { + return m.UnbondingTx + } + return nil +} + +func (m *MsgCreateBTCDelegation) GetUnbondingTime() uint32 { + if m != nil { + return m.UnbondingTime + } + return 0 +} + +func (m *MsgCreateBTCDelegation) GetUnbondingValue() int64 { + if m != nil { + return m.UnbondingValue + } + return 0 +} + // MsgCreateBTCDelegationResponse is the response for MsgCreateBTCDelegation type MsgCreateBTCDelegationResponse struct { } @@ -289,36 +324,40 @@ func (m *MsgCreateBTCDelegationResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgCreateBTCDelegationResponse proto.InternalMessageInfo -// MsgBTCUndelegate is the message undelegating existing and active delegation -type MsgBTCUndelegate struct { +// MsgAddCovenantSigs is the message for handling signatures from a covenant member +type MsgAddCovenantSigs struct { Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` - // unbonding_tx is bitcoin unbonding transaction i.e transaction that spends - // staking output and sends it to the unbonding output - UnbondingTx []byte `protobuf:"bytes,2,opt,name=unbonding_tx,json=unbondingTx,proto3" json:"unbonding_tx,omitempty"` - // unbonding_time is the time lock used in unbonding transaction - UnbondingTime uint32 `protobuf:"varint,3,opt,name=unbonding_time,json=unbondingTime,proto3" json:"unbonding_time,omitempty"` - // unbonding_value is amount of satoshis locked in unbonding output. - // NOTE: staking_value and unbonding_value could be different because of the difference between the fee for staking tx and that for unbonding - UnbondingValue int64 `protobuf:"varint,4,opt,name=unbonding_value,json=unbondingValue,proto3" json:"unbonding_value,omitempty"` - // slashing_tx is the slashing tx which slash unbonding contract - // Note that the tx itself does not contain signatures, which are off-chain. - SlashingTx *BTCSlashingTx `protobuf:"bytes,5,opt,name=slashing_tx,json=slashingTx,proto3,customtype=BTCSlashingTx" json:"slashing_tx,omitempty"` - // delegator_slashing_sig is the signature on the slashing tx by the delegator (i.e., SK corresponding to btc_pk). - DelegatorSlashingSig *github_com_babylonchain_babylon_types.BIP340Signature `protobuf:"bytes,6,opt,name=delegator_slashing_sig,json=delegatorSlashingSig,proto3,customtype=github.com/babylonchain/babylon/types.BIP340Signature" json:"delegator_slashing_sig,omitempty"` + // pk is the BTC public key of the covenant member + Pk *github_com_babylonchain_babylon_types.BIP340PubKey `protobuf:"bytes,2,opt,name=pk,proto3,customtype=github.com/babylonchain/babylon/types.BIP340PubKey" json:"pk,omitempty"` + // staking_tx_hash is the hash of the staking tx. + // It uniquely identifies a BTC delegation + StakingTxHash string `protobuf:"bytes,3,opt,name=staking_tx_hash,json=stakingTxHash,proto3" json:"staking_tx_hash,omitempty"` + // sigs is a list of adaptor signatures of the covenant + // the order of sigs should respect the order of validators + // of the corresponding delegation + SlashingTxSigs [][]byte `protobuf:"bytes,4,rep,name=slashing_tx_sigs,json=slashingTxSigs,proto3" json:"slashing_tx_sigs,omitempty"` + // unbonding_tx_sig is the signature of the covenant on the unbonding tx submitted to babylon + // the signature follows encoding in BIP-340 spec + UnbondingTxSig *github_com_babylonchain_babylon_types.BIP340Signature `protobuf:"bytes,5,opt,name=unbonding_tx_sig,json=unbondingTxSig,proto3,customtype=github.com/babylonchain/babylon/types.BIP340Signature" json:"unbonding_tx_sig,omitempty"` + // slashing_unbonding_tx_sigs is a list of adaptor signatures of the covenant + // on slashing tx corresponding to unbonding tx submitted to babylon + // the order of sigs should respect the order of validators + // of the corresponding delegation + SlashingUnbondingTxSigs [][]byte `protobuf:"bytes,6,rep,name=slashing_unbonding_tx_sigs,json=slashingUnbondingTxSigs,proto3" json:"slashing_unbonding_tx_sigs,omitempty"` } -func (m *MsgBTCUndelegate) Reset() { *m = MsgBTCUndelegate{} } -func (m *MsgBTCUndelegate) String() string { return proto.CompactTextString(m) } -func (*MsgBTCUndelegate) ProtoMessage() {} -func (*MsgBTCUndelegate) Descriptor() ([]byte, []int) { +func (m *MsgAddCovenantSigs) Reset() { *m = MsgAddCovenantSigs{} } +func (m *MsgAddCovenantSigs) String() string { return proto.CompactTextString(m) } +func (*MsgAddCovenantSigs) ProtoMessage() {} +func (*MsgAddCovenantSigs) Descriptor() ([]byte, []int) { return fileDescriptor_4baddb53e97f38f2, []int{4} } -func (m *MsgBTCUndelegate) XXX_Unmarshal(b []byte) error { +func (m *MsgAddCovenantSigs) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *MsgBTCUndelegate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *MsgAddCovenantSigs) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_MsgBTCUndelegate.Marshal(b, m, deterministic) + return xxx_messageInfo_MsgAddCovenantSigs.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -328,62 +367,62 @@ func (m *MsgBTCUndelegate) XXX_Marshal(b []byte, deterministic bool) ([]byte, er return b[:n], nil } } -func (m *MsgBTCUndelegate) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgBTCUndelegate.Merge(m, src) +func (m *MsgAddCovenantSigs) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgAddCovenantSigs.Merge(m, src) } -func (m *MsgBTCUndelegate) XXX_Size() int { +func (m *MsgAddCovenantSigs) XXX_Size() int { return m.Size() } -func (m *MsgBTCUndelegate) XXX_DiscardUnknown() { - xxx_messageInfo_MsgBTCUndelegate.DiscardUnknown(m) +func (m *MsgAddCovenantSigs) XXX_DiscardUnknown() { + xxx_messageInfo_MsgAddCovenantSigs.DiscardUnknown(m) } -var xxx_messageInfo_MsgBTCUndelegate proto.InternalMessageInfo +var xxx_messageInfo_MsgAddCovenantSigs proto.InternalMessageInfo -func (m *MsgBTCUndelegate) GetSigner() string { +func (m *MsgAddCovenantSigs) GetSigner() string { if m != nil { return m.Signer } return "" } -func (m *MsgBTCUndelegate) GetUnbondingTx() []byte { +func (m *MsgAddCovenantSigs) GetStakingTxHash() string { if m != nil { - return m.UnbondingTx + return m.StakingTxHash } - return nil + return "" } -func (m *MsgBTCUndelegate) GetUnbondingTime() uint32 { +func (m *MsgAddCovenantSigs) GetSlashingTxSigs() [][]byte { if m != nil { - return m.UnbondingTime + return m.SlashingTxSigs } - return 0 + return nil } -func (m *MsgBTCUndelegate) GetUnbondingValue() int64 { +func (m *MsgAddCovenantSigs) GetSlashingUnbondingTxSigs() [][]byte { if m != nil { - return m.UnbondingValue + return m.SlashingUnbondingTxSigs } - return 0 + return nil } -// MsgBtcUndelegateResponse is the response for MsgBtcUndelegate -type MsgBTCUndelegateResponse struct { +// MsgAddCovenantSigsResponse is the response for MsgAddCovenantSigs +type MsgAddCovenantSigsResponse struct { } -func (m *MsgBTCUndelegateResponse) Reset() { *m = MsgBTCUndelegateResponse{} } -func (m *MsgBTCUndelegateResponse) String() string { return proto.CompactTextString(m) } -func (*MsgBTCUndelegateResponse) ProtoMessage() {} -func (*MsgBTCUndelegateResponse) Descriptor() ([]byte, []int) { +func (m *MsgAddCovenantSigsResponse) Reset() { *m = MsgAddCovenantSigsResponse{} } +func (m *MsgAddCovenantSigsResponse) String() string { return proto.CompactTextString(m) } +func (*MsgAddCovenantSigsResponse) ProtoMessage() {} +func (*MsgAddCovenantSigsResponse) Descriptor() ([]byte, []int) { return fileDescriptor_4baddb53e97f38f2, []int{5} } -func (m *MsgBTCUndelegateResponse) XXX_Unmarshal(b []byte) error { +func (m *MsgAddCovenantSigsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *MsgBTCUndelegateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *MsgAddCovenantSigsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_MsgBTCUndelegateResponse.Marshal(b, m, deterministic) + return xxx_messageInfo_MsgAddCovenantSigsResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -393,44 +432,43 @@ func (m *MsgBTCUndelegateResponse) XXX_Marshal(b []byte, deterministic bool) ([] return b[:n], nil } } -func (m *MsgBTCUndelegateResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgBTCUndelegateResponse.Merge(m, src) +func (m *MsgAddCovenantSigsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgAddCovenantSigsResponse.Merge(m, src) } -func (m *MsgBTCUndelegateResponse) XXX_Size() int { +func (m *MsgAddCovenantSigsResponse) XXX_Size() int { return m.Size() } -func (m *MsgBTCUndelegateResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgBTCUndelegateResponse.DiscardUnknown(m) +func (m *MsgAddCovenantSigsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgAddCovenantSigsResponse.DiscardUnknown(m) } -var xxx_messageInfo_MsgBTCUndelegateResponse proto.InternalMessageInfo +var xxx_messageInfo_MsgAddCovenantSigsResponse proto.InternalMessageInfo -// MsgAddCovenantSig is the message for handling a signature from covenant -type MsgAddCovenantSig struct { +// MsgBTCUndelegate is the message for handling signature on unbonding tx +// from its delegator. This signature effectively proves that the delegator +// wants to unbond this BTC delegation +type MsgBTCUndelegate struct { Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` - // pk is the BTC public key of the covenant member - Pk *github_com_babylonchain_babylon_types.BIP340PubKey `protobuf:"bytes,2,opt,name=pk,proto3,customtype=github.com/babylonchain/babylon/types.BIP340PubKey" json:"pk,omitempty"` // staking_tx_hash is the hash of the staking tx. // It uniquely identifies a BTC delegation - StakingTxHash string `protobuf:"bytes,3,opt,name=staking_tx_hash,json=stakingTxHash,proto3" json:"staking_tx_hash,omitempty"` - // sigs is a list of adaptor signatures of the covenant - // the order of sigs should respect the order of validators - // of the corresponding delegation - Sigs [][]byte `protobuf:"bytes,4,rep,name=sigs,proto3" json:"sigs,omitempty"` + StakingTxHash string `protobuf:"bytes,2,opt,name=staking_tx_hash,json=stakingTxHash,proto3" json:"staking_tx_hash,omitempty"` + // unbonding_tx_sig is the signature of the staker on the unbonding tx submitted to babylon + // the signature follows encoding in BIP-340 spec + UnbondingTxSig *github_com_babylonchain_babylon_types.BIP340Signature `protobuf:"bytes,3,opt,name=unbonding_tx_sig,json=unbondingTxSig,proto3,customtype=github.com/babylonchain/babylon/types.BIP340Signature" json:"unbonding_tx_sig,omitempty"` } -func (m *MsgAddCovenantSig) Reset() { *m = MsgAddCovenantSig{} } -func (m *MsgAddCovenantSig) String() string { return proto.CompactTextString(m) } -func (*MsgAddCovenantSig) ProtoMessage() {} -func (*MsgAddCovenantSig) Descriptor() ([]byte, []int) { +func (m *MsgBTCUndelegate) Reset() { *m = MsgBTCUndelegate{} } +func (m *MsgBTCUndelegate) String() string { return proto.CompactTextString(m) } +func (*MsgBTCUndelegate) ProtoMessage() {} +func (*MsgBTCUndelegate) Descriptor() ([]byte, []int) { return fileDescriptor_4baddb53e97f38f2, []int{6} } -func (m *MsgAddCovenantSig) XXX_Unmarshal(b []byte) error { +func (m *MsgBTCUndelegate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *MsgAddCovenantSig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *MsgBTCUndelegate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_MsgAddCovenantSig.Marshal(b, m, deterministic) + return xxx_messageInfo_MsgBTCUndelegate.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -440,55 +478,48 @@ func (m *MsgAddCovenantSig) XXX_Marshal(b []byte, deterministic bool) ([]byte, e return b[:n], nil } } -func (m *MsgAddCovenantSig) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgAddCovenantSig.Merge(m, src) +func (m *MsgBTCUndelegate) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgBTCUndelegate.Merge(m, src) } -func (m *MsgAddCovenantSig) XXX_Size() int { +func (m *MsgBTCUndelegate) XXX_Size() int { return m.Size() } -func (m *MsgAddCovenantSig) XXX_DiscardUnknown() { - xxx_messageInfo_MsgAddCovenantSig.DiscardUnknown(m) +func (m *MsgBTCUndelegate) XXX_DiscardUnknown() { + xxx_messageInfo_MsgBTCUndelegate.DiscardUnknown(m) } -var xxx_messageInfo_MsgAddCovenantSig proto.InternalMessageInfo +var xxx_messageInfo_MsgBTCUndelegate proto.InternalMessageInfo -func (m *MsgAddCovenantSig) GetSigner() string { +func (m *MsgBTCUndelegate) GetSigner() string { if m != nil { return m.Signer } return "" } -func (m *MsgAddCovenantSig) GetStakingTxHash() string { +func (m *MsgBTCUndelegate) GetStakingTxHash() string { if m != nil { return m.StakingTxHash } return "" } -func (m *MsgAddCovenantSig) GetSigs() [][]byte { - if m != nil { - return m.Sigs - } - return nil -} - -// MsgAddCovenantSigResponse is the response for MsgAddCovenantSig -type MsgAddCovenantSigResponse struct { +// MsgBTCUndelegateResponse is the response for MsgBTCUndelegate +type MsgBTCUndelegateResponse struct { } -func (m *MsgAddCovenantSigResponse) Reset() { *m = MsgAddCovenantSigResponse{} } -func (m *MsgAddCovenantSigResponse) String() string { return proto.CompactTextString(m) } -func (*MsgAddCovenantSigResponse) ProtoMessage() {} -func (*MsgAddCovenantSigResponse) Descriptor() ([]byte, []int) { +func (m *MsgBTCUndelegateResponse) Reset() { *m = MsgBTCUndelegateResponse{} } +func (m *MsgBTCUndelegateResponse) String() string { return proto.CompactTextString(m) } +func (*MsgBTCUndelegateResponse) ProtoMessage() {} +func (*MsgBTCUndelegateResponse) Descriptor() ([]byte, []int) { return fileDescriptor_4baddb53e97f38f2, []int{7} } -func (m *MsgAddCovenantSigResponse) XXX_Unmarshal(b []byte) error { +func (m *MsgBTCUndelegateResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *MsgAddCovenantSigResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *MsgBTCUndelegateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_MsgAddCovenantSigResponse.Marshal(b, m, deterministic) + return xxx_messageInfo_MsgBTCUndelegateResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -498,17 +529,17 @@ func (m *MsgAddCovenantSigResponse) XXX_Marshal(b []byte, deterministic bool) ([ return b[:n], nil } } -func (m *MsgAddCovenantSigResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgAddCovenantSigResponse.Merge(m, src) +func (m *MsgBTCUndelegateResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgBTCUndelegateResponse.Merge(m, src) } -func (m *MsgAddCovenantSigResponse) XXX_Size() int { +func (m *MsgBTCUndelegateResponse) XXX_Size() int { return m.Size() } -func (m *MsgAddCovenantSigResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgAddCovenantSigResponse.DiscardUnknown(m) +func (m *MsgBTCUndelegateResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgBTCUndelegateResponse.DiscardUnknown(m) } -var xxx_messageInfo_MsgAddCovenantSigResponse proto.InternalMessageInfo +var xxx_messageInfo_MsgBTCUndelegateResponse proto.InternalMessageInfo // MsgUpdateParams defines a message for updating btcstaking module parameters. type MsgUpdateParams struct { @@ -607,206 +638,95 @@ func (m *MsgUpdateParamsResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo -// MsgAddCovenantUnbondingSigs is the message for handling a signature from covenant -type MsgAddCovenantUnbondingSigs struct { - Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` - // pk is the BTC public key of the covenant member - Pk *github_com_babylonchain_babylon_types.BIP340PubKey `protobuf:"bytes,2,opt,name=pk,proto3,customtype=github.com/babylonchain/babylon/types.BIP340PubKey" json:"pk,omitempty"` - // staking_tx_hash is the hash of the staking tx. - // (val_pk, del_pk, staking_tx_hash) uniquely identifies a BTC delegation - StakingTxHash string `protobuf:"bytes,3,opt,name=staking_tx_hash,json=stakingTxHash,proto3" json:"staking_tx_hash,omitempty"` - // unbonding_tx_sig is the signature of the covenant on the unbonding tx submitted to babylon - // the signature follows encoding in BIP-340 spec - UnbondingTxSig *github_com_babylonchain_babylon_types.BIP340Signature `protobuf:"bytes,4,opt,name=unbonding_tx_sig,json=unbondingTxSig,proto3,customtype=github.com/babylonchain/babylon/types.BIP340Signature" json:"unbonding_tx_sig,omitempty"` - // slashing_unbonding_tx_sigs is a list of adaptor signatures of the covenant - // on slashing tx corresponding to unbonding tx submitted to babylon - // the order of sigs should respect the order of validators - // of the corresponding delegation - SlashingUnbondingTxSigs [][]byte `protobuf:"bytes,5,rep,name=slashing_unbonding_tx_sigs,json=slashingUnbondingTxSigs,proto3" json:"slashing_unbonding_tx_sigs,omitempty"` -} - -func (m *MsgAddCovenantUnbondingSigs) Reset() { *m = MsgAddCovenantUnbondingSigs{} } -func (m *MsgAddCovenantUnbondingSigs) String() string { return proto.CompactTextString(m) } -func (*MsgAddCovenantUnbondingSigs) ProtoMessage() {} -func (*MsgAddCovenantUnbondingSigs) Descriptor() ([]byte, []int) { - return fileDescriptor_4baddb53e97f38f2, []int{10} -} -func (m *MsgAddCovenantUnbondingSigs) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgAddCovenantUnbondingSigs) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgAddCovenantUnbondingSigs.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *MsgAddCovenantUnbondingSigs) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgAddCovenantUnbondingSigs.Merge(m, src) -} -func (m *MsgAddCovenantUnbondingSigs) XXX_Size() int { - return m.Size() -} -func (m *MsgAddCovenantUnbondingSigs) XXX_DiscardUnknown() { - xxx_messageInfo_MsgAddCovenantUnbondingSigs.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgAddCovenantUnbondingSigs proto.InternalMessageInfo - -func (m *MsgAddCovenantUnbondingSigs) GetSigner() string { - if m != nil { - return m.Signer - } - return "" -} - -func (m *MsgAddCovenantUnbondingSigs) GetStakingTxHash() string { - if m != nil { - return m.StakingTxHash - } - return "" -} - -func (m *MsgAddCovenantUnbondingSigs) GetSlashingUnbondingTxSigs() [][]byte { - if m != nil { - return m.SlashingUnbondingTxSigs - } - return nil -} - -// MsgAddCovenantSigResponse is the response for MsgAddCovenantSig -type MsgAddCovenantUnbondingSigsResponse struct { -} - -func (m *MsgAddCovenantUnbondingSigsResponse) Reset() { *m = MsgAddCovenantUnbondingSigsResponse{} } -func (m *MsgAddCovenantUnbondingSigsResponse) String() string { return proto.CompactTextString(m) } -func (*MsgAddCovenantUnbondingSigsResponse) ProtoMessage() {} -func (*MsgAddCovenantUnbondingSigsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_4baddb53e97f38f2, []int{11} -} -func (m *MsgAddCovenantUnbondingSigsResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgAddCovenantUnbondingSigsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgAddCovenantUnbondingSigsResponse.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *MsgAddCovenantUnbondingSigsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgAddCovenantUnbondingSigsResponse.Merge(m, src) -} -func (m *MsgAddCovenantUnbondingSigsResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgAddCovenantUnbondingSigsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgAddCovenantUnbondingSigsResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgAddCovenantUnbondingSigsResponse proto.InternalMessageInfo - func init() { proto.RegisterType((*MsgCreateBTCValidator)(nil), "babylon.btcstaking.v1.MsgCreateBTCValidator") proto.RegisterType((*MsgCreateBTCValidatorResponse)(nil), "babylon.btcstaking.v1.MsgCreateBTCValidatorResponse") proto.RegisterType((*MsgCreateBTCDelegation)(nil), "babylon.btcstaking.v1.MsgCreateBTCDelegation") proto.RegisterType((*MsgCreateBTCDelegationResponse)(nil), "babylon.btcstaking.v1.MsgCreateBTCDelegationResponse") + proto.RegisterType((*MsgAddCovenantSigs)(nil), "babylon.btcstaking.v1.MsgAddCovenantSigs") + proto.RegisterType((*MsgAddCovenantSigsResponse)(nil), "babylon.btcstaking.v1.MsgAddCovenantSigsResponse") proto.RegisterType((*MsgBTCUndelegate)(nil), "babylon.btcstaking.v1.MsgBTCUndelegate") proto.RegisterType((*MsgBTCUndelegateResponse)(nil), "babylon.btcstaking.v1.MsgBTCUndelegateResponse") - proto.RegisterType((*MsgAddCovenantSig)(nil), "babylon.btcstaking.v1.MsgAddCovenantSig") - proto.RegisterType((*MsgAddCovenantSigResponse)(nil), "babylon.btcstaking.v1.MsgAddCovenantSigResponse") proto.RegisterType((*MsgUpdateParams)(nil), "babylon.btcstaking.v1.MsgUpdateParams") proto.RegisterType((*MsgUpdateParamsResponse)(nil), "babylon.btcstaking.v1.MsgUpdateParamsResponse") - proto.RegisterType((*MsgAddCovenantUnbondingSigs)(nil), "babylon.btcstaking.v1.MsgAddCovenantUnbondingSigs") - proto.RegisterType((*MsgAddCovenantUnbondingSigsResponse)(nil), "babylon.btcstaking.v1.MsgAddCovenantUnbondingSigsResponse") } func init() { proto.RegisterFile("babylon/btcstaking/v1/tx.proto", fileDescriptor_4baddb53e97f38f2) } var fileDescriptor_4baddb53e97f38f2 = []byte{ - // 1149 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x57, 0x4d, 0x6f, 0x1a, 0x57, - 0x17, 0xf6, 0xf0, 0xf5, 0xbe, 0x3e, 0x80, 0x9d, 0x4c, 0x93, 0x78, 0x8c, 0x15, 0x20, 0xb8, 0x49, - 0x68, 0x14, 0x0f, 0x31, 0x89, 0x2d, 0xd5, 0x91, 0x2a, 0x05, 0xbb, 0x55, 0xa2, 0x1a, 0x15, 0x0d, - 0x38, 0x8b, 0x4a, 0x2d, 0xba, 0x0c, 0xd7, 0xc3, 0x08, 0x98, 0x3b, 0x9a, 0x7b, 0x41, 0xa0, 0x6e, - 0xaa, 0x2e, 0x2b, 0x55, 0xea, 0xaa, 0xbb, 0xfe, 0x87, 0x2c, 0xb2, 0xec, 0x0f, 0xc8, 0xae, 0x69, - 0xd4, 0x45, 0xe5, 0x85, 0x55, 0xd9, 0x8b, 0xfc, 0x8d, 0x6a, 0x66, 0xee, 0x7c, 0x40, 0xa0, 0xc5, - 0x71, 0x17, 0xdd, 0xcd, 0x9d, 0xfb, 0x9c, 0xe7, 0x9c, 0xf3, 0x9c, 0x8f, 0x01, 0xc8, 0xb6, 0x50, - 0x6b, 0xdc, 0x23, 0x46, 0xa9, 0xc5, 0x54, 0xca, 0x50, 0x57, 0x37, 0xb4, 0xd2, 0x70, 0xbb, 0xc4, - 0x46, 0xb2, 0x69, 0x11, 0x46, 0xc4, 0xeb, 0xfc, 0x5e, 0x0e, 0xee, 0xe5, 0xe1, 0x76, 0xe6, 0x9a, - 0x46, 0x34, 0xe2, 0x20, 0x4a, 0xf6, 0x93, 0x0b, 0xce, 0xac, 0xab, 0x84, 0xf6, 0x09, 0x6d, 0xba, - 0x17, 0xee, 0x81, 0x5f, 0xad, 0xb9, 0xa7, 0x52, 0x9f, 0x3a, 0xfc, 0x7d, 0xaa, 0xf1, 0x8b, 0x02, - 0xbf, 0x50, 0xad, 0xb1, 0xc9, 0x48, 0x89, 0x62, 0xd5, 0x2c, 0xef, 0xec, 0x76, 0xb7, 0x4b, 0x5d, - 0x3c, 0xf6, 0x8c, 0x0b, 0xb3, 0x83, 0x34, 0x91, 0x85, 0xfa, 0x1e, 0xe6, 0x7e, 0x08, 0xa3, 0x76, - 0xb0, 0xda, 0x35, 0x89, 0x6e, 0x30, 0x1b, 0x36, 0xf1, 0x82, 0xa3, 0x3f, 0xe4, 0x5e, 0x03, 0xb6, - 0x16, 0x66, 0x68, 0xdb, 0x3b, 0x73, 0x54, 0x6e, 0x8e, 0x5f, 0x62, 0xba, 0x80, 0xc2, 0xcf, 0x51, - 0xb8, 0x5e, 0xa5, 0xda, 0xbe, 0x85, 0x11, 0xc3, 0x95, 0xc6, 0xfe, 0x73, 0xd4, 0xd3, 0xdb, 0x88, - 0x11, 0x4b, 0xbc, 0x01, 0x09, 0xaa, 0x6b, 0x06, 0xb6, 0x24, 0x21, 0x2f, 0x14, 0x97, 0x15, 0x7e, - 0x12, 0x3f, 0x85, 0x64, 0x1b, 0x53, 0xd5, 0xd2, 0x4d, 0xa6, 0x13, 0x43, 0x8a, 0xe4, 0x85, 0x62, - 0xb2, 0xbc, 0x29, 0x73, 0xad, 0x02, 0x85, 0x9d, 0x70, 0xe4, 0x83, 0x00, 0xaa, 0x84, 0xed, 0xc4, - 0x2a, 0x80, 0x4a, 0xfa, 0x7d, 0x9d, 0x52, 0x9b, 0x25, 0x6a, 0xbb, 0xa8, 0x6c, 0x9d, 0x9c, 0xe6, - 0x36, 0x5c, 0x22, 0xda, 0xee, 0xca, 0x3a, 0x29, 0xf5, 0x11, 0xeb, 0xc8, 0x87, 0x58, 0x43, 0xea, - 0xf8, 0x00, 0xab, 0x6f, 0x5e, 0x6e, 0x01, 0xf7, 0x73, 0x80, 0x55, 0x25, 0x44, 0x20, 0x7e, 0x02, - 0xc0, 0x53, 0x6d, 0x9a, 0x5d, 0x29, 0xe6, 0x04, 0x95, 0xf3, 0x82, 0x72, 0x2b, 0x23, 0xfb, 0x95, - 0x91, 0x6b, 0x83, 0xd6, 0xe7, 0x78, 0xac, 0x2c, 0x73, 0x93, 0x5a, 0x57, 0xac, 0x42, 0xa2, 0xc5, - 0x54, 0xdb, 0x36, 0x9e, 0x17, 0x8a, 0xa9, 0xca, 0xee, 0xc9, 0x69, 0xae, 0xac, 0xe9, 0xac, 0x33, - 0x68, 0xc9, 0x2a, 0xe9, 0x97, 0x38, 0x52, 0xed, 0x20, 0xdd, 0xf0, 0x0e, 0x25, 0x36, 0x36, 0x31, - 0x95, 0x2b, 0xcf, 0x6a, 0x0f, 0x1f, 0x3d, 0xe0, 0x94, 0xf1, 0x16, 0x53, 0x6b, 0x5d, 0x71, 0x0f, - 0xa2, 0x26, 0x31, 0xa5, 0x84, 0x13, 0x47, 0x51, 0x9e, 0xd9, 0x82, 0x72, 0xcd, 0x22, 0xe4, 0xf8, - 0x8b, 0xe3, 0x1a, 0xa1, 0x14, 0x3b, 0x59, 0x28, 0xb6, 0xd1, 0x5e, 0xf2, 0xbb, 0xb7, 0x2f, 0xee, - 0x71, 0xb5, 0x0b, 0x39, 0xb8, 0x39, 0xb3, 0x3c, 0x0a, 0xa6, 0x26, 0x31, 0x28, 0x2e, 0xfc, 0x10, - 0x87, 0x1b, 0x61, 0xc4, 0x01, 0xee, 0x61, 0x0d, 0x39, 0x12, 0xcf, 0xab, 0xe0, 0xa4, 0x56, 0x91, - 0x0b, 0x6b, 0xc5, 0x93, 0x8b, 0xbe, 0x47, 0x72, 0x21, 0x9d, 0x63, 0xff, 0x86, 0xce, 0x5f, 0xc1, - 0xea, 0x10, 0xf5, 0x9a, 0x2e, 0x65, 0xb3, 0xa7, 0x53, 0x26, 0xc5, 0xf3, 0xd1, 0x4b, 0xf0, 0xa6, - 0x86, 0xa8, 0x57, 0xb1, 0xa9, 0x0f, 0x75, 0xca, 0xc4, 0x5b, 0x90, 0xe2, 0x29, 0x35, 0x99, 0xde, - 0xc7, 0x4e, 0x3d, 0xd3, 0x4a, 0x92, 0xbf, 0x6b, 0xe8, 0x7d, 0x2c, 0x6e, 0x42, 0xda, 0x83, 0x0c, - 0x51, 0x6f, 0x80, 0xa5, 0xff, 0xe5, 0x85, 0x62, 0x54, 0xf1, 0xec, 0x9e, 0xdb, 0xef, 0xc4, 0xa7, - 0x00, 0x3e, 0xcf, 0x48, 0xfa, 0xbf, 0x23, 0xdc, 0x47, 0x61, 0xe1, 0x42, 0xe3, 0x3d, 0xdc, 0x96, - 0x1b, 0x16, 0x32, 0x28, 0x52, 0xed, 0x22, 0x3e, 0x33, 0x8e, 0x89, 0xb2, 0xec, 0x39, 0x1c, 0x89, - 0x65, 0x48, 0xd2, 0x1e, 0xa2, 0x1d, 0x4e, 0xb5, 0xec, 0x88, 0x78, 0xf5, 0xe4, 0x34, 0x97, 0xae, - 0x34, 0xf6, 0xeb, 0xfc, 0xa6, 0x31, 0x52, 0x80, 0xfa, 0xcf, 0xe2, 0xd7, 0x90, 0x6e, 0xbb, 0x5d, - 0x41, 0xac, 0x26, 0xd5, 0x35, 0x09, 0x1c, 0xab, 0x8f, 0x4f, 0x4e, 0x73, 0x3b, 0x17, 0x91, 0xa8, - 0xae, 0x6b, 0x06, 0x62, 0x03, 0x0b, 0x2b, 0x29, 0x9f, 0xaf, 0xae, 0x6b, 0x93, 0x0d, 0x9b, 0x87, - 0xec, 0xec, 0x76, 0xf4, 0x3b, 0xf6, 0xd7, 0x08, 0x5c, 0xa9, 0x52, 0xad, 0xd2, 0xd8, 0x3f, 0x32, - 0x38, 0x0f, 0x9e, 0xdb, 0xab, 0xb7, 0x20, 0x35, 0x30, 0x5a, 0xc4, 0x68, 0xf3, 0x84, 0xed, 0x6e, - 0x4d, 0x29, 0x49, 0xff, 0x5d, 0x63, 0x24, 0xde, 0x86, 0x95, 0x10, 0xc4, 0x2e, 0x53, 0xd4, 0x29, - 0x53, 0x3a, 0x00, 0xd9, 0x85, 0xba, 0x0b, 0xab, 0x01, 0xcc, 0x2d, 0x55, 0xcc, 0x29, 0x55, 0x60, - 0xed, 0x16, 0x6b, 0x4a, 0xe2, 0xf8, 0x22, 0x12, 0x13, 0xb8, 0x11, 0x92, 0xd8, 0xb3, 0xb6, 0xb5, - 0x4e, 0x5c, 0x56, 0xeb, 0x6b, 0x81, 0xd6, 0x9c, 0xf7, 0x1d, 0xcd, 0x33, 0x20, 0x4d, 0x0b, 0xea, - 0xab, 0xfd, 0x8b, 0x00, 0x57, 0xab, 0x54, 0x7b, 0xd2, 0x6e, 0xef, 0x93, 0x21, 0x36, 0x90, 0xc1, - 0xea, 0xba, 0x36, 0x57, 0xee, 0xcf, 0x20, 0xc2, 0x57, 0xc2, 0xfb, 0x8f, 0x50, 0xc4, 0xec, 0x8a, - 0x77, 0x60, 0x35, 0x68, 0xf8, 0x66, 0x07, 0xd1, 0x8e, 0xbb, 0xe2, 0x95, 0xb4, 0xdf, 0xca, 0x4f, - 0x11, 0xed, 0x88, 0x22, 0xc4, 0xa8, 0xae, 0x51, 0x29, 0x66, 0x0f, 0xad, 0xe2, 0x3c, 0x4f, 0xa6, - 0xb6, 0x01, 0xeb, 0xef, 0x44, 0xef, 0xe7, 0xf6, 0x93, 0x00, 0xab, 0x55, 0xaa, 0x1d, 0x99, 0x6d, - 0xc4, 0x70, 0xcd, 0xf9, 0x96, 0x8a, 0xbb, 0xb0, 0x8c, 0x06, 0xac, 0x43, 0x2c, 0x9d, 0x8d, 0xdd, - 0xe4, 0x2a, 0xd2, 0x9b, 0x97, 0x5b, 0xd7, 0xf8, 0x7a, 0x7b, 0xd2, 0x6e, 0x5b, 0x98, 0xd2, 0x3a, - 0xb3, 0x74, 0x43, 0x53, 0x02, 0xa8, 0xf8, 0x18, 0x12, 0xee, 0xd7, 0x98, 0x2f, 0xc4, 0x9b, 0xf3, - 0xf6, 0x9a, 0x03, 0xaa, 0xc4, 0x5e, 0x9d, 0xe6, 0x96, 0x14, 0x6e, 0xb2, 0xb7, 0x62, 0x87, 0x1c, - 0x90, 0x15, 0xd6, 0x61, 0x6d, 0x2a, 0x2e, 0x3f, 0xe6, 0xdf, 0x23, 0xb0, 0x31, 0x99, 0xd1, 0x91, - 0xd7, 0x7e, 0x75, 0x5d, 0xa3, 0xff, 0x99, 0xca, 0xa8, 0x70, 0x25, 0x3c, 0x78, 0x4e, 0x2f, 0xc7, - 0x2e, 0xdb, 0xcb, 0x2b, 0xa1, 0xb9, 0xb5, 0xdb, 0xf0, 0x31, 0x64, 0xfc, 0x61, 0x99, 0xf6, 0x46, - 0xdd, 0x4d, 0xae, 0xac, 0x79, 0x88, 0xa3, 0x09, 0xdb, 0xa9, 0x3e, 0xb9, 0x0d, 0x9b, 0x7f, 0xa3, - 0xaa, 0xa7, 0x7e, 0xf9, 0xb7, 0x38, 0x44, 0xab, 0x54, 0x13, 0x47, 0x20, 0xce, 0xf8, 0xc9, 0x73, - 0x7f, 0x4e, 0xcd, 0x67, 0x7e, 0x81, 0x33, 0x8f, 0x2e, 0x82, 0xf6, 0x22, 0x10, 0xbf, 0x81, 0x0f, - 0x66, 0x7d, 0xab, 0xb7, 0x16, 0x20, 0x0b, 0xe0, 0x99, 0x9d, 0x0b, 0xc1, 0x7d, 0xe7, 0x3a, 0xa4, - 0x27, 0xd7, 0xee, 0xdd, 0xf9, 0x3c, 0x13, 0xc0, 0x4c, 0x69, 0x41, 0xa0, 0xef, 0xaa, 0x07, 0x2b, - 0x53, 0x3b, 0xa7, 0x38, 0x9f, 0x62, 0x12, 0x99, 0x79, 0xb0, 0x28, 0xd2, 0xf7, 0xf6, 0xbd, 0x00, - 0xd2, 0xdc, 0x91, 0x2a, 0x2f, 0x44, 0x37, 0x61, 0x93, 0xd9, 0xbb, 0xb8, 0x8d, 0x1f, 0xcc, 0x31, - 0xa4, 0x26, 0x56, 0xd2, 0x9d, 0xf9, 0x5c, 0x61, 0x5c, 0x46, 0x5e, 0x0c, 0xe7, 0xf9, 0xc9, 0xc4, - 0xbf, 0x7d, 0xfb, 0xe2, 0x9e, 0x50, 0x39, 0x7c, 0x75, 0x96, 0x15, 0x5e, 0x9f, 0x65, 0x85, 0x3f, - 0xcf, 0xb2, 0xc2, 0x8f, 0xe7, 0xd9, 0xa5, 0xd7, 0xe7, 0xd9, 0xa5, 0x3f, 0xce, 0xb3, 0x4b, 0x5f, - 0xfe, 0xe3, 0x8e, 0x18, 0x85, 0xff, 0x17, 0x38, 0x23, 0xdb, 0x4a, 0x38, 0xff, 0x0b, 0x1e, 0xfe, - 0x15, 0x00, 0x00, 0xff, 0xff, 0x22, 0x62, 0x6f, 0x70, 0x57, 0x0d, 0x00, 0x00, + // 1140 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xdf, 0x6e, 0x1a, 0xc7, + 0x17, 0xf6, 0x82, 0x4d, 0x7e, 0x3e, 0x18, 0x93, 0xdf, 0x26, 0xb6, 0x37, 0xb4, 0x06, 0x4a, 0xda, + 0x84, 0x44, 0xf1, 0x52, 0x9c, 0xd8, 0x52, 0x1d, 0xa9, 0x52, 0xb0, 0x53, 0x25, 0xaa, 0x51, 0xd1, + 0x82, 0x73, 0x51, 0xa9, 0x42, 0xc3, 0x32, 0x5e, 0x46, 0xc0, 0xce, 0x6a, 0x67, 0x40, 0xa0, 0xde, + 0x54, 0x79, 0x82, 0x5e, 0xf5, 0xae, 0xef, 0x90, 0x8b, 0x3c, 0x42, 0xa5, 0xe6, 0x32, 0xca, 0x55, + 0x65, 0xa9, 0x56, 0x65, 0x5f, 0xe4, 0x09, 0x7a, 0x5f, 0xed, 0xee, 0xec, 0x1f, 0x28, 0xa8, 0x76, + 0x9c, 0xbb, 0xdd, 0x99, 0xef, 0x7c, 0xe7, 0x9c, 0xef, 0x9c, 0x33, 0x33, 0x90, 0x6d, 0xa1, 0xd6, + 0xb8, 0x47, 0xcd, 0x52, 0x8b, 0xeb, 0x8c, 0xa3, 0x2e, 0x31, 0x8d, 0xd2, 0xb0, 0x5c, 0xe2, 0x23, + 0xd5, 0xb2, 0x29, 0xa7, 0xf2, 0x9a, 0xd8, 0x57, 0xc3, 0x7d, 0x75, 0x58, 0xce, 0xdc, 0x34, 0xa8, + 0x41, 0x5d, 0x44, 0xc9, 0xf9, 0xf2, 0xc0, 0x99, 0x5b, 0x3a, 0x65, 0x7d, 0xca, 0x9a, 0xde, 0x86, + 0xf7, 0x23, 0xb6, 0x36, 0xbc, 0xbf, 0x52, 0x9f, 0xb9, 0xfc, 0x7d, 0x66, 0x88, 0x8d, 0x82, 0xd8, + 0xd0, 0xed, 0xb1, 0xc5, 0x69, 0x89, 0x61, 0xdd, 0xda, 0xde, 0xd9, 0xed, 0x96, 0x4b, 0x5d, 0x3c, + 0xf6, 0x8d, 0x0b, 0xb3, 0x83, 0xb4, 0x90, 0x8d, 0xfa, 0x3e, 0xe6, 0x41, 0x04, 0xa3, 0x77, 0xb0, + 0xde, 0xb5, 0x28, 0x31, 0xb9, 0x03, 0x9b, 0x58, 0x10, 0xe8, 0xcf, 0x85, 0xd7, 0x90, 0xad, 0x85, + 0x39, 0x2a, 0xfb, 0xff, 0x02, 0x95, 0x9b, 0xe3, 0x97, 0x5a, 0x1e, 0xa0, 0xf0, 0x6b, 0x1c, 0xd6, + 0xaa, 0xcc, 0xd8, 0xb7, 0x31, 0xe2, 0xb8, 0xd2, 0xd8, 0x7f, 0x81, 0x7a, 0xa4, 0x8d, 0x38, 0xb5, + 0xe5, 0x75, 0x48, 0x30, 0x62, 0x98, 0xd8, 0x56, 0xa4, 0xbc, 0x54, 0x5c, 0xd6, 0xc4, 0x9f, 0xfc, + 0x14, 0x92, 0x6d, 0xcc, 0x74, 0x9b, 0x58, 0x9c, 0x50, 0x53, 0x89, 0xe5, 0xa5, 0x62, 0x72, 0xfb, + 0xb6, 0x2a, 0xb4, 0x0a, 0x15, 0x76, 0xc3, 0x51, 0x0f, 0x42, 0xa8, 0x16, 0xb5, 0x93, 0xab, 0x00, + 0x3a, 0xed, 0xf7, 0x09, 0x63, 0x0e, 0x4b, 0xdc, 0x71, 0x51, 0xd9, 0x3a, 0x39, 0xcd, 0x7d, 0xe2, + 0x11, 0xb1, 0x76, 0x57, 0x25, 0xb4, 0xd4, 0x47, 0xbc, 0xa3, 0x1e, 0x62, 0x03, 0xe9, 0xe3, 0x03, + 0xac, 0xbf, 0x7b, 0xbd, 0x05, 0xc2, 0xcf, 0x01, 0xd6, 0xb5, 0x08, 0x81, 0xfc, 0x35, 0x80, 0x48, + 0xb5, 0x69, 0x75, 0x95, 0x45, 0x37, 0xa8, 0x9c, 0x1f, 0x94, 0x57, 0x19, 0x35, 0xa8, 0x8c, 0x5a, + 0x1b, 0xb4, 0xbe, 0xc5, 0x63, 0x6d, 0x59, 0x98, 0xd4, 0xba, 0x72, 0x15, 0x12, 0x2d, 0xae, 0x3b, + 0xb6, 0x4b, 0x79, 0xa9, 0xb8, 0x52, 0xd9, 0x3d, 0x39, 0xcd, 0x6d, 0x1b, 0x84, 0x77, 0x06, 0x2d, + 0x55, 0xa7, 0xfd, 0x92, 0x40, 0xea, 0x1d, 0x44, 0x4c, 0xff, 0xa7, 0xc4, 0xc7, 0x16, 0x66, 0x6a, + 0xe5, 0x79, 0xed, 0xe1, 0xa3, 0x2f, 0x05, 0xe5, 0x52, 0x8b, 0xeb, 0xb5, 0xae, 0xbc, 0x07, 0x71, + 0x8b, 0x5a, 0x4a, 0xc2, 0x8d, 0xa3, 0xa8, 0xce, 0x6c, 0x41, 0xb5, 0x66, 0x53, 0x7a, 0xfc, 0xdd, + 0x71, 0x8d, 0x32, 0x86, 0xdd, 0x2c, 0x34, 0xc7, 0x68, 0x2f, 0xf9, 0xf2, 0xfd, 0xab, 0xfb, 0x42, + 0xed, 0x42, 0x0e, 0x36, 0x67, 0x96, 0x47, 0xc3, 0xcc, 0xa2, 0x26, 0xc3, 0x85, 0x3f, 0xaf, 0xc1, + 0x7a, 0x14, 0x71, 0x80, 0x7b, 0xd8, 0x40, 0xae, 0xc4, 0xf3, 0x2a, 0x38, 0xa9, 0x55, 0xec, 0xd2, + 0x5a, 0x89, 0xe4, 0xe2, 0x1f, 0x90, 0x5c, 0x44, 0xe7, 0xc5, 0x8f, 0xa1, 0xf3, 0x0f, 0x90, 0x1e, + 0xa2, 0x5e, 0xd3, 0xa3, 0x6c, 0xf6, 0x08, 0xe3, 0xca, 0x52, 0x3e, 0x7e, 0x05, 0xde, 0x95, 0x21, + 0xea, 0x55, 0x1c, 0xea, 0x43, 0xc2, 0xb8, 0xfc, 0x19, 0xac, 0x88, 0x94, 0x9a, 0x9c, 0xf4, 0xb1, + 0x5b, 0xcf, 0x94, 0x96, 0x14, 0x6b, 0x0d, 0xd2, 0xc7, 0xf2, 0x6d, 0x48, 0xf9, 0x90, 0x21, 0xea, + 0x0d, 0xb0, 0x72, 0x2d, 0x2f, 0x15, 0xe3, 0x9a, 0x6f, 0xf7, 0xc2, 0x59, 0x93, 0x9f, 0x01, 0x04, + 0x3c, 0x23, 0xe5, 0x7f, 0xae, 0x70, 0xf7, 0xa2, 0xc2, 0x45, 0xc6, 0x7b, 0x58, 0x56, 0x1b, 0x36, + 0x32, 0x19, 0xd2, 0x9d, 0x22, 0x3e, 0x37, 0x8f, 0xa9, 0xb6, 0xec, 0x3b, 0x1c, 0xc9, 0xdb, 0x90, + 0x64, 0x3d, 0xc4, 0x3a, 0x82, 0x6a, 0xd9, 0x15, 0xf1, 0xff, 0x27, 0xa7, 0xb9, 0x54, 0xa5, 0xb1, + 0x5f, 0x17, 0x3b, 0x8d, 0x91, 0x06, 0x2c, 0xf8, 0x96, 0x29, 0xac, 0xb7, 0xbd, 0xae, 0xa0, 0x76, + 0x33, 0xb0, 0x66, 0xc4, 0x50, 0xc0, 0x35, 0xff, 0xea, 0xe4, 0x34, 0xb7, 0x73, 0x19, 0xad, 0xea, + 0xc4, 0x30, 0x11, 0x1f, 0xd8, 0x58, 0xbb, 0x19, 0x10, 0xfb, 0xbe, 0xeb, 0xc4, 0x70, 0x64, 0x1b, + 0x98, 0x2d, 0x6a, 0xb6, 0x45, 0x94, 0x49, 0xc7, 0x8d, 0x96, 0x0c, 0xd6, 0x1a, 0x23, 0xf9, 0x0b, + 0x58, 0x8d, 0x40, 0x1c, 0x6d, 0x57, 0x5c, 0x6d, 0x53, 0x21, 0xc8, 0x51, 0xf7, 0x2e, 0xa4, 0x43, + 0x98, 0xa7, 0x6f, 0xca, 0xd5, 0x37, 0xb4, 0xf6, 0x14, 0x7e, 0x0a, 0x6b, 0x21, 0x30, 0xaa, 0xd0, + 0xea, 0x3c, 0x85, 0x6e, 0x04, 0xf8, 0x70, 0x51, 0x7e, 0x29, 0x41, 0x3e, 0xd4, 0x6a, 0x06, 0xa3, + 0xa3, 0x5a, 0xfa, 0xaa, 0xaa, 0x6d, 0x06, 0x2e, 0x8e, 0xa6, 0x63, 0xa8, 0x13, 0x63, 0xf2, 0x00, + 0xc8, 0x43, 0x76, 0xf6, 0x78, 0x07, 0x27, 0xc0, 0xdf, 0x31, 0x90, 0xab, 0xcc, 0x78, 0xd2, 0x6e, + 0xef, 0xd3, 0x21, 0x36, 0x91, 0xc9, 0xeb, 0xc4, 0x60, 0x73, 0xa7, 0xff, 0x1b, 0x88, 0x89, 0xa9, + 0xff, 0xf0, 0x29, 0x89, 0x59, 0x5d, 0xf9, 0x0e, 0xa4, 0xc3, 0x9e, 0x6e, 0x76, 0x10, 0xeb, 0x78, + 0xa7, 0xb8, 0x96, 0x0a, 0xba, 0xf5, 0x19, 0x62, 0x1d, 0xb9, 0x08, 0xd7, 0x23, 0xf5, 0x70, 0x04, + 0x64, 0xca, 0xa2, 0x33, 0xa3, 0xda, 0x6a, 0xd8, 0xa3, 0x6e, 0xc4, 0x3a, 0x5c, 0x8f, 0xb6, 0x8d, + 0xab, 0xf5, 0xd2, 0x55, 0xb5, 0x5e, 0x8d, 0x74, 0x9d, 0xd3, 0x9b, 0x8f, 0x21, 0x13, 0x84, 0x33, + 0xed, 0x8d, 0x29, 0x09, 0x37, 0xb0, 0x0d, 0x1f, 0x71, 0x34, 0x61, 0xcb, 0x26, 0x2b, 0xf3, 0x29, + 0x64, 0xfe, 0x2d, 0x7b, 0x50, 0x95, 0xdf, 0x24, 0xb8, 0x5e, 0x65, 0x46, 0xa5, 0xb1, 0x7f, 0x64, + 0x8a, 0x72, 0xe3, 0xb9, 0x35, 0x99, 0xa1, 0x65, 0x6c, 0x96, 0x96, 0xb3, 0x14, 0x8a, 0x7f, 0x64, + 0x85, 0x26, 0x93, 0xcc, 0x80, 0x32, 0x9d, 0x45, 0x90, 0xe2, 0x2f, 0x12, 0xa4, 0xab, 0xcc, 0x38, + 0xb2, 0xda, 0x88, 0xe3, 0x9a, 0xfb, 0x94, 0x91, 0x77, 0x61, 0x19, 0x0d, 0x78, 0x87, 0xda, 0x84, + 0x8f, 0xbd, 0x24, 0x2b, 0xca, 0xbb, 0xd7, 0x5b, 0x37, 0xc5, 0xed, 0xf2, 0xa4, 0xdd, 0xb6, 0x31, + 0x63, 0x75, 0x6e, 0x13, 0xd3, 0xd0, 0x42, 0xa8, 0xfc, 0x18, 0x12, 0xde, 0x63, 0x48, 0xdc, 0x47, + 0x9b, 0xf3, 0xae, 0x15, 0x17, 0x54, 0x59, 0x7c, 0x73, 0x9a, 0x5b, 0xd0, 0x84, 0xc9, 0xde, 0xaa, + 0x13, 0x71, 0x48, 0x56, 0xb8, 0x05, 0x1b, 0x53, 0x71, 0xf9, 0x31, 0x6f, 0xff, 0xbe, 0x08, 0xf1, + 0x2a, 0x33, 0xe4, 0x11, 0xc8, 0x33, 0xde, 0x3c, 0x0f, 0xe6, 0x78, 0x9d, 0x79, 0x05, 0x67, 0x1e, + 0x5d, 0x06, 0xed, 0x47, 0x20, 0xff, 0x08, 0x37, 0x66, 0x5d, 0xd6, 0x5b, 0x17, 0x20, 0x0b, 0xe1, + 0x99, 0x9d, 0x4b, 0xc1, 0x03, 0xe7, 0x14, 0xd2, 0xd3, 0xe7, 0xc4, 0xbd, 0xf9, 0x4c, 0x53, 0xd0, + 0x4c, 0xf9, 0xc2, 0xd0, 0xc0, 0xe1, 0x31, 0xac, 0x4c, 0xf4, 0xc7, 0x9d, 0xf9, 0x14, 0x51, 0x5c, + 0x46, 0xbd, 0x18, 0x2e, 0xf0, 0x43, 0x20, 0x35, 0x39, 0x6a, 0x77, 0xe7, 0x13, 0x4c, 0x00, 0x33, + 0xa5, 0x0b, 0x02, 0x7d, 0x57, 0x99, 0xa5, 0x9f, 0xde, 0xbf, 0xba, 0x2f, 0x55, 0x0e, 0xdf, 0x9c, + 0x65, 0xa5, 0xb7, 0x67, 0x59, 0xe9, 0xaf, 0xb3, 0xac, 0xf4, 0xf3, 0x79, 0x76, 0xe1, 0xed, 0x79, + 0x76, 0xe1, 0x8f, 0xf3, 0xec, 0xc2, 0xf7, 0xff, 0x79, 0xa2, 0x8e, 0xa2, 0xcf, 0x71, 0x77, 0x28, + 0x5b, 0x09, 0xf7, 0x39, 0xfe, 0xf0, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x52, 0xfc, 0xf9, 0xf0, + 0xce, 0x0c, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -825,16 +745,12 @@ type MsgClient interface { CreateBTCValidator(ctx context.Context, in *MsgCreateBTCValidator, opts ...grpc.CallOption) (*MsgCreateBTCValidatorResponse, error) // CreateBTCDelegation creates a new BTC delegation CreateBTCDelegation(ctx context.Context, in *MsgCreateBTCDelegation, opts ...grpc.CallOption) (*MsgCreateBTCDelegationResponse, error) - // BtcUndelegate undelegates funds from exsitng btc delegation - BTCUndelegate(ctx context.Context, in *MsgBTCUndelegate, opts ...grpc.CallOption) (*MsgBTCUndelegateResponse, error) - // AddCovenantSig handles a signature from covenant for slashing tx of staking tx for delegation - AddCovenantSig(ctx context.Context, in *MsgAddCovenantSig, opts ...grpc.CallOption) (*MsgAddCovenantSigResponse, error) - // AddCovenantUnbondingSigs handles two signatures from covenant for: - // - unbonding tx submitted to babylon by staker - // - slashing tx corresponding to unbonding tx submitted to babylon by staker - AddCovenantUnbondingSigs(ctx context.Context, in *MsgAddCovenantUnbondingSigs, opts ...grpc.CallOption) (*MsgAddCovenantUnbondingSigsResponse, error) + // AddCovenantSigs handles signatures from a covenant member + AddCovenantSigs(ctx context.Context, in *MsgAddCovenantSigs, opts ...grpc.CallOption) (*MsgAddCovenantSigsResponse, error) // UpdateParams updates the btcstaking module parameters. UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) + // BTCUndelegate handles a signature on unbonding tx from its delegator + BTCUndelegate(ctx context.Context, in *MsgBTCUndelegate, opts ...grpc.CallOption) (*MsgBTCUndelegateResponse, error) } type msgClient struct { @@ -863,36 +779,27 @@ func (c *msgClient) CreateBTCDelegation(ctx context.Context, in *MsgCreateBTCDel return out, nil } -func (c *msgClient) BTCUndelegate(ctx context.Context, in *MsgBTCUndelegate, opts ...grpc.CallOption) (*MsgBTCUndelegateResponse, error) { - out := new(MsgBTCUndelegateResponse) - err := c.cc.Invoke(ctx, "/babylon.btcstaking.v1.Msg/BTCUndelegate", in, out, opts...) +func (c *msgClient) AddCovenantSigs(ctx context.Context, in *MsgAddCovenantSigs, opts ...grpc.CallOption) (*MsgAddCovenantSigsResponse, error) { + out := new(MsgAddCovenantSigsResponse) + err := c.cc.Invoke(ctx, "/babylon.btcstaking.v1.Msg/AddCovenantSigs", in, out, opts...) if err != nil { return nil, err } return out, nil } -func (c *msgClient) AddCovenantSig(ctx context.Context, in *MsgAddCovenantSig, opts ...grpc.CallOption) (*MsgAddCovenantSigResponse, error) { - out := new(MsgAddCovenantSigResponse) - err := c.cc.Invoke(ctx, "/babylon.btcstaking.v1.Msg/AddCovenantSig", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) AddCovenantUnbondingSigs(ctx context.Context, in *MsgAddCovenantUnbondingSigs, opts ...grpc.CallOption) (*MsgAddCovenantUnbondingSigsResponse, error) { - out := new(MsgAddCovenantUnbondingSigsResponse) - err := c.cc.Invoke(ctx, "/babylon.btcstaking.v1.Msg/AddCovenantUnbondingSigs", in, out, opts...) +func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) { + out := new(MsgUpdateParamsResponse) + err := c.cc.Invoke(ctx, "/babylon.btcstaking.v1.Msg/UpdateParams", in, out, opts...) if err != nil { return nil, err } return out, nil } -func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) { - out := new(MsgUpdateParamsResponse) - err := c.cc.Invoke(ctx, "/babylon.btcstaking.v1.Msg/UpdateParams", in, out, opts...) +func (c *msgClient) BTCUndelegate(ctx context.Context, in *MsgBTCUndelegate, opts ...grpc.CallOption) (*MsgBTCUndelegateResponse, error) { + out := new(MsgBTCUndelegateResponse) + err := c.cc.Invoke(ctx, "/babylon.btcstaking.v1.Msg/BTCUndelegate", in, out, opts...) if err != nil { return nil, err } @@ -905,16 +812,12 @@ type MsgServer interface { CreateBTCValidator(context.Context, *MsgCreateBTCValidator) (*MsgCreateBTCValidatorResponse, error) // CreateBTCDelegation creates a new BTC delegation CreateBTCDelegation(context.Context, *MsgCreateBTCDelegation) (*MsgCreateBTCDelegationResponse, error) - // BtcUndelegate undelegates funds from exsitng btc delegation - BTCUndelegate(context.Context, *MsgBTCUndelegate) (*MsgBTCUndelegateResponse, error) - // AddCovenantSig handles a signature from covenant for slashing tx of staking tx for delegation - AddCovenantSig(context.Context, *MsgAddCovenantSig) (*MsgAddCovenantSigResponse, error) - // AddCovenantUnbondingSigs handles two signatures from covenant for: - // - unbonding tx submitted to babylon by staker - // - slashing tx corresponding to unbonding tx submitted to babylon by staker - AddCovenantUnbondingSigs(context.Context, *MsgAddCovenantUnbondingSigs) (*MsgAddCovenantUnbondingSigsResponse, error) + // AddCovenantSigs handles signatures from a covenant member + AddCovenantSigs(context.Context, *MsgAddCovenantSigs) (*MsgAddCovenantSigsResponse, error) // UpdateParams updates the btcstaking module parameters. UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) + // BTCUndelegate handles a signature on unbonding tx from its delegator + BTCUndelegate(context.Context, *MsgBTCUndelegate) (*MsgBTCUndelegateResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -927,18 +830,15 @@ func (*UnimplementedMsgServer) CreateBTCValidator(ctx context.Context, req *MsgC func (*UnimplementedMsgServer) CreateBTCDelegation(ctx context.Context, req *MsgCreateBTCDelegation) (*MsgCreateBTCDelegationResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateBTCDelegation not implemented") } -func (*UnimplementedMsgServer) BTCUndelegate(ctx context.Context, req *MsgBTCUndelegate) (*MsgBTCUndelegateResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method BTCUndelegate not implemented") -} -func (*UnimplementedMsgServer) AddCovenantSig(ctx context.Context, req *MsgAddCovenantSig) (*MsgAddCovenantSigResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method AddCovenantSig not implemented") -} -func (*UnimplementedMsgServer) AddCovenantUnbondingSigs(ctx context.Context, req *MsgAddCovenantUnbondingSigs) (*MsgAddCovenantUnbondingSigsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method AddCovenantUnbondingSigs not implemented") +func (*UnimplementedMsgServer) AddCovenantSigs(ctx context.Context, req *MsgAddCovenantSigs) (*MsgAddCovenantSigsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddCovenantSigs not implemented") } func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") } +func (*UnimplementedMsgServer) BTCUndelegate(ctx context.Context, req *MsgBTCUndelegate) (*MsgBTCUndelegateResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method BTCUndelegate not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -980,74 +880,56 @@ func _Msg_CreateBTCDelegation_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } -func _Msg_BTCUndelegate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgBTCUndelegate) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).BTCUndelegate(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/babylon.btcstaking.v1.Msg/BTCUndelegate", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).BTCUndelegate(ctx, req.(*MsgBTCUndelegate)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_AddCovenantSig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgAddCovenantSig) +func _Msg_AddCovenantSigs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgAddCovenantSigs) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(MsgServer).AddCovenantSig(ctx, in) + return srv.(MsgServer).AddCovenantSigs(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/babylon.btcstaking.v1.Msg/AddCovenantSig", + FullMethod: "/babylon.btcstaking.v1.Msg/AddCovenantSigs", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).AddCovenantSig(ctx, req.(*MsgAddCovenantSig)) + return srv.(MsgServer).AddCovenantSigs(ctx, req.(*MsgAddCovenantSigs)) } return interceptor(ctx, in, info, handler) } -func _Msg_AddCovenantUnbondingSigs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgAddCovenantUnbondingSigs) +func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateParams) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(MsgServer).AddCovenantUnbondingSigs(ctx, in) + return srv.(MsgServer).UpdateParams(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/babylon.btcstaking.v1.Msg/AddCovenantUnbondingSigs", + FullMethod: "/babylon.btcstaking.v1.Msg/UpdateParams", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).AddCovenantUnbondingSigs(ctx, req.(*MsgAddCovenantUnbondingSigs)) + return srv.(MsgServer).UpdateParams(ctx, req.(*MsgUpdateParams)) } return interceptor(ctx, in, info, handler) } -func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgUpdateParams) +func _Msg_BTCUndelegate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgBTCUndelegate) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(MsgServer).UpdateParams(ctx, in) + return srv.(MsgServer).BTCUndelegate(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/babylon.btcstaking.v1.Msg/UpdateParams", + FullMethod: "/babylon.btcstaking.v1.Msg/BTCUndelegate", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).UpdateParams(ctx, req.(*MsgUpdateParams)) + return srv.(MsgServer).BTCUndelegate(ctx, req.(*MsgBTCUndelegate)) } return interceptor(ctx, in, info, handler) } @@ -1065,21 +947,17 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ Handler: _Msg_CreateBTCDelegation_Handler, }, { - MethodName: "BTCUndelegate", - Handler: _Msg_BTCUndelegate_Handler, - }, - { - MethodName: "AddCovenantSig", - Handler: _Msg_AddCovenantSig_Handler, - }, - { - MethodName: "AddCovenantUnbondingSigs", - Handler: _Msg_AddCovenantUnbondingSigs_Handler, + MethodName: "AddCovenantSigs", + Handler: _Msg_AddCovenantSigs_Handler, }, { MethodName: "UpdateParams", Handler: _Msg_UpdateParams_Handler, }, + { + MethodName: "BTCUndelegate", + Handler: _Msg_BTCUndelegate_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "babylon/btcstaking/v1/tx.proto", @@ -1218,11 +1096,52 @@ func (m *MsgCreateBTCDelegation) MarshalToSizedBuffer(dAtA []byte) (int, error) _ = i var l int _ = l - if m.DelegatorSig != nil { + if m.DelegatorUnbondingSlashingSig != nil { { - size := m.DelegatorSig.Size() + size := m.DelegatorUnbondingSlashingSig.Size() i -= size - if _, err := m.DelegatorSig.MarshalTo(dAtA[i:]); err != nil { + if _, err := m.DelegatorUnbondingSlashingSig.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x7a + } + if m.UnbondingSlashingTx != nil { + { + size := m.UnbondingSlashingTx.Size() + i -= size + if _, err := m.UnbondingSlashingTx.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x72 + } + if m.UnbondingValue != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.UnbondingValue)) + i-- + dAtA[i] = 0x68 + } + if m.UnbondingTime != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.UnbondingTime)) + i-- + dAtA[i] = 0x60 + } + if len(m.UnbondingTx) > 0 { + i -= len(m.UnbondingTx) + copy(dAtA[i:], m.UnbondingTx) + i = encodeVarintTx(dAtA, i, uint64(len(m.UnbondingTx))) + i-- + dAtA[i] = 0x5a + } + if m.DelegatorSlashingSig != nil { + { + size := m.DelegatorSlashingSig.Size() + i -= size + if _, err := m.DelegatorSlashingSig.MarshalTo(dAtA[i:]); err != nil { return 0, err } i = encodeVarintTx(dAtA, i, uint64(size)) @@ -1347,7 +1266,7 @@ func (m *MsgCreateBTCDelegationResponse) MarshalToSizedBuffer(dAtA []byte) (int, return len(dAtA) - i, nil } -func (m *MsgBTCUndelegate) Marshal() (dAtA []byte, err error) { +func (m *MsgAddCovenantSigs) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1357,33 +1276,30 @@ func (m *MsgBTCUndelegate) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *MsgBTCUndelegate) MarshalTo(dAtA []byte) (int, error) { +func (m *MsgAddCovenantSigs) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *MsgBTCUndelegate) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *MsgAddCovenantSigs) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if m.DelegatorSlashingSig != nil { - { - size := m.DelegatorSlashingSig.Size() - i -= size - if _, err := m.DelegatorSlashingSig.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintTx(dAtA, i, uint64(size)) + if len(m.SlashingUnbondingTxSigs) > 0 { + for iNdEx := len(m.SlashingUnbondingTxSigs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.SlashingUnbondingTxSigs[iNdEx]) + copy(dAtA[i:], m.SlashingUnbondingTxSigs[iNdEx]) + i = encodeVarintTx(dAtA, i, uint64(len(m.SlashingUnbondingTxSigs[iNdEx]))) + i-- + dAtA[i] = 0x32 } - i-- - dAtA[i] = 0x32 } - if m.SlashingTx != nil { + if m.UnbondingTxSig != nil { { - size := m.SlashingTx.Size() + size := m.UnbondingTxSig.Size() i -= size - if _, err := m.SlashingTx.MarshalTo(dAtA[i:]); err != nil { + if _, err := m.UnbondingTxSig.MarshalTo(dAtA[i:]); err != nil { return 0, err } i = encodeVarintTx(dAtA, i, uint64(size)) @@ -1391,81 +1307,11 @@ func (m *MsgBTCUndelegate) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x2a } - if m.UnbondingValue != 0 { - i = encodeVarintTx(dAtA, i, uint64(m.UnbondingValue)) - i-- - dAtA[i] = 0x20 - } - if m.UnbondingTime != 0 { - i = encodeVarintTx(dAtA, i, uint64(m.UnbondingTime)) - i-- - dAtA[i] = 0x18 - } - if len(m.UnbondingTx) > 0 { - i -= len(m.UnbondingTx) - copy(dAtA[i:], m.UnbondingTx) - i = encodeVarintTx(dAtA, i, uint64(len(m.UnbondingTx))) - i-- - dAtA[i] = 0x12 - } - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgBTCUndelegateResponse) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *MsgBTCUndelegateResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgBTCUndelegateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgAddCovenantSig) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *MsgAddCovenantSig) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgAddCovenantSig) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Sigs) > 0 { - for iNdEx := len(m.Sigs) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.Sigs[iNdEx]) - copy(dAtA[i:], m.Sigs[iNdEx]) - i = encodeVarintTx(dAtA, i, uint64(len(m.Sigs[iNdEx]))) + if len(m.SlashingTxSigs) > 0 { + for iNdEx := len(m.SlashingTxSigs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.SlashingTxSigs[iNdEx]) + copy(dAtA[i:], m.SlashingTxSigs[iNdEx]) + i = encodeVarintTx(dAtA, i, uint64(len(m.SlashingTxSigs[iNdEx]))) i-- dAtA[i] = 0x22 } @@ -1499,7 +1345,7 @@ func (m *MsgAddCovenantSig) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *MsgAddCovenantSigResponse) Marshal() (dAtA []byte, err error) { +func (m *MsgAddCovenantSigsResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1509,12 +1355,12 @@ func (m *MsgAddCovenantSigResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *MsgAddCovenantSigResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *MsgAddCovenantSigsResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *MsgAddCovenantSigResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *MsgAddCovenantSigsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -1522,7 +1368,7 @@ func (m *MsgAddCovenantSigResponse) MarshalToSizedBuffer(dAtA []byte) (int, erro return len(dAtA) - i, nil } -func (m *MsgUpdateParams) Marshal() (dAtA []byte, err error) { +func (m *MsgBTCUndelegate) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1532,37 +1378,46 @@ func (m *MsgUpdateParams) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *MsgUpdateParams) MarshalTo(dAtA []byte) (int, error) { +func (m *MsgBTCUndelegate) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *MsgUpdateParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *MsgBTCUndelegate) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - { - size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err + if m.UnbondingTxSig != nil { + { + size := m.UnbondingTxSig.Size() + i -= size + if _, err := m.UnbondingTxSig.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1a } - i-- - dAtA[i] = 0x12 - if len(m.Authority) > 0 { - i -= len(m.Authority) - copy(dAtA[i:], m.Authority) - i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + if len(m.StakingTxHash) > 0 { + i -= len(m.StakingTxHash) + copy(dAtA[i:], m.StakingTxHash) + i = encodeVarintTx(dAtA, i, uint64(len(m.StakingTxHash))) + i-- + dAtA[i] = 0x12 + } + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) i-- dAtA[i] = 0xa } return len(dAtA) - i, nil } -func (m *MsgUpdateParamsResponse) Marshal() (dAtA []byte, err error) { +func (m *MsgBTCUndelegateResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1572,12 +1427,12 @@ func (m *MsgUpdateParamsResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *MsgUpdateParamsResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *MsgBTCUndelegateResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *MsgUpdateParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *MsgBTCUndelegateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -1585,7 +1440,7 @@ func (m *MsgUpdateParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) return len(dAtA) - i, nil } -func (m *MsgAddCovenantUnbondingSigs) Marshal() (dAtA []byte, err error) { +func (m *MsgUpdateParams) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1595,67 +1450,37 @@ func (m *MsgAddCovenantUnbondingSigs) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *MsgAddCovenantUnbondingSigs) MarshalTo(dAtA []byte) (int, error) { +func (m *MsgUpdateParams) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgAddCovenantUnbondingSigs) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.SlashingUnbondingTxSigs) > 0 { - for iNdEx := len(m.SlashingUnbondingTxSigs) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.SlashingUnbondingTxSigs[iNdEx]) - copy(dAtA[i:], m.SlashingUnbondingTxSigs[iNdEx]) - i = encodeVarintTx(dAtA, i, uint64(len(m.SlashingUnbondingTxSigs[iNdEx]))) - i-- - dAtA[i] = 0x2a - } - } - if m.UnbondingTxSig != nil { - { - size := m.UnbondingTxSig.Size() - i -= size - if _, err := m.UnbondingTxSig.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - } - if len(m.StakingTxHash) > 0 { - i -= len(m.StakingTxHash) - copy(dAtA[i:], m.StakingTxHash) - i = encodeVarintTx(dAtA, i, uint64(len(m.StakingTxHash))) - i-- - dAtA[i] = 0x1a - } - if m.Pk != nil { - { - size := m.Pk.Size() - i -= size - if _, err := m.Pk.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintTx(dAtA, i, uint64(size)) +} + +func (m *MsgUpdateParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } - i-- - dAtA[i] = 0x12 + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) } - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0x12 + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) i-- dAtA[i] = 0xa } return len(dAtA) - i, nil } -func (m *MsgAddCovenantUnbondingSigsResponse) Marshal() (dAtA []byte, err error) { +func (m *MsgUpdateParamsResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1665,12 +1490,12 @@ func (m *MsgAddCovenantUnbondingSigsResponse) Marshal() (dAtA []byte, err error) return dAtA[:n], nil } -func (m *MsgAddCovenantUnbondingSigsResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *MsgUpdateParamsResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *MsgAddCovenantUnbondingSigsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *MsgUpdateParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -1773,30 +1598,8 @@ func (m *MsgCreateBTCDelegation) Size() (n int) { l = m.SlashingTx.Size() n += 1 + l + sovTx(uint64(l)) } - if m.DelegatorSig != nil { - l = m.DelegatorSig.Size() - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgCreateBTCDelegationResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgBTCUndelegate) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Signer) - if l > 0 { + if m.DelegatorSlashingSig != nil { + l = m.DelegatorSlashingSig.Size() n += 1 + l + sovTx(uint64(l)) } l = len(m.UnbondingTx) @@ -1809,18 +1612,18 @@ func (m *MsgBTCUndelegate) Size() (n int) { if m.UnbondingValue != 0 { n += 1 + sovTx(uint64(m.UnbondingValue)) } - if m.SlashingTx != nil { - l = m.SlashingTx.Size() + if m.UnbondingSlashingTx != nil { + l = m.UnbondingSlashingTx.Size() n += 1 + l + sovTx(uint64(l)) } - if m.DelegatorSlashingSig != nil { - l = m.DelegatorSlashingSig.Size() + if m.DelegatorUnbondingSlashingSig != nil { + l = m.DelegatorUnbondingSlashingSig.Size() n += 1 + l + sovTx(uint64(l)) } return n } -func (m *MsgBTCUndelegateResponse) Size() (n int) { +func (m *MsgCreateBTCDelegationResponse) Size() (n int) { if m == nil { return 0 } @@ -1829,7 +1632,7 @@ func (m *MsgBTCUndelegateResponse) Size() (n int) { return n } -func (m *MsgAddCovenantSig) Size() (n int) { +func (m *MsgAddCovenantSigs) Size() (n int) { if m == nil { return 0 } @@ -1847,8 +1650,18 @@ func (m *MsgAddCovenantSig) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - if len(m.Sigs) > 0 { - for _, b := range m.Sigs { + if len(m.SlashingTxSigs) > 0 { + for _, b := range m.SlashingTxSigs { + l = len(b) + n += 1 + l + sovTx(uint64(l)) + } + } + if m.UnbondingTxSig != nil { + l = m.UnbondingTxSig.Size() + n += 1 + l + sovTx(uint64(l)) + } + if len(m.SlashingUnbondingTxSigs) > 0 { + for _, b := range m.SlashingUnbondingTxSigs { l = len(b) n += 1 + l + sovTx(uint64(l)) } @@ -1856,7 +1669,7 @@ func (m *MsgAddCovenantSig) Size() (n int) { return n } -func (m *MsgAddCovenantSigResponse) Size() (n int) { +func (m *MsgAddCovenantSigsResponse) Size() (n int) { if m == nil { return 0 } @@ -1865,22 +1678,28 @@ func (m *MsgAddCovenantSigResponse) Size() (n int) { return n } -func (m *MsgUpdateParams) Size() (n int) { +func (m *MsgBTCUndelegate) Size() (n int) { if m == nil { return 0 } var l int _ = l - l = len(m.Authority) + l = len(m.Signer) if l > 0 { n += 1 + l + sovTx(uint64(l)) } - l = m.Params.Size() - n += 1 + l + sovTx(uint64(l)) + l = len(m.StakingTxHash) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.UnbondingTxSig != nil { + l = m.UnbondingTxSig.Size() + n += 1 + l + sovTx(uint64(l)) + } return n } -func (m *MsgUpdateParamsResponse) Size() (n int) { +func (m *MsgBTCUndelegateResponse) Size() (n int) { if m == nil { return 0 } @@ -1889,38 +1708,22 @@ func (m *MsgUpdateParamsResponse) Size() (n int) { return n } -func (m *MsgAddCovenantUnbondingSigs) Size() (n int) { +func (m *MsgUpdateParams) Size() (n int) { if m == nil { return 0 } var l int _ = l - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - if m.Pk != nil { - l = m.Pk.Size() - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.StakingTxHash) + l = len(m.Authority) if l > 0 { n += 1 + l + sovTx(uint64(l)) } - if m.UnbondingTxSig != nil { - l = m.UnbondingTxSig.Size() - n += 1 + l + sovTx(uint64(l)) - } - if len(m.SlashingUnbondingTxSigs) > 0 { - for _, b := range m.SlashingUnbondingTxSigs { - l = len(b) - n += 1 + l + sovTx(uint64(l)) - } - } + l = m.Params.Size() + n += 1 + l + sovTx(uint64(l)) return n } -func (m *MsgAddCovenantUnbondingSigsResponse) Size() (n int) { +func (m *MsgUpdateParamsResponse) Size() (n int) { if m == nil { return 0 } @@ -2560,7 +2363,7 @@ func (m *MsgCreateBTCDelegation) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 10: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DelegatorSig", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field DelegatorSlashingSig", wireType) } var byteLen int for shift := uint(0); ; shift += 7 { @@ -2588,144 +2391,12 @@ func (m *MsgCreateBTCDelegation) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } var v github_com_babylonchain_babylon_types.BIP340Signature - m.DelegatorSig = &v - if err := m.DelegatorSig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *MsgCreateBTCDelegationResponse) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgCreateBTCDelegationResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgCreateBTCDelegationResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { + m.DelegatorSlashingSig = &v + if err := m.DelegatorSlashingSig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *MsgBTCUndelegate) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgBTCUndelegate: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgBTCUndelegate: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Signer = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 2: + case 11: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field UnbondingTx", wireType) } @@ -2759,7 +2430,7 @@ func (m *MsgBTCUndelegate) Unmarshal(dAtA []byte) error { m.UnbondingTx = []byte{} } iNdEx = postIndex - case 3: + case 12: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field UnbondingTime", wireType) } @@ -2778,7 +2449,7 @@ func (m *MsgBTCUndelegate) Unmarshal(dAtA []byte) error { break } } - case 4: + case 13: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field UnbondingValue", wireType) } @@ -2797,9 +2468,9 @@ func (m *MsgBTCUndelegate) Unmarshal(dAtA []byte) error { break } } - case 5: + case 14: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SlashingTx", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field UnbondingSlashingTx", wireType) } var byteLen int for shift := uint(0); ; shift += 7 { @@ -2827,14 +2498,14 @@ func (m *MsgBTCUndelegate) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } var v BTCSlashingTx - m.SlashingTx = &v - if err := m.SlashingTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.UnbondingSlashingTx = &v + if err := m.UnbondingSlashingTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 6: + case 15: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DelegatorSlashingSig", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field DelegatorUnbondingSlashingSig", wireType) } var byteLen int for shift := uint(0); ; shift += 7 { @@ -2862,8 +2533,8 @@ func (m *MsgBTCUndelegate) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } var v github_com_babylonchain_babylon_types.BIP340Signature - m.DelegatorSlashingSig = &v - if err := m.DelegatorSlashingSig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.DelegatorUnbondingSlashingSig = &v + if err := m.DelegatorUnbondingSlashingSig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -2888,7 +2559,7 @@ func (m *MsgBTCUndelegate) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgBTCUndelegateResponse) Unmarshal(dAtA []byte) error { +func (m *MsgCreateBTCDelegationResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2911,10 +2582,10 @@ func (m *MsgBTCUndelegateResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgBTCUndelegateResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgCreateBTCDelegationResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgBTCUndelegateResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgCreateBTCDelegationResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -2938,7 +2609,7 @@ func (m *MsgBTCUndelegateResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgAddCovenantSig) Unmarshal(dAtA []byte) error { +func (m *MsgAddCovenantSigs) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2961,10 +2632,10 @@ func (m *MsgAddCovenantSig) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgAddCovenantSig: wiretype end group for non-group") + return fmt.Errorf("proto: MsgAddCovenantSigs: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgAddCovenantSig: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgAddCovenantSigs: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -3068,7 +2739,74 @@ func (m *MsgAddCovenantSig) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Sigs", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field SlashingTxSigs", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SlashingTxSigs = append(m.SlashingTxSigs, make([]byte, postIndex-iNdEx)) + copy(m.SlashingTxSigs[len(m.SlashingTxSigs)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UnbondingTxSig", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var v github_com_babylonchain_babylon_types.BIP340Signature + m.UnbondingTxSig = &v + if err := m.UnbondingTxSig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SlashingUnbondingTxSigs", wireType) } var byteLen int for shift := uint(0); ; shift += 7 { @@ -3095,8 +2833,8 @@ func (m *MsgAddCovenantSig) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Sigs = append(m.Sigs, make([]byte, postIndex-iNdEx)) - copy(m.Sigs[len(m.Sigs)-1], dAtA[iNdEx:postIndex]) + m.SlashingUnbondingTxSigs = append(m.SlashingUnbondingTxSigs, make([]byte, postIndex-iNdEx)) + copy(m.SlashingUnbondingTxSigs[len(m.SlashingUnbondingTxSigs)-1], dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -3119,7 +2857,7 @@ func (m *MsgAddCovenantSig) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgAddCovenantSigResponse) Unmarshal(dAtA []byte) error { +func (m *MsgAddCovenantSigsResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -3142,10 +2880,10 @@ func (m *MsgAddCovenantSigResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgAddCovenantSigResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgAddCovenantSigsResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgAddCovenantSigResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgAddCovenantSigsResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -3169,7 +2907,7 @@ func (m *MsgAddCovenantSigResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { +func (m *MsgBTCUndelegate) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -3192,15 +2930,15 @@ func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgUpdateParams: wiretype end group for non-group") + return fmt.Errorf("proto: MsgBTCUndelegate: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUpdateParams: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgBTCUndelegate: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -3228,13 +2966,13 @@ func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Authority = string(dAtA[iNdEx:postIndex]) + m.Signer = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field StakingTxHash", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -3244,22 +2982,56 @@ func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthTx } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLengthTx } if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.StakingTxHash = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UnbondingTxSig", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var v github_com_babylonchain_babylon_types.BIP340Signature + m.UnbondingTxSig = &v + if err := m.UnbondingTxSig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -3284,7 +3056,7 @@ func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error { +func (m *MsgBTCUndelegateResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -3307,10 +3079,10 @@ func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgUpdateParamsResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgBTCUndelegateResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUpdateParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgBTCUndelegateResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -3334,7 +3106,7 @@ func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgAddCovenantUnbondingSigs) Unmarshal(dAtA []byte) error { +func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -3357,15 +3129,15 @@ func (m *MsgAddCovenantUnbondingSigs) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgAddCovenantUnbondingSigs: wiretype end group for non-group") + return fmt.Errorf("proto: MsgUpdateParams: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgAddCovenantUnbondingSigs: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgUpdateParams: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -3393,80 +3165,13 @@ func (m *MsgAddCovenantUnbondingSigs) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Signer = string(dAtA[iNdEx:postIndex]) + m.Authority = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Pk", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - var v github_com_babylonchain_babylon_types.BIP340PubKey - m.Pk = &v - if err := m.Pk.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field StakingTxHash", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.StakingTxHash = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field UnbondingTxSig", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) } - var byteLen int + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -3476,59 +3181,25 @@ func (m *MsgAddCovenantUnbondingSigs) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - byteLen |= int(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - if byteLen < 0 { + if msglen < 0 { return ErrInvalidLengthTx } - postIndex := iNdEx + byteLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthTx } if postIndex > l { return io.ErrUnexpectedEOF } - var v github_com_babylonchain_babylon_types.BIP340Signature - m.UnbondingTxSig = &v - if err := m.UnbondingTxSig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SlashingUnbondingTxSigs", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.SlashingUnbondingTxSigs = append(m.SlashingUnbondingTxSigs, make([]byte, postIndex-iNdEx)) - copy(m.SlashingUnbondingTxSigs[len(m.SlashingUnbondingTxSigs)-1], dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -3550,7 +3221,7 @@ func (m *MsgAddCovenantUnbondingSigs) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgAddCovenantUnbondingSigsResponse) Unmarshal(dAtA []byte) error { +func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -3573,10 +3244,10 @@ func (m *MsgAddCovenantUnbondingSigsResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgAddCovenantUnbondingSigsResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgUpdateParamsResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgAddCovenantUnbondingSigsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgUpdateParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: