Skip to content

Commit

Permalink
feat(adr-26): Separate inclusion proof from staking tx info (#111)
Browse files Browse the repository at this point in the history
[ref](https://github.com/babylonlabs-io/pm/blob/main/adr/adr-026-pre-approval-staking-flow.md).

This PR implements the separates the handling inclusion proof from btc
delegation. In particular, this PR:
1. introduces a new parameter `delegation_creation_base_gas_fee_sat`
which will be used to consume more gas when the inclusion proof is not
included in the delegation
2. separated the handling of inclusion proof into a different method
3. do not set start height and end height if the inclusion proof is not
included
4. do not emit voting power change even if the inclusion proof is not
included

A subsequent PR will introduce a new message to handle the inclusion
proof
  • Loading branch information
gitferry authored Oct 1, 2024
1 parent 39f8e56 commit c6b08f4
Show file tree
Hide file tree
Showing 20 changed files with 850 additions and 388 deletions.
3 changes: 2 additions & 1 deletion app/upgrades/signetlaunch/btcstaking_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ const BtcStakingParamStr = `
"min_unbonding_time_blocks": 0,
"unbonding_fee_sat": "1000",
"min_commission_rate": "0.03",
"max_active_finality_providers": 100
"max_active_finality_providers": 100,
"delegation_creation_base_gas_fee": 1000
}`
14 changes: 13 additions & 1 deletion proto/babylon/btcstaking/v1/btcstaking.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "gogoproto/gogo.proto";
import "cosmos_proto/cosmos.proto";
import "cosmos/staking/v1beta1/staking.proto";
import "babylon/btcstaking/v1/pop.proto";
import "babylon/btccheckpoint/v1/btccheckpoint.proto";

option go_package = "github.com/babylonlabs-io/babylon/x/btcstaking/types";

Expand Down Expand Up @@ -195,4 +196,15 @@ message SelectiveSlashingEvidence {
// the covenant adaptor/Schnorr signature pair. It is the consequence
// of selective slashing.
bytes recovered_fp_btc_sk = 3;
}
}

// InclusionProof proves the existence of tx on BTC blockchain
// including
// - the position of the tx on BTC blockchain
// - the Merkle proof that this tx is on the above position
message InclusionProof {
// key is the position (txIdx, blockHash) of this tx on BTC blockchain
babylon.btccheckpoint.v1.TransactionKey key = 1;
// proof is the Merkle proof that this tx is included in the position in `key`
bytes proof = 2;
}
2 changes: 2 additions & 0 deletions proto/babylon/btcstaking/v1/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ message Params {
];
// max_active_finality_providers is the maximum number of active finality providers in the BTC staking protocol
uint32 max_active_finality_providers = 13;
// base gas fee for delegation creation
uint64 delegation_creation_base_gas_fee = 14;
}

// StoredParams attach information about the version of stored parameters
Expand Down
22 changes: 12 additions & 10 deletions proto/babylon/btcstaking/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import "gogoproto/gogo.proto";
import "cosmos_proto/cosmos.proto";
import "cosmos/msg/v1/msg.proto";
import "babylon/btcstaking/v1/params.proto";
import "babylon/btccheckpoint/v1/btccheckpoint.proto";
import "cosmos/staking/v1beta1/staking.proto";
import "babylon/btcstaking/v1/pop.proto";
import "babylon/btcstaking/v1/btcstaking.proto";

option go_package = "github.com/babylonlabs-io/babylon/x/btcstaking/types";

Expand Down Expand Up @@ -90,34 +90,36 @@ message MsgCreateBTCDelegation {
uint32 staking_time = 5;
// staking_value is the amount of satoshis locked in staking output
int64 staking_value = 6;
// staking_tx is the staking tx along with the merkle proof of inclusion in btc block
babylon.btccheckpoint.v1.TransactionInfo staking_tx = 7;
// staking_tx is a bitcoin staking transaction i.e transaction that locks funds
bytes staking_tx = 7 ;
// staking_tx_inclusion_proof is the inclusion proof of the staking tx in BTC chain
InclusionProof staking_tx_inclusion_proof = 8;
// slashing_tx is the slashing tx
// Note that the tx itself does not contain signatures, which are off-chain.
bytes slashing_tx = 8 [ (gogoproto.customtype) = "BTCSlashingTx" ];
bytes slashing_tx = 9 [ (gogoproto.customtype) = "BTCSlashingTx" ];
// 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 finality provider in
// order to be spendable.
bytes delegator_slashing_sig = 9 [ (gogoproto.customtype) = "github.com/babylonlabs-io/babylon/types.BIP340Signature" ];
bytes delegator_slashing_sig = 10 [ (gogoproto.customtype) = "github.com/babylonlabs-io/babylon/types.BIP340Signature" ];
// unbonding_time is the time lock used when funds are being unbonded. It is be used in:
// - unbonding transaction, time lock spending path
// - staking slashing transaction, change output
// - unbonding slashing transaction, change output
// It must be smaller than math.MaxUInt16 and larger that max(MinUnbondingTime, CheckpointFinalizationTimeout)
uint32 unbonding_time = 10;
uint32 unbonding_time = 11;
// fields related to unbonding transaction
// unbonding_tx is a bitcoin unbonding transaction i.e transaction that spends
// staking output and sends it to the unbonding output
bytes unbonding_tx = 11;
bytes unbonding_tx = 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 = 12;
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 unbonding_slashing_tx = 13 [ (gogoproto.customtype) = "BTCSlashingTx" ];
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 = 14 [ (gogoproto.customtype) = "github.com/babylonlabs-io/babylon/types.BIP340Signature" ];
bytes delegator_unbonding_slashing_sig = 15 [ (gogoproto.customtype) = "github.com/babylonlabs-io/babylon/types.BIP340Signature" ];
}
// MsgCreateBTCDelegationResponse is the response for MsgCreateBTCDelegation
message MsgCreateBTCDelegationResponse {}
Expand Down
28 changes: 16 additions & 12 deletions test/e2e/btc_staking_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"github.com/babylonlabs-io/babylon/test/e2e/initialization"
"github.com/babylonlabs-io/babylon/testutil/datagen"
bbn "github.com/babylonlabs-io/babylon/types"
btcctypes "github.com/babylonlabs-io/babylon/x/btccheckpoint/types"
bstypes "github.com/babylonlabs-io/babylon/x/btcstaking/types"
ckpttypes "github.com/babylonlabs-io/babylon/x/checkpointing/types"
ftypes "github.com/babylonlabs-io/babylon/x/finality/types"
Expand Down Expand Up @@ -100,7 +99,7 @@ func (s *BTCStakingTestSuite) Test1CreateFinalityProviderAndDelegation() {

// generate staking tx and slashing tx
stakingTimeBlocks := uint16(math.MaxUint16)
testStakingInfo, stakingTxInfo, testUnbondingInfo, delegatorSig := s.BTCStakingUnbondSlashInfo(nonValidatorNode, params, stakingTimeBlocks, cacheFP)
testStakingInfo, stakingTx, inclusionProof, testUnbondingInfo, delegatorSig := s.BTCStakingUnbondSlashInfo(nonValidatorNode, params, stakingTimeBlocks, cacheFP)

delUnbondingSlashingSig, err := testUnbondingInfo.GenDelSlashingTxSig(delBTCSK)
s.NoError(err)
Expand All @@ -109,7 +108,8 @@ func (s *BTCStakingTestSuite) Test1CreateFinalityProviderAndDelegation() {
nonValidatorNode.CreateBTCDelegation(
bbn.NewBIP340PubKeyFromBTCPK(delBTCPK),
pop,
stakingTxInfo,
stakingTx,
inclusionProof,
cacheFP.BtcPk,
stakingTimeBlocks,
btcutil.Amount(stakingValue),
Expand Down Expand Up @@ -501,7 +501,7 @@ func (s *BTCStakingTestSuite) Test6MultisigBTCDelegation() {

// generate staking tx and slashing tx
stakingTimeBlocks := uint16(math.MaxUint16)
testStakingInfo, stakingTxInfo, testUnbondingInfo, delegatorSig := s.BTCStakingUnbondSlashInfo(nonValidatorNode, params, stakingTimeBlocks, cacheFP)
testStakingInfo, stakingTx, inclusionProof, testUnbondingInfo, delegatorSig := s.BTCStakingUnbondSlashInfo(nonValidatorNode, params, stakingTimeBlocks, cacheFP)

delUnbondingSlashingSig, err := testUnbondingInfo.GenDelSlashingTxSig(delBTCSK)
s.NoError(err)
Expand All @@ -510,7 +510,8 @@ func (s *BTCStakingTestSuite) Test6MultisigBTCDelegation() {
jsonTx := nonValidatorNode.CreateBTCDelegation(
bbn.NewBIP340PubKeyFromBTCPK(delBTCPK),
pop,
stakingTxInfo,
stakingTx,
inclusionProof,
cacheFP.BtcPk,
stakingTimeBlocks,
btcutil.Amount(stakingValue),
Expand Down Expand Up @@ -571,7 +572,7 @@ func (s *BTCStakingTestSuite) Test7BTCDelegationFeeGrant() {

// generate staking tx and slashing tx
stakingTimeBlocks := uint16(math.MaxUint16) - 5
testStakingInfo, stakingTxInfo, testUnbondingInfo, delegatorSig := s.BTCStakingUnbondSlashInfo(nonValidatorNode, btcStkParams, stakingTimeBlocks, cacheFP)
testStakingInfo, stakingTx, inclusionProof, testUnbondingInfo, delegatorSig := s.BTCStakingUnbondSlashInfo(nonValidatorNode, btcStkParams, stakingTimeBlocks, cacheFP)

delUnbondingSlashingSig, err := testUnbondingInfo.GenDelSlashingTxSig(delBTCSK)
s.NoError(err)
Expand All @@ -590,7 +591,8 @@ func (s *BTCStakingTestSuite) Test7BTCDelegationFeeGrant() {
nonValidatorNode.CreateBTCDelegation(
bbn.NewBIP340PubKeyFromBTCPK(delBTCPK),
pop,
stakingTxInfo,
stakingTx,
inclusionProof,
cacheFP.BtcPk,
stakingTimeBlocks,
btcutil.Amount(stakingValue),
Expand Down Expand Up @@ -662,7 +664,7 @@ func (s *BTCStakingTestSuite) Test8BTCDelegationFeeGrantTyped() {

// generate staking tx and slashing tx
stakingTimeBlocks := uint16(math.MaxUint16) - 2
testStakingInfo, stakingTxInfo, testUnbondingInfo, delegatorSig := s.BTCStakingUnbondSlashInfo(node, btcStkParams, stakingTimeBlocks, cacheFP)
testStakingInfo, stakingTx, inclusionProof, testUnbondingInfo, delegatorSig := s.BTCStakingUnbondSlashInfo(node, btcStkParams, stakingTimeBlocks, cacheFP)

delUnbondingSlashingSig, err := testUnbondingInfo.GenDelSlashingTxSig(delBTCSK)
s.NoError(err)
Expand Down Expand Up @@ -724,7 +726,8 @@ func (s *BTCStakingTestSuite) Test8BTCDelegationFeeGrantTyped() {
node.CreateBTCDelegation(
bbn.NewBIP340PubKeyFromBTCPK(delBTCPK),
pop,
stakingTxInfo,
stakingTx,
inclusionProof,
cacheFP.BtcPk,
stakingTimeBlocks,
btcutil.Amount(stakingValue),
Expand Down Expand Up @@ -898,7 +901,8 @@ func (s *BTCStakingTestSuite) BTCStakingUnbondSlashInfo(
fp *bstypes.FinalityProvider,
) (
testStakingInfo *datagen.TestStakingSlashingInfo,
stakingTxInfo *btcctypes.TransactionInfo,
stakingTx []byte,
txInclusionProof *bstypes.InclusionProof,
testUnbondingInfo *datagen.TestUnbondingSlashingInfo,
delegatorSig *bbn.BIP340Signature,
) {
Expand Down Expand Up @@ -935,7 +939,7 @@ func (s *BTCStakingTestSuite) BTCStakingUnbondSlashInfo(
for i := 0; i < initialization.BabylonBtcConfirmationPeriod; i++ {
node.InsertNewEmptyBtcHeader(r)
}
stakingTxInfo = btcctypes.NewTransactionInfoFromSpvProof(blockWithStakingTx.SpvProof)
inclusionProof := bstypes.NewInclusionProofFromSpvProof(blockWithStakingTx.SpvProof)

// generate BTC undelegation stuff
stkTxHash := testStakingInfo.StakingTx.TxHash()
Expand Down Expand Up @@ -967,5 +971,5 @@ func (s *BTCStakingTestSuite) BTCStakingUnbondSlashInfo(
)
s.NoError(err)

return testStakingInfo, stakingTxInfo, testUnbondingInfo, delegatorSig
return testStakingInfo, blockWithStakingTx.SpvProof.BtcTransaction, inclusionProof, testUnbondingInfo, delegatorSig
}
11 changes: 7 additions & 4 deletions test/e2e/configurer/chain/commands_btcstaking.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
asig "github.com/babylonlabs-io/babylon/crypto/schnorr-adaptor-signature"
"github.com/babylonlabs-io/babylon/test/e2e/containers"
bbn "github.com/babylonlabs-io/babylon/types"
btcctypes "github.com/babylonlabs-io/babylon/x/btccheckpoint/types"
bstypes "github.com/babylonlabs-io/babylon/x/btcstaking/types"
)

Expand All @@ -45,7 +44,8 @@ func (n *NodeConfig) CreateFinalityProvider(walletAddrOrName string, btcPK *bbn.
func (n *NodeConfig) CreateBTCDelegation(
btcPk *bbn.BIP340PubKey,
pop *bstypes.ProofOfPossessionBTC,
stakingTxInfo *btcctypes.TransactionInfo,
stakingTx []byte,
inclusionProof *bstypes.InclusionProof,
fpPK *bbn.BIP340PubKey,
stakingTimeBlocks uint16,
stakingValue btcutil.Amount,
Expand All @@ -69,7 +69,10 @@ func (n *NodeConfig) CreateBTCDelegation(
require.NoError(n.t, err)

// get staking tx info hex
stakingTxInfoHex, err := stakingTxInfo.ToHexStr()
stakingTxHex := hex.EncodeToString(stakingTx)

// get inclusion proof hex
inclusionProofHex, err := inclusionProof.MarshalHex()
require.NoError(n.t, err)

fpPKHex := fpPK.MarshalHex()
Expand All @@ -93,7 +96,7 @@ func (n *NodeConfig) CreateBTCDelegation(

cmd := []string{
"babylond", "tx", "btcstaking", "create-btc-delegation",
btcPkHex, popHex, stakingTxInfoHex, fpPKHex, stakingTimeString, stakingValueString, slashingTxHex, delegatorSigHex, unbondingTxHex, unbondingSlashingTxHex, unbondingTimeStr, unbondingValueStr, delUnbondingSlashingSigHex,
btcPkHex, popHex, stakingTxHex, inclusionProofHex, fpPKHex, stakingTimeString, stakingValueString, slashingTxHex, delegatorSigHex, unbondingTxHex, unbondingSlashingTxHex, unbondingTimeStr, unbondingValueStr, delUnbondingSlashingSigHex,
fmt.Sprintf("--from=%s", fromWalletName), containers.FlagHome, flagKeyringTest,
n.FlagChainID(), "--log_format=json",
}
Expand Down
5 changes: 3 additions & 2 deletions x/btccheckpoint/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import (
"fmt"
"math/big"

"github.com/babylonlabs-io/babylon/btctxformatter"
"github.com/babylonlabs-io/babylon/types"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/babylonlabs-io/babylon/btctxformatter"
"github.com/babylonlabs-io/babylon/types"
)

// RawCheckpointSubmission Semantically valid checkpoint submission with:
Expand Down
41 changes: 25 additions & 16 deletions x/btcstaking/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (

asig "github.com/babylonlabs-io/babylon/crypto/schnorr-adaptor-signature"
bbn "github.com/babylonlabs-io/babylon/types"
btcctypes "github.com/babylonlabs-io/babylon/x/btccheckpoint/types"
"github.com/babylonlabs-io/babylon/x/btcstaking/types"
)

Expand Down Expand Up @@ -190,8 +189,8 @@ func NewEditFinalityProviderCmd() *cobra.Command {

func NewCreateBTCDelegationCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create-btc-delegation [btc_pk] [pop_hex] [staking_tx_info] [fp_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(13),
Use: "create-btc-delegation [btc_pk] [pop_hex] [staking_tx] [inclusion_proof] [fp_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
Expand All @@ -215,67 +214,76 @@ func NewCreateBTCDelegationCmd() *cobra.Command {
return err
}

// get staking tx info
stakingTxInfo, err := btcctypes.NewTransactionInfoFromHex(args[2])
// get staking tx bytes
stakingTx, err := hex.DecodeString(args[2])
if err != nil {
return err
}

var inclusionProof *types.InclusionProof
// inclusionProof can be nil if empty argument is provided
if len(args[3]) > 0 {
inclusionProof, err = types.NewInclusionProofFromHex(args[3])
if err != nil {
return err
}
}

// TODO: Support multiple finality providers
// get finality provider PK
fpPK, err := bbn.NewBIP340PubKeyFromHex(args[3])
fpPK, err := bbn.NewBIP340PubKeyFromHex(args[4])
if err != nil {
return err
}

// get staking time
stakingTime, err := parseLockTime(args[4])
stakingTime, err := parseLockTime(args[5])
if err != nil {
return err
}

stakingValue, err := parseBtcAmount(args[5])
stakingValue, err := parseBtcAmount(args[6])
if err != nil {
return err
}

// get slashing tx
slashingTx, err := types.NewBTCSlashingTxFromHex(args[6])
slashingTx, err := types.NewBTCSlashingTxFromHex(args[7])
if err != nil {
return err
}

// get delegator sig on slashing tx
delegatorSlashingSig, err := bbn.NewBIP340SignatureFromHex(args[7])
delegatorSlashingSig, err := bbn.NewBIP340SignatureFromHex(args[8])
if err != nil {
return err
}

// get unbonding tx
_, unbondingTxBytes, err := bbn.NewBTCTxFromHex(args[8])
_, unbondingTxBytes, err := bbn.NewBTCTxFromHex(args[9])
if err != nil {
return err
}

// get unbonding slashing tx
unbondingSlashingTx, err := types.NewBTCSlashingTxFromHex(args[9])
unbondingSlashingTx, err := types.NewBTCSlashingTxFromHex(args[10])
if err != nil {
return err
}

// get staking time
unbondingTime, err := parseLockTime(args[10])
unbondingTime, err := parseLockTime(args[11])
if err != nil {
return err
}

unbondingValue, err := parseBtcAmount(args[11])
unbondingValue, err := parseBtcAmount(args[12])
if err != nil {
return err
}

// get delegator sig on unbonding slashing tx
delegatorUnbondingSlashingSig, err := bbn.NewBIP340SignatureFromHex(args[12])
delegatorUnbondingSlashingSig, err := bbn.NewBIP340SignatureFromHex(args[13])
if err != nil {
return err
}
Expand All @@ -287,7 +295,8 @@ func NewCreateBTCDelegationCmd() *cobra.Command {
Pop: pop,
StakingTime: uint32(stakingTime),
StakingValue: int64(stakingValue),
StakingTx: stakingTxInfo,
StakingTx: stakingTx,
StakingTxInclusionProof: inclusionProof,
SlashingTx: slashingTx,
DelegatorSlashingSig: delegatorSlashingSig,
UnbondingTx: unbondingTxBytes,
Expand Down
Loading

0 comments on commit c6b08f4

Please sign in to comment.