-
Notifications
You must be signed in to change notification settings - Fork 165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: support multiple chain ids in zoneconcierge chains info api #362
Changes from all commits
cfd10a0
e3e9913
0e563f2
b076f45
5b43df7
f5121d4
c058d25
08d18f1
e1ee110
2be6a46
f9cf919
fba823f
6af0216
7fcfa35
70dead9
65f945b
8da5b99
e36eaf6
fa511e9
beecb9e
39a9297
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -209,15 +209,14 @@ func (n *NodeConfig) QueryCheckpointChains() (*[]string, error) { | |
return &chainsResponse.ChainIds, nil | ||
} | ||
|
||
func (n *NodeConfig) QueryCheckpointChainInfo(chainId string) (*zctypes.ChainInfo, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this method removed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I couldn't find its usage in any of the existing e2e tests so removed it. @KonradStaniec I am not sure how to run e2e tests properly locally. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so to run tests:
To add new tests, proper place is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @KonradStaniec, I have added a relevant assertion in the |
||
infoPath := fmt.Sprintf("/babylon/zoneconcierge/v1/chain_info/%s", chainId) | ||
bz, err := n.QueryGRPCGateway(infoPath) | ||
func (n *NodeConfig) QueryCheckpointChainsInfo(chainID string) ([]*zctypes.ChainInfo, error) { | ||
bz, err := n.QueryGRPCGateway("/babylon/zoneconcierge/v1/chains_info", "chain_ids", chainID) | ||
require.NoError(n.t, err) | ||
var infoResponse zctypes.QueryChainInfoResponse | ||
var infoResponse zctypes.QueryChainsInfoResponse | ||
if err := util.Cdc.UnmarshalJSON(bz, &infoResponse); err != nil { | ||
return nil, err | ||
} | ||
return infoResponse.ChainInfo, nil | ||
return infoResponse.ChainsInfo, nil | ||
} | ||
|
||
func (n *NodeConfig) QueryCurrentEpoch() (uint64, error) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,13 +2,11 @@ package cli | |
|
||
import ( | ||
"fmt" | ||
// "strings" | ||
|
||
"github.com/cosmos/cosmos-sdk/client/flags" | ||
"github.com/spf13/cobra" | ||
|
||
"github.com/cosmos/cosmos-sdk/client" | ||
// "github.com/cosmos/cosmos-sdk/client/flags" | ||
// sdk "github.com/cosmos/cosmos-sdk/types" | ||
|
||
"github.com/babylonchain/babylon/x/zoneconcierge/types" | ||
) | ||
|
@@ -24,5 +22,28 @@ func GetQueryCmd(queryRoute string) *cobra.Command { | |
RunE: client.ValidateCmd, | ||
} | ||
|
||
cmd.AddCommand(CmdChainsInfo()) | ||
return cmd | ||
} | ||
|
||
func CmdChainsInfo() *cobra.Command { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for adding this command! |
||
cmd := &cobra.Command{ | ||
Use: "chains-info <chain-ids>", | ||
Short: "retrieves the latest info for a list of chains with given IDs", | ||
Args: cobra.ArbitraryArgs, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
clientCtx := client.GetClientContextFromCmd(cmd) | ||
queryClient := types.NewQueryClient(clientCtx) | ||
req := types.QueryChainsInfoRequest{ChainIds: args} | ||
resp, err := queryClient.ChainsInfo(cmd.Context(), &req) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return clientCtx.PrintProto(resp) | ||
}, | ||
} | ||
|
||
flags.AddQueryFlagsToCmd(cmd) | ||
return cmd | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,15 +3,18 @@ package keeper | |
import ( | ||
"context" | ||
|
||
"github.com/babylonchain/babylon/x/zoneconcierge/types" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/cosmos/cosmos-sdk/types/query" | ||
"google.golang.org/grpc/codes" | ||
"google.golang.org/grpc/status" | ||
|
||
"github.com/babylonchain/babylon/x/zoneconcierge/types" | ||
) | ||
|
||
var _ types.QueryServer = Keeper{} | ||
|
||
const maxQueryChainsInfoLimit = 100 | ||
|
||
func (k Keeper) ChainList(c context.Context, req *types.QueryChainListRequest) (*types.QueryChainListResponse, error) { | ||
if req == nil { | ||
return nil, status.Error(codes.InvalidArgument, "invalid request") | ||
|
@@ -37,24 +40,46 @@ func (k Keeper) ChainList(c context.Context, req *types.QueryChainListRequest) ( | |
return resp, nil | ||
} | ||
|
||
// ChainInfo returns the latest info of a chain with given ID | ||
func (k Keeper) ChainInfo(c context.Context, req *types.QueryChainInfoRequest) (*types.QueryChainInfoResponse, error) { | ||
// ChainsInfo returns the latest info for a list of chains with given IDs | ||
func (k Keeper) ChainsInfo(c context.Context, req *types.QueryChainsInfoRequest) (*types.QueryChainsInfoResponse, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Usually requests which returns lists should be paginated. Here it is a bit tricky as we provide list of chain-ids and return list of chain info responses. In perfect world we would need to put some kinda of limit on number of chain-ids requested and tie it somehow to pagination. The limit is needed to avoid someone querying node for 1M of chain-ids, and exhausting node memory when it will try to read 1M Maybe for not just put limit in place ? (50 or 100 chain ids ?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure, good point. I have hardcoded a max limit of 100 now. |
||
if req == nil { | ||
return nil, status.Error(codes.InvalidArgument, "invalid request") | ||
} | ||
|
||
if len(req.ChainId) == 0 { | ||
return nil, status.Error(codes.InvalidArgument, "chain ID cannot be empty") | ||
if len(req.ChainIds) == 0 { | ||
return nil, status.Error(codes.InvalidArgument, "chain IDs cannot be empty") | ||
} | ||
|
||
if len(req.ChainIds) > maxQueryChainsInfoLimit { | ||
return nil, status.Errorf(codes.InvalidArgument, "cannot query more than %d chains", maxQueryChainsInfoLimit) | ||
} | ||
|
||
encountered := map[string]bool{} | ||
for _, chainID := range req.ChainIds { | ||
if len(chainID) == 0 { | ||
return nil, status.Error(codes.InvalidArgument, "chain ID cannot be empty") | ||
} | ||
|
||
// check for duplicates and return error on first duplicate found | ||
if encountered[chainID] { | ||
return nil, status.Errorf(codes.InvalidArgument, "duplicate chain ID %s", chainID) | ||
} else { | ||
encountered[chainID] = true | ||
} | ||
} | ||
|
||
ctx := sdk.UnwrapSDKContext(c) | ||
var chainsInfo []*types.ChainInfo | ||
for _, chainID := range req.ChainIds { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe also check if a chain ID is an empty string. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure, fixed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we move the check after L49? so that as long as there is an empty chain ID then no query will be performed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure, fixed. |
||
chainInfo, err := k.GetChainInfo(ctx, chainID) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we are missing handling of the case when caller puts duplicated chain-id in the request list, imo it makes no sense to return duplicated chain-info results. There two ways on handling that:
I think I would go for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good catch, sure I have implemented 2 now. |
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// find the chain info of this epoch | ||
chainInfo, err := k.GetChainInfo(ctx, req.ChainId) | ||
if err != nil { | ||
return nil, err | ||
chainsInfo = append(chainsInfo, chainInfo) | ||
} | ||
resp := &types.QueryChainInfoResponse{ChainInfo: chainInfo} | ||
|
||
resp := &types.QueryChainsInfoResponse{ChainsInfo: chainsInfo} | ||
return resp, nil | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to take a list of strings via the URL? Tbh this api is helpful for manually checking the liveness of checkpoints
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I think it's already being passed that way in current setup. So the GET call would translate to
/babylon/zoneconcierge/v1/chains_info?chain_ids=1&chain_ids=2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about this again, I couldn't test with multiple chain ids so I am not very clear if protobuf repeated strings would translate to HTTP get query params or body.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I could not think of any straightforward way either, nor could I find any practice for such APIs. So probably let's stick to your current change