Skip to content

Commit

Permalink
feat: Implement ADR-26 - pre-approval flow (#117)
Browse files Browse the repository at this point in the history
Initial implementation of pre-approval flow following -
https://github.com/babylonlabs-io/pm/blob/main/adr/adr-026-pre-approval-staking-flow.md
---------

Co-authored-by: Cirrus Gai <[email protected]>
  • Loading branch information
KonradStaniec and gitferry authored Oct 2, 2024
1 parent 6b5e633 commit 04e12eb
Show file tree
Hide file tree
Showing 31 changed files with 2,409 additions and 582 deletions.
22 changes: 22 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,28 @@ jobs:
run: |
make test-e2e-cache-btc-staking
e2e-run-btc-staking-pre-approval:
needs: [e2e-docker-build-babylon]
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download babylon artifact
uses: actions/download-artifact@v4
with:
name: babylond-${{ github.sha }}
path: /tmp
- name: Docker load babylond
run: |
docker load < /tmp/docker-babylond.tar.gz
- name: Cache Go
uses: actions/setup-go@v5
with:
go-version: 1.21
- name: Run e2e TestBTCStakingPreApprovalTestSuite
run: |
make test-e2e-cache-btc-staking-pre-approval
e2e-run-upgrade-signet:
needs: [e2e-docker-build-babylon, e2e-docker-build-babylon-before-upgrade, e2e-docker-build-e2e-init-chain]
runs-on: ubuntu-22.04
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ enable in-protocol minimum gas price
to upgrade handler and rename `signet-launch` to `v1`
* [#55](https://github.com/babylonlabs-io/babylon/pull/55) Remove `x/zoneconcierge`
module
* [#117](https://github.com/babylonlabs-io/babylon/pull/117) Add support for
pre-approval flow (ADR-026)

### Bug fixes

Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ test-e2e-cache-btc-timestamping-phase-2-rly:
test-e2e-cache-btc-staking:
go test -run TestBTCStakingTestSuite -mod=readonly -timeout=60m -v $(PACKAGES_E2E) --tags=e2e

test-e2e-cache-btc-staking-pre-approval:
go test -run TestBTCStakingPreApprovalTestSuite -mod=readonly -timeout=60m -v $(PACKAGES_E2E) --tags=e2e

test-e2e-cache-upgrade-signet:
go test -run TestSoftwareUpgradeSignetLaunchTestSuite -mod=readonly -timeout=60m -v $(PACKAGES_E2E) --tags=e2e

Expand Down
3 changes: 2 additions & 1 deletion app/upgrades/v1/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
}`
65 changes: 44 additions & 21 deletions 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 @@ -72,38 +73,40 @@ message BTCDelegation {
// If there is more than 1 PKs, then this means the delegation is restaked
// to multiple finality providers
repeated bytes fp_btc_pk_list = 4 [ (gogoproto.customtype) = "github.com/babylonlabs-io/babylon/types.BIP340PubKey" ];
// staking_time is the number of blocks for which the delegation is locked on BTC chain
uint32 staking_time = 5;
// start_height is the start BTC height of the BTC delegation
// it is the start BTC height of the timelock
uint64 start_height = 5;
uint64 start_height = 6;
// end_height is the end height of the BTC delegation
// it is the end BTC height of the timelock - w
uint64 end_height = 6;
// it is calculated by end_height = start_height + staking_time
uint64 end_height = 7;
// total_sat is the total amount of BTC stakes in this delegation
// quantified in satoshi
uint64 total_sat = 7;
uint64 total_sat = 8;
// staking_tx is the staking tx
bytes staking_tx = 8;
bytes staking_tx = 9;
// staking_output_idx is the index of the staking output in the staking tx
uint32 staking_output_idx = 9;
uint32 staking_output_idx = 10;
// slashing_tx is the slashing tx
// It is partially signed by SK corresponding to btc_pk, but not signed by
// finality provider or covenant yet.
bytes slashing_tx = 10 [ (gogoproto.customtype) = "BTCSlashingTx" ];
bytes slashing_tx = 11 [ (gogoproto.customtype) = "BTCSlashingTx" ];
// delegator_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.
bytes delegator_sig = 11 [ (gogoproto.customtype) = "github.com/babylonlabs-io/babylon/types.BIP340Signature" ];
bytes delegator_sig = 12 [ (gogoproto.customtype) = "github.com/babylonlabs-io/babylon/types.BIP340Signature" ];
// covenant_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_sigs = 12;
repeated CovenantAdaptorSignatures covenant_sigs = 13;
// unbonding_time describes how long the funds will be locked either in unbonding output
// or slashing change output
uint32 unbonding_time = 13;
uint32 unbonding_time = 14;
// btc_undelegation is the information about the early unbonding path of the BTC delegation
BTCUndelegation btc_undelegation = 14;
BTCUndelegation btc_undelegation = 15;
// version of the params used to validate the delegation
uint32 params_version = 15;
uint32 params_version = 16;
}

// BTCUndelegation contains the information about the early unbonding path of the BTC delegation
Expand Down Expand Up @@ -146,21 +149,30 @@ message BTCDelegatorDelegationIndex {
repeated bytes staking_tx_hash_list = 1;
}

// 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.
// BTCDelegationStatus is the status of a delegation.
// There are two possible valid state transition paths for a BTC delegation:
// - PENDING -> ACTIVE -> UNBONDED
// - PENDING -> VERIFIED -> ACTIVE -> UNBONDED
// and one invalid state transition path:
// - PENDING -> VERIFIED -> UNBONDED i.e the staker unbonded before
// activating delegation on Babylon chain.
// In valid transition paths, the delegation becomes UNBONDED when:
// - either the staking transaction timelock expires
// - or the staker requests early undelegation through MsgBTCUndelegate message.
enum BTCDelegationStatus {
// PENDING defines a delegation that is waiting for covenant signatures to become active.
// PENDING defines a delegation that is waiting for covenant signatures.
PENDING = 0;
// VERIFIED defines a delegation that has covenant signatures but is not yet
// included in the BTC chain.
VERIFIED = 1;
// ACTIVE defines a delegation that has voting power
ACTIVE = 1;
ACTIVE = 2;
// UNBONDED defines a delegation no longer has voting power:
// - either reaching the end of staking transaction timelock
// - or receiving unbonding tx with signatures from staker and covenant committee
UNBONDED = 2;
UNBONDED = 3;
// ANY is any of the above status
ANY = 3;
ANY = 4;
}

// SignatureInfo is a BIP-340 signature together with its signer's BIP-340 PK
Expand Down Expand Up @@ -195,4 +207,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
38 changes: 28 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 All @@ -22,6 +22,8 @@ service Msg {
rpc EditFinalityProvider(MsgEditFinalityProvider) returns (MsgEditFinalityProviderResponse);
// CreateBTCDelegation creates a new BTC delegation
rpc CreateBTCDelegation(MsgCreateBTCDelegation) returns (MsgCreateBTCDelegationResponse);
// AddBTCDelegationInclusionProof adds inclusion proof of a given delegation on BTC chain
rpc AddBTCDelegationInclusionProof(MsgAddBTCDelegationInclusionProof) returns (MsgAddBTCDelegationInclusionProofResponse);
// AddCovenantSigs handles signatures from a covenant member
rpc AddCovenantSigs(MsgAddCovenantSigs) returns (MsgAddCovenantSigsResponse);
// BTCUndelegate handles a signature on unbonding tx from its delegator
Expand Down Expand Up @@ -90,38 +92,54 @@ 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 {}

// MsgAddBTCDelegationInclusionProof is the message for adding proof of inclusion of BTC delegation on BTC chain
message MsgAddBTCDelegationInclusionProof {
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;
// staking_tx_inclusion_proof is the inclusion proof of the staking tx in BTC chain
InclusionProof staking_tx_inclusion_proof = 3;
}
// MsgAddBTCDelegationInclusionProofResponse is the response for MsgAddBTCDelegationInclusionProof
message MsgAddBTCDelegationInclusionProofResponse {}

// MsgAddCovenantSigs is the message for handling signatures from a covenant member
message MsgAddCovenantSigs {
option (cosmos.msg.v1.signer) = "signer";
Expand Down
Loading

0 comments on commit 04e12eb

Please sign in to comment.