Skip to content

Commit

Permalink
Unbonding tx signatures (#69)
Browse files Browse the repository at this point in the history
- add handling of jury and validator signatures for unbonding transaction.
  • Loading branch information
KonradStaniec authored Sep 5, 2023
1 parent 918d8fe commit 1e8b5fa
Show file tree
Hide file tree
Showing 14 changed files with 2,542 additions and 584 deletions.
6 changes: 5 additions & 1 deletion proto/babylon/btcstaking/v1/btcstaking.proto
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,11 @@ enum BTCDelegationStatus {
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 jury.
// Delegation in this state already lost its voting power.
UNBONDING = 2;
// EXPIRED defines a delegation that has expired
EXPIRED = 2;
EXPIRED = 3;
}

49 changes: 48 additions & 1 deletion proto/babylon/btcstaking/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@ service Msg {
rpc CreateBTCDelegation(MsgCreateBTCDelegation) returns (MsgCreateBTCDelegationResponse);
// BtcUndelegate undelegates funds from exsitng btc delegation
rpc BTCUndelegate(MsgBTCUndelegate) returns (MsgBTCUndelegateResponse);
// AddJurySig handles a signature from jury
// AddJurySig handles a signature from jury for slashing tx of staking tx for delegation
rpc AddJurySig(MsgAddJurySig) returns (MsgAddJurySigResponse);
// AddJuryUnbondingSigs handles two signatures from jury for:
// - unbonding tx submitted to babylon by staker
// - slashing tx corresponding to unbodning tx submitted to babylon by staker
rpc AddJuryUnbondingSigs(MsgAddJuryUnbondingSigs) returns (MsgAddJuryUnbondingSigsResponse);
// AddValidatorUnbondingSig handles a signature from validator for unbonding tx submitted to babylon by staker
rpc AddValidatorUnbondingSig(MsgAddValidatorUnbondingSig) returns (MsgAddValidatorUnbondingSigResponse);
// UpdateParams updates the btcstaking module parameters.
rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse);
}
Expand Down Expand Up @@ -126,3 +132,44 @@ message MsgUpdateParams {
// MsgUpdateParamsResponse is the response to the MsgUpdateParams message.
message MsgUpdateParamsResponse {}

// MsgAddJuryUnbondingSigs is the message for handling a signature from jury
message MsgAddJuryUnbondingSigs {
string signer = 1;
// val_pk is the Bitcoin secp256k1 PK of the BTC validator
// the PK follows encoding in BIP-340 spec
bytes val_pk = 2 [ (gogoproto.customtype) = "github.com/babylonchain/babylon/types.BIP340PubKey" ];
// del_pk is the Bitcoin secp256k1 PK of the BTC delegation
// the PK follows encoding in BIP-340 spec
bytes del_pk = 3 [ (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 = 4;
// unbonding_tx_sig is the signature of the jury 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_sig is the signature of the jury on slashing tx corresponding to unbodning tx submitted to babylon
// the signature follows encoding in BIP-340 spec
bytes slashing_unbonding_tx_sig = 6 [ (gogoproto.customtype) = "github.com/babylonchain/babylon/types.BIP340Signature" ];

}
// MsgAddJurySigResponse is the response for MsgAddJurySig
message MsgAddJuryUnbondingSigsResponse {}

// MsgAddValidatorUnbondingSig is the message for unbodning tx submitted to babylon by staker
message MsgAddValidatorUnbondingSig {
string signer = 1;
// val_pk is the Bitcoin secp256k1 PK of the BTC validator
// the PK follows encoding in BIP-340 spec
bytes val_pk = 2 [ (gogoproto.customtype) = "github.com/babylonchain/babylon/types.BIP340PubKey" ];
// del_pk is the Bitcoin secp256k1 PK of the BTC delegation
// the PK follows encoding in BIP-340 spec
bytes del_pk = 3 [ (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 = 4;
// unbonding_tx_sig is the signature of validator for unbodning tx submitted to babylon by staker
// the signature follows encoding in BIP-340 spec
bytes unbonding_tx_sig = 5 [ (gogoproto.customtype) = "github.com/babylonchain/babylon/types.BIP340Signature" ];
}
// MsgAddJurySigResponse is the response for MsgAddJurySig
message MsgAddValidatorUnbondingSigResponse {}
87 changes: 87 additions & 0 deletions test/e2e/btc_staking_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,3 +343,90 @@ func (s *BTCStakingTestSuite) Test4SubmitStakerUnbonding() {
delegation := valDelegations[0].Dels[0]
s.NotNil(delegation.BtcUndelegation)
}

// Test5SubmitStakerUnbonding is an end-to-end test for jury and validator submitting signatures
// for unbonding transaction
func (s *BTCStakingTestSuite) Test5SubmitUnbondingSignatures() {
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.Nil(delegation.BtcUndelegation.ValidatorUnbondingSig)
s.Nil(delegation.BtcUndelegation.JuryUnbondingSig)
s.Nil(delegation.BtcUndelegation.JurySlashingSig)

// First sent validator signature
stakingTxMsg, err := delegation.StakingTx.ToMsgTx()
s.NoError(err)
stakingTxHash := delegation.StakingTx.MustGetTxHash()

validatorUnbondingSig, err := delegation.BtcUndelegation.UnbondingTx.Sign(
stakingTxMsg,
delegation.StakingTx.Script,
valSK,
net,
)
s.NoError(err)

nonValidatorNode.AddValidatorUnbondingSig(btcVal.BtcPk, bbn.NewBIP340PubKeyFromBTCPK(delBTCPK), stakingTxHash, validatorUnbondingSig)
nonValidatorNode.WaitForNextBlock()

allDelegationsValSig := nonValidatorNode.QueryBTCValidatorDelegations(btcVal.BtcPk.MarshalHex())
s.Len(allDelegationsValSig, 1)
delegationWithValSig := allDelegationsValSig[0].Dels[0]
s.NotNil(delegationWithValSig.BtcUndelegation)
s.NotNil(delegationWithValSig.BtcUndelegation.ValidatorUnbondingSig)

btcTip, err := nonValidatorNode.QueryTip()
s.NoError(err)
s.Equal(
bstypes.BTCDelegationStatus_UNBONDING,
delegationWithValSig.GetStatus(btcTip.Height, initialization.BabylonBtcFinalizationPeriod),
)

// Next send jury signatures
juryUnbondingSig, err := delegation.BtcUndelegation.UnbondingTx.Sign(
stakingTxMsg,
delegation.StakingTx.Script,
jurySK,
net,
)
s.NoError(err)

unbondingTxMsg, err := delegation.BtcUndelegation.UnbondingTx.ToMsgTx()
s.NoError(err)
jurySlashingSig, err := delegation.BtcUndelegation.SlashingTx.Sign(
unbondingTxMsg,
delegation.BtcUndelegation.UnbondingTx.Script,
jurySK,
net,
)
s.NoError(err)
nonValidatorNode.AddJuryUnbondingSigs(btcVal.BtcPk, bbn.NewBIP340PubKeyFromBTCPK(delBTCPK), stakingTxHash, juryUnbondingSig, jurySlashingSig)
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.NotNil(delegationWithSigs.BtcUndelegation.ValidatorUnbondingSig)
s.NotNil(delegationWithSigs.BtcUndelegation.JuryUnbondingSig)
s.NotNil(delegationWithSigs.BtcUndelegation.JurySlashingSig)
btcTip, err = nonValidatorNode.QueryTip()
s.NoError(err)
s.Equal(
bstypes.BTCDelegationStatus_EXPIRED,
delegationWithSigs.GetStatus(btcTip.Height, initialization.BabylonBtcFinalizationPeriod),
)
}
32 changes: 32 additions & 0 deletions test/e2e/configurer/chain/commands_btcstaking.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,35 @@ func (n *NodeConfig) CreateBTCUndelegation(unbondingTx *bstypes.BabylonBTCTaproo
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) AddJuryUnbondingSigs(
valPK *bbn.BIP340PubKey,
delPK *bbn.BIP340PubKey,
stakingTxHash string,
unbondingTxSig *bbn.BIP340Signature,
slashUnbondingTxSig *bbn.BIP340Signature) {
n.LogActionF("adding validator signature")

valPKHex := valPK.MarshalHex()
delPKHex := delPK.MarshalHex()
unbondingTxSigHex := unbondingTxSig.ToHexStr()
slashUnbondingTxSigHex := slashUnbondingTxSig.ToHexStr()

cmd := []string{"babylond", "tx", "btcstaking", "add-jury-unbonding-sigs", valPKHex, delPKHex, stakingTxHash, unbondingTxSigHex, slashUnbondingTxSigHex, "--from=val"}
_, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd)
require.NoError(n.t, err)
n.LogActionF("successfully added jury unbonding sigs")
}
107 changes: 107 additions & 0 deletions x/btcstaking/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ func GetTxCmd() *cobra.Command {
NewCreateBTCDelegationCmd(),
NewAddJurySigCmd(),
NewCreateBTCUndelegationCmd(),
NewAddJuryUnbondingSigsCmd(),
NewAddValidatorUnbondingSigCmd(),
)

return cmd
Expand Down Expand Up @@ -302,3 +304,108 @@ func NewCreateBTCUndelegationCmd() *cobra.Command {

return cmd
}

func NewAddJuryUnbondingSigsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "add-jury-unbonding-sigs [val_pk] [del_pk] [staking_tx_hash] [unbonding_tx_sg] [slashing_unbonding_tx_sig]",
Args: cobra.ExactArgs(5),
Short: "Add jury signatures for unbonding tx and slash unbonding tx",
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

// get validator PK
valPK, err := bbn.NewBIP340PubKeyFromHex(args[0])
if err != nil {
return err
}

// get delegator PK
delPK, err := bbn.NewBIP340PubKeyFromHex(args[1])
if err != nil {
return err
}

// get staking tx hash
stakingTxHash := args[2]

// get jury sigature for unbonding tx
unbondingSig, err := bbn.NewBIP340SignatureFromHex(args[3])
if err != nil {
return err
}

// get jury sigature for slash unbonding tx
slashUnbondingSig, err := bbn.NewBIP340SignatureFromHex(args[4])
if err != nil {
return err
}

msg := types.MsgAddJuryUnbondingSigs{
Signer: clientCtx.FromAddress.String(),
ValPk: valPK,
DelPk: delPK,
StakingTxHash: stakingTxHash,
UnbondingTxSig: unbondingSig,
SlashingUnbondingTxSig: slashUnbondingSig,
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}

func NewAddValidatorUnbondingSigCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "add-validator-unbonding-sig [val_pk] [del_pk] [staking_tx_hash] [sig]",
Args: cobra.ExactArgs(4),
Short: "Add a validator signature for unbonding tx",
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

// get validator PK
valPK, err := bbn.NewBIP340PubKeyFromHex(args[0])
if err != nil {
return err
}

// get delegator PK
delPK, err := bbn.NewBIP340PubKeyFromHex(args[1])
if err != nil {
return err
}

// get staking tx hash
stakingTxHash := args[2]

// get validator sigature
sig, err := bbn.NewBIP340SignatureFromHex(args[3])
if err != nil {
return err
}

msg := types.MsgAddValidatorUnbondingSig{
Signer: clientCtx.FromAddress.String(),
ValPk: valPK,
DelPk: delPK,
StakingTxHash: stakingTxHash,
UnbondingTxSig: sig,
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}
Loading

0 comments on commit 1e8b5fa

Please sign in to comment.