Skip to content

Commit

Permalink
chore: Add consensus state heights query (backport cosmos#1336) (cosm…
Browse files Browse the repository at this point in the history
…os#1507)

* chore: Add consensus state heights query (cosmos#1336)

* add ConsensusStateHeights query

* add cli for ConsensusStateHeights Query

* update CHANGELOG.md

* Update modules/core/02-client/keeper/grpc_query.go

Co-authored-by: Damian Nolan <damiannolan@gmail.com>

* Update modules/core/02-client/client/cli/query.go

Co-authored-by: Damian Nolan <damiannolan@gmail.com>

* Update modules/core/02-client/client/cli/query.go

Co-authored-by: Damian Nolan <damiannolan@gmail.com>

* Update modules/core/02-client/client/cli/query.go

Co-authored-by: Damian Nolan <damiannolan@gmail.com>

* update consensus height query

* very minor changes in modules/core/02-client grpc_query_test

* Update modules/core/02-client/keeper/grpc_query_test.go

Co-authored-by: Sean King <seantking@users.noreply.github.com>

* Update modules/core/02-client/keeper/grpc_query_test.go

Co-authored-by: Sean King <seantking@users.noreply.github.com>

* Update modules/core/02-client/keeper/grpc_query_test.go

Co-authored-by: Sean King <seantking@users.noreply.github.com>

* Update modules/core/02-client/keeper/grpc_query_test.go

Co-authored-by: Sean King <seantking@users.noreply.github.com>

* Update modules/core/02-client/client/cli/query.go

Co-authored-by: Sean King <seantking@users.noreply.github.com>

* Update modules/core/02-client/keeper/grpc_query_test.go

Co-authored-by: Carlos Rodriguez <carlos@interchain.io>

* Update CHANGELOG.md

Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>

* update swagger.yaml; update 02-client grpc_query_test

* Update modules/core/02-client/keeper/grpc_query_test.go

Co-authored-by: Damian Nolan <damiannolan@gmail.com>

* nit

Co-authored-by: Damian Nolan <damiannolan@gmail.com>
Co-authored-by: Sean King <seantking@users.noreply.github.com>
Co-authored-by: Carlos Rodriguez <carlos@interchain.io>
Co-authored-by: vuong <56973102+vuong177@users.noreply.github.com>
Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>
(cherry picked from commit 042d818)

* fix conflicts and change gRPC web route to consensus_state/{client_id}/heights

Co-authored-by: khanh <50263489+catShaark@users.noreply.github.com>
Co-authored-by: crodriguezvega <carlos@interchain.io>
  • Loading branch information
3 people authored and dudong2 committed Jan 19, 2023
1 parent 7b92fcc commit 25b3e1b
Show file tree
Hide file tree
Showing 8 changed files with 678 additions and 36 deletions.
411 changes: 409 additions & 2 deletions docs/client/swagger-ui/swagger.yaml

Large diffs are not rendered by default.

37 changes: 37 additions & 0 deletions docs/ibc/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@
- [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse)
- [QueryClientStatusRequest](#ibc.core.client.v1.QueryClientStatusRequest)
- [QueryClientStatusResponse](#ibc.core.client.v1.QueryClientStatusResponse)
- [QueryConsensusStateHeightsRequest](#ibc.core.client.v1.QueryConsensusStateHeightsRequest)
- [QueryConsensusStateHeightsResponse](#ibc.core.client.v1.QueryConsensusStateHeightsResponse)
- [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest)
- [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse)
- [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest)
Expand Down Expand Up @@ -2324,6 +2326,40 @@ method. It returns the current status of the IBC client.



<a name="ibc.core.client.v1.QueryConsensusStateHeightsRequest"></a>

### QueryConsensusStateHeightsRequest
QueryConsensusStateHeightsRequest is the request type for Query/ConsensusStateHeights
RPC method.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `client_id` | [string](#string) | | client identifier |
| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request |






<a name="ibc.core.client.v1.QueryConsensusStateHeightsResponse"></a>

### QueryConsensusStateHeightsResponse
QueryConsensusStateHeightsResponse is the response type for the
Query/ConsensusStateHeights RPC method


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `consensus_state_heights` | [Height](#ibc.core.client.v1.Height) | repeated | consensus state heights |
| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response |






<a name="ibc.core.client.v1.QueryConsensusStateRequest"></a>

### QueryConsensusStateRequest
Expand Down Expand Up @@ -2467,6 +2503,7 @@ Query provides defines the gRPC querier service
| `ClientStates` | [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) | [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) | ClientStates queries all the IBC light clients of a chain. | GET|/ibc/core/client/v1/client_states|
| `ConsensusState` | [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) | [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) | ConsensusState queries a consensus state associated with a client state at a given height. | GET|/ibc/core/client/v1/consensus_states/{client_id}/revision/{revision_number}/height/{revision_height}|
| `ConsensusStates` | [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) | [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) | ConsensusStates queries all the consensus state associated with a given client. | GET|/ibc/core/client/v1/consensus_states/{client_id}|
| `ConsensusStateHeights` | [QueryConsensusStateHeightsRequest](#ibc.core.client.v1.QueryConsensusStateHeightsRequest) | [QueryConsensusStateHeightsResponse](#ibc.core.client.v1.QueryConsensusStateHeightsResponse) | ConsensusStateHeights queries the height of every consensus states associated with a given client. | GET|/ibc/core/client/v1/consensus_states/{client_id}/heights|
| `ClientStatus` | [QueryClientStatusRequest](#ibc.core.client.v1.QueryClientStatusRequest) | [QueryClientStatusResponse](#ibc.core.client.v1.QueryClientStatusResponse) | Status queries the status of an IBC client. | GET|/ibc/core/client/v1/client_status/{client_id}|
| `ClientParams` | [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) | [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) | ClientParams queries all parameters of the ibc client. | GET|/ibc/client/v1/params|
| `UpgradedClientState` | [QueryUpgradedClientStateRequest](#ibc.core.client.v1.QueryUpgradedClientStateRequest) | [QueryUpgradedClientStateResponse](#ibc.core.client.v1.QueryUpgradedClientStateResponse) | UpgradedClientState queries an Upgraded IBC light client. | GET|/ibc/core/client/v1/upgraded_client_states|
Expand Down
1 change: 1 addition & 0 deletions modules/core/02-client/client/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func GetQueryCmd() *cobra.Command {
GetCmdQueryClientState(),
GetCmdQueryClientStatus(),
GetCmdQueryConsensusStates(),
GetCmdQueryConsensusStateHeights(),
GetCmdQueryConsensusState(),
GetCmdQueryHeader(),
GetCmdSelfConsensusState(),
Expand Down
43 changes: 43 additions & 0 deletions modules/core/02-client/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,49 @@ func GetCmdQueryConsensusStates() *cobra.Command {
return cmd
}

// GetCmdQueryConsensusStateHeights defines the command to query the heights of all client consensus states associated with the
// provided client ID.
func GetCmdQueryConsensusStateHeights() *cobra.Command {
cmd := &cobra.Command{
Use: "consensus-state-heights [client-id]",
Short: "Query the heights of all consensus states of a client.",
Long: "Query the heights of all consensus states associated with the provided client ID.",
Example: fmt.Sprintf("%s query %s %s consensus-state-heights [client-id]", version.AppName, host.ModuleName, types.SubModuleName),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}

clientID := args[0]

queryClient := types.NewQueryClient(clientCtx)

pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}

req := &types.QueryConsensusStateHeightsRequest{
ClientId: clientID,
Pagination: pageReq,
}

res, err := queryClient.ConsensusStateHeights(cmd.Context(), req)
if err != nil {
return err
}

return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "consensus state heights")

return cmd
}

// GetCmdQueryConsensusState defines the command to query the consensus state of
// the chain as defined in https://github.com/cosmos/ibc/tree/master/spec/core/ics-002-client-semantics#query
func GetCmdQueryConsensusState() *cobra.Command {
Expand Down
40 changes: 40 additions & 0 deletions modules/core/02-client/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,46 @@ func (q Keeper) ConsensusStates(c context.Context, req *types.QueryConsensusStat
}, nil
}

// ConsensusStateHeights implements the Query/ConsensusStateHeights gRPC method
func (q Keeper) ConsensusStateHeights(c context.Context, req *types.QueryConsensusStateHeightsRequest) (*types.QueryConsensusStateHeightsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}

if err := host.ClientIdentifierValidator(req.ClientId); err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}

ctx := sdk.UnwrapSDKContext(c)

var consensusStateHeights []types.Height
store := prefix.NewStore(ctx.KVStore(q.storeKey), host.FullClientKey(req.ClientId, []byte(fmt.Sprintf("%s/", host.KeyConsensusStatePrefix))))

pageRes, err := query.FilteredPaginate(store, req.Pagination, func(key, _ []byte, accumulate bool) (bool, error) {
// filter any metadata stored under consensus state key
if bytes.Contains(key, []byte("/")) {
return false, nil
}

height, err := types.ParseHeight(string(key))
if err != nil {
return false, err
}

consensusStateHeights = append(consensusStateHeights, height)
return true, nil
})

if err != nil {
return nil, err
}

return &types.QueryConsensusStateHeightsResponse{
ConsensusStateHeights: consensusStateHeights,
Pagination: pageRes,
}, nil
}

// ClientStatus implements the Query/ClientStatus gRPC method
func (q Keeper) ClientStatus(c context.Context, req *types.QueryClientStatusRequest) (*types.QueryClientStatusResponse, error) {
if req == nil {
Expand Down
154 changes: 120 additions & 34 deletions modules/core/02-client/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package keeper_test

import (
"fmt"
"time"

codectypes "github.com/line/lbm-sdk/codec/types"
sdk "github.com/line/lbm-sdk/types"
Expand All @@ -11,7 +10,6 @@ import (
"google.golang.org/grpc/metadata"

"github.com/line/ibc-go/v3/modules/core/02-client/types"
commitmenttypes "github.com/line/ibc-go/v3/modules/core/23-commitment/types"
"github.com/line/ibc-go/v3/modules/core/exported"
ibcoctypes "github.com/line/ibc-go/v3/modules/light-clients/99-ostracon/types"
ibctesting "github.com/line/ibc-go/v3/testing"
Expand Down Expand Up @@ -294,7 +292,7 @@ func (suite *KeeperTestSuite) TestQueryConsensusState() {
func (suite *KeeperTestSuite) TestQueryConsensusStates() {
var (
req *types.QueryConsensusStatesRequest
expConsensusStates = []types.ConsensusStateWithHeight{}
expConsensusStates []types.ConsensusStateWithHeight
)

testCases := []struct {
Expand All @@ -303,14 +301,7 @@ func (suite *KeeperTestSuite) TestQueryConsensusStates() {
expPass bool
}{
{
"invalid client identifier",
func() {
req = &types.QueryConsensusStatesRequest{}
},
false,
},
{
"empty pagination",
"success: without pagination",
func() {
req = &types.QueryConsensusStatesRequest{
ClientId: testClientID,
Expand All @@ -334,29 +325,30 @@ func (suite *KeeperTestSuite) TestQueryConsensusStates() {
{
"success",
func() {
cs := ibcoctypes.NewConsensusState(
suite.consensusState.Timestamp, commitmenttypes.NewMerkleRoot([]byte("hash1")), nil,
)
cs2 := ibcoctypes.NewConsensusState(
suite.consensusState.Timestamp.Add(time.Second), commitmenttypes.NewMerkleRoot([]byte("hash2")), nil,
)

clientState := ibcoctypes.NewClientState(
testChainID, ibcoctypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false,
)

// Use CreateClient to ensure that processedTime metadata gets stored.
clientId, err := suite.keeper.CreateClient(suite.ctx, clientState, cs)
path := ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.SetupClients(path)

height1 := path.EndpointA.GetClientState().GetLatestHeight().(types.Height)
expConsensusStates = append(
expConsensusStates,
types.NewConsensusStateWithHeight(
height1,
path.EndpointA.GetConsensusState(height1),
))

err := path.EndpointA.UpdateClient()
suite.Require().NoError(err)
suite.keeper.SetClientConsensusState(suite.ctx, clientId, testClientHeight.Increment(), cs2)

// order is swapped because the res is sorted by client id
expConsensusStates = []types.ConsensusStateWithHeight{
types.NewConsensusStateWithHeight(testClientHeight, cs),
types.NewConsensusStateWithHeight(testClientHeight.Increment().(types.Height), cs2),
}
height2 := path.EndpointA.GetClientState().GetLatestHeight().(types.Height)
expConsensusStates = append(
expConsensusStates,
types.NewConsensusStateWithHeight(
height2,
path.EndpointA.GetConsensusState(height2),
))

req = &types.QueryConsensusStatesRequest{
ClientId: clientId,
ClientId: path.EndpointA.ClientID,
Pagination: &query.PageRequest{
Limit: 3,
CountTotal: true,
Expand All @@ -365,16 +357,22 @@ func (suite *KeeperTestSuite) TestQueryConsensusStates() {
},
true,
},
{
"invalid client identifier",
func() {
req = &types.QueryConsensusStatesRequest{}
},
false,
},
}

for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset

tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)

res, err := suite.queryClient.ConsensusStates(ctx, req)
ctx := sdk.WrapSDKContext(suite.chainA.GetContext())
res, err := suite.chainA.QueryServer.ConsensusStates(ctx, req)

if tc.expPass {
suite.Require().NoError(err)
Expand All @@ -395,6 +393,94 @@ func (suite *KeeperTestSuite) TestQueryConsensusStates() {
}
}

func (suite *KeeperTestSuite) TestQueryConsensusStateHeights() {
var (
req *types.QueryConsensusStateHeightsRequest
expConsensusStateHeights []types.Height
)

testCases := []struct {
msg string
malleate func()
expPass bool
}{
{
"success: without pagination",
func() {
req = &types.QueryConsensusStateHeightsRequest{
ClientId: testClientID,
}
},
true,
},
{
"success: response contains no results",
func() {
req = &types.QueryConsensusStateHeightsRequest{
ClientId: testClientID,
Pagination: &query.PageRequest{
Limit: 3,
CountTotal: true,
},
}
},
true,
},
{
"success: returns consensus heights",
func() {
path := ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.SetupClients(path)

expConsensusStateHeights = append(expConsensusStateHeights, path.EndpointA.GetClientState().GetLatestHeight().(types.Height))

err := path.EndpointA.UpdateClient()
suite.Require().NoError(err)

expConsensusStateHeights = append(expConsensusStateHeights, path.EndpointA.GetClientState().GetLatestHeight().(types.Height))

req = &types.QueryConsensusStateHeightsRequest{
ClientId: path.EndpointA.ClientID,
Pagination: &query.PageRequest{
Limit: 3,
CountTotal: true,
},
}
},
true,
},
{
"invalid client identifier",
func() {
req = &types.QueryConsensusStateHeightsRequest{}
},
false,
},
}

for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset

tc.malleate()
ctx := sdk.WrapSDKContext(suite.chainA.GetContext())
res, err := suite.chainA.QueryServer.ConsensusStateHeights(ctx, req)

if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(len(expConsensusStateHeights), len(res.ConsensusStateHeights))
for i := range expConsensusStateHeights {
suite.Require().NotNil(res.ConsensusStateHeights[i])
suite.Require().Equal(expConsensusStateHeights[i], res.ConsensusStateHeights[i])
}
} else {
suite.Require().Error(err)
}
})
}
}

func (suite *KeeperTestSuite) TestQueryClientStatus() {
var (
req *types.QueryClientStatusRequest
Expand Down
5 changes: 5 additions & 0 deletions modules/core/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ func (q Keeper) ConsensusStates(c context.Context, req *clienttypes.QueryConsens
return q.ClientKeeper.ConsensusStates(c, req)
}

// ConsensusStateHeights implements the IBC QueryServer interface
func (q Keeper) ConsensusStateHeights(c context.Context, req *clienttypes.QueryConsensusStateHeightsRequest) (*clienttypes.QueryConsensusStateHeightsResponse, error) {
return q.ClientKeeper.ConsensusStateHeights(c, req)
}

// ClientStatus implements the IBC QueryServer interface
func (q Keeper) ClientStatus(c context.Context, req *clienttypes.QueryClientStatusRequest) (*clienttypes.QueryClientStatusResponse, error) {
return q.ClientKeeper.ClientStatus(c, req)
Expand Down
Loading

0 comments on commit 25b3e1b

Please sign in to comment.