Skip to content

Commit

Permalink
feat: Automatic consumer registration (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
gusin13 authored Aug 14, 2024
1 parent 74a24c9 commit bd458da
Show file tree
Hide file tree
Showing 23 changed files with 940 additions and 133 deletions.
1 change: 1 addition & 0 deletions app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@ func (ak *AppKeepers) InitKeepers(
epochingKeeper,
storeQuerier,
&ak.BTCStakingKeeper,
&ak.BTCStkConsumerKeeper,
scopedZoneConciergeKeeper,
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
Expand Down
32 changes: 21 additions & 11 deletions proto/babylon/zoneconcierge/v1/packet.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ syntax = "proto3";
package babylon.zoneconcierge.v1;

import "babylon/btccheckpoint/v1/btccheckpoint.proto";
import "babylon/checkpointing/v1/checkpoint.proto";
import "babylon/btclightclient/v1/btclightclient.proto";
import "babylon/epoching/v1/epoching.proto";
import "babylon/btcstaking/v1/packet.proto";
import "babylon/checkpointing/v1/checkpoint.proto";
import "babylon/epoching/v1/epoching.proto";
import "babylon/zoneconcierge/v1/zoneconcierge.proto";

option go_package = "github.com/babylonlabs-io/babylon/x/zoneconcierge/types";
Expand All @@ -14,14 +14,15 @@ option go_package = "github.com/babylonlabs-io/babylon/x/zoneconcierge/types";
// ZoneConcierge
message ZoneconciergePacketData {
// packet is the actual message carried in the IBC packet
oneof packet {
BTCTimestamp btc_timestamp = 1;
oneof packet {
BTCTimestamp btc_timestamp = 1;
babylon.btcstaking.v1.BTCStakingIBCPacket btc_staking = 2;
ConsumerRegisterIBCPacket consumer_register = 3;
}
}

// BTCTimestamp is a BTC timestamp that carries information of a BTC-finalised epoch
// It includes a number of BTC headers, a raw checkpoint, an epoch metadata, and
// It includes a number of BTC headers, a raw checkpoint, an epoch metadata, and
// a CZ header if there exists CZ headers checkpointed to this epoch.
// Upon a newly finalised epoch in Babylon, Babylon will send a BTC timestamp to each
// Cosmos zone that has phase-2 integration with Babylon via IBC.
Expand All @@ -30,16 +31,16 @@ message BTCTimestamp {
babylon.zoneconcierge.v1.IndexedHeader header = 1;

/*
Data for BTC light client
Data for BTC light client
*/
// btc_headers is BTC headers between
// - the block AFTER the common ancestor of BTC tip at epoch `lastFinalizedEpoch-1` and BTC tip at epoch `lastFinalizedEpoch`
// - BTC tip at epoch `lastFinalizedEpoch`
// - BTC tip at epoch `lastFinalizedEpoch`
// where `lastFinalizedEpoch` is the last finalised epoch in Babylon
repeated babylon.btclightclient.v1.BTCHeaderInfo btc_headers = 2;

/*
Data for Babylon epoch chain
Data for Babylon epoch chain
*/
// epoch_info is the metadata of the sealed epoch
babylon.epoching.v1.Epoch epoch_info = 3;
Expand All @@ -48,8 +49,17 @@ message BTCTimestamp {
// btc_submission_key is position of two BTC txs that include the raw checkpoint of this epoch
babylon.btccheckpoint.v1.SubmissionKey btc_submission_key = 5;

/*
Proofs that the header is finalized
/*
Proofs that the header is finalized
*/
babylon.zoneconcierge.v1.ProofFinalizedChainInfo proof = 6;
}
}

// ConsumerRegisterPacketData 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;
}
4 changes: 2 additions & 2 deletions proto/buf.lock
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ deps:
- remote: buf.build
owner: cosmos
repository: ibc
commit: ef1dd1634b6c429bb2b52d983a683ce3
digest: shake256:8325b0de8e8a2e027a8d33e0585a13273ce34b510cbedf7b785882a785baa62d42405ab2a836ea42fb1ddf098580f5cfc2414b1851dfcdd0b7c84851e96afeb9
commit: c159402ffeef4c21a7f9f0643817ae0d
digest: shake256:694e3f5a1d469798bb6cb3510f6f489e10d9309d1f2e8f7a369a776947602195f13ab65972d2d586a1134978b6a6fa28a43e5d7710ef5032ba0c7fbbe6038f08
- remote: buf.build
owner: cosmos
repository: ics23
Expand Down
38 changes: 19 additions & 19 deletions test/e2e/btc_staking_integration_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"math"
"time"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/babylonlabs-io/babylon/test/e2e/configurer"
"github.com/babylonlabs-io/babylon/test/e2e/configurer/chain"
"github.com/babylonlabs-io/babylon/test/e2e/initialization"
Expand All @@ -18,6 +16,7 @@ import (
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/wire"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/query"
channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types"
"github.com/stretchr/testify/suite"
Expand Down Expand Up @@ -60,14 +59,14 @@ func (s *BTCStakingIntegrationTestSuite) TearDownSuite() {
}

// Test1RegisterNewConsumer registers a new consumer on Babylon
func (s *BTCStakingIntegrationTestSuite) Test1RegisterNewConsumer() {
func (s *BTCStakingIntegrationTestSuite) Test1AutoRegisterAndVerifyNewConsumer() {
chainA := s.configurer.GetChainConfig(0)
chainA.WaitUntilHeight(1)
babylonNode, err := chainA.GetNodeAtIndex(2)
s.NoError(err)

consumerID := s.getIBCClientID()
s.registerVerifyConsumer(babylonNode, consumerID)
s.verifyConsumerRegistration(babylonNode, consumerID)
}

// Test2CreateConsumerFinalityProvider -
Expand Down Expand Up @@ -409,23 +408,24 @@ func (s *BTCStakingIntegrationTestSuite) Test6ContractQueries() {
// TODO: add test for slashing when its supported in smart contract

// helper function: register a random consumer on Babylon and verify it
func (s *BTCStakingIntegrationTestSuite) registerVerifyConsumer(babylonNode *chain.NodeConfig, consumerID string) *bsctypes.ConsumerRegister {
// Register a random consumer on Babylon
randomConsumer := &bsctypes.ConsumerRegister{
ConsumerId: consumerID,
ConsumerName: datagen.GenRandomHexStr(r, 5),
ConsumerDescription: "Chain description: " + datagen.GenRandomHexStr(r, 15),
}
babylonNode.RegisterConsumer(randomConsumer.ConsumerId, randomConsumer.ConsumerName, randomConsumer.ConsumerDescription)
babylonNode.WaitForNextBlock()
func (s *BTCStakingIntegrationTestSuite) verifyConsumerRegistration(babylonNode *chain.NodeConfig, consumerID string) *bsctypes.ConsumerRegister {
var consumerRegistry []*bsctypes.ConsumerRegister

s.Eventually(func() bool {
consumerRegistry = babylonNode.QueryConsumerRegistry(consumerID)
return len(consumerRegistry) == 1
}, time.Minute, 5*time.Second, "Consumer was not registered within the expected time")

// Query the consumer registry to verify the consumer was registered
consumerRegistry := babylonNode.QueryConsumerRegistry(randomConsumer.ConsumerId)
s.Require().Len(consumerRegistry, 1)
s.Require().Equal(randomConsumer.ConsumerId, consumerRegistry[0].ConsumerId)
s.Require().Equal(randomConsumer.ConsumerName, consumerRegistry[0].ConsumerName)
s.Require().Equal(randomConsumer.ConsumerDescription, consumerRegistry[0].ConsumerDescription)
return randomConsumer
registeredConsumer := consumerRegistry[0]

//s.Require().Equal(consumerID, registeredConsumer.ConsumerId)
s.T().Logf("Consumer registered: ID=%s, Name=%s, Description=%s",
registeredConsumer.ConsumerId,
registeredConsumer.ConsumerName,
registeredConsumer.ConsumerDescription)

return registeredConsumer
}

// helper function: create a random consumer finality provider on Babylon and verify it
Expand Down
Binary file modified test/e2e/bytecode/babylon_contract.wasm
Binary file not shown.
Binary file modified test/e2e/bytecode/btc_staking.wasm
Binary file not shown.
16 changes: 15 additions & 1 deletion test/e2e/configurer/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,27 @@ func (bc *baseConfigurer) InstantiateBabylonContract(enableBTCStaking bool) erro
nonValidatorNode.WaitForNextBlock()
btcStakingContractWasmId := int(nonValidatorNode.QueryLatestWasmCodeID())

initMsg = fmt.Sprintf(`{ "network": %q, "babylon_tag": %q, "btc_confirmation_depth": %d, "checkpoint_finalization_timeout": %d, "notify_cosmos_zone": %s, "btc_staking_code_id": %d }`,
consumerName := "TestConsumer"
consumerDescription := "Test Consumer Description"

initMsg = fmt.Sprintf(`{
"network": %q,
"babylon_tag": %q,
"btc_confirmation_depth": %d,
"checkpoint_finalization_timeout": %d,
"notify_cosmos_zone": %s,
"btc_staking_code_id": %d,
"consumer_name": %q,
"consumer_description": %q
}`,
types.BtcRegtest,
types2.DefaultCheckpointTag,
1,
2,
"false",
btcStakingContractWasmId,
consumerName,
consumerDescription,
)
}

Expand Down
2 changes: 1 addition & 1 deletion test/e2e/containers/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ func (m *Manager) RunNodeResource(chainId string, containerName, valCondifDir st
Entrypoint: []string{
"sh",
"-c",
"babylond start " + FlagHome,
"babylond start " + FlagHome + " --log_level trace --trace",
},
ExposedPorts: []string{"26656", "26657", "1317", "9090"},
Mounts: []string{
Expand Down
3 changes: 2 additions & 1 deletion testutil/keeper/zoneconcierge.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func (zoneconciergeStoreQuerier) Query(req *storetypes.RequestQuery) (*storetype
}, nil
}

func ZoneConciergeKeeper(t testing.TB, btclcKeeper types.BTCLightClientKeeper, checkpointingKeeper types.CheckpointingKeeper, btccKeeper types.BtcCheckpointKeeper, epochingKeeper types.EpochingKeeper, bsKeeper types.BTCStakingKeeper) (*keeper.Keeper, sdk.Context) {
func ZoneConciergeKeeper(t testing.TB, btclcKeeper types.BTCLightClientKeeper, checkpointingKeeper types.CheckpointingKeeper, btccKeeper types.BtcCheckpointKeeper, epochingKeeper types.EpochingKeeper, bsKeeper types.BTCStakingKeeper, btcStkKeeper types.BTCStkConsumerKeeper) (*keeper.Keeper, sdk.Context) {
logger := log.NewTestLogger(t)
storeKey := storetypes.NewKVStoreKey(types.StoreKey)
memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey)
Expand Down Expand Up @@ -98,6 +98,7 @@ func ZoneConciergeKeeper(t testing.TB, btclcKeeper types.BTCLightClientKeeper, c
epochingKeeper,
zoneconciergeStoreQuerier{},
bsKeeper,
btcStkKeeper,
capabilityKeeper.ScopeToModule("ZoneconciergeScopedKeeper"),
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
Expand Down
14 changes: 14 additions & 0 deletions x/btcstkconsumer/keeper/consumer_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,20 @@ func (k Keeper) GetAllRegisteredConsumerIDs(ctx context.Context) []string {
return consumerIDs
}

// RegisterConsumer validates and registers a new consumer
func (k Keeper) RegisterConsumer(ctx context.Context, consumerRegister *types.ConsumerRegister) error {
if err := consumerRegister.Validate(); err != nil {
return types.ErrInvalidConsumerRegister.Wrapf("invalid consumer: %v", err)
}

if k.IsConsumerRegistered(ctx, consumerRegister.ConsumerId) {
return types.ErrConsumerAlreadyRegistered
}

k.SetConsumerRegister(ctx, consumerRegister)
return nil
}

// consumerRegistryStore stores the information of registered CZ consumers
// prefix: ConsumerRegisterKey
// key: consumerID
Expand Down
13 changes: 4 additions & 9 deletions x/btcstkconsumer/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,17 @@ var _ types.MsgServer = msgServer{}

// RegisterConsumer registers a CZ consumer
func (ms msgServer) RegisterConsumer(goCtx context.Context, req *types.MsgRegisterConsumer) (*types.MsgRegisterConsumerResponse, error) {
// Create ChanRegister from MsgRegisterConsumer
consumerRegister := types.ConsumerRegister{
consumerRegister := &types.ConsumerRegister{
ConsumerId: req.ConsumerId,
ConsumerName: req.ConsumerName,
ConsumerDescription: req.ConsumerDescription,
}

if err := consumerRegister.Validate(); err != nil {
return nil, types.ErrInvalidConsumerRegister.Wrapf("invalid consumer: %v", err)
}

ctx := sdk.UnwrapSDKContext(goCtx)
if ms.IsConsumerRegistered(ctx, req.ConsumerId) {
return nil, types.ErrConsumerAlreadyRegistered
err := ms.Keeper.RegisterConsumer(ctx, consumerRegister)
if err != nil {
return nil, err
}
ms.SetConsumerRegister(ctx, &consumerRegister)

return &types.MsgRegisterConsumerResponse{}, nil
}
3 changes: 3 additions & 0 deletions x/btcstkconsumer/types/chain_register.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ func (cr *ConsumerRegister) Validate() error {
if len(cr.ConsumerName) == 0 {
return fmt.Errorf("ConsumerName must be non-empty")
}
if len(cr.ConsumerDescription) == 0 {
return fmt.Errorf("ConsumerDescription must be non-empty")
}

return nil
}
Loading

0 comments on commit bd458da

Please sign in to comment.