Skip to content

Commit

Permalink
zoneconcierge: permissioned integration (#291)
Browse files Browse the repository at this point in the history
Resolves babylonlabs-io/pm#44

This PR implements the permissioned integration and generic consumer
registry, including

- [x] generic consumer registry compatible with Cosmos/ETH L2 consumers
- [x] parameter for governance gating consumer addition
- [x] ensuring IBC channel creation only when the IBC light client is in
consumer registry
- [x] removing the Cosmos consumer registration upon IBC handshake in
Babylon
- [x] removing the Cosmos consumer registration upon IBC handshake in
Babylon contract
- [x] fuzz tests for Cosmos integration
- [x] e2e tests for Cosmos integration

ADR: babylonlabs-io/pm#121
Accompanying PR in the contract side:
babylonlabs-io/babylon-contract#87


There are two TODOs that will be addressed in subsequent PRs:

- msg for removing registered consumer
- fuzz/e2e test for ETH L2 integrations

---------

Co-authored-by: Mauro Lacy <[email protected]>
  • Loading branch information
SebastianElvis and maurolacy authored Dec 3, 2024
1 parent ad3e100 commit 4898d8d
Show file tree
Hide file tree
Showing 55 changed files with 1,677 additions and 959 deletions.
5 changes: 1 addition & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,6 @@ jobs:
uses: actions/setup-go@v5
with:
go-version: 1.21
- name: Start BCD consumer integration containers
run: |
sudo make -C contrib/images start-bcd-consumer-integration
- name: Run BCD consumer integration test
run: |
sudo make test-e2e-cache-bcd-consumer-integration
sudo make test-e2e-bcd-consumer-integration
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -270,14 +270,14 @@ test-e2e-cache:
$(MAKE) clean-e2e
$(MAKE) test-e2e-cache-btc-staking-pre-approval
$(MAKE) test-e2e-cache-ibc-transfer
$(MAKE) test-e2e-cache-bcd-consumer-integration
$(MAKE) test-e2e-bcd-consumer-integration
# $(MAKE) test-e2e-cache-upgrade-v1

clean-e2e:
docker container rm -f $(shell docker container ls -a -q) || true
docker network prune -f || true

test-e2e-cache-bcd-consumer-integration: start-bcd-consumer-integration
test-e2e-bcd-consumer-integration: start-bcd-consumer-integration
go test -run TestBCDConsumerIntegrationTestSuite -mod=readonly -timeout=60m -v $(PACKAGES_E2E) --tags=e2e

test-e2e-cache-btc-timestamping:
Expand Down Expand Up @@ -446,7 +446,7 @@ build-docker: ## Build babylond Docker image
build-docker-e2e:
$(MAKE) -C contrib/images babylond-e2e
$(MAKE) -C contrib/images e2e-init-chain
$(MAKE) -C contrib/images build-bcd-consumer-integration
$(MAKE) -C contrib/images build-ibcsim-bcd

build-cosmos-relayer-docker: ## Build Docker image for the Cosmos relayer
$(MAKE) -C contrib/images cosmos-relayer
Expand Down
51 changes: 27 additions & 24 deletions app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,30 @@ func (ak *AppKeepers) InitKeepers(
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)

wasmOpts = append(owasm.RegisterCustomPlugins(&ak.EpochingKeeper, &ak.CheckpointingKeeper, &ak.BTCLightClientKeeper, &ak.ZoneConciergeKeeper), wasmOpts...)
wasmOpts = append(owasm.RegisterGrpcQueries(*bApp.GRPCQueryRouter(), appCodec), wasmOpts...)

ak.WasmKeeper = wasmkeeper.NewKeeper(
appCodec,
runtime.NewKVStoreService(keys[wasmtypes.StoreKey]),
ak.AccountKeeper,
ak.BankKeeper,
ak.StakingKeeper,
distrkeeper.NewQuerier(ak.DistrKeeper),
ak.IBCFeeKeeper,
ak.IBCKeeper.ChannelKeeper,
ak.IBCKeeper.PortKeeper,
scopedWasmKeeper,
ak.TransferKeeper,
bApp.MsgServiceRouter(),
bApp.GRPCQueryRouter(),
homePath,
wasmConfig,
WasmCapabilities(),
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
wasmOpts...,
)

// register the proposal types
// Deprecated: Avoid adding new handlers, instead use the new proposal flow
// by granting the governance module the right to execute the message.
Expand Down Expand Up @@ -487,6 +511,8 @@ func (ak *AppKeepers) InitKeepers(
runtime.NewKVStoreService(keys[bsctypes.StoreKey]),
ak.AccountKeeper,
ak.BankKeeper,
ak.IBCKeeper.ClientKeeper,
ak.WasmKeeper,
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)

Expand Down Expand Up @@ -529,6 +555,7 @@ func (ak *AppKeepers) InitKeepers(
runtime.NewKVStoreService(keys[zctypes.StoreKey]),
ak.IBCFeeKeeper,
ak.IBCKeeper.ClientKeeper,
ak.IBCKeeper.ConnectionKeeper,
ak.IBCKeeper.ChannelKeeper,
ak.IBCKeeper.PortKeeper,
ak.AccountKeeper,
Expand Down Expand Up @@ -578,30 +605,6 @@ func (ak *AppKeepers) InitKeepers(
// If evidence needs to be handled for the app, set routes in router here and seal
ak.EvidenceKeeper = *evidenceKeeper

wasmOpts = append(owasm.RegisterCustomPlugins(&ak.EpochingKeeper, &ak.CheckpointingKeeper, &ak.BTCLightClientKeeper, &ak.ZoneConciergeKeeper), wasmOpts...)
wasmOpts = append(owasm.RegisterGrpcQueries(*bApp.GRPCQueryRouter(), appCodec), wasmOpts...)

ak.WasmKeeper = wasmkeeper.NewKeeper(
appCodec,
runtime.NewKVStoreService(keys[wasmtypes.StoreKey]),
ak.AccountKeeper,
ak.BankKeeper,
ak.StakingKeeper,
distrkeeper.NewQuerier(ak.DistrKeeper),
ak.IBCFeeKeeper,
ak.IBCKeeper.ChannelKeeper,
ak.IBCKeeper.PortKeeper,
scopedWasmKeeper,
ak.TransferKeeper,
bApp.MsgServiceRouter(),
bApp.GRPCQueryRouter(),
homePath,
wasmConfig,
WasmCapabilities(),
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
wasmOpts...,
)

ibcWasmConfig :=
ibcwasmtypes.WasmConfig{
DataDir: filepath.Join(homePath, "ibc_08-wasm"),
Expand Down
4 changes: 1 addition & 3 deletions contrib/images/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ build-ibcsim-bcd:
ibcsim-bcd-rmi:
docker rmi babylonlabs-io/ibcsim-bcd 2>/dev/null; true

build-bcd-consumer-integration: babylond-e2e build-ibcsim-bcd

start-bcd-consumer-integration: stop-bcd-consumer-integration
ibcsim-bcd/pre-deployment.sh
docker compose -f ibcsim-bcd/docker-compose.yml up -d
Expand All @@ -45,4 +43,4 @@ stop-bcd-consumer-integration:
docker compose -f ibcsim-bcd/docker-compose.yml down
rm -rf ibcsim-bcd/.testnets

.PHONY: all babylond babylond-before-upgrade cosmos-relayer e2e-init-chain babylond-rmi babylond-rmi-upgrade cosmos-relayer-rmi build-ibcsim-bcd ibcsim-bcd-rmi build-bcd-consumer-integration-test start-bcd-consumer-integration-test stop-bcd-consumer-integration-test
.PHONY: all babylond babylond-before-upgrade cosmos-relayer e2e-init-chain babylond-rmi babylond-rmi-upgrade cosmos-relayer-rmi build-ibcsim-bcd ibcsim-bcd-rmi start-bcd-consumer-integration-test stop-bcd-consumer-integration-test
4 changes: 2 additions & 2 deletions contrib/images/ibcsim-bcd/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ENV PATH $GOPATH/bin:$PATH

ENV GO111MODULE on
ENV RELAYER_TAG v2.5.2
ENV BABYLON_SDK_TAG v0.6.0-rc.0
ENV BABYLON_SDK_VERSION v0.6.0-rc.1

# Install the relayer
RUN git clone https://github.com/cosmos/relayer.git
Expand All @@ -27,7 +27,7 @@ RUN cd relayer && git fetch origin && git checkout ${RELAYER_TAG} && make instal
# Install bcd
RUN git clone https://github.com/babylonlabs-io/babylon-sdk.git && \
cd babylon-sdk && \
git checkout ${BABYLON_SDK_TAG} && \
git checkout ${BABYLON_SDK_VERSION} && \
make install && \
cd -

Expand Down
74 changes: 37 additions & 37 deletions proto/babylon/btcstaking/v1/packet.proto
Original file line number Diff line number Diff line change
Expand Up @@ -58,70 +58,70 @@ message NewFinalityProvider {
// upon a BTC delegation newly receives covenant signatures and thus becomes active
message ActiveBTCDelegation {
// staker_addr is the address to receive rewards from BTC delegation.
string staker_addr = 11;
string staker_addr = 1;
// btc_pk_hex is the Bitcoin secp256k1 PK of this BTC delegation
// the PK follows encoding in BIP-340 spec in hex format
string btc_pk_hex = 1;
string btc_pk_hex = 2;
// fp_btc_pk_list is the list of BIP-340 PKs of the finality providers that
// this BTC delegation delegates to
repeated string fp_btc_pk_list = 2;
repeated string fp_btc_pk_list = 3;
// start_height is the start BTC height of the BTC delegation
// it is the start BTC height of the timelock
uint32 start_height = 3;
uint32 start_height = 4;
// end_height is the end height of the BTC delegation
// it is the end BTC height of the timelock - w
uint32 end_height = 4;
uint32 end_height = 5;
// total_sat is the total amount of BTC stakes in this delegation
// quantified in satoshi
uint64 total_sat = 5;
uint64 total_sat = 6;
// staking_tx is the staking tx
bytes staking_tx = 6;
bytes staking_tx = 7;
// slashing_tx is the slashing tx
bytes slashing_tx = 7;
bytes slashing_tx = 8;
// delegator_slashing_sig is the signature on the slashing tx
// by the delegator (i.e., SK corresponding to btc_pk) as string hex.
// It will be a part of the witness for the staking tx output.
bytes delegator_slashing_sig = 8;
bytes delegator_slashing_sig = 9;
// 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 = 9;
repeated CovenantAdaptorSignatures covenant_sigs = 10;
// staking_output_idx is the index of the staking output in the staking tx
uint32 staking_output_idx = 10;
uint32 staking_output_idx = 11;
// unbonding_time used in unbonding output timelock path and in slashing transactions
// change outputs
uint32 unbonding_time = 13;
uint32 unbonding_time = 12;
// undelegation_info is the undelegation info of this delegation.
BTCUndelegationInfo undelegation_info = 14;
BTCUndelegationInfo undelegation_info = 13;
// params version used to validate delegation
uint32 params_version = 15;
uint32 params_version = 14;
}

// BTCUndelegationInfo provides all necessary info about the undeleagation
message BTCUndelegationInfo {
// unbonding_tx is the transaction which will transfer the funds from staking
// output to unbonding output. Unbonding output will usually have lower timelock
// than staking output.
bytes unbonding_tx = 1;
// 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 = 2;
// covenant_unbonding_sig_list is the list of signatures on the unbonding tx
// by covenant members
repeated SignatureInfo covenant_unbonding_sig_list = 3;
// slashing_tx is the unbonding slashing tx
bytes slashing_tx = 4;
// 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 = 5;
// covenant_slashing_sigs is a list of adaptor signatures on the
// unbonding slashing tx by each covenant member
// It will be a part of the witness for the staking tx output.
repeated CovenantAdaptorSignatures covenant_slashing_sigs = 6;
// unbonding_tx is the transaction which will transfer the funds from staking
// output to unbonding output. Unbonding output will usually have lower timelock
// than staking output.
bytes unbonding_tx = 1;
// slashing_tx is the slashing tx for unbonding transactions
// It is partially signed by SK corresponding to btc_pk, but not signed by
// finality provider or covenant yet.
bytes slashing_tx = 2;
// 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 = 3;
// 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 = 4;
// covenant_unbonding_sig_list is the list of signatures on the unbonding tx
// by covenant members
// It must be provided after processing undelegate message by Babylon
repeated SignatureInfo covenant_unbonding_sig_list = 5;
// delegator_unbonding_info is the information about transaction which spent
// the staking output
DelegatorUnbondingInfo delegator_unbonding_info = 6;
}

// SlashedBTCDelegation is an IBC packet sent from Babylon to consumer
Expand Down
34 changes: 33 additions & 1 deletion proto/babylon/btcstkconsumer/v1/btcstkconsumer.proto
Original file line number Diff line number Diff line change
@@ -1,15 +1,47 @@
syntax = "proto3";
package babylon.btcstkconsumer.v1;

import "gogoproto/gogo.proto";
import "cosmos_proto/cosmos.proto";

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

// ConsumerType defines the type of consumer chain
enum ConsumerType {
// COSMOS represents a Cosmos SDK chain consumer
COSMOS = 0;
// ETH_L2 represents an Ethereum L2 chain consumer
ETH_L2 = 1;
}

// ConsumerRegister is the registration information of a consumer
message ConsumerRegister {
// consumer_id is the ID of the consumer
// - for Cosmos SDK chains, the consumer ID will be the IBC client ID
// - for ETH L2 chains, the consumer ID will be the chain ID of the ETH L2
// chain
string consumer_id = 1;
// consumer_name is the name of the consumer
string consumer_name = 2;
// consumer_description is a description for the consumer (can be empty)
string consumer_description = 3;
}
// consumer_metadata is necessary metadata of the consumer, and the data
// depends on the type of integration
oneof consumer_metadata {
CosmosConsumerMetadata cosmos_consumer_metadata = 4;
ETHL2ConsumerMetadata eth_l2_consumer_metadata = 5;
};
}

// CosmosConsumerMetadata is the metadata for the Cosmos integration
message CosmosConsumerMetadata {
// channel_id defines the IBC channel ID for the consumer chain
string channel_id = 1;
}

// ETHL2ConsumerMetadata is the metadata for the ETH L2 integration
message ETHL2ConsumerMetadata {
// finality_contract_address is the address of the finality contract for
// the ETH L2 integration
string finality_contract_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}
6 changes: 5 additions & 1 deletion proto/babylon/btcstkconsumer/v1/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ option go_package = "github.com/babylonlabs-io/babylon/x/btcstkconsumer/types";
message Params {
option (amino.name) = "babylon/x/btcstkconsumer/v1/Params";
option (gogoproto.equal) = true;
}

// permissioned_integration is a flag to enable permissioned integration, i.e.,
// requiring governance proposal to approve new integrations.
bool permissioned_integration = 1;
}
5 changes: 5 additions & 0 deletions proto/babylon/btcstkconsumer/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ message MsgRegisterConsumer {
string consumer_name = 3;
// consumer_description is a description for the consumer (can be empty)
string consumer_description = 4;
// eth_l2_finality_contract_address is the Cosmos address of the
// finality contract. The finality contract is deployed on Babylon and
// serves as the data availability layer for finality signatures of the ETH L2.
// (if set, then this means this is an ETH L2 integration)
string eth_l2_finality_contract_address = 5 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

// MsgRegisterConsumerResponse is the response to the MsgRegisterConsumer message.
Expand Down
12 changes: 1 addition & 11 deletions proto/babylon/zoneconcierge/v1/packet.proto
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ message ZoneconciergePacketData {
oneof packet {
BTCTimestamp btc_timestamp = 1;
babylon.btcstaking.v1.BTCStakingIBCPacket btc_staking = 2;
ConsumerRegisterIBCPacket consumer_register = 3;
ConsumerSlashingIBCPacket consumer_slashing = 4;
ConsumerSlashingIBCPacket consumer_slashing = 3;
}
}

Expand Down Expand Up @@ -57,15 +56,6 @@ message BTCTimestamp {
babylon.zoneconcierge.v1.ProofFinalizedChainInfo proof = 6;
}

// ConsumerRegisterIBCPacket defines the packet data for Consumer registration
message ConsumerRegisterIBCPacket {
// consumer_name is a unique identifier for the consumer chain
string consumer_name = 1;

// consumer_description is a brief explanation of the consumer chain's purpose
string consumer_description = 2;
}

// ConsumerSlashingIBCPacket defines the slashing information that a Consumer sends to Babylon's ZoneConcierge upon a
// Consumer slashing event.
// It includes the FP public key, the Consumer block height at the slashing event, and the double sign evidence.
Expand Down
16 changes: 10 additions & 6 deletions test/e2e/bcd_consumer_integration/clientcontroller/cosmwasm/msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,16 @@ type SignatureInfo struct {
}

type BtcUndelegationInfo struct {
UnbondingTx []byte `json:"unbonding_tx"`
DelegatorUnbondingSig []byte `json:"delegator_unbonding_sig"`
CovenantUnbondingSigs []SignatureInfo `json:"covenant_unbonding_sig_list"`
SlashingTx []byte `json:"slashing_tx"`
DelegatorSlashingSig []byte `json:"delegator_slashing_sig"`
CovenantSlashingSigs []CovenantAdaptorSignatures `json:"covenant_slashing_sigs"`
UnbondingTx []byte `json:"unbonding_tx"`
SlashingTx []byte `json:"slashing_tx"`
DelegatorSlashingSig []byte `json:"delegator_slashing_sig"`
CovenantSlashingSigs []*CovenantAdaptorSignatures `json:"covenant_slashing_sigs"`
CovenantUnbondingSigList []*SignatureInfo `json:"covenant_unbonding_sig_list"`
DelegatorUnbondingInfo *DelegatorUnbondingInfo `json:"delegator_unbonding_info"`
}

type DelegatorUnbondingInfo struct {
SpendStakeTx []byte `json:"spend_stake_tx"`
}

type ActiveBtcDelegation struct {
Expand Down
Loading

0 comments on commit 4898d8d

Please sign in to comment.