diff --git a/test/e2e/btc_timestamping_e2e_test.go b/test/e2e/btc_timestamping_e2e_test.go index f67141503..c344e6e17 100644 --- a/test/e2e/btc_timestamping_e2e_test.go +++ b/test/e2e/btc_timestamping_e2e_test.go @@ -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].ConsumerId, initialization.ChainBID) + s.Equal(chainsInfo[0].ConsumerId, clientID) // Finalize epoch 1, 2, 3, as first headers of opposing chain are in epoch 3 var ( @@ -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].ConsumerId, 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.ConsumerId, initialization.ChainBID) + s.Equal(finalizedChainsInfo[0].FinalizedChainInfo.ConsumerId, clientID) s.Equal(finalizedChainsInfo[0].EpochInfo.EpochNumber, endEpochNum) currEpoch, err := nonValidatorNode.QueryCurrentEpoch() diff --git a/test/e2e/btc_timestamping_phase2_hermes_test.go b/test/e2e/btc_timestamping_phase2_hermes_test.go index b8eb6a1e8..4f656e068 100644 --- a/test/e2e/btc_timestamping_phase2_hermes_test.go +++ b/test/e2e/btc_timestamping_phase2_hermes_test.go @@ -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" @@ -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) @@ -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 diff --git a/test/e2e/btc_timestamping_phase2_rly_test.go b/test/e2e/btc_timestamping_phase2_rly_test.go index 7dc31959e..744fc7d06 100644 --- a/test/e2e/btc_timestamping_phase2_rly_test.go +++ b/test/e2e/btc_timestamping_phase2_rly_test.go @@ -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" @@ -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) @@ -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 diff --git a/test/e2e/configurer/chain/queries.go b/test/e2e/configurer/chain/queries.go index 4e1725cd4..d981974d5 100644 --- a/test/e2e/configurer/chain/queries.go +++ b/test/e2e/configurer/chain/queries.go @@ -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) @@ -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) @@ -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) diff --git a/test/e2e/configurer/chain/queries_ibc.go b/test/e2e/configurer/chain/queries_ibc.go index f5889b229..39c5cc3e7 100644 --- a/test/e2e/configurer/chain/queries_ibc.go +++ b/test/e2e/configurer/chain/queries_ibc.go @@ -23,6 +23,21 @@ func (n *NodeConfig) QueryIBCChannels() (*channeltypes.QueryChannelsResponse, er return &resp, nil } +func (n *NodeConfig) QueryChannelClientState(channelID, portID string) (*channeltypes.QueryChannelClientStateResponse, error) { + path := fmt.Sprintf("/ibc/core/channel/v1/channels/%s/ports/%s/client_state", channelID, portID) + bz, err := n.QueryGRPCGateway(path, url.Values{}) + if err != nil { + return nil, err + } + + var resp channeltypes.QueryChannelClientStateResponse + if err := util.Cdc.UnmarshalJSON(bz, &resp); err != nil { + return nil, err + } + + return &resp, nil +} + func (n *NodeConfig) QueryNextSequenceReceive(channelID, portID string) (*channeltypes.QueryNextSequenceReceiveResponse, error) { path := fmt.Sprintf("/ibc/core/channel/v1/channels/%s/ports/%s/next_sequence", channelID, portID) bz, err := n.QueryGRPCGateway(path, url.Values{}) diff --git a/testutil/datagen/tendermint.go b/testutil/datagen/tendermint.go index c09368739..82985156d 100644 --- a/testutil/datagen/tendermint.go +++ b/testutil/datagen/tendermint.go @@ -21,11 +21,11 @@ func GenRandomTMHeader(r *rand.Rand, chainID string, height uint64) *cmtproto.He } } -func GenRandomIBCTMHeader(r *rand.Rand, chainID string, height uint64) *ibctmtypes.Header { +func GenRandomIBCTMHeader(r *rand.Rand, height uint64) *ibctmtypes.Header { return &ibctmtypes.Header{ SignedHeader: &cmtproto.SignedHeader{ Header: &cmtproto.Header{ - ChainID: chainID, + ChainID: GenRandomHexStr(r, 10), Height: int64(height), AppHash: GenRandomByteArray(r, 32), }, @@ -34,13 +34,10 @@ func GenRandomIBCTMHeader(r *rand.Rand, chainID string, height uint64) *ibctmtyp } func GenRandomTMHeaderInfo(r *rand.Rand, chainID string, height uint64) *header.Info { - tmHeader := GenRandomIBCTMHeader(r, chainID, height) return &header.Info{ - Height: tmHeader.Header.Height, - Hash: tmHeader.Header.DataHash, - Time: tmHeader.Header.Time, - ChainID: tmHeader.Header.ChainID, - AppHash: tmHeader.Header.AppHash, + Height: int64(height), + ChainID: chainID, + AppHash: GenRandomByteArray(r, 32), } } diff --git a/x/zoneconcierge/README.md b/x/zoneconcierge/README.md index f873f4030..046c5567a 100644 --- a/x/zoneconcierge/README.md +++ b/x/zoneconcierge/README.md @@ -211,9 +211,9 @@ message Params { ### ChainInfo The [chain info storage](./keeper/chain_info_indexer.go) maintains `ChainInfo` -for each PoS blockchain. The key is the PoS blockchain's `ChainID`, and the -value is a `ChainInfo` object. The `ChainInfo` is a structure storing the -information of a PoS blockchain that checkpoints to Babylon. +for each PoS blockchain. The key is the PoS blockchain's `ConsumerID`, which is the +ID of the IBC light client. The value is a `ChainInfo` object. The `ChainInfo` is +a structure storing the information of a PoS blockchain that checkpoints to Babylon. ```protobuf // ChainInfo is the information of a CZ @@ -235,14 +235,14 @@ message ChainInfo { The [epoch chain info storage](./keeper/epoch_chain_info_indexer.go) maintains `ChainInfo` at the end of each Babylon epoch for each PoS blockchain. The key is -the PoS blockchain's `ChainID` plus the epoch number, and the value is a +the PoS blockchain's `ConsumerID` plus the epoch number, and the value is a `ChainInfo` object. ### CanonicalChain The [canonical chain storage](./keeper/canonical_chain_indexer.go) maintains the metadata of canonical IBC headers of a PoS blockchain. The key is the consumer -chain's `ChainID` plus the height, and the value is a `IndexedHeader` object. +chain's `ConsumerID` plus the height, and the value is a `IndexedHeader` object. `IndexedHeader` is a structure storing IBC header's metadata. ```protobuf @@ -277,7 +277,7 @@ message IndexedHeader { ### Fork The [fork storage](./keeper/fork_indexer.go) maintains the metadata of canonical -IBC headers of a PoS blockchain. The key is the PoS blockchain's `ChainID` plus +IBC headers of a PoS blockchain. The key is the PoS blockchain's `ConsumerID` plus the height, and the value is a list of `IndexedHeader` objects, which represent fork headers at that height. @@ -421,9 +421,9 @@ Babylon. The logic is defined at is still canonical in the segment to the current tip of the BTC light client. 3. For each of these IBC channels: - 1. Find the `ChainID` of the counterparty chain (i.e., the PoS blockchain) in + 1. Find the `ConsumerID` of the counterparty chain (i.e., the PoS blockchain) in the IBC channel. - 2. Get the `ChainInfo` of the `ChainID` at the last finalized epoch. + 2. Get the `ChainInfo` of the `ConsumerID` at the last finalized epoch. 3. Get the metadata of the last finalized epoch and its corresponding raw checkpoint. 4. Generate the proof that the last PoS blockchain's canonical header is diff --git a/x/zoneconcierge/keeper/epoch_chain_info_indexer_test.go b/x/zoneconcierge/keeper/epoch_chain_info_indexer_test.go index 59dc52c50..472c76dd5 100644 --- a/x/zoneconcierge/keeper/epoch_chain_info_indexer_test.go +++ b/x/zoneconcierge/keeper/epoch_chain_info_indexer_test.go @@ -20,7 +20,7 @@ func FuzzEpochChainInfoIndexer(f *testing.F) { babylonApp := app.Setup(t, false) zcKeeper := babylonApp.ZoneConciergeKeeper ctx := babylonApp.NewContext(false) - czChainID := "test-chainid" + consumerID := "test-consumerid" hooks := zcKeeper.Hooks() @@ -33,13 +33,13 @@ func FuzzEpochChainInfoIndexer(f *testing.F) { // invoke the hook a random number of times to simulate a random number of blocks numHeaders := datagen.RandomInt(r, 100) + 1 numForkHeaders := datagen.RandomInt(r, 10) + 1 - SimulateNewHeadersAndForks(ctx, r, &zcKeeper, czChainID, 0, numHeaders, numForkHeaders) + SimulateNewHeadersAndForks(ctx, r, &zcKeeper, consumerID, 0, numHeaders, numForkHeaders) // end this epoch hooks.AfterEpochEnds(ctx, epochNum) // check if the chain info of this epoch is recorded or not - chainInfoWithProof, err := zcKeeper.GetEpochChainInfo(ctx, czChainID, epochNum) + chainInfoWithProof, err := zcKeeper.GetEpochChainInfo(ctx, consumerID, epochNum) chainInfo := chainInfoWithProof.ChainInfo require.NoError(t, err) require.Equal(t, numHeaders-1, chainInfo.LatestHeader.Height) @@ -57,7 +57,7 @@ func FuzzGetEpochHeaders(f *testing.F) { babylonApp := app.Setup(t, false) zcKeeper := babylonApp.ZoneConciergeKeeper ctx := babylonApp.NewContext(false) - czChainID := "test-chainid" + consumerID := "test-consumerid" hooks := zcKeeper.Hooks() @@ -87,7 +87,7 @@ func FuzzGetEpochHeaders(f *testing.F) { numHeadersList = append(numHeadersList, datagen.RandomInt(r, 100)+1) numForkHeadersList = append(numForkHeadersList, datagen.RandomInt(r, 10)+1) // trigger hooks to append these headers and fork headers - expectedHeaders, _ := SimulateNewHeadersAndForks(ctx, r, &zcKeeper, czChainID, nextHeightList[i], numHeadersList[i], numForkHeadersList[i]) + expectedHeaders, _ := SimulateNewHeadersAndForks(ctx, r, &zcKeeper, consumerID, nextHeightList[i], numHeadersList[i], numForkHeadersList[i]) expectedHeadersMap[epochNum] = expectedHeaders // prepare nextHeight for the next request nextHeightList = append(nextHeightList, nextHeightList[i]+numHeadersList[i]) @@ -102,7 +102,7 @@ func FuzzGetEpochHeaders(f *testing.F) { for i := uint64(0); i < numReqs; i++ { epochNum := epochNumList[i] // check if the headers are same as expected - headers, err := zcKeeper.GetEpochHeaders(ctx, czChainID, epochNum) + headers, err := zcKeeper.GetEpochHeaders(ctx, consumerID, epochNum) require.NoError(t, err) require.Equal(t, len(expectedHeadersMap[epochNum]), len(headers)) for j := 0; j < len(expectedHeadersMap[epochNum]); j++ { diff --git a/x/zoneconcierge/keeper/fork_indexer_test.go b/x/zoneconcierge/keeper/fork_indexer_test.go index b54fce894..e1fb2a954 100644 --- a/x/zoneconcierge/keeper/fork_indexer_test.go +++ b/x/zoneconcierge/keeper/fork_indexer_test.go @@ -18,28 +18,27 @@ func FuzzForkIndexer(f *testing.F) { babylonApp := app.Setup(t, false) zcKeeper := babylonApp.ZoneConciergeKeeper ctx := babylonApp.NewContext(false) - czChainID := "test-chainid" + consumerID := "test-consumerid" // invoke the hook a random number of times to simulate a random number of blocks numHeaders := datagen.RandomInt(r, 100) + 1 numForkHeaders := datagen.RandomInt(r, 10) + 1 - _, forkHeaders := SimulateNewHeadersAndForks(ctx, r, &zcKeeper, czChainID, 0, numHeaders, numForkHeaders) + _, forkHeaders := SimulateNewHeadersAndForks(ctx, r, &zcKeeper, consumerID, 0, numHeaders, numForkHeaders) // check if the fork is updated or not - forks := zcKeeper.GetForks(ctx, czChainID, numHeaders-1) + forks := zcKeeper.GetForks(ctx, consumerID, numHeaders-1) require.Equal(t, numForkHeaders, uint64(len(forks.Headers))) for i := range forks.Headers { - require.Equal(t, czChainID, forks.Headers[i].ConsumerId) require.Equal(t, numHeaders-1, forks.Headers[i].Height) require.Equal(t, forkHeaders[i].Header.AppHash, forks.Headers[i].Hash) } // check if the chain info is updated or not - chainInfo, err := zcKeeper.GetChainInfo(ctx, czChainID) + chainInfo, err := zcKeeper.GetChainInfo(ctx, consumerID) require.NoError(t, err) require.Equal(t, numForkHeaders, uint64(len(chainInfo.LatestForks.Headers))) for i := range forks.Headers { - require.Equal(t, czChainID, chainInfo.LatestForks.Headers[i].ConsumerId) + require.Equal(t, consumerID, chainInfo.LatestForks.Headers[i].ConsumerId) require.Equal(t, numHeaders-1, chainInfo.LatestForks.Headers[i].Height) require.Equal(t, forkHeaders[i].Header.AppHash, chainInfo.LatestForks.Headers[i].Hash) } diff --git a/x/zoneconcierge/keeper/grpc_query.go b/x/zoneconcierge/keeper/grpc_query.go index 22e56e8aa..5b0e7ee62 100644 --- a/x/zoneconcierge/keeper/grpc_query.go +++ b/x/zoneconcierge/keeper/grpc_query.go @@ -57,7 +57,7 @@ func (k Keeper) ChainsInfo(c context.Context, req *types.QueryChainsInfoRequest) // return if no chain IDs are provided if len(req.ConsumerIds) == 0 { - return nil, status.Error(codes.InvalidArgument, "chain IDs cannot be empty") + return nil, status.Error(codes.InvalidArgument, "consumer IDs cannot be empty") } // return if chain IDs exceed the limit @@ -118,7 +118,7 @@ func (k Keeper) EpochChainsInfo(c context.Context, req *types.QueryEpochChainsIn // return if no chain IDs are provided if len(req.ConsumerIds) == 0 { - return nil, status.Error(codes.InvalidArgument, "chain IDs cannot be empty") + return nil, status.Error(codes.InvalidArgument, "consumer IDs cannot be empty") } // return if chain IDs exceed the limit diff --git a/x/zoneconcierge/keeper/grpc_query_test.go b/x/zoneconcierge/keeper/grpc_query_test.go index 03777faf3..1b5d91e8e 100644 --- a/x/zoneconcierge/keeper/grpc_query_test.go +++ b/x/zoneconcierge/keeper/grpc_query_test.go @@ -37,21 +37,21 @@ func FuzzChainList(f *testing.F) { // invoke the hook a random number of times with random chain IDs numHeaders := datagen.RandomInt(r, 100) + 1 - allChainIDs := []string{} + allConsumerIDs := []string{} for i := uint64(0); i < numHeaders; i++ { var consumerID string // simulate the scenario that some headers belong to the same chain if i > 0 && datagen.OneInN(r, 2) { - consumerID = allChainIDs[r.Intn(len(allChainIDs))] + consumerID = allConsumerIDs[r.Intn(len(allConsumerIDs))] } else { consumerID = datagen.GenRandomHexStr(r, 30) - allChainIDs = append(allChainIDs, consumerID) + allConsumerIDs = append(allConsumerIDs, consumerID) } - header := datagen.GenRandomIBCTMHeader(r, consumerID, 0) - zcKeeper.HandleHeaderWithValidCommit(ctx, datagen.GenRandomByteArray(r, 32), datagen.HeaderToHeaderInfo(header), consumerID, false) + header := datagen.GenRandomIBCTMHeader(r, 0) + zcKeeper.HandleHeaderWithValidCommit(ctx, datagen.GenRandomByteArray(r, 32), datagen.HeaderToHeaderInfo(header), false) } - limit := datagen.RandomInt(r, len(allChainIDs)) + 1 + limit := datagen.RandomInt(r, len(allConsumerIDs)) + 1 // make query to get actual chain IDs resp, err := zcKeeper.ChainList(ctx, &zctypes.QueryChainListRequest{ @@ -63,9 +63,9 @@ func FuzzChainList(f *testing.F) { actualConsumerIDs := resp.ConsumerIds require.Equal(t, limit, uint64(len(actualConsumerIDs))) - allChainIDs = zcKeeper.GetAllConsumerIDs(ctx) + allConsumerIDs = zcKeeper.GetAllConsumerIDs(ctx) for i := uint64(0); i < limit; i++ { - require.Equal(t, allChainIDs[i], actualConsumerIDs[i]) + require.Equal(t, allConsumerIDs[i], actualConsumerIDs[i]) } }) } @@ -121,22 +121,22 @@ func FuzzHeader(f *testing.F) { babylonApp := app.Setup(t, false) zcKeeper := babylonApp.ZoneConciergeKeeper ctx := babylonApp.NewContext(false) - czChainID := "test-chainid" + consumerID := "test-consumerid" // invoke the hook a random number of times to simulate a random number of blocks numHeaders := datagen.RandomInt(r, 100) + 2 numForkHeaders := datagen.RandomInt(r, 10) + 1 - headers, forkHeaders := SimulateNewHeadersAndForks(ctx, r, &zcKeeper, czChainID, 0, numHeaders, numForkHeaders) + headers, forkHeaders := SimulateNewHeadersAndForks(ctx, r, &zcKeeper, consumerID, 0, numHeaders, numForkHeaders) // find header at a random height and assert correctness against the expected header randomHeight := datagen.RandomInt(r, int(numHeaders-1)) - resp, err := zcKeeper.Header(ctx, &zctypes.QueryHeaderRequest{ConsumerId: czChainID, Height: randomHeight}) + resp, err := zcKeeper.Header(ctx, &zctypes.QueryHeaderRequest{ConsumerId: consumerID, Height: randomHeight}) require.NoError(t, err) require.Equal(t, headers[randomHeight].Header.AppHash, resp.Header.Hash) require.Len(t, resp.ForkHeaders.Headers, 0) // find the last header and fork headers then assert correctness - resp, err = zcKeeper.Header(ctx, &zctypes.QueryHeaderRequest{ConsumerId: czChainID, Height: numHeaders - 1}) + resp, err = zcKeeper.Header(ctx, &zctypes.QueryHeaderRequest{ConsumerId: consumerID, Height: numHeaders - 1}) require.NoError(t, err) require.Equal(t, headers[numHeaders-1].Header.AppHash, resp.Header.Hash) require.Len(t, resp.ForkHeaders.Headers, int(numForkHeaders)) @@ -220,12 +220,12 @@ func FuzzEpochChainsInfo(f *testing.F) { // if num of chain ids exceed the max limit, query should fail largeNumChains := datagen.RandomInt(r, 10) + 101 - var maxChainIDs []string + var maxConsumerIDs []string for i := uint64(0); i < largeNumChains; i++ { - maxChainIDs = append(maxChainIDs, datagen.GenRandomHexStr(r, 30)) + maxConsumerIDs = append(maxConsumerIDs, datagen.GenRandomHexStr(r, 30)) } randomEpochNum := datagen.RandomInt(r, 10) + 1 - _, err := zcKeeper.EpochChainsInfo(ctx, &zctypes.QueryEpochChainsInfoRequest{EpochNum: randomEpochNum, ConsumerIds: maxChainIDs}) + _, err := zcKeeper.EpochChainsInfo(ctx, &zctypes.QueryEpochChainsInfoRequest{EpochNum: randomEpochNum, ConsumerIds: maxConsumerIDs}) require.Error(t, err) // if no input is passed in, query should fail @@ -237,8 +237,8 @@ func FuzzEpochChainsInfo(f *testing.F) { require.Error(t, err) // if chain ids contain duplicates, query should fail - randomChainID := datagen.GenRandomHexStr(r, 30) - dupConsumerIds := []string{randomChainID, randomChainID} + randomConsumerID := datagen.GenRandomHexStr(r, 30) + dupConsumerIds := []string{randomConsumerID, randomConsumerID} _, err = zcKeeper.EpochChainsInfo(ctx, &zctypes.QueryEpochChainsInfoRequest{EpochNum: randomEpochNum, ConsumerIds: dupConsumerIds}) require.Error(t, err) }) @@ -253,17 +253,17 @@ func FuzzListHeaders(f *testing.F) { babylonApp := app.Setup(t, false) zcKeeper := babylonApp.ZoneConciergeKeeper ctx := babylonApp.NewContext(false) - czChainID := "test-chainid" + consumerID := "test-consumerid" // invoke the hook a random number of times to simulate a random number of blocks numHeaders := datagen.RandomInt(r, 100) + 1 numForkHeaders := datagen.RandomInt(r, 10) + 1 - headers, _ := SimulateNewHeadersAndForks(ctx, r, &zcKeeper, czChainID, 0, numHeaders, numForkHeaders) + headers, _ := SimulateNewHeadersAndForks(ctx, r, &zcKeeper, consumerID, 0, numHeaders, numForkHeaders) // a request with randomised pagination limit := datagen.RandomInt(r, int(numHeaders)) + 1 req := &zctypes.QueryListHeadersRequest{ - ConsumerId: czChainID, + ConsumerId: consumerID, Pagination: &query.PageRequest{ Limit: limit, }, @@ -287,7 +287,7 @@ func FuzzListEpochHeaders(f *testing.F) { zcKeeper := babylonApp.ZoneConciergeKeeper epochingKeeper := babylonApp.EpochingKeeper ctx := babylonApp.NewContext(false) - czChainID := "test-chainid" + consumerID := "test-consumerid" hooks := zcKeeper.Hooks() @@ -318,7 +318,7 @@ func FuzzListEpochHeaders(f *testing.F) { numHeadersList = append(numHeadersList, datagen.RandomInt(r, 100)+1) numForkHeadersList = append(numForkHeadersList, datagen.RandomInt(r, 10)+1) // trigger hooks to append these headers and fork headers - expectedHeaders, _ := SimulateNewHeadersAndForks(ctx, r, &zcKeeper, czChainID, nextHeightList[i], numHeadersList[i], numForkHeadersList[i]) + expectedHeaders, _ := SimulateNewHeadersAndForks(ctx, r, &zcKeeper, consumerID, nextHeightList[i], numHeadersList[i], numForkHeadersList[i]) expectedHeadersMap[epochNum] = expectedHeaders // prepare nextHeight for the next request nextHeightList = append(nextHeightList, nextHeightList[i]+numHeadersList[i]) @@ -334,7 +334,7 @@ func FuzzListEpochHeaders(f *testing.F) { epochNum := epochNumList[i] // make request req := &zctypes.QueryListEpochHeadersRequest{ - ConsumerId: czChainID, + ConsumerId: consumerID, EpochNum: epochNum, } resp, err := zcKeeper.ListEpochHeaders(ctx, req) @@ -405,17 +405,17 @@ func FuzzFinalizedChainInfo(f *testing.F) { ) numChains := datagen.RandomInt(r, 100) + 1 for i := uint64(0); i < numChains; i++ { - czChainIDLen := datagen.RandomInt(r, 40) + 10 - czChainID := string(datagen.GenRandomByteArray(r, czChainIDLen)) + consumerIDLen := datagen.RandomInt(r, 40) + 10 + consumerID := string(datagen.GenRandomByteArray(r, consumerIDLen)) // invoke the hook a random number of times to simulate a random number of blocks numHeaders := datagen.RandomInt(r, 100) + 1 numForkHeaders := datagen.RandomInt(r, 10) + 1 - SimulateNewHeadersAndForks(ctx, r, zcKeeper, czChainID, 0, numHeaders, numForkHeaders) + SimulateNewHeadersAndForks(ctx, r, zcKeeper, consumerID, 0, numHeaders, numForkHeaders) - consumerIDs = append(consumerIDs, czChainID) + consumerIDs = append(consumerIDs, consumerID) chainsInfo = append(chainsInfo, chainInfo{ - consumerID: czChainID, + consumerID: consumerID, numHeaders: numHeaders, numForkHeaders: numForkHeaders, }) diff --git a/x/zoneconcierge/keeper/header_handler.go b/x/zoneconcierge/keeper/header_handler.go index c96b9347d..412664328 100644 --- a/x/zoneconcierge/keeper/header_handler.go +++ b/x/zoneconcierge/keeper/header_handler.go @@ -10,11 +10,11 @@ import ( ) // HandleHeaderWithValidCommit handles a CZ header with a valid QC -func (k Keeper) HandleHeaderWithValidCommit(ctx context.Context, txHash []byte, header *types.HeaderInfo, clientID string, isOnFork bool) { +func (k Keeper) HandleHeaderWithValidCommit(ctx context.Context, txHash []byte, header *types.HeaderInfo, isOnFork bool) { sdkCtx := sdk.UnwrapSDKContext(ctx) babylonHeader := sdkCtx.HeaderInfo() indexedHeader := types.IndexedHeader{ - ConsumerId: clientID, + ConsumerId: header.ClientId, Hash: header.AppHash, Height: header.Height, Time: &header.Time, diff --git a/x/zoneconcierge/keeper/ibc_header_decorator.go b/x/zoneconcierge/keeper/ibc_header_decorator.go index ecac68f9a..930f33e6e 100644 --- a/x/zoneconcierge/keeper/ibc_header_decorator.go +++ b/x/zoneconcierge/keeper/ibc_header_decorator.go @@ -22,22 +22,21 @@ func NewIBCHeaderDecorator(k Keeper) *IBCHeaderDecorator { } } -func (d *IBCHeaderDecorator) parseMsgUpdateClient(ctx sdk.Context, m sdk.Msg) (*types.HeaderInfo, *ibctmtypes.ClientState, string) { +func (d *IBCHeaderDecorator) getHeaderAndClientState(ctx sdk.Context, m sdk.Msg) (*types.HeaderInfo, *ibctmtypes.ClientState) { // ensure the message is MsgUpdateClient msgUpdateClient, ok := m.(*clienttypes.MsgUpdateClient) if !ok { - return nil, nil, "" + return nil, nil } - clientID := msgUpdateClient.ClientId // unpack ClientMsg inside MsgUpdateClient clientMsg, err := clienttypes.UnpackClientMessage(msgUpdateClient.ClientMessage) if err != nil { - return nil, nil, "" + return nil, nil } // ensure the ClientMsg is a Comet header ibctmHeader, ok := clientMsg.(*ibctmtypes.Header) if !ok { - return nil, nil, "" + return nil, nil } // all good, we get the headerInfo @@ -52,15 +51,15 @@ func (d *IBCHeaderDecorator) parseMsgUpdateClient(ctx sdk.Context, m sdk.Msg) (* // ensure the corresponding clientState exists clientState, exist := d.k.clientKeeper.GetClientState(ctx, msgUpdateClient.ClientId) if !exist { - return nil, nil, "" + return nil, nil } // ensure the clientState is a Comet clientState cmtClientState, ok := clientState.(*ibctmtypes.ClientState) if !ok { - return nil, nil, "" + return nil, nil } - return headerInfo, cmtClientState, clientID + return headerInfo, cmtClientState } func (d *IBCHeaderDecorator) PostHandle(ctx sdk.Context, tx sdk.Tx, simulate, success bool, next sdk.PostHandler) (sdk.Context, error) { @@ -79,7 +78,7 @@ func (d *IBCHeaderDecorator) PostHandle(ctx sdk.Context, tx sdk.Tx, simulate, su for _, msg := range tx.GetMsgs() { // try to extract the headerInfo and the client's status - headerInfo, clientState, clientID := d.parseMsgUpdateClient(ctx, msg) + headerInfo, clientState := d.getHeaderAndClientState(ctx, msg) if headerInfo == nil { continue } @@ -92,7 +91,7 @@ func (d *IBCHeaderDecorator) PostHandle(ctx sdk.Context, tx sdk.Tx, simulate, su // fail, eventually failing the entire tx. All state updates due to this // failed tx will be rolled back. isOnFork := !clientState.FrozenHeight.IsZero() - d.k.HandleHeaderWithValidCommit(ctx, txHash, headerInfo, clientID, isOnFork) + d.k.HandleHeaderWithValidCommit(ctx, txHash, headerInfo, isOnFork) // unfreeze client (by setting FrozenHeight to zero again) if the client is frozen // due to a fork header diff --git a/x/zoneconcierge/keeper/ibc_packet_btc_timestamp.go b/x/zoneconcierge/keeper/ibc_packet_btc_timestamp.go index 428ec16fe..218d25ed6 100644 --- a/x/zoneconcierge/keeper/ibc_packet_btc_timestamp.go +++ b/x/zoneconcierge/keeper/ibc_packet_btc_timestamp.go @@ -6,7 +6,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" - ibctmtypes "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" bbn "github.com/babylonlabs-io/babylon/types" btcctypes "github.com/babylonlabs-io/babylon/x/btccheckpoint/types" @@ -27,21 +26,16 @@ type finalizedInfo struct { BTCHeaders []*btclctypes.BTCHeaderInfo } -// getChainID gets the ID of the counterparty chain under the given channel -func (k Keeper) getChainID(ctx context.Context, channel channeltypes.IdentifiedChannel) (string, error) { +// getClientID gets the ID of the IBC client under the given channel +// We will use the client ID as the consumer ID to uniquely identify +// the consumer chain +func (k Keeper) getClientID(ctx context.Context, channel channeltypes.IdentifiedChannel) (string, error) { sdkCtx := sdk.UnwrapSDKContext(ctx) - // get clientState under this channel - _, clientState, err := k.channelKeeper.GetChannelClientState(sdkCtx, channel.PortId, channel.ChannelId) + clientID, _, err := k.channelKeeper.GetChannelClientState(sdkCtx, channel.PortId, channel.ChannelId) if err != nil { return "", err } - // cast clientState to comet clientState - // TODO: support for chains other than Cosmos zones - cmtClientState, ok := clientState.(*ibctmtypes.ClientState) - if !ok { - return "", fmt.Errorf("client must be a Comet client, expected: %T, got: %T", &ibctmtypes.ClientState{}, cmtClientState) - } - return cmtClientState.ChainId, nil + return clientID, nil } // getFinalizedInfo returns metadata and proofs that are identical to all BTC timestamps in the same epoch @@ -235,7 +229,7 @@ func (k Keeper) BroadcastBTCTimestamps( // for each channel, construct and send BTC timestamp for _, channel := range openZCChannels { // get the ID of the chain under this channel - consumerID, err := k.getChainID(ctx, channel) + consumerID, err := k.getClientID(ctx, channel) if err != nil { k.Logger(sdkCtx).Error("failed to get chain ID, skip sending BTC timestamp for this chain", "channelID", channel.ChannelId, "error", err) continue diff --git a/x/zoneconcierge/keeper/keeper_test.go b/x/zoneconcierge/keeper/keeper_test.go index aaf972240..d6a68a57e 100644 --- a/x/zoneconcierge/keeper/keeper_test.go +++ b/x/zoneconcierge/keeper/keeper_test.go @@ -15,8 +15,8 @@ func SimulateNewHeaders(ctx context.Context, r *rand.Rand, k *zckeeper.Keeper, c headers := []*ibctmtypes.Header{} // invoke the hook a number of times to simulate a number of blocks for i := uint64(0); i < numHeaders; i++ { - header := datagen.GenRandomIBCTMHeader(r, consumerID, startHeight+i) - k.HandleHeaderWithValidCommit(ctx, datagen.GenRandomByteArray(r, 32), datagen.HeaderToHeaderInfo(header), consumerID, false) + header := datagen.GenRandomIBCTMHeader(r, startHeight+i) + k.HandleHeaderWithValidCommit(ctx, datagen.GenRandomByteArray(r, 32), datagen.HeaderToHeaderInfo(header), false) headers = append(headers, header) } return headers @@ -27,16 +27,16 @@ func SimulateNewHeadersAndForks(ctx context.Context, r *rand.Rand, k *zckeeper.K headers := []*ibctmtypes.Header{} // invoke the hook a number of times to simulate a number of blocks for i := uint64(0); i < numHeaders; i++ { - header := datagen.GenRandomIBCTMHeader(r, consumerID, startHeight+i) - k.HandleHeaderWithValidCommit(ctx, datagen.GenRandomByteArray(r, 32), datagen.HeaderToHeaderInfo(header), consumerID, false) + header := datagen.GenRandomIBCTMHeader(r, startHeight+i) + k.HandleHeaderWithValidCommit(ctx, datagen.GenRandomByteArray(r, 32), datagen.HeaderToHeaderInfo(header), false) headers = append(headers, header) } // generate a number of fork headers forkHeaders := []*ibctmtypes.Header{} for i := uint64(0); i < numForkHeaders; i++ { - header := datagen.GenRandomIBCTMHeader(r, consumerID, startHeight+numHeaders-1) - k.HandleHeaderWithValidCommit(ctx, datagen.GenRandomByteArray(r, 32), datagen.HeaderToHeaderInfo(header), consumerID, true) + header := datagen.GenRandomIBCTMHeader(r, startHeight+numHeaders-1) + k.HandleHeaderWithValidCommit(ctx, datagen.GenRandomByteArray(r, 32), datagen.HeaderToHeaderInfo(header), true) forkHeaders = append(forkHeaders, header) } return headers, forkHeaders diff --git a/x/zoneconcierge/keeper/proof_btc_timestamp_test.go b/x/zoneconcierge/keeper/proof_btc_timestamp_test.go index c1f0aa673..535079d8f 100644 --- a/x/zoneconcierge/keeper/proof_btc_timestamp_test.go +++ b/x/zoneconcierge/keeper/proof_btc_timestamp_test.go @@ -43,9 +43,9 @@ func FuzzProofCZHeaderInEpoch(f *testing.F) { // handle a random header from a random consumer chain consumerID := datagen.GenRandomHexStr(r, 10) height := datagen.RandomInt(r, 100) + 1 - ibctmHeader := datagen.GenRandomIBCTMHeader(r, consumerID, height) + ibctmHeader := datagen.GenRandomIBCTMHeader(r, height) headerInfo := datagen.HeaderToHeaderInfo(ibctmHeader) - zck.HandleHeaderWithValidCommit(h.Ctx, datagen.GenRandomByteArray(r, 32), headerInfo, consumerID, false) + zck.HandleHeaderWithValidCommit(h.Ctx, datagen.GenRandomByteArray(r, 32), headerInfo, false) // ensure the header is successfully inserted indexedHeader, err := zck.GetHeader(h.Ctx, consumerID, height) diff --git a/x/zoneconcierge/types/btc_timestamp_test.go b/x/zoneconcierge/types/btc_timestamp_test.go index fc2a9e43b..a0d8d8d46 100644 --- a/x/zoneconcierge/types/btc_timestamp_test.go +++ b/x/zoneconcierge/types/btc_timestamp_test.go @@ -61,9 +61,9 @@ func FuzzBTCTimestamp(f *testing.F) { // handle a random header from a random consumer chain consumerID := datagen.GenRandomHexStr(r, 10) height := datagen.RandomInt(r, 100) + 1 - ibctmHeader := datagen.GenRandomIBCTMHeader(r, consumerID, height) + ibctmHeader := datagen.GenRandomIBCTMHeader(r, height) headerInfo := datagen.HeaderToHeaderInfo(ibctmHeader) - zck.HandleHeaderWithValidCommit(h.Ctx, datagen.GenRandomByteArray(r, 32), headerInfo, consumerID, false) + zck.HandleHeaderWithValidCommit(h.Ctx, datagen.GenRandomByteArray(r, 32), headerInfo, false) // ensure the header is successfully inserted indexedHeader, err := zck.GetHeader(h.Ctx, consumerID, height)