Skip to content

Commit

Permalink
zoneconcierge: replace chain ID with client ID for consumers (#32)
Browse files Browse the repository at this point in the history
Subsumes #22 

---

Fixes babylonlabs-io/pm#12

This PR replaces the chain ID with the client ID for consumers in the
BTC timestamping protocol. This is in line with [the IBC security
model](https://tutorials.cosmos.network/academy/3-ibc/1-what-is-ibc.html)
where each IBC light client corresponds to a chain, and with the BTC
staking integration implementation.

The PR includes:

- renaming all chain ID to consumer ID, same as BTC staking integration
does
- using client ID to identify {epoch, finalised} chain info
- changing all queries, fuzz tests, e2e tests, and doc accordingly

TODO before merging the PR:

- [x] wait until @gitferry verifies we can do software upgrade with
empty DB and updated DB schema

Plan after the PR:

- Fixing compatiblity with BE/FE (need arch decisions here)
  • Loading branch information
SebastianElvis authored Aug 27, 2024
1 parent 9a37d60 commit 3d713f2
Show file tree
Hide file tree
Showing 35 changed files with 776 additions and 742 deletions.
208 changes: 105 additions & 103 deletions client/docs/swagger-ui/swagger.yaml

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions client/query/zoneconcierge.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ func (c *QueryClient) QueryZoneConcierge(f func(ctx context.Context, queryClient
}

// FinalizedConnectedChainsInfo queries the zoneconcierge module to get the finalization information for a connected chain
func (c *QueryClient) FinalizedConnectedChainsInfo(chainIds []string) (*zctypes.QueryFinalizedChainsInfoResponse, error) {
func (c *QueryClient) FinalizedConnectedChainsInfo(consumerIds []string) (*zctypes.QueryFinalizedChainsInfoResponse, error) {
var resp *zctypes.QueryFinalizedChainsInfoResponse
err := c.QueryZoneConcierge(func(ctx context.Context, queryClient zctypes.QueryClient) error {
var err error
req := &zctypes.QueryFinalizedChainsInfoRequest{
ChainIds: chainIds,
ConsumerIds: consumerIds,
}
resp, err = queryClient.FinalizedChainsInfo(ctx, req)
return err
Expand All @@ -36,12 +36,12 @@ func (c *QueryClient) FinalizedConnectedChainsInfo(chainIds []string) (*zctypes.
}

// ConnectedChainsInfo queries the zoneconcierge module to get information for a connected chain
func (c *QueryClient) ConnectedChainsInfo(chainIds []string) (*zctypes.QueryChainsInfoResponse, error) {
func (c *QueryClient) ConnectedChainsInfo(consumerIds []string) (*zctypes.QueryChainsInfoResponse, error) {
var resp *zctypes.QueryChainsInfoResponse
err := c.QueryZoneConcierge(func(ctx context.Context, queryClient zctypes.QueryClient) error {
var err error
req := &zctypes.QueryChainsInfoRequest{
ChainIds: chainIds,
ConsumerIds: consumerIds,
}
resp, err = queryClient.ChainsInfo(ctx, req)
return err
Expand All @@ -64,12 +64,12 @@ func (c *QueryClient) ConnectedChainList() (*zctypes.QueryChainListResponse, err
}

// ConnectedChainHeaders queries the zoneconcierge module for the headers of a connected chain
func (c *QueryClient) ConnectedChainHeaders(chainID string, pagination *sdkquerytypes.PageRequest) (*zctypes.QueryListHeadersResponse, error) {
func (c *QueryClient) ConnectedChainHeaders(consumerID string, pagination *sdkquerytypes.PageRequest) (*zctypes.QueryListHeadersResponse, error) {
var resp *zctypes.QueryListHeadersResponse
err := c.QueryZoneConcierge(func(ctx context.Context, queryClient zctypes.QueryClient) error {
var err error
req := &zctypes.QueryListHeadersRequest{
ChainId: chainID,
ConsumerId: consumerID,
Pagination: pagination,
}
resp, err = queryClient.ListHeaders(ctx, req)
Expand All @@ -80,13 +80,13 @@ func (c *QueryClient) ConnectedChainHeaders(chainID string, pagination *sdkquery
}

// ConnectedChainsEpochInfo queries the zoneconcierge module for the chain information of a connected chain at a particular epoch
func (c *QueryClient) ConnectedChainsEpochInfo(chainIds []string, epochNum uint64) (*zctypes.QueryEpochChainsInfoResponse, error) {
func (c *QueryClient) ConnectedChainsEpochInfo(consumerIds []string, epochNum uint64) (*zctypes.QueryEpochChainsInfoResponse, error) {
var resp *zctypes.QueryEpochChainsInfoResponse
err := c.QueryZoneConcierge(func(ctx context.Context, queryClient zctypes.QueryClient) error {
var err error
req := &zctypes.QueryEpochChainsInfoRequest{
ChainIds: chainIds,
EpochNum: epochNum,
ConsumerIds: consumerIds,
EpochNum: epochNum,
}
resp, err = queryClient.EpochChainsInfo(ctx, req)
return err
Expand Down
30 changes: 15 additions & 15 deletions proto/babylon/zoneconcierge/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ service Query {
// Header queries the CZ header and fork headers at a given height.
rpc Header(QueryHeaderRequest) returns (QueryHeaderResponse) {
option (google.api.http).get =
"/babylon/zoneconcierge/v1/chain_info/{chain_id}/header/{height}";
"/babylon/zoneconcierge/v1/chain_info/{consumer_id}/header/{height}";
}
// ChainList queries the list of chains that checkpoint to Babylon
rpc ChainList(QueryChainListRequest) returns (QueryChainListResponse) {
Expand All @@ -43,14 +43,14 @@ service Query {
// pagination support
rpc ListHeaders(QueryListHeadersRequest) returns (QueryListHeadersResponse) {
option (google.api.http).get =
"/babylon/zoneconcierge/v1/headers/{chain_id}";
"/babylon/zoneconcierge/v1/headers/{consumer_id}";
}
// ListEpochHeaders queries the headers of a chain timestamped in a given
// epoch of Babylon, with pagination support
rpc ListEpochHeaders(QueryListEpochHeadersRequest)
returns (QueryListEpochHeadersResponse) {
option (google.api.http).get =
"/babylon/zoneconcierge/v1/headers/{chain_id}/epochs/{epoch_num}";
"/babylon/zoneconcierge/v1/headers/{consumer_id}/epochs/{epoch_num}";
}
// FinalizedChainsInfo queries the BTC-finalised info of chains with given IDs, with proofs
rpc FinalizedChainsInfo(QueryFinalizedChainsInfoRequest)
Expand All @@ -63,7 +63,7 @@ service Query {
rpc FinalizedChainInfoUntilHeight(QueryFinalizedChainInfoUntilHeightRequest)
returns (QueryFinalizedChainInfoUntilHeightResponse) {
option (google.api.http).get =
"/babylon/zoneconcierge/v1/finalized_chain_info/{chain_id}/height/"
"/babylon/zoneconcierge/v1/finalized_chain_info/{consumer_id}/height/"
"{height}";
}
}
Expand All @@ -79,7 +79,7 @@ message QueryParamsResponse {

// QueryHeaderRequest is request type for the Query/Header RPC method.
message QueryHeaderRequest {
string chain_id = 1;
string consumer_id = 1;
uint64 height = 2;
}

Expand All @@ -97,14 +97,14 @@ message QueryChainListRequest {

// QueryChainListResponse is response type for the Query/ChainList RPC method
message QueryChainListResponse {
// chain_ids are IDs of the chains in ascending alphabetical order
repeated string chain_ids = 1;
// consumer_ids are IDs of the chains in ascending alphabetical order
repeated string consumer_ids = 1;
// pagination defines the pagination in the response
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

// QueryChainsInfoRequest is request type for the Query/ChainsInfo RPC method.
message QueryChainsInfoRequest { repeated string chain_ids = 1; }
message QueryChainsInfoRequest { repeated string consumer_ids = 1; }

// QueryChainsInfoResponse is response type for the Query/ChainsInfo RPC method.
message QueryChainsInfoResponse {
Expand All @@ -115,7 +115,7 @@ message QueryChainsInfoResponse {
// method.
message QueryEpochChainsInfoRequest {
uint64 epoch_num = 1;
repeated string chain_ids = 2;
repeated string consumer_ids = 2;
}

// QueryEpochChainsInfoResponse is response type for the Query/EpochChainsInfo RPC
Expand All @@ -127,7 +127,7 @@ message QueryEpochChainsInfoResponse {

// QueryListHeadersRequest is request type for the Query/ListHeaders RPC method.
message QueryListHeadersRequest {
string chain_id = 1;
string consumer_id = 1;
// pagination defines whether to have the pagination in the request
cosmos.base.query.v1beta1.PageRequest pagination = 2;
}
Expand All @@ -145,7 +145,7 @@ message QueryListHeadersResponse {
// RPC method.
message QueryListEpochHeadersRequest {
uint64 epoch_num = 1;
string chain_id = 2;
string consumer_id = 2;
}

// QueryListEpochHeadersResponse is response type for the Query/ListEpochHeaders
Expand All @@ -158,8 +158,8 @@ message QueryListEpochHeadersResponse {
// QueryFinalizedChainsInfoRequest is request type for the
// Query/FinalizedChainsInfo RPC method.
message QueryFinalizedChainsInfoRequest {
// chain_ids is the list of ids of CZs
repeated string chain_ids = 1;
// consumer_ids is the list of ids of CZs
repeated string consumer_ids = 1;
// prove indicates whether the querier wants to get proofs of this timestamp
bool prove = 2;
}
Expand All @@ -173,8 +173,8 @@ message QueryFinalizedChainsInfoResponse {
// QueryFinalizedChainInfoUntilHeightRequest is request type for the
// Query/FinalizedChainInfoUntilHeight RPC method.
message QueryFinalizedChainInfoUntilHeightRequest {
// chain_id is the ID of the CZ
string chain_id = 1;
// consumer_id is the ID of the CZ
string consumer_id = 1;
// height is the height of the CZ chain
// such that the returned finalised chain info will be no later than this
// height
Expand Down
12 changes: 6 additions & 6 deletions proto/babylon/zoneconcierge/v1/zoneconcierge.proto
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ option go_package = "github.com/babylonlabs-io/babylon/x/zoneconcierge/types";

// IndexedHeader is the metadata of a CZ header
message IndexedHeader {
// chain_id is the unique ID of the chain
string chain_id = 1;
// consumer_id is the unique ID of the consumer
string consumer_id = 1;
// hash is the hash of this header
bytes hash = 2;
// height is the height of this header on CZ ledger
Expand Down Expand Up @@ -60,8 +60,8 @@ message Forks {

// ChainInfo is the information of a CZ
message ChainInfo {
// chain_id is the ID of the chain
string chain_id = 1;
// consumer_id is the ID of the consumer
string consumer_id = 1;
// latest_header is the latest header in CZ's canonical chain
IndexedHeader latest_header = 2;
// latest_forks is the latest forks, formed as a series of IndexedHeader (from
Expand All @@ -84,8 +84,8 @@ message ChainInfoWithProof {

// FinalizedChainInfo is the information of a CZ that is BTC-finalised
message FinalizedChainInfo {
// chain_id is the ID of the chain
string chain_id = 1;
// consumer_id is the ID of the consumer
string consumer_id = 1;
// finalized_chain_info is the info of the CZ
babylon.zoneconcierge.v1.ChainInfo finalized_chain_info = 2;

Expand Down
21 changes: 15 additions & 6 deletions test/e2e/btc_timestamping_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,19 @@ func (s *BTCTimestampingTestSuite) Test4IbcCheckpointing() {
nonValidatorNode, err := chainA.GetNodeAtIndex(2)
s.NoError(err)

// Query open IBC channels and assert there is only one
channels, err := nonValidatorNode.QueryIBCChannels()
s.NoError(err)
s.Equal(1, len(channels.Channels), "Expected only one open IBC channel")
// Get the client ID under this IBC channel
channelClientState, err := nonValidatorNode.QueryChannelClientState(channels.Channels[0].ChannelId, channels.Channels[0].PortId)
s.NoError(err)
clientID := channelClientState.IdentifiedClientState.ClientId

// Query checkpoint chain info for opposing chain
chainsInfo, err := nonValidatorNode.QueryChainsInfo([]string{initialization.ChainBID})
chainsInfo, err := nonValidatorNode.QueryChainsInfo([]string{clientID})
s.NoError(err)
s.Equal(chainsInfo[0].ChainId, initialization.ChainBID)
s.Equal(chainsInfo[0].ConsumerId, clientID)

// Finalize epoch 1, 2, 3, as first headers of opposing chain are in epoch 3
var (
Expand All @@ -140,17 +149,17 @@ func (s *BTCTimestampingTestSuite) Test4IbcCheckpointing() {
nonValidatorNode.WaitForNextBlock()

// Check we have epoch info for opposing chain and some basic assertions
epochChainsInfo, err := nonValidatorNode.QueryEpochChainsInfo(endEpochNum, []string{initialization.ChainBID})
epochChainsInfo, err := nonValidatorNode.QueryEpochChainsInfo(endEpochNum, []string{clientID})
s.NoError(err)
s.Equal(epochChainsInfo[0].ChainId, initialization.ChainBID)
s.Equal(epochChainsInfo[0].ConsumerId, clientID)
s.Equal(epochChainsInfo[0].LatestHeader.BabylonEpoch, endEpochNum)

// Check we have finalized epoch info for opposing chain and some basic assertions
finalizedChainsInfo, err := nonValidatorNode.QueryFinalizedChainsInfo([]string{initialization.ChainBID})
finalizedChainsInfo, err := nonValidatorNode.QueryFinalizedChainsInfo([]string{clientID})
s.NoError(err)

// TODO Add more assertion here. Maybe check proofs ?
s.Equal(finalizedChainsInfo[0].FinalizedChainInfo.ChainId, initialization.ChainBID)
s.Equal(finalizedChainsInfo[0].FinalizedChainInfo.ConsumerId, clientID)
s.Equal(finalizedChainsInfo[0].EpochInfo.EpochNumber, endEpochNum)

currEpoch, err := nonValidatorNode.QueryCurrentEpoch()
Expand Down
11 changes: 9 additions & 2 deletions test/e2e/btc_timestamping_phase2_hermes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"time"

"github.com/babylonlabs-io/babylon/test/e2e/configurer"
"github.com/babylonlabs-io/babylon/test/e2e/initialization"
ct "github.com/babylonlabs-io/babylon/x/checkpointing/types"
"github.com/cosmos/cosmos-sdk/types/query"
channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types"
Expand Down Expand Up @@ -51,6 +50,8 @@ func (s *BTCTimestampingPhase2HermesTestSuite) TearDownSuite() {

func (s *BTCTimestampingPhase2HermesTestSuite) Test1IbcCheckpointingPhase2Hermes() {
chainA := s.configurer.GetChainConfig(0)
nonValidatorNode, err := chainA.GetNodeAtIndex(2)
s.NoError(err)

babylonNode, err := chainA.GetNodeAtIndex(2)
s.NoError(err)
Expand Down Expand Up @@ -98,9 +99,15 @@ func (s *BTCTimestampingPhase2HermesTestSuite) Test1IbcCheckpointingPhase2Hermes
return true
}, time.Minute, time.Second*2)

// Get the client ID under this IBC channel
channelClientState, err := nonValidatorNode.QueryChannelClientState(babylonChannel.ChannelId, babylonChannel.PortId)
s.NoError(err)
clientID := channelClientState.IdentifiedClientState.ClientId

// Query checkpoint chain info for the consumer chain
listHeaderResp, err := babylonNode.QueryListHeaders(initialization.ChainBID, &query.PageRequest{Limit: 1})
listHeaderResp, err := babylonNode.QueryListHeaders(clientID, &query.PageRequest{Limit: 1})
s.NoError(err)
s.GreaterOrEqual(len(listHeaderResp.Headers), 1)
startEpochNum := listHeaderResp.Headers[0].BabylonEpoch
endEpochNum := startEpochNum + 2

Expand Down
11 changes: 9 additions & 2 deletions test/e2e/btc_timestamping_phase2_rly_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"time"

"github.com/babylonlabs-io/babylon/test/e2e/configurer"
"github.com/babylonlabs-io/babylon/test/e2e/initialization"
ct "github.com/babylonlabs-io/babylon/x/checkpointing/types"
"github.com/cosmos/cosmos-sdk/types/query"
channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types"
Expand Down Expand Up @@ -51,6 +50,8 @@ func (s *BTCTimestampingPhase2RlyTestSuite) TearDownSuite() {

func (s *BTCTimestampingPhase2RlyTestSuite) Test1IbcCheckpointingPhase2Rly() {
chainA := s.configurer.GetChainConfig(0)
nonValidatorNode, err := chainA.GetNodeAtIndex(2)
s.NoError(err)

babylonNode, err := chainA.GetNodeAtIndex(2)
s.NoError(err)
Expand Down Expand Up @@ -98,9 +99,15 @@ func (s *BTCTimestampingPhase2RlyTestSuite) Test1IbcCheckpointingPhase2Rly() {
return true
}, time.Minute, time.Second*2)

// Get the client ID under this IBC channel
channelClientState, err := nonValidatorNode.QueryChannelClientState(babylonChannel.ChannelId, babylonChannel.PortId)
s.NoError(err)
clientID := channelClientState.IdentifiedClientState.ClientId

// Query checkpoint chain info for the consumer chain
listHeaderResp, err := babylonNode.QueryListHeaders(initialization.ChainBID, &query.PageRequest{Limit: 1})
listHeaderResp, err := babylonNode.QueryListHeaders(clientID, &query.PageRequest{Limit: 1})
s.NoError(err)
s.GreaterOrEqual(len(listHeaderResp.Headers), 1)
startEpochNum := listHeaderResp.Headers[0].BabylonEpoch
endEpochNum := startEpochNum + 2

Expand Down
24 changes: 12 additions & 12 deletions test/e2e/configurer/chain/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,14 +245,14 @@ func (n *NodeConfig) QueryHeaderDepth(hash string) (uint64, error) {
return blcResponse.Depth, nil
}

func (n *NodeConfig) QueryListHeaders(chainID string, pagination *query.PageRequest) (*zctypes.QueryListHeadersResponse, error) {
func (n *NodeConfig) QueryListHeaders(consumerID string, pagination *query.PageRequest) (*zctypes.QueryListHeadersResponse, error) {
queryParams := url.Values{}
if pagination != nil {
queryParams.Set("pagination.key", base64.URLEncoding.EncodeToString(pagination.Key))
queryParams.Set("pagination.limit", strconv.Itoa(int(pagination.Limit)))
}

path := fmt.Sprintf("babylon/zoneconcierge/v1/headers/%s", chainID)
path := fmt.Sprintf("babylon/zoneconcierge/v1/headers/%s", consumerID)
bz, err := n.QueryGRPCGateway(path, queryParams)
require.NoError(n.t, err)

Expand All @@ -264,10 +264,10 @@ func (n *NodeConfig) QueryListHeaders(chainID string, pagination *query.PageRequ
return &resp, nil
}

func (n *NodeConfig) QueryFinalizedChainsInfo(chainIDs []string) ([]*zctypes.FinalizedChainInfo, error) {
func (n *NodeConfig) QueryFinalizedChainsInfo(consumerIDs []string) ([]*zctypes.FinalizedChainInfo, error) {
queryParams := url.Values{}
for _, chainId := range chainIDs {
queryParams.Add("chain_ids", chainId)
for _, consumerID := range consumerIDs {
queryParams.Add("consumer_ids", consumerID)
}

bz, err := n.QueryGRPCGateway("babylon/zoneconcierge/v1/finalized_chains_info", queryParams)
Expand All @@ -281,11 +281,11 @@ func (n *NodeConfig) QueryFinalizedChainsInfo(chainIDs []string) ([]*zctypes.Fin
return resp.FinalizedChainsInfo, nil
}

func (n *NodeConfig) QueryEpochChainsInfo(epochNum uint64, chainIDs []string) ([]*zctypes.ChainInfo, error) {
func (n *NodeConfig) QueryEpochChainsInfo(epochNum uint64, consumerIDs []string) ([]*zctypes.ChainInfo, error) {
queryParams := url.Values{}
for _, chainId := range chainIDs {
for _, consumerID := range consumerIDs {
queryParams.Add("epoch_num", fmt.Sprintf("%d", epochNum))
queryParams.Add("chain_ids", chainId)
queryParams.Add("consumer_ids", consumerID)
}

bz, err := n.QueryGRPCGateway("babylon/zoneconcierge/v1/epoch_chains_info", queryParams)
Expand All @@ -306,13 +306,13 @@ func (n *NodeConfig) QueryChains() (*[]string, error) {
if err := util.Cdc.UnmarshalJSON(bz, &chainsResponse); err != nil {
return nil, err
}
return &chainsResponse.ChainIds, nil
return &chainsResponse.ConsumerIds, nil
}

func (n *NodeConfig) QueryChainsInfo(chainIDs []string) ([]*zctypes.ChainInfo, error) {
func (n *NodeConfig) QueryChainsInfo(consumerIDs []string) ([]*zctypes.ChainInfo, error) {
queryParams := url.Values{}
for _, chainId := range chainIDs {
queryParams.Add("chain_ids", chainId)
for _, consumerId := range consumerIDs {
queryParams.Add("consumer_ids", consumerId)
}

bz, err := n.QueryGRPCGateway("/babylon/zoneconcierge/v1/chains_info", queryParams)
Expand Down
Loading

0 comments on commit 3d713f2

Please sign in to comment.